teiid SVN: r4472 - in trunk: api/src/main/java/org/teiid/translator and 17 other directories.
by teiid-commits@lists.jboss.org
Author: rareddy
Date: 2012-09-25 18:15:11 -0400 (Tue, 25 Sep 2012)
New Revision: 4472
Added:
trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/JDBCDirectQueryExecution.java
trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/TestJDBCDirectQueryExecution.java
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPDirectCreateUpdateDeleteQueryExecution.java
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPDirectSearchQueryExecution.java
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPQueryExecution.java
trunk/connectors/translator-ldap/src/test/java/org/teiid/translator/ldap/TestLDAPDirectQueryExecution.java
trunk/connectors/translator-salesforce/src/main/java/org/teiid/translator/salesforce/execution/DirectQueryExecution.java
trunk/connectors/translator-salesforce/src/test/java/org/teiid/translator/salesforce/execution/TestSalesForceDirectQueryExecution.java
trunk/engine/src/main/java/org/teiid/query/metadata/DirectQueryMetadataRepository.java
Modified:
trunk/api/src/main/java/org/teiid/translator/BaseDelegatingExecutionFactory.java
trunk/api/src/main/java/org/teiid/translator/ExecutionFactory.java
trunk/api/src/test/java/org/teiid/translator/TestBaseDelegatingExecutionFactory.java
trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/JDBCExecutionException.java
trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/JDBCExecutionFactory.java
trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/JDBCPlugin.java
trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/JDBCProcedureExecution.java
trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/oracle/OracleExecutionFactory.java
trunk/connectors/translator-jdbc/src/main/resources/org/teiid/translator/jdbc/i18n.properties
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/IQueryToLdapSearchParser.java
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPExecutionFactory.java
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPPlugin.java
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPSearchDetails.java
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPSyncQueryExecution.java
trunk/connectors/translator-ldap/src/main/resources/org/teiid/translator/ldap/i18n.properties
trunk/connectors/translator-ldap/src/test/java/org/teiid/translator/ldap/TestIQueryToLdapSearchParser.java
trunk/connectors/translator-olap/src/main/java/org/teiid/translator/olap/OlapExecutionFactory.java
trunk/connectors/translator-olap/src/main/java/org/teiid/translator/olap/OlapQueryExecution.java
trunk/connectors/translator-salesforce/src/main/java/org/teiid/translator/salesforce/SalesForceExecutionFactory.java
trunk/connectors/translator-salesforce/src/main/java/org/teiid/translator/salesforce/SalesForcePlugin.java
trunk/connectors/translator-salesforce/src/main/resources/org/teiid/translator/salesforce/i18n.properties
trunk/engine/src/test/java/org/teiid/query/unittest/RealMetadataFactory.java
trunk/pom.xml
trunk/runtime/src/main/java/org/teiid/runtime/AbstractVDBDeployer.java
trunk/test-integration/common/src/test/java/org/teiid/dqp/internal/process/TestExecutionReuse.java
Log:
TEIID-2176: Adding the native query procedures to JDBC, LDAP, Salesforce and OLAP translators.
Modified: trunk/api/src/main/java/org/teiid/translator/BaseDelegatingExecutionFactory.java
===================================================================
--- trunk/api/src/main/java/org/teiid/translator/BaseDelegatingExecutionFactory.java 2012-09-25 18:58:05 UTC (rev 4471)
+++ trunk/api/src/main/java/org/teiid/translator/BaseDelegatingExecutionFactory.java 2012-09-25 22:15:11 UTC (rev 4472)
@@ -24,6 +24,7 @@
import java.util.List;
+import org.teiid.language.Argument;
import org.teiid.language.Call;
import org.teiid.language.Command;
import org.teiid.language.LanguageFactory;
@@ -451,4 +452,18 @@
public boolean supportsArrayType() {
return delegate.supportsArrayType();
}
+ @Override
+ public String getNativeQueryProcedureName() {
+ return delegate.getNativeQueryProcedureName();
+ }
+
+ public boolean supportsNativeQueries() {
+ return delegate.supportsNativeQueries();
+ }
+ @Override
+ public ResultSetExecution createDirectExecution(List<Argument> arguments,
+ Command command, ExecutionContext executionContext,
+ RuntimeMetadata metadata, C connection) throws TranslatorException {
+ return delegate.createDirectExecution(arguments, command, executionContext, metadata, connection);
+ }
}
Modified: trunk/api/src/main/java/org/teiid/translator/ExecutionFactory.java
===================================================================
--- trunk/api/src/main/java/org/teiid/translator/ExecutionFactory.java 2012-09-25 18:58:05 UTC (rev 4471)
+++ trunk/api/src/main/java/org/teiid/translator/ExecutionFactory.java 2012-09-25 22:15:11 UTC (rev 4472)
@@ -33,6 +33,7 @@
import org.teiid.connector.DataPlugin;
import org.teiid.core.TeiidException;
import org.teiid.core.util.ReflectionHelper;
+import org.teiid.language.Argument;
import org.teiid.language.BatchedUpdates;
import org.teiid.language.Call;
import org.teiid.language.Command;
@@ -113,8 +114,9 @@
private int maxInSize = DEFAULT_MAX_IN_CRITERIA_SIZE;
private int maxDependentInPredicates = DEFAULT_MAX_IN_CRITERIA_SIZE;
private boolean copyLobs;
-
+ private boolean supportsNativeQueries;
private LinkedList<FunctionMethod> pushdownFunctionMethods = new LinkedList<FunctionMethod>();
+ private String nativeProcedureName = "native"; //$NON-NLS-1$
/**
* Initialize the connector with supplied configuration
@@ -268,6 +270,13 @@
* @return An execution object that can use to execute the command
*/
public Execution createExecution(Command command, ExecutionContext executionContext, RuntimeMetadata metadata, C connection) throws TranslatorException {
+ if (command instanceof Call) {
+ Call obj = (Call)command;
+ if (supportsNativeQueries() && obj.getMetadataObject().getName().equals(getNativeQueryProcedureName())) {
+ List<Argument> arguments = obj.getArguments();
+ return createDirectExecution(arguments, command, executionContext, metadata, connection);
+ }
+ }
if (command instanceof QueryExpression) {
return createResultSetExecution((QueryExpression)command, executionContext, metadata, connection);
}
@@ -292,6 +301,11 @@
throw new TranslatorException(DataPlugin.Event.TEIID60001, DataPlugin.Util.gs(DataPlugin.Event.TEIID60001, "createUpdateExecution")); //$NON-NLS-1$
}
+ @SuppressWarnings("unused")
+ public ResultSetExecution createDirectExecution(List<Argument> arguments, Command command, ExecutionContext executionContext, RuntimeMetadata metadata, C connection) throws TranslatorException {
+ throw new TranslatorException(DataPlugin.Event.TEIID60001, DataPlugin.Util.gs(DataPlugin.Event.TEIID60001, "createDirectExecution")); //$NON-NLS-1$
+ }
+
/**
* Support indicates connector can accept queries with SELECT DISTINCT
* @since 3.1 SP2
@@ -1035,5 +1049,31 @@
public boolean supportsArrayType() {
return false;
}
-
+
+ /**
+ * True, if this translator supports execution of source specific commands unaltered through 'native' procedure.
+ * @return
+ */
+ @TranslatorProperty(display="Supports Native Queries", description="True, if this translator supports execution of source specific commands unaltered through 'native' procedure", advanced=true)
+ public boolean supportsNativeQueries() {
+ return this.supportsNativeQueries;
+ }
+
+ public void setSupportsNativeQueries(boolean state) {
+ this.supportsNativeQueries = state;
+ }
+
+ /**
+ * Defines the name of the procedure that need to be treated as "native" query processing procedure. This metadata or signature
+ * of the procedure is defined automatically.
+ * @return
+ */
+ @TranslatorProperty(display="Name of the native query", description="The name of the procedure that is considered as the name of the direct query procedure", advanced=true)
+ public String getNativeQueryProcedureName() {
+ return this.nativeProcedureName;
+ }
+
+ public void setNativeQueryProcedureName(String name) {
+ this.nativeProcedureName = name;
+ }
}
Modified: trunk/api/src/test/java/org/teiid/translator/TestBaseDelegatingExecutionFactory.java
===================================================================
--- trunk/api/src/test/java/org/teiid/translator/TestBaseDelegatingExecutionFactory.java 2012-09-25 18:58:05 UTC (rev 4471)
+++ trunk/api/src/test/java/org/teiid/translator/TestBaseDelegatingExecutionFactory.java 2012-09-25 22:15:11 UTC (rev 4472)
@@ -34,7 +34,7 @@
Method[] methods = ExecutionFactory.class.getDeclaredMethods();
Method[] proxyMethods = BaseDelegatingExecutionFactory.class.getDeclaredMethods();
//excluding the setter methods the counts should be equal
- assertEquals(methods.length - 10, proxyMethods.length);
+ assertEquals(methods.length - 12, proxyMethods.length);
}
}
Added: trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/JDBCDirectQueryExecution.java
===================================================================
--- trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/JDBCDirectQueryExecution.java (rev 0)
+++ trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/JDBCDirectQueryExecution.java 2012-09-25 22:15:11 UTC (rev 4472)
@@ -0,0 +1,158 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+/*
+ */
+
+package org.teiid.translator.jdbc;
+
+import java.sql.CallableStatement;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.teiid.language.Argument;
+import org.teiid.language.Command;
+import org.teiid.logging.LogConstants;
+import org.teiid.logging.LogManager;
+import org.teiid.translator.DataNotAvailableException;
+import org.teiid.translator.ExecutionContext;
+import org.teiid.translator.ProcedureExecution;
+import org.teiid.translator.TranslatorException;
+import org.teiid.translator.TypeFacility;
+
+
+public class JDBCDirectQueryExecution extends JDBCQueryExecution implements ProcedureExecution {
+
+ protected int columnCount;
+ private List<Argument> arguments;
+ protected int updateCount = -1;
+
+ public JDBCDirectQueryExecution(List<Argument> arguments, Command command, Connection connection, ExecutionContext context, JDBCExecutionFactory env) {
+ super(command, connection, context, env);
+ this.arguments = arguments;
+ }
+
+ @Override
+ public void execute() throws TranslatorException {
+ String sourceSQL = (String) this.arguments.get(0).getArgumentValue().getValue();
+ List<Argument> parameters = this.arguments.subList(1, this.arguments.size());
+
+ LogManager.logTrace(LogConstants.CTX_CONNECTOR, "Source sql", sourceSQL); //$NON-NLS-1$
+ boolean prepared = (sourceSQL.indexOf('?') != -1);
+ boolean callable = (sourceSQL.indexOf("call ") != -1); //$NON-NLS-1$
+ int paramCount = getParamCount(sourceSQL);
+
+ try {
+ if (callable) {
+ CallableStatement cstmt = getCallableStatement(sourceSQL);
+ this.results = this.executionFactory.executeStoredProcedure(cstmt, parameters, TypeFacility.RUNTIME_TYPES.OBJECT);
+ this.columnCount = this.results.getMetaData().getColumnCount();
+ }
+ else {
+ Statement stmt;
+ boolean hasResults = false;
+
+ if(prepared) {
+ PreparedStatement pstatement = getPreparedStatement(sourceSQL);
+ for (int i = 0; i < paramCount; i++) {
+ if (this.arguments.size()-1 < paramCount) {
+ throw new TranslatorException(JDBCPlugin.Util.gs(JDBCPlugin.Event.TEIID11019, sourceSQL));
+ }
+ Argument arg = this.arguments.get(i+1);
+ pstatement.setObject(i+1, arg.getArgumentValue().getValue());
+ }
+ stmt = pstatement;
+ hasResults = pstatement.execute();
+ }
+ else {
+ stmt = getStatement();
+ hasResults = stmt.execute(sourceSQL);
+ }
+
+ if (hasResults) {
+ this.results = stmt.getResultSet();
+ this.columnCount = this.results.getMetaData().getColumnCount();
+ }
+ else {
+ this.updateCount = stmt.getUpdateCount();
+ }
+ }
+ addStatementWarnings();
+ } catch (SQLException e) {
+ throw new JDBCExecutionException(JDBCPlugin.Event.TEIID11008, e, sourceSQL);
+ }
+ }
+
+ private int getParamCount(String sourceSQL) {
+ int paramCount = 0;
+ int idx = -1;
+ while (true) {
+ idx = sourceSQL.indexOf('?', idx+1);
+ if (idx == -1) {
+ break;
+ }
+ paramCount++;
+ }
+ return paramCount;
+ }
+
+ @Override
+ public List<?> next() throws TranslatorException, DataNotAvailableException {
+ try {
+ ArrayList<Object[]> row = new ArrayList<Object[]>(1);
+
+ if (this.results != null) {
+ if (this.results.next()) {
+ // New row for result set
+ List<Object> vals = new ArrayList<Object>(this.columnCount);
+
+ for (int i = 0; i < this.columnCount; i++) {
+ // Convert from 0-based to 1-based
+ Object value = this.executionFactory.retrieveValue(this.results, i+1, TypeFacility.RUNTIME_TYPES.OBJECT);
+ vals.add(value);
+ }
+ row.add(vals.toArray(new Object[vals.size()]));
+ return row;
+ }
+ }
+ else if (this.updateCount != -1) {
+ List<Object> vals = new ArrayList<Object>(1);
+ vals.add(new Integer(this.updateCount));
+ this.updateCount = -1;
+ row.add(vals.toArray(new Object[vals.size()]));
+ return row;
+ }
+ } catch (SQLException e) {
+ throw new TranslatorException(e,JDBCPlugin.Util.getString("JDBCTranslator.Unexpected_exception_translating_results___8", e.getMessage())); //$NON-NLS-1$
+ }
+ return null;
+ }
+
+ @Override
+ public List<?> getOutputParameterValues() throws TranslatorException {
+ return null;
+ }
+}
Property changes on: trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/JDBCDirectQueryExecution.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Modified: trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/JDBCExecutionException.java
===================================================================
--- trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/JDBCExecutionException.java 2012-09-25 18:58:05 UTC (rev 4471)
+++ trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/JDBCExecutionException.java 2012-09-25 22:15:11 UTC (rev 4472)
@@ -37,4 +37,9 @@
super(error, commands == null || commands.length == 0 ? event.toString()+":"+error.getMessage() : event.toString()+":"+JDBCPlugin.Util.gs(JDBCPlugin.Event.TEIID11004, Arrays.toString(commands))); //$NON-NLS-1$ //$NON-NLS-2$
setCode(String.valueOf(error.getErrorCode()));
}
+
+ public JDBCExecutionException(BundleUtil.Event event, SQLException error, String command) {
+ super(error, event.toString()+":"+JDBCPlugin.Util.gs(JDBCPlugin.Event.TEIID11004, command)); //$NON-NLS-1$
+ setCode(String.valueOf(error.getErrorCode()));
+ }
}
Modified: trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/JDBCExecutionFactory.java
===================================================================
--- trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/JDBCExecutionFactory.java 2012-09-25 18:58:05 UTC (rev 4471)
+++ trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/JDBCExecutionFactory.java 2012-09-25 22:15:11 UTC (rev 4472)
@@ -140,6 +140,7 @@
setSupportsInnerJoins(true);
setMaxInCriteriaSize(DEFAULT_MAX_IN_CRITERIA);
setMaxDependentInPredicates(DEFAULT_MAX_DEPENDENT_PREDICATES);
+ setSupportsNativeQueries(true);
}
@Override
@@ -207,6 +208,14 @@
}
@Override
+ public ResultSetExecution createDirectExecution(List<Argument> arguments, Command command, ExecutionContext executionContext, RuntimeMetadata metadata, Connection conn)
+ throws TranslatorException {
+ //TODO: This is not correct; this should be only called once for connection creation
+ obtainedConnection(conn);
+ return new JDBCDirectQueryExecution(arguments, command, conn, executionContext, this);
+ }
+
+ @Override
public ProcedureExecution createProcedureExecution(Call command, ExecutionContext executionContext, RuntimeMetadata metadata, Connection conn)
throws TranslatorException {
//TODO: This is not correct; this should be only called once for connection creation
@@ -717,15 +726,14 @@
* stored procedures differently, subclasses should override this method
* if necessary.
*/
- public ResultSet executeStoredProcedure(CallableStatement statement, TranslatedCommand command, Class<?> returnType) throws SQLException {
- List params = command.getPreparedValues();
+ public ResultSet executeStoredProcedure(CallableStatement statement, List<Argument> preparedValues, Class<?> returnType) throws SQLException {
int index = 1;
if(returnType != null){
registerSpecificTypeOfOutParameter(statement, returnType, index++);
}
- Iterator iter = params.iterator();
+ Iterator iter = preparedValues.iterator();
while(iter.hasNext()){
Argument param = (Argument)iter.next();
Modified: trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/JDBCPlugin.java
===================================================================
--- trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/JDBCPlugin.java 2012-09-25 18:58:05 UTC (rev 4471)
+++ trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/JDBCPlugin.java 2012-09-25 22:15:11 UTC (rev 4472)
@@ -54,5 +54,6 @@
TEIID11016,
TEIID11017,
TEIID11018,
+ TEIID11019
}
}
Modified: trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/JDBCProcedureExecution.java
===================================================================
--- trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/JDBCProcedureExecution.java 2012-09-25 18:58:05 UTC (rev 4471)
+++ trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/JDBCProcedureExecution.java 2012-09-25 22:15:11 UTC (rev 4472)
@@ -64,7 +64,7 @@
try{
//create parameter index map
CallableStatement cstmt = getCallableStatement(sql);
- this.results = this.executionFactory.executeStoredProcedure(cstmt, translatedComm, procedure.getReturnType());
+ this.results = this.executionFactory.executeStoredProcedure(cstmt, translatedComm.getPreparedValues(), procedure.getReturnType());
addStatementWarnings();
}catch(SQLException e){
throw new TranslatorException(JDBCPlugin.Event.TEIID11004, e, JDBCPlugin.Util.gs(JDBCPlugin.Event.TEIID11004, sql));
Modified: trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/oracle/OracleExecutionFactory.java
===================================================================
--- trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/oracle/OracleExecutionFactory.java 2012-09-25 18:58:05 UTC (rev 4471)
+++ trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/oracle/OracleExecutionFactory.java 2012-09-25 22:15:11 UTC (rev 4472)
@@ -730,8 +730,8 @@
@Override
public ResultSet executeStoredProcedure(CallableStatement statement,
- TranslatedCommand command, Class<?> returnType) throws SQLException {
- ResultSet rs = super.executeStoredProcedure(statement, command, returnType);
+ List<Argument> preparedValues, Class<?> returnType) throws SQLException {
+ ResultSet rs = super.executeStoredProcedure(statement, preparedValues, returnType);
if (!oracleSuppliedDriver || returnType != RefCursorType.class) {
return rs;
}
Modified: trunk/connectors/translator-jdbc/src/main/resources/org/teiid/translator/jdbc/i18n.properties
===================================================================
--- trunk/connectors/translator-jdbc/src/main/resources/org/teiid/translator/jdbc/i18n.properties 2012-09-25 18:58:05 UTC (rev 4471)
+++ trunk/connectors/translator-jdbc/src/main/resources/org/teiid/translator/jdbc/i18n.properties 2012-09-25 22:15:11 UTC (rev 4472)
@@ -32,4 +32,5 @@
TEIID11002=Failed to report the JDBC driver and connection information
TEIID11006=Teiid runtime names, which are case insensitive, for the imported metadata are not unique. If not already set, use the setting importer.useFullSchemaName to create Teiid names that include the source schema.
TEIID11017=Invalid name in source sequence format. Expected <element name> {0} <sequence name>.<sequence value>, but was {1}
-TEIID11018=Connection is null; Datasource may not have been defined. Requires a active connection to retrieve the metadata.
\ No newline at end of file
+TEIID11018=Connection is null; Datasource may not have been defined. Requires a active connection to retrieve the metadata.
+TEIID11019=For direct JDBC execution of command "{0}", not any/all parameters are supplied for the prepared jdbc call.
\ No newline at end of file
Added: trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/TestJDBCDirectQueryExecution.java
===================================================================
--- trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/TestJDBCDirectQueryExecution.java (rev 0)
+++ trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/TestJDBCDirectQueryExecution.java 2012-09-25 22:15:11 UTC (rev 4472)
@@ -0,0 +1,136 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package org.teiid.translator.jdbc;
+
+import static org.junit.Assert.*;
+
+import java.sql.CallableStatement;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.Statement;
+
+
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.teiid.language.Command;
+import org.teiid.metadata.RuntimeMetadata;
+import org.teiid.translator.ExecutionContext;
+import org.teiid.translator.ResultSetExecution;
+
+@SuppressWarnings("nls")
+public class TestJDBCDirectQueryExecution {
+
+ @Test public void testProcedureExecution() throws Exception {
+ Command command = TranslationHelper.helpTranslate(TranslationHelper.BQT_VDB, "exec native('{?=call spTest8a()}')"); //$NON-NLS-1$
+ Connection connection = Mockito.mock(Connection.class);
+ CallableStatement cs = Mockito.mock(CallableStatement.class);
+ ResultSet rs = Mockito.mock(ResultSet.class);
+ ResultSetMetaData rsm = Mockito.mock(ResultSetMetaData.class);
+
+ Mockito.stub(cs.getUpdateCount()).toReturn(-1);
+ Mockito.stub(cs.getResultSet()).toReturn(rs);
+ Mockito.stub(rs.getMetaData()).toReturn(rsm);
+ Mockito.stub(rsm.getColumnCount()).toReturn(1);
+ Mockito.stub(connection.prepareCall("{?=call spTest8a()}")).toReturn(cs); //$NON-NLS-1$
+ Mockito.stub(rs.next()).toReturn(true);
+ Mockito.stub(rs.getObject(1)).toReturn(5);
+ Mockito.stub(connection.getMetaData()).toReturn(Mockito.mock(DatabaseMetaData.class));
+
+ JDBCExecutionFactory ef = new JDBCExecutionFactory();
+ ResultSetExecution execution = (ResultSetExecution)ef.createExecution(command, Mockito.mock(ExecutionContext.class), Mockito.mock(RuntimeMetadata.class), connection);
+ execution.execute();
+ assertArrayEquals(new Object[] {5}, (Object[])execution.next().get(0));
+ }
+
+ @Test public void testSelectExecution() throws Exception {
+ Command command = TranslationHelper.helpTranslate(TranslationHelper.BQT_VDB, "call native('select * from Source')"); //$NON-NLS-1$
+ Connection connection = Mockito.mock(Connection.class);
+ Statement stmt = Mockito.mock(Statement.class);
+ ResultSet rs = Mockito.mock(ResultSet.class);
+ ResultSetMetaData rsm = Mockito.mock(ResultSetMetaData.class);
+
+ Mockito.stub(stmt.getUpdateCount()).toReturn(-1);
+ Mockito.stub(stmt.getResultSet()).toReturn(rs);
+ Mockito.stub(rs.getMetaData()).toReturn(rsm);
+ Mockito.stub(rsm.getColumnCount()).toReturn(2);
+ Mockito.stub(connection.createStatement()).toReturn(stmt); //$NON-NLS-1$
+ Mockito.stub(stmt.execute("select * from Source")).toReturn(true);
+ Mockito.stub(rs.next()).toReturn(true);
+ Mockito.stub(rs.getObject(1)).toReturn(5);
+ Mockito.stub(rs.getObject(2)).toReturn("five");
+ Mockito.stub(connection.getMetaData()).toReturn(Mockito.mock(DatabaseMetaData.class));
+
+ JDBCExecutionFactory ef = new JDBCExecutionFactory();
+ ResultSetExecution execution = (ResultSetExecution)ef.createExecution(command, Mockito.mock(ExecutionContext.class), Mockito.mock(RuntimeMetadata.class), connection);
+ execution.execute();
+ assertArrayEquals(new Object[] {5, "five"}, (Object[])execution.next().get(0));
+ }
+
+ @Test public void testPrepareExecution() throws Exception {
+ Command command = TranslationHelper.helpTranslate(TranslationHelper.BQT_VDB, "call native('select * from Source where e1 = ?', 2)"); //$NON-NLS-1$
+ Connection connection = Mockito.mock(Connection.class);
+ PreparedStatement stmt = Mockito.mock(PreparedStatement.class);
+ ResultSet rs = Mockito.mock(ResultSet.class);
+ ResultSetMetaData rsm = Mockito.mock(ResultSetMetaData.class);
+
+ Mockito.stub(stmt.getUpdateCount()).toReturn(-1);
+ Mockito.stub(stmt.getResultSet()).toReturn(rs);
+ Mockito.stub(stmt.execute()).toReturn(true);
+ Mockito.stub(rs.getMetaData()).toReturn(rsm);
+ Mockito.stub(rsm.getColumnCount()).toReturn(2);
+ Mockito.stub(connection.prepareStatement("select * from Source where e1 = ?")).toReturn(stmt); //$NON-NLS-1$
+ Mockito.stub(rs.next()).toReturn(true);
+ Mockito.stub(rs.getObject(1)).toReturn(5);
+ Mockito.stub(rs.getObject(2)).toReturn("five");
+ Mockito.stub(connection.getMetaData()).toReturn(Mockito.mock(DatabaseMetaData.class));
+
+ JDBCExecutionFactory ef = new JDBCExecutionFactory();
+ ResultSetExecution execution = (ResultSetExecution)ef.createExecution(command, Mockito.mock(ExecutionContext.class), Mockito.mock(RuntimeMetadata.class), connection);
+ execution.execute();
+ assertArrayEquals(new Object[] {5, "five"}, (Object[])execution.next().get(0));
+ }
+
+ @Test public void testPrepareUpdateCount() throws Exception {
+ Command command = TranslationHelper.helpTranslate(TranslationHelper.BQT_VDB, "call native('update source set e1=? where e2 = ?', 2, 'foo')"); //$NON-NLS-1$
+ Connection connection = Mockito.mock(Connection.class);
+ PreparedStatement stmt = Mockito.mock(PreparedStatement.class);
+ ResultSet rs = Mockito.mock(ResultSet.class);
+ ResultSetMetaData rsm = Mockito.mock(ResultSetMetaData.class);
+
+ Mockito.stub(stmt.getUpdateCount()).toReturn(-1);
+ Mockito.stub(stmt.getUpdateCount()).toReturn(5);
+ Mockito.stub(stmt.execute()).toReturn(false);
+ Mockito.stub(rs.getMetaData()).toReturn(rsm);
+ Mockito.stub(rsm.getColumnCount()).toReturn(2);
+ Mockito.stub(connection.prepareStatement("update source set e1=? where e2 = ?")).toReturn(stmt); //$NON-NLS-1$
+ Mockito.stub(connection.getMetaData()).toReturn(Mockito.mock(DatabaseMetaData.class));
+
+ JDBCExecutionFactory ef = new JDBCExecutionFactory();
+ ResultSetExecution execution = (ResultSetExecution)ef.createExecution(command, Mockito.mock(ExecutionContext.class), Mockito.mock(RuntimeMetadata.class), connection);
+ execution.execute();
+ assertArrayEquals(new Object[] {5}, (Object[])execution.next().get(0));
+ }
+}
Property changes on: trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/TestJDBCDirectQueryExecution.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Modified: trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/IQueryToLdapSearchParser.java
===================================================================
--- trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/IQueryToLdapSearchParser.java 2012-09-25 18:58:05 UTC (rev 4471)
+++ trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/IQueryToLdapSearchParser.java 2012-09-25 22:15:11 UTC (rev 4472)
@@ -41,32 +41,10 @@
import java.util.LinkedList;
import java.util.List;
-import javax.naming.NamingException;
-import javax.naming.directory.BasicAttribute;
import javax.naming.directory.SearchControls;
import javax.naming.ldap.SortKey;
-import org.teiid.language.AggregateFunction;
-import org.teiid.language.AndOr;
-import org.teiid.language.ColumnReference;
-import org.teiid.language.Comparison;
-import org.teiid.language.Condition;
-import org.teiid.language.DerivedColumn;
-import org.teiid.language.Exists;
-import org.teiid.language.Expression;
-import org.teiid.language.Function;
-import org.teiid.language.In;
-import org.teiid.language.Like;
-import org.teiid.language.Limit;
-import org.teiid.language.Literal;
-import org.teiid.language.NamedTable;
-import org.teiid.language.Not;
-import org.teiid.language.OrderBy;
-import org.teiid.language.ScalarSubquery;
-import org.teiid.language.SearchedCase;
-import org.teiid.language.Select;
-import org.teiid.language.SortSpecification;
-import org.teiid.language.TableReference;
+import org.teiid.language.*;
import org.teiid.language.Comparison.Operator;
import org.teiid.language.SortSpecification.Ordering;
import org.teiid.logging.LogConstants;
@@ -113,7 +91,6 @@
public LDAPSearchDetails translateSQLQueryToLDAPSearch(Select query) throws TranslatorException {
// Parse SELECT symbols.
// The columns will be translated into LDAP attributes of interest.
- ArrayList<BasicAttribute> attributeList = getAttributesFromSelectSymbols(query);
ArrayList<Column> elementList = getElementsFromSelectSymbols(query);
// Parse FROM table.
@@ -165,14 +142,9 @@
}
// Create Search Details
- LDAPSearchDetails sd = new LDAPSearchDetails(contextName, searchScope, filterBuilder.toString(), attributeList, sortKeys, countLimit, elementList);
+ LDAPSearchDetails sd = new LDAPSearchDetails(contextName, searchScope, filterBuilder.toString(), sortKeys, countLimit, elementList);
// Search Details logging
- try {
- sd.printDetailsToLog();
- } catch (NamingException nme) {
- final String msg = LDAPPlugin.Util.getString("IQueryToLdapSearchParser.searchDetailsLoggingError"); //$NON-NLS-1$
- throw new TranslatorException(msg);
- }
+ sd.printDetailsToLog();
return sd;
@@ -588,7 +560,7 @@
// GHH 20080326 - found that code to fall back on Name if NameInSource
// was null wasn't working properly, so replaced with tried and true
// code from another custom connector.
- public String getNameFromElement(Column e) {
+ public static String getNameFromElement(Column e) {
String ldapAttributeName = null;
ldapAttributeName = e.getNameInSource();
if (ldapAttributeName == null || ldapAttributeName.equals("")) { //$NON-NLS-1$
@@ -614,28 +586,6 @@
return selectElementList;
}
- /**
- * Method to get attribute list from the supplied query
- * @param query the supplied Query
- * @return the list of attributes
- */
- private ArrayList<BasicAttribute> getAttributesFromSelectSymbols(Select query) {
- ArrayList<BasicAttribute> ldapAttributeList = new ArrayList<BasicAttribute>();
-
- Iterator<DerivedColumn> selectSymbolItr = query.getDerivedColumns().iterator();
- int i=0;
- while(selectSymbolItr.hasNext()) {
- Column e = getElementFromSymbol(selectSymbolItr.next());
- String ldapAttributeName = this.getNameFromElement(e);
- Object ldapAttributeClass = e.getJavaType();
-
- // Store the element's name and class type, so that we know what to look for in the search results.
- BasicAttribute newAttr = new BasicAttribute(ldapAttributeName, ldapAttributeClass);
- ldapAttributeList.add(newAttr);
- i++;
- }
- return ldapAttributeList;
- }
/**
* Helper method for getting runtime {@link org.teiid.connector.metadata.runtime.Element} from a
Added: trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPDirectCreateUpdateDeleteQueryExecution.java
===================================================================
--- trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPDirectCreateUpdateDeleteQueryExecution.java (rev 0)
+++ trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPDirectCreateUpdateDeleteQueryExecution.java 2012-09-25 22:15:11 UTC (rev 4472)
@@ -0,0 +1,190 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+package org.teiid.translator.ldap;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import javax.naming.NamingException;
+import javax.naming.directory.BasicAttribute;
+import javax.naming.directory.BasicAttributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.ModificationItem;
+import javax.naming.ldap.LdapContext;
+
+import org.teiid.language.Argument;
+import org.teiid.translator.DataNotAvailableException;
+import org.teiid.translator.ExecutionContext;
+import org.teiid.translator.ProcedureExecution;
+import org.teiid.translator.TranslatorException;
+
+public class LDAPDirectCreateUpdateDeleteQueryExecution implements ProcedureExecution {
+ private static final String ATTRIBUTES = "attributes"; //$NON-NLS-1$
+ private List<Argument> arguments;
+ protected LdapContext ldapConnection;
+ protected LDAPExecutionFactory executionFactory;
+ protected ExecutionContext executionContext;
+ private int updateCount = -1;
+
+ public LDAPDirectCreateUpdateDeleteQueryExecution(List<Argument> arguments, LDAPExecutionFactory factory, ExecutionContext executionContext, LdapContext connection) {
+ this.arguments = arguments;
+ this.executionFactory = factory;
+ this.executionContext = executionContext;
+ this.ldapConnection = connection;
+ }
+
+ @Override
+ public void execute() throws TranslatorException {
+ String query = (String)arguments.get(0).getArgumentValue().getValue();
+ String firstToken = null;
+
+ StringTokenizer st = new StringTokenizer(query, ";"); //$NON-NLS-1$
+ if (st.hasMoreTokens()) {
+ firstToken = st.nextToken();
+ if (!firstToken.equalsIgnoreCase("create") && !firstToken.equalsIgnoreCase("update") && !firstToken.equalsIgnoreCase("delete")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ throw new TranslatorException(LDAPPlugin.Util.gs(LDAPPlugin.Event.TEIID12009));
+ }
+ }
+
+ LdapContext ldapCtx = null;
+ try {
+ ldapCtx = (LdapContext)this.ldapConnection.lookup(""); //$NON-NLS-1$
+ } catch (NamingException ne) {
+ throw new TranslatorException(LDAPPlugin.Util.getString("LDAPUpdateExecution.createContextError",ne.getExplanation()));//$NON-NLS-1$
+ }
+
+ if (firstToken.equalsIgnoreCase("delete")) { // //$NON-NLS-1$
+ String theDN = getDN(st); // the token after the marker is always DN
+ try {
+ ldapCtx.destroySubcontext(theDN);
+ this.updateCount = 1;
+ } catch (NamingException ne) {
+ throw new TranslatorException(LDAPPlugin.Util.getString("LDAPUpdateExecution.deleteFailed",theDN,ne.getExplanation()));//$NON-NLS-1$
+ } catch (Exception e) {
+ throw new TranslatorException(e, LDAPPlugin.Util.getString("LDAPUpdateExecution.deleteFailedUnexpected",theDN));//$NON-NLS-1$
+ }
+ }
+ else if (firstToken.equalsIgnoreCase("create")) { //$NON-NLS-1$
+ String theDN = getDN(st); // the token after the marker is always DN
+ ArrayList<BasicAttribute> attributes = getAttributes(st, this.arguments);
+ BasicAttributes attrs = new BasicAttributes();
+ for (BasicAttribute ba:attributes) {
+ attrs.put(ba);
+ }
+ try {
+ ldapCtx.createSubcontext(theDN, attrs);
+ this.updateCount = 1;
+ } catch (NamingException ne) {
+ throw new TranslatorException(LDAPPlugin.Util.getString("LDAPUpdateExecution.insertFailed", theDN, ne.getExplanation()));//$NON-NLS-1$
+ } catch (Exception e) {
+ throw new TranslatorException(e,LDAPPlugin.Util.getString("LDAPUpdateExecution.insertFailedUnexpected", theDN));//$NON-NLS-1$
+ }
+ }
+ else if (firstToken.equalsIgnoreCase("update")) { //$NON-NLS-1$
+ String theDN = getDN(st); // the token after the marker is always DN
+ ArrayList<BasicAttribute> attributes = getAttributes(st, this.arguments);
+ ModificationItem[] updateMods = new ModificationItem[attributes.size()];
+ int i=0;
+ for (BasicAttribute ba:attributes) {
+ updateMods[i++] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, ba);
+ }
+ try {
+ ldapCtx.modifyAttributes(theDN, updateMods);
+ this.updateCount = 1;
+ } catch (NamingException ne) {
+ throw new TranslatorException(LDAPPlugin.Util.getString("LDAPUpdateExecution.updateFailed", theDN, ne.getExplanation()));//$NON-NLS-1$
+ } catch (Exception e) {
+ throw new TranslatorException(e, LDAPPlugin.Util.getString("LDAPUpdateExecution.updateFailedUnexpected",theDN));//$NON-NLS-1$
+ }
+ }
+
+ }
+
+ private String getDN(StringTokenizer st) throws TranslatorException {
+ if (!st.hasMoreTokens()) {
+ throw new TranslatorException(LDAPPlugin.Util.gs(LDAPPlugin.Event.TEIID12010));
+ }
+ return st.nextToken();
+ }
+
+ private ArrayList<BasicAttribute> getAttributes(StringTokenizer st, List<Argument> arguments) throws TranslatorException {
+ if (!st.hasMoreTokens()) {
+ throw new TranslatorException(LDAPPlugin.Util.gs(LDAPPlugin.Event.TEIID12011));
+ }
+
+ ArrayList<BasicAttribute> attributes = new ArrayList<BasicAttribute>();
+
+ while(st.hasMoreElements()) {
+ String var = st.nextToken();
+
+ int index = var.indexOf('=');
+ if (index == -1) {
+ continue;
+ }
+ String key = var.substring(0, index).trim().toLowerCase();
+ String value = var.substring(index+1).trim();
+
+ if (key.equalsIgnoreCase(ATTRIBUTES)) {
+ StringTokenizer attrTokens = new StringTokenizer(value, ","); //$NON-NLS-1$
+ int attrCount = 1;
+ while(attrTokens.hasMoreElements()) {
+ String name = attrTokens.nextToken().trim();
+ if (arguments.size() <= attrCount) {
+ throw new TranslatorException(LDAPPlugin.Util.gs(LDAPPlugin.Event.TEIID12012, name));
+ }
+ Argument argument = arguments.get(attrCount++);
+ Object anObj = argument.getArgumentValue().getValue();
+ attributes.add(new BasicAttribute(name, anObj));
+ }
+
+ }
+ }
+ return attributes;
+ }
+
+ @Override
+ public List<?> getOutputParameterValues() throws TranslatorException {
+ return null;
+ }
+
+ @Override
+ public List<?> next() throws TranslatorException, DataNotAvailableException {
+ if (this.updateCount != -1) {
+ Object[] columns = new Object[1];
+ columns[0] = this.updateCount;
+ List<Object[]> row = new ArrayList<Object[]>(1);
+ row.add(columns);
+ this.updateCount = -1;
+ return row;
+ }
+ return null;
+ }
+
+ @Override
+ public void close() {
+ }
+
+ @Override
+ public void cancel() throws TranslatorException {
+ }
+}
Property changes on: trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPDirectCreateUpdateDeleteQueryExecution.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPDirectSearchQueryExecution.java
===================================================================
--- trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPDirectSearchQueryExecution.java (rev 0)
+++ trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPDirectSearchQueryExecution.java 2012-09-25 22:15:11 UTC (rev 4472)
@@ -0,0 +1,161 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+package org.teiid.translator.ldap;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import javax.naming.directory.SearchControls;
+import javax.naming.ldap.LdapContext;
+
+import org.teiid.language.Argument;
+import org.teiid.metadata.Column;
+import org.teiid.metadata.Datatype;
+import org.teiid.translator.DataNotAvailableException;
+import org.teiid.translator.ExecutionContext;
+import org.teiid.translator.ProcedureExecution;
+import org.teiid.translator.TranslatorException;
+import org.teiid.translator.TypeFacility;
+
+public class LDAPDirectSearchQueryExecution extends LDAPSyncQueryExecution implements ProcedureExecution {
+
+ private static final String ATTRIBUTES = "attributes"; //$NON-NLS-1$
+ private static final String COUNT_LIMIT = "count-limit"; //$NON-NLS-1$
+ private static final String TIMEOUT = "timeout";//$NON-NLS-1$
+ private static final String SEARCH_SCOPE = "search-scope";//$NON-NLS-1$
+ private static final String CRITERIA = "filter";//$NON-NLS-1$
+ private static final String CONTEXT_NAME = "context-name";//$NON-NLS-1$
+
+ private List<Argument> arguments;
+
+ public LDAPDirectSearchQueryExecution(List<Argument> arguments, LDAPExecutionFactory factory, ExecutionContext executionContext, LdapContext connection) {
+ super(null, factory, executionContext, connection);
+ this.arguments = arguments;
+ }
+
+ @Override
+ public void execute() throws TranslatorException {
+ this.delegate = buildRequest();
+ this.delegate.execute();
+ }
+
+ private LDAPQueryExecution buildRequest() throws TranslatorException {
+ String query = (String)arguments.get(0).getArgumentValue().getValue();
+
+ ArrayList<String> attributes = new ArrayList<String>();
+ ArrayList<Column> columns = new ArrayList<Column>();
+ String contextName = null;
+ String criteria = ""; //$NON-NLS-1$
+ String searchScope = this.executionFactory.getSearchDefaultScope().name();
+ int timeLimit = 0;
+ long countLimit = 0;
+
+ StringTokenizer st = new StringTokenizer(query, ";"); //$NON-NLS-1$
+ while (st.hasMoreTokens()) {
+ String var = st.nextToken();
+ int index = var.indexOf('=');
+ if (index == -1) {
+ continue;
+ }
+ String key = var.substring(0, index).trim().toLowerCase();
+ String value = var.substring(index+1).trim();
+
+ if (key.equalsIgnoreCase(CONTEXT_NAME)) {
+ contextName = value;
+ }
+ else if (key.equalsIgnoreCase(CRITERIA)) {
+ criteria = value;
+ }
+ else if (key.equalsIgnoreCase(SEARCH_SCOPE)) {
+ searchScope = value;
+ }
+ else if (key.equalsIgnoreCase(TIMEOUT)) {
+ timeLimit = Integer.parseInt(value);
+ }
+ else if (key.equalsIgnoreCase(COUNT_LIMIT)) {
+ countLimit = Long.parseLong(value);
+ }
+ else if (key.equalsIgnoreCase(ATTRIBUTES)) {
+ StringTokenizer attrTokens = new StringTokenizer(value, ","); //$NON-NLS-1$
+ while(attrTokens.hasMoreElements()) {
+ String name = attrTokens.nextToken().trim();
+ attributes.add(name);
+
+ Column column = new Column();
+ column.setName(name);
+ Datatype type = new Datatype();
+ type.setName(TypeFacility.RUNTIME_NAMES.OBJECT);
+ type.setJavaClassName(Object.class.getCanonicalName());
+ column.setDatatype(type, true);
+ columns.add(column);
+ }
+ }
+ }
+
+ int searchScopeInt = buildSearchScope(searchScope);
+
+ // build search controls
+ SearchControls controls = new SearchControls();
+ controls.setSearchScope(searchScopeInt);
+ controls.setTimeLimit(timeLimit);
+ controls.setCountLimit(countLimit);
+ controls.setReturningAttributes(attributes.toArray(new String[attributes.size()]));
+
+ LDAPSearchDetails searchDetails = new LDAPSearchDetails(contextName, searchScopeInt, criteria, null, countLimit, columns);
+
+ // Create and configure the new search context.
+ LdapContext context = createSearchContext(contextName);
+ return new LDAPQueryExecution(context, searchDetails, controls, this.executionFactory, this.executionContext);
+ }
+
+ private int buildSearchScope(String searchScope) {
+ int searchScopeInt = 0;
+ // this could be one of OBJECT_SCOPE, ONELEVEL_SCOPE, SUBTREE_SCOPE
+ if (searchScope.equalsIgnoreCase("OBJECT_SCOPE")) { //$NON-NLS-1$
+ searchScopeInt = SearchControls.OBJECT_SCOPE;
+ }
+ else if (searchScope.equalsIgnoreCase("ONELEVEL_SCOPE")) {//$NON-NLS-1$
+ searchScopeInt = SearchControls.ONELEVEL_SCOPE;
+ }
+ else if (searchScope.equalsIgnoreCase("SUBTREE_SCOPE")) {//$NON-NLS-1$
+ searchScopeInt = SearchControls.SUBTREE_SCOPE;
+ }
+ return searchScopeInt;
+ }
+
+ @Override
+ public List<?> next() throws TranslatorException, DataNotAvailableException {
+ List<?> vals = super.next();
+ if (vals == null) {
+ return null;
+ }
+ List<Object[]> row = new ArrayList<Object[]>(1);
+ row.add(vals.toArray(new Object[vals.size()]));
+ return row;
+ }
+
+ @Override
+ public List<?> getOutputParameterValues() throws TranslatorException {
+ return null;
+ }
+}
Property changes on: trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPDirectSearchQueryExecution.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Modified: trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPExecutionFactory.java
===================================================================
--- trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPExecutionFactory.java 2012-09-25 18:58:05 UTC (rev 4471)
+++ trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPExecutionFactory.java 2012-09-25 22:15:11 UTC (rev 4472)
@@ -21,9 +21,12 @@
*/
package org.teiid.translator.ldap;
+import java.util.List;
+
import javax.naming.ldap.LdapContext;
import javax.resource.cci.ConnectionFactory;
+import org.teiid.language.Argument;
import org.teiid.language.Command;
import org.teiid.language.QueryExpression;
import org.teiid.language.Select;
@@ -59,6 +62,7 @@
public LDAPExecutionFactory() {
this.setMaxInCriteriaSize(1000);
this.setMaxDependentInPredicates(25); //no spec limit on query size, AD is 10MB for the query
+ setSupportsNativeQueries(true);
}
@TranslatorProperty(display="Default Search Base DN", description="Default Base DN for LDAP Searches")
@@ -101,6 +105,15 @@
}
@Override
+ public ResultSetExecution createDirectExecution(List<Argument> arguments,Command command, ExecutionContext executionContext,RuntimeMetadata metadata, LdapContext context) throws TranslatorException {
+ String query = (String) arguments.get(0).getArgumentValue().getValue();
+ if (query.startsWith("search;")) { //$NON-NLS-1$
+ return new LDAPDirectSearchQueryExecution(arguments, this, executionContext, context);
+ }
+ return new LDAPDirectCreateUpdateDeleteQueryExecution(arguments, this, executionContext, context);
+ }
+
+ @Override
public boolean supportsCompareCriteriaEquals() {
return true;
}
Modified: trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPPlugin.java
===================================================================
--- trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPPlugin.java 2012-09-25 18:58:05 UTC (rev 4471)
+++ trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPPlugin.java 2012-09-25 22:15:11 UTC (rev 4472)
@@ -46,6 +46,10 @@
TEIID12005,
TEIID12006,
TEIID12007,
- TEIID12008
+ TEIID12008,
+ TEIID12009,
+ TEIID12010,
+ TEIID12011,
+ TEIID12012,
}
}
Added: trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPQueryExecution.java
===================================================================
--- trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPQueryExecution.java (rev 0)
+++ trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPQueryExecution.java 2012-09-25 22:15:11 UTC (rev 4472)
@@ -0,0 +1,437 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+/**
+ *
+ * Please see the user's guide for a full description of capabilties, etc.
+ *
+ * Description/Assumptions:
+ * 1. Table's name in source defines the base DN (or context) for the search.
+ * Example: Table.NameInSource=ou=people,dc=gene,dc=com
+ * [Optional] The table's name in source can also define a search scope. Append
+ * a "?" character as a delimiter to the base DN, and add the search scope string.
+ * The following scopes are available:
+ * SUBTREE_SCOPE
+ * ONELEVEL_SCOPE
+ * OBJECT_SCOPE
+ * [Default] LDAPConnectorConstants.ldapDefaultSearchScope
+ * is the default scope used, if no scope is defined (currently, ONELEVEL_SCOPE).
+ *
+ * 2. Column's name in source defines the LDAP attribute name.
+ * [Default] If no name in source is defined, then we attempt to use the column name
+ * as the LDAP attribute name.
+ *
+ *
+ * TODO: Implement paged searches -- the LDAP server must support VirtualListViews.
+ * TODO: Implement cancel.
+ * TODO: Add Sun/Netscape implementation, AD/OpenLDAP implementation.
+ *
+ *
+ * Note:
+ * Greater than is treated as >=
+ * Less-than is treater as <=
+ * If an LDAP entry has more than one entry for an attribute of interest (e.g. a select item), we only return the
+ * first occurrance. The first occurance is not predictably the same each time, either, according to the LDAP spec.
+ * If an attribute is not present, we return the empty string. Arguably, we could throw an exception.
+ *
+ * Sun LDAP won't support Sort Orders for very large datasets. So, we've set the sorting to NONCRITICAL, which
+ * allows Sun to ignore the sort order. This will result in the results to come back as unsorted, without any error.
+ *
+ * Removed support for ORDER BY for two reasons:
+ * 1: LDAP appears to have a limit to the number of records that
+ * can be server-side sorted. When the limit is reached, two things can happen:
+ * a. If sortControl is set to CRITICAL, then the search fails.
+ * b. If sortControl is NONCRITICAL, then the search returns, unsorted.
+ * We'd like to support ORDER BY, no matter how large the size, so we turn it off,
+ * and allow MetaMatrix to do it for us.
+ * 2: Supporting ORDER BY appears to negatively effect the query plan
+ * when cost analysis is used. We stop using dependent queries, and start
+ * using inner joins.
+ *
+ */
+
+package org.teiid.translator.ldap;
+
+import java.io.IOException;
+import java.sql.Timestamp;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.SizeLimitExceededException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+import javax.naming.ldap.Control;
+import javax.naming.ldap.LdapContext;
+import javax.naming.ldap.PagedResultsControl;
+import javax.naming.ldap.PagedResultsResponseControl;
+import javax.naming.ldap.SortControl;
+import javax.naming.ldap.SortKey;
+
+import org.teiid.logging.LogConstants;
+import org.teiid.logging.LogManager;
+import org.teiid.metadata.Column;
+import org.teiid.translator.ExecutionContext;
+import org.teiid.translator.ResultSetExecution;
+import org.teiid.translator.TranslatorException;
+import org.teiid.translator.TypeFacility;
+
+
+
+/**
+ * LDAPSyncQueryExecution is responsible for executing an LDAP search
+ * corresponding to a read-only "select" query from MetaMatrix.
+ */
+public class LDAPQueryExecution implements ResultSetExecution {
+
+ private static final String delimiter = "?"; //$NON-NLS-1$
+
+ private LDAPSearchDetails searchDetails;
+ private LdapContext ldapCtx;
+ private NamingEnumeration<?> searchEnumeration;
+ private LDAPExecutionFactory executionFactory;
+ private ExecutionContext executionContext;
+ private SearchControls ctrls;
+ private int resultCount;
+
+ /**
+ * Constructor
+ * @param executionMode the execution mode.
+ * @param ctx the execution context.
+ * @param logger the ConnectorLogger
+ * @param connection the LDAP Context
+ */
+ public LDAPQueryExecution(LdapContext ldapContext,LDAPSearchDetails search, SearchControls searchControls, LDAPExecutionFactory factory,ExecutionContext context) {
+ this.searchDetails = search;
+ this.ldapCtx = ldapContext;
+ this.ctrls = searchControls;
+ this.executionFactory = factory;
+ this.executionContext = context;
+ }
+
+ /**
+ * method to execute the supplied query
+ * @param query the query object.
+ * @param maxBatchSize the max batch size.
+ */
+ @Override
+ public void execute() throws TranslatorException {
+ String ctxName = this.searchDetails.getContextName();
+ String filter = this.searchDetails.getContextFilter();
+ if (ctxName == null || filter == null || this.ctrls == null) {
+ throw new TranslatorException("Search context, filter, or controls were null. Cannot execute search."); //$NON-NLS-1$
+ }
+ setRequestControls(null);
+ // Execute the search.
+ executeSearch();
+ }
+
+ /**
+ * Set the standard request controls
+ */
+ private void setRequestControls(byte[] cookie) throws TranslatorException {
+ List<Control> ctrl = new ArrayList<Control>();
+ SortKey[] keys = searchDetails.getSortKeys();
+ try {
+ if (keys != null) {
+ ctrl.add(new SortControl(keys, Control.NONCRITICAL));
+ }
+ if (this.executionFactory.usePagination()) {
+ ctrl.add(new PagedResultsControl(this.executionContext.getBatchSize(), cookie, Control.CRITICAL));
+ }
+ if (!ctrl.isEmpty()) {
+ this.ldapCtx.setRequestControls(ctrl.toArray(new Control[ctrl.size()]));
+ LogManager.logTrace(LogConstants.CTX_CONNECTOR, "Sort/pagination controls were created successfully."); //$NON-NLS-1$
+ }
+ } catch (NamingException ne) {
+ final String msg = LDAPPlugin.Util.getString("LDAPSyncQueryExecution.setControlsError") + //$NON-NLS-1$
+ " : "+ne.getExplanation(); //$NON-NLS-1$
+ throw new TranslatorException(ne, msg);
+ } catch(IOException e) {
+ throw new TranslatorException(e);
+ }
+ }
+
+ /**
+ * Perform the LDAP search against the subcontext, using the filter and
+ * search controls appropriate to the query and model metadata.
+ */
+ private void executeSearch() throws TranslatorException {
+ String filter = searchDetails.getContextFilter();
+ try {
+ searchEnumeration = this.ldapCtx.search("", filter, ctrls); //$NON-NLS-1$
+ } catch (NamingException ne) {
+ final String msg = LDAPPlugin.Util.getString("LDAPSyncQueryExecution.execSearchError"); //$NON-NLS-1$
+ throw new TranslatorException(ne, msg + " : " + ne.getExplanation()); //$NON-NLS-1$
+ } catch(Exception e) {
+ final String msg = LDAPPlugin.Util.getString("LDAPSyncQueryExecution.execSearchError"); //$NON-NLS-1$
+ throw new TranslatorException(e, msg);
+ }
+ }
+
+ // GHH 20080326 - attempt to implement cancel here. First try to
+ // close the searchEnumeration, then the search context.
+ // We are very conservative when closing the enumeration
+ // but less so when closing context, since it is safe to call close
+ // on contexts multiple times
+ @Override
+ public void cancel() throws TranslatorException {
+ close();
+ }
+
+ // GHH 20080326 - replaced existing implementation with the same
+ // code as used by cancel method. First try to
+ // close the searchEnumeration, then the search context
+ // We are very conservative when closing the enumeration
+ // but less so when closing context, since it is safe to call close
+ // on contexts multiple times
+ @Override
+ public void close() {
+ if (searchEnumeration != null) {
+ try {
+ searchEnumeration.close();
+ } catch (Exception e) { } // catch everything, because NamingEnumeration has undefined behavior if it previously hit an exception
+ }
+ if (ldapCtx != null) {
+ try {
+ ldapCtx.close();
+ } catch (NamingException ne) {
+ LogManager.logWarning(LogConstants.CTX_CONNECTOR, LDAPPlugin.Util.gs(LDAPPlugin.Event.TEIID12003, ne.getExplanation()));
+ }
+ }
+ }
+
+ /**
+ * Fetch the next batch of data from the LDAP searchEnumerationr result.
+ * @return the next Batch of results.
+ */
+ // GHH 20080326 - set all batches as last batch after an exception
+ // is thrown calling a method on the enumeration. Per Javadoc for
+ // javax.naming.NamingEnumeration, enumeration is invalid after an
+ // exception is thrown - by setting last batch indicator we prevent
+ // it from being used again.
+ // GHH 20080326 - also added return of explanation for generic
+ // NamingException
+ public List<?> next() throws TranslatorException {
+ try {
+ // The search has been executed, so process up to one batch of
+ // results.
+ List<?> result = null;
+ while (result == null && searchEnumeration != null && searchEnumeration.hasMore())
+ {
+ SearchResult searchResult = (SearchResult) searchEnumeration.next();
+ result = getRow(searchResult);
+ }
+
+ if (result == null && this.executionFactory.usePagination()) {
+ byte[] cookie = null;
+ Control[] controls = ldapCtx.getResponseControls();
+ if (controls != null) {
+ for (int i = 0; i < controls.length; i++) {
+ if (controls[i] instanceof PagedResultsResponseControl) {
+ PagedResultsResponseControl prrc = (PagedResultsResponseControl)controls[i];
+ cookie = prrc.getCookie();
+ }
+ }
+ }
+
+ if (cookie == null) {
+ return null;
+ }
+
+ setRequestControls(cookie);
+ executeSearch();
+ return next();
+ }
+
+ if (result != null) {
+ resultCount++;
+ }
+ return result;
+ } catch (SizeLimitExceededException e) {
+ if (resultCount != searchDetails.getCountLimit()) {
+ String msg = LDAPPlugin.Util.gs(LDAPPlugin.Event.TEIID12008);
+ TranslatorException te = new TranslatorException(e, msg);
+ if (executionFactory.isExceptionOnSizeLimitExceeded()) {
+ throw te;
+ }
+ this.executionContext.addWarning(te);
+ LogManager.logWarning(LogConstants.CTX_CONNECTOR, e, msg);
+ }
+ return null; // GHH 20080326 - if size limit exceeded don't try to read more results
+ } catch (NamingException ne) {
+ throw new TranslatorException(ne, LDAPPlugin.Util.gs("ldap_error")); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Create a row using the searchResult and add it to the supplied batch.
+ * @param batch the supplied batch
+ * @param result the search result
+ */
+ // GHH 20080326 - added fetching of DN of result, for directories that
+ // do not include it as an attribute
+ private List<?> getRow(SearchResult result) throws TranslatorException {
+ Attributes attrs = result.getAttributes();
+ String resultDN = result.getNameInNamespace(); // added GHH 20080326
+ ArrayList<Column> attributeList = searchDetails.getElementList();
+ List<Object> row = new ArrayList<Object>(attributeList.size());
+
+ for (Column col : attributeList) {
+ addResultToRow(col, resultDN, attrs, row); // GHH 20080326 - added resultDN parameter to call
+ }
+ return row;
+ }
+
+ /**
+ * Add Result to Row
+ * @param modelElement the model element
+ * @param attrs the attributes
+ * @param row the row
+ */
+ // GHH 20080326 - added resultDistinguishedName to method signature. If
+ // there is an element in the model named "DN" and there is no attribute
+ // with this name in the search result, we return this new parameter
+ // value for that column in the result
+ // GHH 20080326 - added handling of ClassCastException when non-string
+ // attribute is returned
+ private void addResultToRow(Column modelElement, String resultDistinguishedName, Attributes attrs, List<Object> row) throws TranslatorException {
+
+ String strResult = null;
+ String modelAttrName = IQueryToLdapSearchParser.getNameFromElement(modelElement);
+ Class<?> modelAttrClass = modelElement.getJavaType();
+
+ String multivalAttr = modelElement.getDefaultValue();
+
+ if(modelAttrName == null) {
+ final String msg = LDAPPlugin.Util.getString("LDAPSyncQueryExecution.nullAttrError"); //$NON-NLS-1$
+ throw new TranslatorException(msg);
+ }
+
+ Attribute resultAttr = attrs.get(modelAttrName);
+
+ // If the attribute is not present, we return NULL.
+ if(resultAttr == null) {
+ // MPW - 2-20-07 - Changed from returning empty string to returning null.
+ //row.add("");
+ //logger.logTrace("Did not find a match for attribute named: " + modelAttrName);
+ // GHH 20080326 - return DN from input parameter
+ // if DN attribute is not present in search result
+ if (modelAttrName.toUpperCase().equals("DN")) { //$NON-NLS-1$
+ row.add(resultDistinguishedName);
+ }
+ else {
+ row.add(null);
+ }
+ return;
+ }
+ Object objResult = null;
+ try {
+ if(TypeFacility.RUNTIME_TYPES.STRING.equals(modelAttrClass) && "multivalued-concat".equalsIgnoreCase(multivalAttr)) { //$NON-NLS-1$
+ // mpw 5/09
+ // Order the multi-valued attrs alphabetically before creating a single string,
+ // using the delimiter to separate each token
+ ArrayList<String> multivalList = new ArrayList<String>();
+ NamingEnumeration<?> attrNE = resultAttr.getAll();
+ int length = 0;
+ while(attrNE.hasMore()) {
+ String val = (String)attrNE.next();
+ multivalList.add(val);
+ length += ((val==null?0:val.length()) + 1);
+ }
+ Collections.sort(multivalList);
+
+ StringBuilder multivalSB = new StringBuilder(length);
+ Iterator<String> itr = multivalList.iterator();
+ while(itr.hasNext()) {
+ multivalSB.append(itr.next());
+ if (itr.hasNext()) {
+ multivalSB.append(delimiter);
+ }
+ }
+ row.add(multivalSB.toString());
+ return;
+ }
+
+ //just a single value
+ objResult = resultAttr.get();
+ } catch (NamingException ne) {
+ final String msg = LDAPPlugin.Util.gs(LDAPPlugin.Event.TEIID12004, modelAttrName) +" : "+ne.getExplanation(); //$NON-NLS-1$m
+ LogManager.logWarning(LogConstants.CTX_CONNECTOR, msg);
+ throw new TranslatorException(msg);
+ }
+
+ // GHH 20080326 - if attribute is not a string or empty, just
+ // return null.
+ // TODO - allow return of non-strings (always byte[]) as
+ // MM object (or blob). Perhaps also add directory-specific logic
+ // to deserialize byte[] attributes into Java objects
+ // when appropriate
+ if (objResult instanceof String) {
+ strResult = (String)objResult;
+ // MPW - 3.9.07 - Also return NULL when attribute is unset or empty string.
+ // There is no way to differentiate between being unset and being the empty string.
+ if(strResult.equals("")) { //$NON-NLS-1$
+ strResult = null;
+ }
+ }
+
+ // MPW: 3-11-07: Added support for java.lang.Integer conversion.
+ if(TypeFacility.RUNTIME_TYPES.TIMESTAMP.equals(modelAttrClass)) {
+ String timestampFormat = modelElement.getFormat();
+ if(timestampFormat == null) {
+ timestampFormat = LDAPConnectorConstants.ldapTimestampFormat;
+ }
+ SimpleDateFormat dateFormat = new SimpleDateFormat(timestampFormat);
+ try {
+ if(strResult != null) {
+ Date dateResult = dateFormat.parse(strResult);
+ Timestamp tsResult = new Timestamp(dateResult.getTime());
+ row.add(tsResult);
+ } else {
+ row.add(null);
+ }
+ } catch(ParseException pe) {
+ throw new TranslatorException(pe, LDAPPlugin.Util.getString("LDAPSyncQueryExecution.timestampParseFailed", modelAttrName)); //$NON-NLS-1$
+ }
+
+ // TODO: Extend support for more types in the future.
+ // Specifically, add support for byte arrays, since that's actually supported
+ // in the underlying data source.
+ } else {
+ row.add(strResult); //the Teiid type conversion logic will handle refine from here if necessary
+ }
+ }
+
+ // for testing.
+ LDAPSearchDetails getSearchDetails() {
+ return this.searchDetails;
+ }
+}
Property changes on: trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPQueryExecution.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Modified: trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPSearchDetails.java
===================================================================
--- trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPSearchDetails.java 2012-09-25 18:58:05 UTC (rev 4471)
+++ trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPSearchDetails.java 2012-09-25 22:15:11 UTC (rev 4472)
@@ -25,8 +25,6 @@
import java.util.ArrayList;
import java.util.Iterator;
-import javax.naming.NamingException;
-import javax.naming.directory.Attribute;
import javax.naming.directory.SearchControls;
import javax.naming.ldap.SortKey;
@@ -45,7 +43,6 @@
private String contextName;
private int searchScope;
private String contextFilter;
- private ArrayList attributeList;
private SortKey[] keys;
// private LdapSortKey[] netscapeKeys;
// If limit is set to -1, this means no limit (return all rows)
@@ -62,12 +59,11 @@
* @param limit
* @param elementList
*/
- public LDAPSearchDetails(String name, int searchScope, String filter, ArrayList attributeList, SortKey[] keys, long limit, ArrayList elementList) {
+ public LDAPSearchDetails(String name, int searchScope, String filter, SortKey[] keys, long limit, ArrayList elementList) {
this.contextName = name;
this.searchScope = searchScope;
this.contextFilter = filter;
- this.attributeList = attributeList;
this.keys = keys;
this.limit = limit;
this.elementList = elementList;
@@ -98,14 +94,6 @@
}
/**
- * get the attribute list
- * @return the attribute list
- */
- public ArrayList getAttributeList() {
- return attributeList;
- }
-
- /**
* get the element list
* @return the element list
*/
@@ -150,7 +138,7 @@
/**
* Print Method for Logging - (Detail level logging)
*/
- public void printDetailsToLog() throws NamingException {
+ public void printDetailsToLog() {
// Log Search Scope
LogManager.logDetail(LogConstants.CTX_CONNECTOR, "Search context: " + contextName); //$NON-NLS-1$
if(searchScope == SearchControls.SUBTREE_SCOPE) {
@@ -163,11 +151,12 @@
// Log Search Attributes
LogManager.logDetail(LogConstants.CTX_CONNECTOR,"Search attributes: "); //$NON-NLS-1$
- Iterator itr = this.attributeList.iterator();
+ Iterator itr = this.elementList.iterator();
int i = 0;
while(itr.hasNext()) {
- Attribute attr = (Attribute)itr.next();
- LogManager.logDetail(LogConstants.CTX_CONNECTOR, "Attribute [" + i + "]: " + attr.getID() + " (" +attr.get().toString() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ Column attr = (Column)itr.next();
+ String attrName = IQueryToLdapSearchParser.getNameFromElement(attr);
+ LogManager.logDetail(LogConstants.CTX_CONNECTOR, "Attribute [" + i + "]: " + attrName + " (" +attr.toString() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
i++;
}
Modified: trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPSyncQueryExecution.java
===================================================================
--- trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPSyncQueryExecution.java 2012-09-25 18:58:05 UTC (rev 4471)
+++ trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPSyncQueryExecution.java 2012-09-25 22:15:11 UTC (rev 4472)
@@ -71,69 +71,45 @@
package org.teiid.translator.ldap;
-import java.io.IOException;
-import java.sql.Timestamp;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.Iterator;
import java.util.List;
-import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
-import javax.naming.SizeLimitExceededException;
-import javax.naming.directory.Attribute;
-import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
-import javax.naming.directory.SearchResult;
-import javax.naming.ldap.Control;
import javax.naming.ldap.LdapContext;
-import javax.naming.ldap.PagedResultsControl;
-import javax.naming.ldap.PagedResultsResponseControl;
-import javax.naming.ldap.SortControl;
-import javax.naming.ldap.SortKey;
import org.teiid.language.Select;
import org.teiid.logging.LogConstants;
import org.teiid.logging.LogManager;
import org.teiid.metadata.Column;
+import org.teiid.translator.DataNotAvailableException;
import org.teiid.translator.ExecutionContext;
import org.teiid.translator.ResultSetExecution;
import org.teiid.translator.TranslatorException;
-import org.teiid.translator.TypeFacility;
/**
* LDAPSyncQueryExecution is responsible for executing an LDAP search
- * corresponding to a read-only "select" query from MetaMatrix.
+ * corresponding to a read-only "select" query from Teiid.
*/
public class LDAPSyncQueryExecution implements ResultSetExecution {
- private static final String delimiter = "?"; //$NON-NLS-1$
-
- private LDAPSearchDetails searchDetails;
- private LdapContext ldapConnection;
- private LdapContext ldapCtx;
- private NamingEnumeration<?> searchEnumeration;
- private IQueryToLdapSearchParser parser;
+ protected LdapContext ldapConnection;
private Select query;
- private LDAPExecutionFactory executionFactory;
- private ExecutionContext executionContext;
- private SearchControls ctrls;
- private int resultCount;
-
+ protected LDAPExecutionFactory executionFactory;
+ protected ExecutionContext executionContext;
+ protected LDAPQueryExecution delegate;
+
/**
* Constructor
* @param executionMode the execution mode.
* @param ctx the execution context.
* @param logger the ConnectorLogger
- * @param ldapCtx the LDAP Context
+ * @param connection the LDAP Context
*/
- public LDAPSyncQueryExecution(Select query, LDAPExecutionFactory factory, ExecutionContext context, LdapContext ldapCtx) {
- this.ldapConnection = ldapCtx;
+ public LDAPSyncQueryExecution(Select query, LDAPExecutionFactory factory, ExecutionContext context, LdapContext connection) {
+ this.ldapConnection = connection;
this.query = query;
this.executionFactory = factory;
this.executionContext = context;
@@ -147,76 +123,46 @@
@Override
public void execute() throws TranslatorException {
// Parse the IQuery, and translate it into an appropriate LDAP search.
- this.parser = new IQueryToLdapSearchParser(this.executionFactory);
- searchDetails = parser.translateSQLQueryToLDAPSearch(query);
+ IQueryToLdapSearchParser parser = new IQueryToLdapSearchParser(this.executionFactory);
+ LDAPSearchDetails searchDetails = parser.translateSQLQueryToLDAPSearch(query);
// Create and configure the new search context.
- createSearchContext();
- ctrls = setSearchControls();
- String ctxName = searchDetails.getContextName();
- String filter = searchDetails.getContextFilter();
- if (ctxName == null || filter == null || ctrls == null) {
- throw new TranslatorException("Search context, filter, or controls were null. Cannot execute search."); //$NON-NLS-1$
- }
- setRequestControls(null);
- // Execute the search.
- executeSearch();
+ LdapContext context = createSearchContext(searchDetails.getContextName());
+ SearchControls ctrls = setSearchControls(searchDetails);
+
+ this.delegate = new LDAPQueryExecution(context, searchDetails, ctrls, this.executionFactory, this.executionContext);
+ this.delegate.execute();
}
- /**
- * Set the standard request controls
- */
- private void setRequestControls(byte[] cookie) throws TranslatorException {
- List<Control> ctrl = new ArrayList<Control>();
- SortKey[] keys = searchDetails.getSortKeys();
- try {
- if (keys != null) {
- ctrl.add(new SortControl(keys, Control.NONCRITICAL));
- }
- if (this.executionFactory.usePagination()) {
- ctrl.add(new PagedResultsControl(this.executionContext.getBatchSize(), cookie, Control.CRITICAL));
- }
- if (!ctrl.isEmpty()) {
- this.ldapCtx.setRequestControls(ctrl.toArray(new Control[ctrl.size()]));
- LogManager.logTrace(LogConstants.CTX_CONNECTOR, "Sort/pagination controls were created successfully."); //$NON-NLS-1$
- }
- } catch (NamingException ne) {
- final String msg = LDAPPlugin.Util.getString("LDAPSyncQueryExecution.setControlsError") + //$NON-NLS-1$
- " : "+ne.getExplanation(); //$NON-NLS-1$
- throw new TranslatorException(ne, msg);
- } catch(IOException e) {
- throw new TranslatorException(e);
- }
- }
+
/**
* Perform a lookup against the initial LDAP context, which
* sets the context to something appropriate for the search that is about to occur.
*
*/
- private void createSearchContext() throws TranslatorException {
+ protected LdapContext createSearchContext(String contextName) throws TranslatorException {
try {
- ldapCtx = (LdapContext) this.ldapConnection.lookup(searchDetails.getContextName());
+ return (LdapContext) this.ldapConnection.lookup(contextName);
} catch (NamingException ne) {
- if (searchDetails.getContextName() != null) {
- LogManager.logError(LogConstants.CTX_CONNECTOR, LDAPPlugin.Util.gs(LDAPPlugin.Event.TEIID12002, searchDetails.getContextName()));
+ if (contextName != null) {
+ LogManager.logError(LogConstants.CTX_CONNECTOR, LDAPPlugin.Util.gs(LDAPPlugin.Event.TEIID12002, contextName));
}
final String msg = LDAPPlugin.Util.getString("LDAPSyncQueryExecution.createContextError"); //$NON-NLS-1$
throw new TranslatorException(msg);
}
}
-
/**
* Set the search controls
*/
- private SearchControls setSearchControls() {
+ private SearchControls setSearchControls(LDAPSearchDetails searchDetails) {
SearchControls ctrls = new SearchControls();
//ArrayList modelAttrList = searchDetails.getAttributeList();
ArrayList<Column> modelAttrList = searchDetails.getElementList();
String[] attrs = new String[modelAttrList.size()];
for (int i = 0; i < attrs.length; i++) {
- attrs[i] = (parser.getNameFromElement(modelAttrList.get(i)));
+ attrs[i] = (IQueryToLdapSearchParser.getNameFromElement(modelAttrList.get(i)));
}
ctrls.setSearchScope(searchDetails.getSearchScope());
@@ -229,255 +175,23 @@
return ctrls;
}
- /**
- * Perform the LDAP search against the subcontext, using the filter and
- * search controls appropriate to the query and model metadata.
- */
- private void executeSearch() throws TranslatorException {
- String filter = searchDetails.getContextFilter();
- try {
- searchEnumeration = this.ldapCtx.search("", filter, ctrls); //$NON-NLS-1$
- } catch (NamingException ne) {
- final String msg = LDAPPlugin.Util.getString("LDAPSyncQueryExecution.execSearchError"); //$NON-NLS-1$
- throw new TranslatorException(ne, msg + " : " + ne.getExplanation()); //$NON-NLS-1$
- } catch(Exception e) {
- final String msg = LDAPPlugin.Util.getString("LDAPSyncQueryExecution.execSearchError"); //$NON-NLS-1$
- throw new TranslatorException(e, msg);
- }
+ @Override
+ public List<?> next() throws TranslatorException, DataNotAvailableException {
+ return this.delegate.next();
}
-
- // GHH 20080326 - attempt to implement cancel here. First try to
- // close the searchEnumeration, then the search context.
- // We are very conservative when closing the enumeration
- // but less so when closing context, since it is safe to call close
- // on contexts multiple times
+
@Override
public void cancel() throws TranslatorException {
- close();
+ this.delegate.cancel();
}
- // GHH 20080326 - replaced existing implementation with the same
- // code as used by cancel method. First try to
- // close the searchEnumeration, then the search context
- // We are very conservative when closing the enumeration
- // but less so when closing context, since it is safe to call close
- // on contexts multiple times
@Override
public void close() {
- if (searchEnumeration != null) {
- try {
- searchEnumeration.close();
- } catch (Exception e) { } // catch everything, because NamingEnumeration has undefined behavior if it previously hit an exception
- }
- if (ldapCtx != null) {
- try {
- ldapCtx.close();
- } catch (NamingException ne) {
- LogManager.logWarning(LogConstants.CTX_CONNECTOR, LDAPPlugin.Util.gs(LDAPPlugin.Event.TEIID12003, ne.getExplanation()));
- }
- }
+ this.delegate.close();
}
- /**
- * Fetch the next batch of data from the LDAP searchEnumerationr result.
- * @return the next Batch of results.
- */
- // GHH 20080326 - set all batches as last batch after an exception
- // is thrown calling a method on the enumeration. Per Javadoc for
- // javax.naming.NamingEnumeration, enumeration is invalid after an
- // exception is thrown - by setting last batch indicator we prevent
- // it from being used again.
- // GHH 20080326 - also added return of explanation for generic
- // NamingException
- public List<?> next() throws TranslatorException {
- try {
- // The search has been executed, so process up to one batch of
- // results.
- List<?> result = null;
- while (result == null && searchEnumeration != null && searchEnumeration.hasMore())
- {
- SearchResult searchResult = (SearchResult) searchEnumeration.next();
- result = getRow(searchResult);
- }
-
- if (result == null && this.executionFactory.usePagination()) {
- byte[] cookie = null;
- Control[] controls = ldapCtx.getResponseControls();
- if (controls != null) {
- for (int i = 0; i < controls.length; i++) {
- if (controls[i] instanceof PagedResultsResponseControl) {
- PagedResultsResponseControl prrc = (PagedResultsResponseControl)controls[i];
- cookie = prrc.getCookie();
- }
- }
- }
-
- if (cookie == null) {
- return null;
- }
-
- setRequestControls(cookie);
- executeSearch();
- return next();
- }
-
- if (result != null) {
- resultCount++;
- }
- return result;
- } catch (SizeLimitExceededException e) {
- if (resultCount != searchDetails.getCountLimit()) {
- String msg = LDAPPlugin.Util.gs(LDAPPlugin.Event.TEIID12008);
- TranslatorException te = new TranslatorException(e, msg);
- if (executionFactory.isExceptionOnSizeLimitExceeded()) {
- throw te;
- }
- this.executionContext.addWarning(te);
- LogManager.logWarning(LogConstants.CTX_CONNECTOR, e, msg);
- }
- return null; // GHH 20080326 - if size limit exceeded don't try to read more results
- } catch (NamingException ne) {
- throw new TranslatorException(ne, LDAPPlugin.Util.gs("ldap_error")); //$NON-NLS-1$
- }
+ // testing
+ LDAPQueryExecution getDelegate() {
+ return this.delegate;
}
-
- /**
- * Create a row using the searchResult and add it to the supplied batch.
- * @param batch the supplied batch
- * @param result the search result
- */
- // GHH 20080326 - added fetching of DN of result, for directories that
- // do not include it as an attribute
- private List<?> getRow(SearchResult result) throws TranslatorException {
- Attributes attrs = result.getAttributes();
- String resultDN = result.getNameInNamespace(); // added GHH 20080326
- ArrayList<Column> attributeList = searchDetails.getElementList();
- List<Object> row = new ArrayList<Object>(attributeList.size());
-
- for (Column col : attributeList) {
- addResultToRow(col, resultDN, attrs, row); // GHH 20080326 - added resultDN parameter to call
- }
- return row;
- }
-
- /**
- * Add Result to Row
- * @param modelElement the model element
- * @param attrs the attributes
- * @param row the row
- */
- // GHH 20080326 - added resultDistinguishedName to method signature. If
- // there is an element in the model named "DN" and there is no attribute
- // with this name in the search result, we return this new parameter
- // value for that column in the result
- // GHH 20080326 - added handling of ClassCastException when non-string
- // attribute is returned
- private void addResultToRow(Column modelElement, String resultDistinguishedName, Attributes attrs, List<Object> row) throws TranslatorException {
-
- String strResult = null;
- String modelAttrName = parser.getNameFromElement(modelElement);
- Class<?> modelAttrClass = modelElement.getJavaType();
-
- String multivalAttr = modelElement.getDefaultValue();
-
- if(modelAttrName == null) {
- final String msg = LDAPPlugin.Util.getString("LDAPSyncQueryExecution.nullAttrError"); //$NON-NLS-1$
- throw new TranslatorException(msg);
- }
-
- Attribute resultAttr = attrs.get(modelAttrName);
-
- // If the attribute is not present, we return NULL.
- if(resultAttr == null) {
- // MPW - 2-20-07 - Changed from returning empty string to returning null.
- //row.add("");
- //logger.logTrace("Did not find a match for attribute named: " + modelAttrName);
- // GHH 20080326 - return DN from input parameter
- // if DN attribute is not present in search result
- if (modelAttrName.toUpperCase().equals("DN")) { //$NON-NLS-1$
- row.add(resultDistinguishedName);
- }
- else {
- row.add(null);
- }
- return;
- }
- Object objResult = null;
- try {
- if(TypeFacility.RUNTIME_TYPES.STRING.equals(modelAttrClass) && "multivalued-concat".equalsIgnoreCase(multivalAttr)) { //$NON-NLS-1$
- // mpw 5/09
- // Order the multi-valued attrs alphabetically before creating a single string,
- // using the delimiter to separate each token
- ArrayList<String> multivalList = new ArrayList<String>();
- NamingEnumeration<?> attrNE = resultAttr.getAll();
- int length = 0;
- while(attrNE.hasMore()) {
- String val = (String)attrNE.next();
- multivalList.add(val);
- length += ((val==null?0:val.length()) + 1);
- }
- Collections.sort(multivalList);
-
- StringBuilder multivalSB = new StringBuilder(length);
- Iterator<String> itr = multivalList.iterator();
- while(itr.hasNext()) {
- multivalSB.append(itr.next());
- if (itr.hasNext()) {
- multivalSB.append(delimiter);
- }
- }
- row.add(multivalSB.toString());
- return;
- }
-
- //just a single value
- objResult = resultAttr.get();
- } catch (NamingException ne) {
- final String msg = LDAPPlugin.Util.gs(LDAPPlugin.Event.TEIID12004, modelAttrName) +" : "+ne.getExplanation(); //$NON-NLS-1$m
- LogManager.logWarning(LogConstants.CTX_CONNECTOR, msg);
- throw new TranslatorException(msg);
- }
-
- // GHH 20080326 - if attribute is not a string or empty, just
- // return null.
- // TODO - allow return of non-strings (always byte[]) as
- // MM object (or blob). Perhaps also add directory-specific logic
- // to deserialize byte[] attributes into Java objects
- // when appropriate
- if (objResult instanceof String) {
- strResult = (String)objResult;
- // MPW - 3.9.07 - Also return NULL when attribute is unset or empty string.
- // There is no way to differentiate between being unset and being the empty string.
- if(strResult.equals("")) { //$NON-NLS-1$
- strResult = null;
- }
- }
-
- // MPW: 3-11-07: Added support for java.lang.Integer conversion.
- if(TypeFacility.RUNTIME_TYPES.TIMESTAMP.equals(modelAttrClass)) {
- String timestampFormat = modelElement.getFormat();
- if(timestampFormat == null) {
- timestampFormat = LDAPConnectorConstants.ldapTimestampFormat;
- }
- SimpleDateFormat dateFormat = new SimpleDateFormat(timestampFormat);
- try {
- if(strResult != null) {
- Date dateResult = dateFormat.parse(strResult);
- Timestamp tsResult = new Timestamp(dateResult.getTime());
- row.add(tsResult);
- } else {
- row.add(null);
- }
- } catch(ParseException pe) {
- throw new TranslatorException(pe, LDAPPlugin.Util.getString("LDAPSyncQueryExecution.timestampParseFailed", modelAttrName)); //$NON-NLS-1$
- }
-
- // TODO: Extend support for more types in the future.
- // Specifically, add support for byte arrays, since that's actually supported
- // in the underlying data source.
- } else {
- row.add(strResult); //the Teiid type conversion logic will handle refine from here if necessary
- }
- }
-
}
Modified: trunk/connectors/translator-ldap/src/main/resources/org/teiid/translator/ldap/i18n.properties
===================================================================
--- trunk/connectors/translator-ldap/src/main/resources/org/teiid/translator/ldap/i18n.properties 2012-09-25 18:58:05 UTC (rev 4471)
+++ trunk/connectors/translator-ldap/src/main/resources/org/teiid/translator/ldap/i18n.properties 2012-09-25 22:15:11 UTC (rev 4472)
@@ -67,4 +67,8 @@
TEIID12006=Received IScalarSubquery, but it is not supported. Check capabilties.
TEIID12007=Received ISearchedCaseExpression, but it is not supported. Check capabilties.
TEIID12002=Attempted to search context: {0}
-TEIID12008=LDAP Search results exceeded size limit. Results may be incomplete.
\ No newline at end of file
+TEIID12008=LDAP Search results exceeded size limit. Results may be incomplete.
+TEIID12009=Unknown LDAP Request; the query string must start with [search|create|update|delete]
+TEIID12010=The DN is not defined; DN should be the token after the marker tokens [search|create|update|delete]
+TEIID12011=attributes are not defined; use "attributes=..." form using the comma delimited to specify all the names.
+TEIID12012=create/update operation did not find the value for attribute {0}; Each attribute value is defined as the separate parameter in the procedure call.
\ No newline at end of file
Modified: trunk/connectors/translator-ldap/src/test/java/org/teiid/translator/ldap/TestIQueryToLdapSearchParser.java
===================================================================
--- trunk/connectors/translator-ldap/src/test/java/org/teiid/translator/ldap/TestIQueryToLdapSearchParser.java 2012-09-25 18:58:05 UTC (rev 4471)
+++ trunk/connectors/translator-ldap/src/test/java/org/teiid/translator/ldap/TestIQueryToLdapSearchParser.java 2012-09-25 22:15:11 UTC (rev 4472)
@@ -27,7 +27,6 @@
import java.util.Iterator;
import java.util.List;
-import javax.naming.directory.Attribute;
import javax.naming.directory.SearchControls;
import javax.naming.ldap.SortKey;
@@ -92,7 +91,7 @@
// Get all of the actual values
String contextName = searchDetails.getContextName();
String contextFilter = searchDetails.getContextFilter();
- List attrList = searchDetails.getAttributeList();
+ List attrList = searchDetails.getElementList();
long countLimit = searchDetails.getCountLimit();
int searchScope = searchDetails.getSearchScope();
SortKey[] sortKeys = searchDetails.getSortKeys();
@@ -105,7 +104,7 @@
Iterator iter = attrList.iterator();
Iterator eIter = expectedAttrNameList.iterator();
while(iter.hasNext()&&eIter.hasNext()) {
- String actualName = ((Attribute)iter.next()).getID();
+ String actualName = IQueryToLdapSearchParser.getNameFromElement((Column)iter.next());
String expectedName = (String)eIter.next();
assertEquals(actualName, expectedName);
}
Added: trunk/connectors/translator-ldap/src/test/java/org/teiid/translator/ldap/TestLDAPDirectQueryExecution.java
===================================================================
--- trunk/connectors/translator-ldap/src/test/java/org/teiid/translator/ldap/TestLDAPDirectQueryExecution.java (rev 0)
+++ trunk/connectors/translator-ldap/src/test/java/org/teiid/translator/ldap/TestLDAPDirectQueryExecution.java 2012-09-25 22:15:11 UTC (rev 4472)
@@ -0,0 +1,187 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+package org.teiid.translator.ldap;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.math.BigDecimal;
+
+import javax.naming.directory.BasicAttributes;
+import javax.naming.directory.ModificationItem;
+import javax.naming.ldap.LdapContext;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+import org.teiid.cdk.api.TranslationUtility;
+import org.teiid.cdk.unittest.FakeTranslationFactory;
+import org.teiid.language.Command;
+import org.teiid.metadata.RuntimeMetadata;
+import org.teiid.translator.ExecutionContext;
+import org.teiid.translator.TranslatorException;
+
+@SuppressWarnings("nls")
+public class TestLDAPDirectQueryExecution {
+
+ private static LDAPExecutionFactory TRANSLATOR;
+
+ @BeforeClass
+ public static void setUp() throws TranslatorException {
+ TRANSLATOR = new LDAPExecutionFactory();
+ TRANSLATOR.start();
+ }
+
+ @Test public void testSearch() throws Exception {
+ String input = "exec native('search;context-name=corporate;filter=(objectClass=*);count-limit=5;timout=6;search-scope=ONELEVEL_SCOPE;attributes=uid,cn')";
+
+ TranslationUtility util = FakeTranslationFactory.getInstance().getExampleTranslationUtility();
+ Command command = util.parseCommand(input);
+ ExecutionContext ec = Mockito.mock(ExecutionContext.class);
+ RuntimeMetadata rm = Mockito.mock(RuntimeMetadata.class);
+ LdapContext connection = Mockito.mock(LdapContext.class);
+ LdapContext ctx = Mockito.mock(LdapContext.class);
+ Mockito.stub(connection.lookup("corporate")).toReturn(ctx);
+
+ LDAPDirectSearchQueryExecution execution = (LDAPDirectSearchQueryExecution)TRANSLATOR.createExecution(command, ec, rm, connection);
+ execution.execute();
+ LDAPSearchDetails details = execution.getDelegate().getSearchDetails();
+
+ assertEquals("corporate", details.getContextName());
+ assertEquals("(objectClass=*)", details.getContextFilter());
+ assertEquals(5, details.getCountLimit());
+ assertEquals(1, details.getSearchScope());
+ assertEquals(2, details.getElementList().size());
+ assertEquals("uid", details.getElementList().get(0).getName());
+ assertEquals("cn", details.getElementList().get(1).getName());
+ }
+
+ @Test public void testWithoutMarker() throws Exception {
+ String input = "exec native('context-name=corporate;filter=(objectClass=*);count-limit=5;timout=6;search-scope=ONELEVEL_SCOPE;attributes=uid,cn')";
+
+ TranslationUtility util = FakeTranslationFactory.getInstance().getExampleTranslationUtility();
+ Command command = util.parseCommand(input);
+ ExecutionContext ec = Mockito.mock(ExecutionContext.class);
+ RuntimeMetadata rm = Mockito.mock(RuntimeMetadata.class);
+ LdapContext connection = Mockito.mock(LdapContext.class);
+ LdapContext ctx = Mockito.mock(LdapContext.class);
+ Mockito.stub(connection.lookup("corporate")).toReturn(ctx);
+
+ try {
+ LDAPDirectSearchQueryExecution execution = (LDAPDirectSearchQueryExecution)TRANSLATOR.createExecution(command, ec, rm, connection);
+ execution.execute();
+ fail("the above should have thrown exception");
+ } catch (ClassCastException e) {
+ }
+ }
+
+ @Test public void testDelete() throws Exception {
+ String input = "exec native('delete;uid=doe,ou=people,o=teiid.org')";
+
+ TranslationUtility util = FakeTranslationFactory.getInstance().getExampleTranslationUtility();
+ Command command = util.parseCommand(input);
+ ExecutionContext ec = Mockito.mock(ExecutionContext.class);
+ RuntimeMetadata rm = Mockito.mock(RuntimeMetadata.class);
+ LdapContext connection = Mockito.mock(LdapContext.class);
+ LdapContext ctx = Mockito.mock(LdapContext.class);
+ Mockito.stub(connection.lookup("")).toReturn(ctx);
+
+ LDAPDirectCreateUpdateDeleteQueryExecution execution = (LDAPDirectCreateUpdateDeleteQueryExecution)TRANSLATOR.createExecution(command, ec, rm, connection);
+ execution.execute();
+
+ Mockito.verify(ctx, Mockito.times(1)).destroySubcontext("uid=doe,ou=people,o=teiid.org");
+ }
+
+ @Test public void testUpdate() throws Exception {
+ String input = "exec native('update;uid=doe,ou=people,o=teiid.org;attributes=one,two,three', 'one', 2, 3.0)";
+
+ TranslationUtility util = FakeTranslationFactory.getInstance().getExampleTranslationUtility();
+ Command command = util.parseCommand(input);
+ ExecutionContext ec = Mockito.mock(ExecutionContext.class);
+ RuntimeMetadata rm = Mockito.mock(RuntimeMetadata.class);
+ LdapContext connection = Mockito.mock(LdapContext.class);
+ LdapContext ctx = Mockito.mock(LdapContext.class);
+ Mockito.stub(connection.lookup("")).toReturn(ctx);
+
+ LDAPDirectCreateUpdateDeleteQueryExecution execution = (LDAPDirectCreateUpdateDeleteQueryExecution)TRANSLATOR.createExecution(command, ec, rm, connection);
+ execution.execute();
+
+ ArgumentCaptor<String> nameArgument = ArgumentCaptor.forClass(String.class);
+ ArgumentCaptor<ModificationItem[]> modificationItemArgument = ArgumentCaptor.forClass(ModificationItem[].class);
+ Mockito.verify(ctx).modifyAttributes(nameArgument.capture(),modificationItemArgument.capture());
+
+ assertEquals("uid=doe,ou=people,o=teiid.org", nameArgument.getValue());
+ assertEquals("one", modificationItemArgument.getValue()[0].getAttribute().getID());
+ assertEquals("one", modificationItemArgument.getValue()[0].getAttribute().get());
+ assertEquals("two", modificationItemArgument.getValue()[1].getAttribute().getID());
+ assertEquals(2, modificationItemArgument.getValue()[1].getAttribute().get());
+ assertEquals("three", modificationItemArgument.getValue()[2].getAttribute().getID());
+ assertEquals(new BigDecimal("3.0"), modificationItemArgument.getValue()[2].getAttribute().get());
+ }
+
+ @Test public void testCreate() throws Exception {
+ String input = "exec native('create;uid=doe,ou=people,o=teiid.org;attributes=one,two,three', 'one', 2, 3.0)";
+
+ TranslationUtility util = FakeTranslationFactory.getInstance().getExampleTranslationUtility();
+ Command command = util.parseCommand(input);
+ ExecutionContext ec = Mockito.mock(ExecutionContext.class);
+ RuntimeMetadata rm = Mockito.mock(RuntimeMetadata.class);
+ LdapContext connection = Mockito.mock(LdapContext.class);
+ LdapContext ctx = Mockito.mock(LdapContext.class);
+ Mockito.stub(connection.lookup("")).toReturn(ctx);
+
+ LDAPDirectCreateUpdateDeleteQueryExecution execution = (LDAPDirectCreateUpdateDeleteQueryExecution)TRANSLATOR.createExecution(command, ec, rm, connection);
+ execution.execute();
+
+ ArgumentCaptor<String> nameArgument = ArgumentCaptor.forClass(String.class);
+ ArgumentCaptor<BasicAttributes> createItemArgument = ArgumentCaptor.forClass(BasicAttributes.class);
+ Mockito.verify(ctx).createSubcontext(nameArgument.capture(), createItemArgument.capture());
+
+ assertEquals("uid=doe,ou=people,o=teiid.org", nameArgument.getValue());
+ assertEquals("one", createItemArgument.getValue().get("one").getID());
+ assertEquals("one", createItemArgument.getValue().get("one").get());
+ assertEquals("two", createItemArgument.getValue().get("two").getID());
+ assertEquals(2, createItemArgument.getValue().get("two").get());
+ assertEquals("three", createItemArgument.getValue().get("three").getID());
+ assertEquals(new BigDecimal("3.0"), createItemArgument.getValue().get("three").get());
+ }
+
+ @Test public void testCreateFail() throws Exception {
+ String input = "exec native('create;uid=doe,ou=people,o=teiid.org;attributes=one,two,three', 'one')";
+
+ TranslationUtility util = FakeTranslationFactory.getInstance().getExampleTranslationUtility();
+ Command command = util.parseCommand(input);
+ ExecutionContext ec = Mockito.mock(ExecutionContext.class);
+ RuntimeMetadata rm = Mockito.mock(RuntimeMetadata.class);
+ LdapContext connection = Mockito.mock(LdapContext.class);
+ LdapContext ctx = Mockito.mock(LdapContext.class);
+ Mockito.stub(connection.lookup("")).toReturn(ctx);
+
+ try {
+ LDAPDirectCreateUpdateDeleteQueryExecution execution = (LDAPDirectCreateUpdateDeleteQueryExecution)TRANSLATOR.createExecution(command, ec, rm, connection);
+ execution.execute();
+ fail("should have failed because there are not enough values");
+ } catch (TranslatorException e) {
+ }
+ }
+}
Property changes on: trunk/connectors/translator-ldap/src/test/java/org/teiid/translator/ldap/TestLDAPDirectQueryExecution.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Modified: trunk/connectors/translator-olap/src/main/java/org/teiid/translator/olap/OlapExecutionFactory.java
===================================================================
--- trunk/connectors/translator-olap/src/main/java/org/teiid/translator/olap/OlapExecutionFactory.java 2012-09-25 18:58:05 UTC (rev 4471)
+++ trunk/connectors/translator-olap/src/main/java/org/teiid/translator/olap/OlapExecutionFactory.java 2012-09-25 22:15:11 UTC (rev 4472)
@@ -23,26 +23,22 @@
import java.sql.Connection;
import java.sql.SQLException;
+import java.util.List;
import javax.sql.DataSource;
import org.olap4j.OlapConnection;
import org.olap4j.OlapWrapper;
-import org.teiid.language.Call;
+import org.teiid.language.Argument;
+import org.teiid.language.Command;
import org.teiid.logging.LogConstants;
import org.teiid.logging.LogManager;
-import org.teiid.metadata.MetadataFactory;
-import org.teiid.metadata.Procedure;
-import org.teiid.metadata.ProcedureParameter;
import org.teiid.metadata.RuntimeMetadata;
-import org.teiid.metadata.BaseColumn.NullType;
-import org.teiid.metadata.ProcedureParameter.Type;
import org.teiid.translator.ExecutionContext;
import org.teiid.translator.ExecutionFactory;
-import org.teiid.translator.ProcedureExecution;
+import org.teiid.translator.ResultSetExecution;
import org.teiid.translator.Translator;
import org.teiid.translator.TranslatorException;
-import org.teiid.translator.TypeFacility;
@Translator(name="olap", description="A translator for OLAP Cubes")
public class OlapExecutionFactory extends ExecutionFactory<DataSource, Connection> {
@@ -50,23 +46,13 @@
public OlapExecutionFactory() {
setSourceRequiredForMetadata(false);
+ setSupportsNativeQueries(true);
+ setNativeQueryProcedureName(INVOKE_MDX);
}
- @Override
- public void getMetadata(MetadataFactory metadataFactory, Connection conn) throws TranslatorException {
- Procedure p = metadataFactory.addProcedure(INVOKE_MDX);
- p.setAnnotation("Invokes a XMLA webservice with provided MDX query that returns an XML result"); //$NON-NLS-1$
-
- // mdx query in xml form
- ProcedureParameter param = metadataFactory.addProcedureParameter("request", TypeFacility.RUNTIME_NAMES.STRING, Type.In, p); //$NON-NLS-1$
- param.setAnnotation("The MDX query to execute"); //$NON-NLS-1$
- param.setNullType(NullType.Nullable);
- metadataFactory.addProcedureResultSetColumn("tuple", TypeFacility.RUNTIME_NAMES.OBJECT, p); //$NON-NLS-1$
- }
-
@Override
- public ProcedureExecution createProcedureExecution(Call command, ExecutionContext executionContext, RuntimeMetadata metadata, Connection connection) throws TranslatorException {
- return new OlapQueryExecution(command, unwrap(connection), executionContext, this);
+ public ResultSetExecution createDirectExecution(List<Argument> arguments, Command command, ExecutionContext executionContext, RuntimeMetadata metadata, Connection connection) throws TranslatorException {
+ return new OlapQueryExecution(arguments, command, unwrap(connection), executionContext, this);
}
private OlapConnection unwrap(Connection conn) throws TranslatorException {
Modified: trunk/connectors/translator-olap/src/main/java/org/teiid/translator/olap/OlapQueryExecution.java
===================================================================
--- trunk/connectors/translator-olap/src/main/java/org/teiid/translator/olap/OlapQueryExecution.java 2012-09-25 18:58:05 UTC (rev 4471)
+++ trunk/connectors/translator-olap/src/main/java/org/teiid/translator/olap/OlapQueryExecution.java 2012-09-25 22:15:11 UTC (rev 4472)
@@ -35,7 +35,6 @@
import org.olap4j.Position;
import org.olap4j.metadata.Member;
import org.teiid.language.Argument;
-import org.teiid.language.Call;
import org.teiid.language.Command;
import org.teiid.logging.LogConstants;
import org.teiid.logging.LogManager;
@@ -57,8 +56,10 @@
private CellSetAxis columnsAxis;
private int colWidth;
private ListIterator<Position> rowPositionIterator;
+ private String mdxQuery;
- public OlapQueryExecution(Command command, OlapConnection connection, ExecutionContext context, OlapExecutionFactory executionFactory) {
+ public OlapQueryExecution(List<Argument> arguments, Command command, OlapConnection connection, ExecutionContext context, OlapExecutionFactory executionFactory) {
+ this.mdxQuery = (String) arguments.get(0).getArgumentValue().getValue();;
this.command = command;
this.connection = connection;
this.context = context;
@@ -68,11 +69,7 @@
@Override
public void execute() throws TranslatorException {
try {
- Call procedure = (Call) this.command;
- List<Argument> arguments = procedure.getArguments();
- String mdxQuery = (String) arguments.get(0).getArgumentValue().getValue();
stmt = this.connection.createStatement();
-
cellSet = stmt.executeOlapQuery(mdxQuery);
CellSetAxis rowAxis = this.cellSet.getAxes().get(Axis.ROWS.axisOrdinal());
rowPositionIterator = rowAxis.iterator();
Modified: trunk/connectors/translator-salesforce/src/main/java/org/teiid/translator/salesforce/SalesForceExecutionFactory.java
===================================================================
--- trunk/connectors/translator-salesforce/src/main/java/org/teiid/translator/salesforce/SalesForceExecutionFactory.java 2012-09-25 18:58:05 UTC (rev 4471)
+++ trunk/connectors/translator-salesforce/src/main/java/org/teiid/translator/salesforce/SalesForceExecutionFactory.java 2012-09-25 22:15:11 UTC (rev 4472)
@@ -29,6 +29,7 @@
import javax.resource.cci.ConnectionFactory;
+import org.teiid.language.Argument;
import org.teiid.language.Call;
import org.teiid.language.Command;
import org.teiid.language.QueryExpression;
@@ -49,6 +50,7 @@
import org.teiid.translator.TypeFacility;
import org.teiid.translator.UpdateExecution;
import org.teiid.translator.salesforce.execution.DeleteExecutionImpl;
+import org.teiid.translator.salesforce.execution.DirectQueryExecution;
import org.teiid.translator.salesforce.execution.InsertExecutionImpl;
import org.teiid.translator.salesforce.execution.ProcedureExecutionParentImpl;
import org.teiid.translator.salesforce.execution.QueryExecutionImpl;
@@ -68,6 +70,7 @@
setSupportsOrderBy(false);
setSupportsOuterJoins(true);
setSupportedJoinCriteria(SupportedJoinCriteria.KEY);
+ setSupportsNativeQueries(true);
}
@TranslatorProperty(display="Audit Model Fields", advanced=true)
@@ -113,7 +116,13 @@
throws TranslatorException {
return new ProcedureExecutionParentImpl(command, connection, metadata, executionContext);
}
+
@Override
+ public ResultSetExecution createDirectExecution(List<Argument> arguments, Command command, ExecutionContext executionContext, RuntimeMetadata metadata, SalesforceConnection connection) throws TranslatorException {
+ return new DirectQueryExecution(arguments, command, connection, metadata, executionContext);
+ }
+
+ @Override
public void getMetadata(MetadataFactory metadataFactory, SalesforceConnection connection) throws TranslatorException {
MetadataProcessor processor = new MetadataProcessor(connection,metadataFactory, this);
processor.processMetadata();
Modified: trunk/connectors/translator-salesforce/src/main/java/org/teiid/translator/salesforce/SalesForcePlugin.java
===================================================================
--- trunk/connectors/translator-salesforce/src/main/java/org/teiid/translator/salesforce/SalesForcePlugin.java 2012-09-25 18:58:05 UTC (rev 4471)
+++ trunk/connectors/translator-salesforce/src/main/java/org/teiid/translator/salesforce/SalesForcePlugin.java 2012-09-25 22:15:11 UTC (rev 4472)
@@ -43,6 +43,10 @@
public static final BundleUtil Util = new BundleUtil(PLUGIN_ID,BUNDLE_NAME,ResourceBundle.getBundle(BUNDLE_NAME));
public static enum Event implements BundleUtil.Event{
- TEIID13001
+ TEIID13001,
+ TEIID13002,
+ TEIID13003,
+ TEIID13004,
+ TEIID13005,
}
}
Added: trunk/connectors/translator-salesforce/src/main/java/org/teiid/translator/salesforce/execution/DirectQueryExecution.java
===================================================================
--- trunk/connectors/translator-salesforce/src/main/java/org/teiid/translator/salesforce/execution/DirectQueryExecution.java (rev 0)
+++ trunk/connectors/translator-salesforce/src/main/java/org/teiid/translator/salesforce/execution/DirectQueryExecution.java 2012-09-25 22:15:11 UTC (rev 4472)
@@ -0,0 +1,289 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+package org.teiid.translator.salesforce.execution;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import javax.resource.ResourceException;
+import javax.xml.bind.JAXBElement;
+import javax.xml.namespace.QName;
+
+import org.teiid.language.Argument;
+import org.teiid.language.Command;
+import org.teiid.metadata.RuntimeMetadata;
+import org.teiid.translator.DataNotAvailableException;
+import org.teiid.translator.ExecutionContext;
+import org.teiid.translator.ProcedureExecution;
+import org.teiid.translator.TranslatorException;
+import org.teiid.translator.salesforce.SalesForcePlugin;
+import org.teiid.translator.salesforce.SalesforceConnection;
+import org.w3c.dom.Element;
+
+import com.sforce.soap.partner.QueryResult;
+import com.sforce.soap.partner.sobject.SObject;
+
+public class DirectQueryExecution implements ProcedureExecution {
+
+ private static final String DELETE_IDS = "ids"; //$NON-NLS-1$
+ private static final String ATTRIBUTES = "attributes"; //$NON-NLS-1$
+ private static final String TYPE = "type"; //$NON-NLS-1$
+ private static final String ID = "id"; //$NON-NLS-1$
+
+ private List<Argument> arguments;
+ private Command command;
+ private SalesforceConnection connection;
+ private RuntimeMetadata metadata;
+ private ExecutionContext context;
+ private QueryResult results;
+ private List<List<Object>> currentBatch;
+ private int updateCount = -1;
+ private boolean updateQuery = false;
+
+ public DirectQueryExecution(List<Argument> arguments, Command command, SalesforceConnection connection, RuntimeMetadata metadata, ExecutionContext context) {
+ this.arguments = arguments;
+ this.command = command;
+ this.connection = connection;
+ this.metadata = metadata;
+ this.context = context;
+ }
+
+ @Override
+ public void execute() throws TranslatorException {
+ String query = (String)this.arguments.get(0).getArgumentValue().getValue();
+ if (query.startsWith("search;")) { //$NON-NLS-1$
+ doSelect(query.substring(7));
+ }
+ else if (query.startsWith("create;")) { //$NON-NLS-1$
+ doInsert(query.substring(7));
+ }
+ else if (query.startsWith("update;")) { //$NON-NLS-1$
+ doUpdate(query.substring(7));
+ }
+ else if (query.startsWith("delete;")) { //$NON-NLS-1$
+ doDelete(query.substring(7));
+ }
+ else {
+ throw new TranslatorException(SalesForcePlugin.Util.gs(SalesForcePlugin.Event.TEIID13002));
+ }
+
+ }
+
+ private void doDelete(String query) throws TranslatorException {
+ List<String> ids = getIds(query);
+ try {
+ this.updateCount = this.connection.delete(ids.toArray(new String[ids.size()]));
+ this.updateQuery = true;
+ } catch (ResourceException e) {
+ throw new TranslatorException(e);
+ }
+ }
+
+ private void doUpdate(String query) throws TranslatorException {
+ DataPayload payload = buildDataPlayload(query, this.arguments);
+ try {
+ this.updateCount = this.connection.update(Arrays.asList(payload));
+ this.updateQuery = true;
+ } catch (ResourceException e) {
+ throw new TranslatorException(e);
+ }
+ }
+
+ private void doInsert(String query) throws TranslatorException {
+ DataPayload payload = buildDataPlayload(query, this.arguments);
+ try {
+ this.updateCount = this.connection.create(payload);
+ this.updateQuery = true;
+ } catch (ResourceException e) {
+ throw new TranslatorException(e);
+ }
+ }
+
+ private void doSelect(String query) throws TranslatorException {
+ try {
+ this.results = this.connection.query(query, this.context.getBatchSize(), Boolean.FALSE);
+ } catch (ResourceException e) {
+ throw new TranslatorException(e);
+ }
+ }
+
+ @Override
+ public List<?> next() throws TranslatorException, DataNotAvailableException {
+ List<?> vals = getRow(this.results);
+ if (vals == null) {
+ return null;
+ }
+ List<Object[]> row = new ArrayList<Object[]>(1);
+ row.add(vals.toArray(new Object[vals.size()]));
+ return row;
+ }
+
+ private List<Object> getRow(QueryResult result) throws TranslatorException {
+
+ // for insert/update/delete clauses
+ if (this.updateQuery) {
+ if (this.updateCount != -1) {
+ List updateResult = Arrays.asList(this.updateCount);
+ this.updateCount = -1;
+ return updateResult;
+ }
+ return null;
+ }
+
+ // select clauses
+ List<Object> row = null;
+
+ if(this.currentBatch == null) {
+ this.currentBatch = loadBatch(this.results);
+ }
+
+ if(!this.currentBatch.isEmpty()) {
+ row = this.currentBatch.remove(0);
+ }
+ else {
+ if(!result.isDone()) {
+ // fetch more results
+ try {
+ this.results = this.connection.queryMore(results.getQueryLocator(), context.getBatchSize());
+ } catch (ResourceException e) {
+ throw new TranslatorException(e);
+ }
+ this.currentBatch = loadBatch(this.results);
+
+ // read next row
+ row = this.currentBatch.remove(0);
+ }
+ }
+ return row;
+ }
+
+ private List<List<Object>> loadBatch(QueryResult queryResult) {
+ List<List<Object>> batch = new ArrayList<List<Object>>();
+ for(SObject sObject : queryResult.getRecords()) {
+ List<Object> fields = sObject.getAny();
+ List<Object> row = new ArrayList<Object>();
+ if (sObject.getId() != null) {
+ row.add(sObject.getId());
+ }
+ for (Object field:fields) {
+ Element elem = (Element)field;
+ String value = elem.getTextContent();
+ row.add(value);
+ }
+ batch.add(row);
+ }
+ return batch;
+ }
+
+ @Override
+ public void close() {
+ }
+
+ @Override
+ public void cancel() throws TranslatorException {
+ }
+
+ private ArrayList<String> getIds(String query) throws TranslatorException {
+ StringTokenizer st = new StringTokenizer(query, ";"); //$NON-NLS-1$
+ if (!st.hasMoreTokens()) {
+ throw new TranslatorException(SalesForcePlugin.Util.gs(SalesForcePlugin.Event.TEIID13003));
+ }
+
+ ArrayList<String> ids = new ArrayList<String>();
+
+ while(st.hasMoreElements()) {
+ String var = st.nextToken();
+ int index = var.indexOf('=');
+ if (index == -1) {
+ continue;
+ }
+ String key = var.substring(0, index).trim().toLowerCase();
+ String value = var.substring(index+1).trim();
+
+ if (key.equalsIgnoreCase(DELETE_IDS)) {
+ StringTokenizer attrTokens = new StringTokenizer(value, ","); //$NON-NLS-1$
+ while (attrTokens.hasMoreElements()) {
+ ids.add(attrTokens.nextToken());
+ }
+ }
+ }
+ return ids;
+ }
+
+ private DataPayload buildDataPlayload(String query, List<Argument> arguments) throws TranslatorException {
+ StringTokenizer st = new StringTokenizer(query, ";"); //$NON-NLS-1$
+ if (!st.hasMoreTokens()) {
+ throw new TranslatorException(SalesForcePlugin.Util.gs(SalesForcePlugin.Event.TEIID13004));
+ }
+
+ ArrayList<JAXBElement> attributes = new ArrayList<JAXBElement>();
+ String type = null;
+ String id = null;
+
+ while(st.hasMoreElements()) {
+ String var = st.nextToken();
+
+ int index = var.indexOf('=');
+ if (index == -1) {
+ continue;
+ }
+ String key = var.substring(0, index).trim().toLowerCase();
+ String value = var.substring(index+1).trim();
+
+
+ if (key.equalsIgnoreCase(ATTRIBUTES)) {
+ StringTokenizer attrTokens = new StringTokenizer(value, ","); //$NON-NLS-1$
+ int attrCount = 1;
+ while(attrTokens.hasMoreElements()) {
+ String name = attrTokens.nextToken().trim();
+ if (arguments.size() <= attrCount) {
+ throw new TranslatorException(SalesForcePlugin.Util.gs(SalesForcePlugin.Event.TEIID13005, name));
+ }
+ Argument argument = arguments.get(attrCount++);
+ Object anObj = argument.getArgumentValue().getValue();
+ QName qname = new QName(name);
+ @SuppressWarnings( "unchecked" )
+ JAXBElement jbe = new JAXBElement( qname, String.class, anObj );
+ attributes.add(jbe);
+ }
+ }
+ else if (key.equalsIgnoreCase(TYPE)) {
+ type = value;
+ }
+ else if (key.equalsIgnoreCase(ID)) {
+ id = value;
+ }
+ }
+ DataPayload payload = new DataPayload();
+ payload.setID(id);
+ payload.setType(type);
+ payload.setMessageElements(attributes);
+ return payload;
+ }
+
+ @Override
+ public List<?> getOutputParameterValues() throws TranslatorException {
+ return null;
+ }
+}
Property changes on: trunk/connectors/translator-salesforce/src/main/java/org/teiid/translator/salesforce/execution/DirectQueryExecution.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Modified: trunk/connectors/translator-salesforce/src/main/resources/org/teiid/translator/salesforce/i18n.properties
===================================================================
--- trunk/connectors/translator-salesforce/src/main/resources/org/teiid/translator/salesforce/i18n.properties 2012-09-25 18:58:05 UTC (rev 4471)
+++ trunk/connectors/translator-salesforce/src/main/resources/org/teiid/translator/salesforce/i18n.properties 2012-09-25 22:15:11 UTC (rev 4472)
@@ -37,4 +37,8 @@
CriteriaVisitor.LIKE.not.supported.on.Id=LIKE criteria are not allowed on columns of native type Id
CriteriaVisitor.LIKE.not.supported.on.multiselect=LIKE criteria are not allowed on columns of native type Multi-Select Picklist
-TEIID13001=Unknown type returned by SalesForce: {0}
\ No newline at end of file
+TEIID13001=Unknown type returned by SalesForce: {0}
+TEIID13002=Unknown request; query must start with one of [search|create|update|delete]
+TEIID13003=The query is missing "id=x,y.." values.
+TEIID13004=The query is missing type, id and attribute values.
+TEIID13005=The attribute count does not match with the value parameters supplied.
\ No newline at end of file
Added: trunk/connectors/translator-salesforce/src/test/java/org/teiid/translator/salesforce/execution/TestSalesForceDirectQueryExecution.java
===================================================================
--- trunk/connectors/translator-salesforce/src/test/java/org/teiid/translator/salesforce/execution/TestSalesForceDirectQueryExecution.java (rev 0)
+++ trunk/connectors/translator-salesforce/src/test/java/org/teiid/translator/salesforce/execution/TestSalesForceDirectQueryExecution.java 2012-09-25 22:15:11 UTC (rev 4472)
@@ -0,0 +1,210 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+package org.teiid.translator.salesforce.execution;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+import org.teiid.cdk.api.TranslationUtility;
+import org.teiid.cdk.unittest.FakeTranslationFactory;
+import org.teiid.language.Command;
+import org.teiid.metadata.RuntimeMetadata;
+import org.teiid.translator.ExecutionContext;
+import org.teiid.translator.TranslatorException;
+import org.teiid.translator.salesforce.SalesForceExecutionFactory;
+import org.teiid.translator.salesforce.SalesforceConnection;
+import org.w3c.dom.Element;
+
+import com.sforce.soap.partner.QueryResult;
+import com.sforce.soap.partner.sobject.SObject;
+
+@SuppressWarnings("nls")
+public class TestSalesForceDirectQueryExecution {
+
+ private static SalesForceExecutionFactory TRANSLATOR;
+
+ @BeforeClass
+ public static void setUp() throws TranslatorException {
+ TRANSLATOR = new SalesForceExecutionFactory();
+ TRANSLATOR.start();
+ }
+
+ @Test public void testSearch() throws Exception {
+ String input = "exec native('search;SELECT Account.Id, Account.Type, Account.Name FROM Account')";
+
+ TranslationUtility util = FakeTranslationFactory.getInstance().getExampleTranslationUtility();
+ Command command = util.parseCommand(input);
+ ExecutionContext ec = Mockito.mock(ExecutionContext.class);
+ RuntimeMetadata rm = Mockito.mock(RuntimeMetadata.class);
+ SalesforceConnection connection = Mockito.mock(SalesforceConnection.class);
+
+ QueryResult qr = Mockito.mock(QueryResult.class);
+ Mockito.stub(qr.isDone()).toReturn(true);
+
+ ArrayList<SObject> results = new ArrayList<SObject>();
+ ArrayList<Object> values = new ArrayList<Object>();
+
+ SObject s = Mockito.mock(SObject.class);
+ //Mockito.stub(s.getId()).toReturn("theID");
+ Mockito.stub(s.getType()).toReturn("Account");
+ results.add(s);
+
+ Element e1 = Mockito.mock(Element.class);
+ Mockito.stub(e1.getTextContent()).toReturn("The ID");
+ values.add(e1);
+
+ Element e2 = Mockito.mock(Element.class);
+ Mockito.stub(e2.getTextContent()).toReturn("The Type");
+ values.add(e2);
+
+ Element e3 = Mockito.mock(Element.class);
+ Mockito.stub(e3.getTextContent()).toReturn("The Name");
+ values.add(e3);
+
+ Mockito.stub(s.getAny()).toReturn(values);
+ Mockito.stub(qr.getRecords()).toReturn(results);
+ Mockito.stub(connection.query("SELECT Account.Id, Account.Type, Account.Name FROM Account", 0, false)).toReturn(qr);
+
+ DirectQueryExecution execution = (DirectQueryExecution)TRANSLATOR.createExecution(command, ec, rm, connection);
+ execution.execute();
+
+ Mockito.verify(connection, Mockito.times(1)).query("SELECT Account.Id, Account.Type, Account.Name FROM Account", 0, false);
+
+ assertArrayEquals(new Object[] {"The ID", "The Type", "The Name"}, (Object[])execution.next().get(0));
+
+ }
+
+ @Test public void testWithoutMarker() throws Exception {
+ String input = "exec native('salesforce query')";
+
+ TranslationUtility util = FakeTranslationFactory.getInstance().getExampleTranslationUtility();
+ Command command = util.parseCommand(input);
+ ExecutionContext ec = Mockito.mock(ExecutionContext.class);
+ RuntimeMetadata rm = Mockito.mock(RuntimeMetadata.class);
+ SalesforceConnection connection = Mockito.mock(SalesforceConnection.class);
+
+ try {
+ DirectQueryExecution execution = (DirectQueryExecution)TRANSLATOR.createExecution(command, ec, rm, connection);
+ execution.execute();
+ fail("the above should have thrown exception");
+ } catch (TranslatorException e) {
+ }
+ }
+
+ @Test public void testDelete() throws Exception {
+ String input = "exec native('delete;ids=id1,id2')";
+
+ TranslationUtility util = FakeTranslationFactory.getInstance().getExampleTranslationUtility();
+ Command command = util.parseCommand(input);
+ ExecutionContext ec = Mockito.mock(ExecutionContext.class);
+ RuntimeMetadata rm = Mockito.mock(RuntimeMetadata.class);
+ SalesforceConnection connection = Mockito.mock(SalesforceConnection.class);
+
+ ArgumentCaptor<String[]> payloadArgument = ArgumentCaptor.forClass(String[].class);
+ Mockito.stub(connection.delete(payloadArgument.capture())).toReturn(23);
+
+ DirectQueryExecution execution = (DirectQueryExecution)TRANSLATOR.createExecution(command, ec, rm, connection);
+ execution.execute();
+
+ Mockito.verify(connection, Mockito.times(1)).delete(payloadArgument.capture());
+
+ assertEquals("id1", payloadArgument.getValue()[0]);
+ assertEquals("id2", payloadArgument.getValue()[1]);
+
+ assertArrayEquals(new Object[] {23}, (Object[])execution.next().get(0));
+ }
+
+ @Test public void testUpdate() throws Exception {
+ String input = "exec native('update;id=pk;type=table;attributes=one,two,three', 'one', 2, 3.0)";
+
+ TranslationUtility util = FakeTranslationFactory.getInstance().getExampleTranslationUtility();
+ Command command = util.parseCommand(input);
+ ExecutionContext ec = Mockito.mock(ExecutionContext.class);
+ RuntimeMetadata rm = Mockito.mock(RuntimeMetadata.class);
+ SalesforceConnection connection = Mockito.mock(SalesforceConnection.class);
+
+ ArgumentCaptor<List> payloadArgument = ArgumentCaptor.forClass(List.class);
+ Mockito.stub(connection.update(payloadArgument.capture())).toReturn(23);
+
+ DirectQueryExecution execution = (DirectQueryExecution)TRANSLATOR.createExecution(command, ec, rm, connection);
+ execution.execute();
+
+ Mockito.verify(connection).update(payloadArgument.capture());
+
+ assertEquals(1, payloadArgument.getValue().size());
+ assertEquals("pk", ((DataPayload)payloadArgument.getValue().get(0)).getID());
+ assertEquals("table", ((DataPayload)payloadArgument.getValue().get(0)).getType());
+ assertEquals(3, ((DataPayload)payloadArgument.getValue().get(0)).getMessageElements().size());
+
+ assertArrayEquals(new Object[] {23}, (Object[])execution.next().get(0));
+ }
+
+ @Test public void testCreate() throws Exception {
+ String input = "exec native('create;id=pk;type=table;attributes=one,two,three', 'one', 2, 3.0)";
+
+ TranslationUtility util = FakeTranslationFactory.getInstance().getExampleTranslationUtility();
+ Command command = util.parseCommand(input);
+ ExecutionContext ec = Mockito.mock(ExecutionContext.class);
+ RuntimeMetadata rm = Mockito.mock(RuntimeMetadata.class);
+ SalesforceConnection connection = Mockito.mock(SalesforceConnection.class);
+
+ ArgumentCaptor<DataPayload> payloadArgument = ArgumentCaptor.forClass(DataPayload.class);
+ Mockito.stub(connection.create(payloadArgument.capture())).toReturn(23);
+
+ DirectQueryExecution execution = (DirectQueryExecution)TRANSLATOR.createExecution(command, ec, rm, connection);
+ execution.execute();
+
+
+ Mockito.verify(connection).create(payloadArgument.capture());
+
+ assertEquals("pk", payloadArgument.getValue().getID());
+ assertEquals("table", payloadArgument.getValue().getType());
+ assertEquals(3, payloadArgument.getValue().getMessageElements().size());
+
+ assertArrayEquals(new Object[] {23}, (Object[])execution.next().get(0));
+ }
+
+ @Test public void testCreateFail() throws Exception {
+ String input = "exec native('create;id=pk;type=table;attributes=one,two,three', 'one')";
+
+ TranslationUtility util = FakeTranslationFactory.getInstance().getExampleTranslationUtility();
+ Command command = util.parseCommand(input);
+ ExecutionContext ec = Mockito.mock(ExecutionContext.class);
+ RuntimeMetadata rm = Mockito.mock(RuntimeMetadata.class);
+ SalesforceConnection connection = Mockito.mock(SalesforceConnection.class);
+
+ try {
+ DirectQueryExecution execution = (DirectQueryExecution)TRANSLATOR.createExecution(command, ec, rm, connection);
+ execution.execute();
+ fail("should have failed because there are not enough values");
+ } catch (TranslatorException e) {
+ }
+ }
+}
Property changes on: trunk/connectors/translator-salesforce/src/test/java/org/teiid/translator/salesforce/execution/TestSalesForceDirectQueryExecution.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: trunk/engine/src/main/java/org/teiid/query/metadata/DirectQueryMetadataRepository.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/metadata/DirectQueryMetadataRepository.java (rev 0)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/DirectQueryMetadataRepository.java 2012-09-25 22:15:11 UTC (rev 4472)
@@ -0,0 +1,58 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+package org.teiid.query.metadata;
+
+import org.teiid.metadata.MetadataFactory;
+import org.teiid.metadata.Procedure;
+import org.teiid.metadata.ProcedureParameter;
+import org.teiid.metadata.BaseColumn.NullType;
+import org.teiid.metadata.ProcedureParameter.Type;
+import org.teiid.translator.ExecutionFactory;
+import org.teiid.translator.TranslatorException;
+import org.teiid.translator.TypeFacility;
+
+/**
+ * This Metadata repository adds the "native" procedure to all the execution factories that support them.
+ */
+public class DirectQueryMetadataRepository extends BaseMetadataRepository {
+
+ @Override
+ public void loadMetadata(MetadataFactory factory, ExecutionFactory executionFactory, Object connectionFactory) throws TranslatorException {
+
+ if (executionFactory != null && executionFactory.supportsNativeQueries()) {
+ Procedure p = factory.addProcedure(executionFactory.getNativeQueryProcedureName());
+ p.setAnnotation("Invokes translator with provided native query that returns result in array of values"); //$NON-NLS-1$
+
+ ProcedureParameter param = factory.addProcedureParameter("request", TypeFacility.RUNTIME_NAMES.STRING, Type.In, p); //$NON-NLS-1$
+ param.setAnnotation("The native query to execute"); //$NON-NLS-1$
+ param.setNullType(NullType.No_Nulls);
+
+ param = factory.addProcedureParameter("variable", TypeFacility.RUNTIME_NAMES.OBJECT, Type.In, p); //$NON-NLS-1$
+ param.setAnnotation("Any number of varaibles, depends upon how a translator uses them individually"); //$NON-NLS-1$
+ param.setNullType(NullType.Nullable);
+ param.setVarArg(true);
+
+ factory.addProcedureResultSetColumn("tuple", TypeFacility.RUNTIME_NAMES.OBJECT, p); //$NON-NLS-1$
+ }
+ super.loadMetadata(factory, executionFactory, connectionFactory);
+ }
+}
Property changes on: trunk/engine/src/main/java/org/teiid/query/metadata/DirectQueryMetadataRepository.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Modified: trunk/engine/src/test/java/org/teiid/query/unittest/RealMetadataFactory.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/unittest/RealMetadataFactory.java 2012-09-25 18:58:05 UTC (rev 4471)
+++ trunk/engine/src/test/java/org/teiid/query/unittest/RealMetadataFactory.java 2012-09-25 22:15:11 UTC (rev 4472)
@@ -114,6 +114,14 @@
Table lobTable = createPhysicalGroup("LobTbl", lob); //$NON-NLS-1$
Table library = createPhysicalGroup("LOB_TESTING_ONE", lob); //$NON-NLS-1$
+ // add direct query procedure
+ ColumnSet<Procedure> nativeProcResults = createResultSet("bqt1.nativers", new String[] {"tuple"}, new String[] { DataTypeManager.DefaultDataTypes.OBJECT}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ ProcedureParameter nativeparam = createParameter("param", ParameterInfo.IN, DataTypeManager.DefaultDataTypes.STRING); //$NON-NLS-1$
+ ProcedureParameter vardic = createParameter("varag", ParameterInfo.IN, DataTypeManager.DefaultDataTypes.OBJECT); //$NON-NLS-1$
+ vardic.setVarArg(true);
+ Procedure nativeProc = createStoredProcedure("native", bqt1, Arrays.asList(nativeparam,vardic)); //$NON-NLS-1$ //$NON-NLS-2$
+ nativeProc.setResultSet(nativeProcResults);
+
createElements( library, new String[] { "CLOB_COLUMN", "BLOB_COLUMN", "KEY_EMULATOR" }, //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
new String[] { DataTypeManager.DefaultDataTypes.CLOB, DataTypeManager.DefaultDataTypes.BLOB, DataTypeManager.DefaultDataTypes.INTEGER });
@@ -1014,6 +1022,13 @@
//end case 3281
+ ColumnSet<Procedure> nativeProcResults = createResultSet("pm1.nativers", new String[] {"tuple"}, new String[] { DataTypeManager.DefaultDataTypes.OBJECT}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ ProcedureParameter nativeparam = createParameter("param", ParameterInfo.IN, DataTypeManager.DefaultDataTypes.STRING); //$NON-NLS-1$
+ ProcedureParameter vardic = createParameter("varag", ParameterInfo.IN, DataTypeManager.DefaultDataTypes.OBJECT); //$NON-NLS-1$
+ vardic.setVarArg(true);
+ Procedure nativeProc = createStoredProcedure("native", pm1, Arrays.asList(nativeparam,vardic)); //$NON-NLS-1$ //$NON-NLS-2$
+ nativeProc.setResultSet(nativeProcResults);
+
ColumnSet<Procedure> rs3 = createResultSet("pm1.rs3", new String[] { "e1", "e2" }, new String[] { DataTypeManager.DefaultDataTypes.STRING, DataTypeManager.DefaultDataTypes.INTEGER }); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
Procedure sp1 = createStoredProcedure("sp1", pm1, null); //$NON-NLS-1$ //$NON-NLS-2$
sp1.setResultSet(rs3);
Modified: trunk/pom.xml
===================================================================
--- trunk/pom.xml 2012-09-25 18:58:05 UTC (rev 4471)
+++ trunk/pom.xml 2012-09-25 22:15:11 UTC (rev 4472)
@@ -252,7 +252,7 @@
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
- <version>1.5</version>
+ <version>1.9.0</version>
<scope>test</scope>
</dependency>
</dependencies>
Modified: trunk/runtime/src/main/java/org/teiid/runtime/AbstractVDBDeployer.java
===================================================================
--- trunk/runtime/src/main/java/org/teiid/runtime/AbstractVDBDeployer.java 2012-09-25 18:58:05 UTC (rev 4471)
+++ trunk/runtime/src/main/java/org/teiid/runtime/AbstractVDBDeployer.java 2012-09-25 22:15:11 UTC (rev 4472)
@@ -45,6 +45,7 @@
import org.teiid.metadata.MetadataStore;
import org.teiid.query.metadata.DDLMetadataRepository;
import org.teiid.query.metadata.NativeMetadataRepository;
+import org.teiid.query.metadata.DirectQueryMetadataRepository;
import org.teiid.translator.TranslatorException;
public abstract class AbstractVDBDeployer {
@@ -76,11 +77,14 @@
private MetadataRepository<?, ?> getMetadataRepository(VDBMetaData vdb, ModelMetaData model, MetadataRepository<?, ?> defaultRepo) throws VirtualDatabaseException {
if (model.getSchemaSourceType() == null) {
if (!vdb.isDynamic()) {
+ defaultRepo.setNext(new DirectQueryMetadataRepository());
return defaultRepo;
}
if (model.isSource()) {
- return new NativeMetadataRepository();
+ NativeMetadataRepository repo = new NativeMetadataRepository();
+ repo.setNext(new DirectQueryMetadataRepository());
+ return repo;
}
throw new VirtualDatabaseException(RuntimePlugin.Util.gs(RuntimePlugin.Event.TEIID40094, model.getName(), vdb.getName(), vdb.getVersion(), null));
}
@@ -88,7 +92,8 @@
MetadataRepository<?, ?> first = null;
MetadataRepository<?, ?> current = null;
MetadataRepository<?, ?> previous = null;
- StringTokenizer st = new StringTokenizer(model.getSchemaSourceType(), ","); //$NON-NLS-1$
+ String schemaTypes = model.getSchemaSourceType();
+ StringTokenizer st = new StringTokenizer(schemaTypes, ","); //$NON-NLS-1$
while (st.hasMoreTokens()) {
String repoType = st.nextToken().trim();
current = getMetadataRepository(repoType);
@@ -106,6 +111,12 @@
previous = current;
current = null;
}
+
+ // TODO:there is good chance that the instances of metadata factory sharing is not good between models,
+ // may that be for chaining purposes, we should do metadata repository factory model here.
+ if (model.getModelType() == ModelMetaData.Type.PHYSICAL) {
+ previous.setNext(new DirectQueryMetadataRepository());
+ }
return first;
}
Modified: trunk/test-integration/common/src/test/java/org/teiid/dqp/internal/process/TestExecutionReuse.java
===================================================================
--- trunk/test-integration/common/src/test/java/org/teiid/dqp/internal/process/TestExecutionReuse.java 2012-09-25 18:58:05 UTC (rev 4471)
+++ trunk/test-integration/common/src/test/java/org/teiid/dqp/internal/process/TestExecutionReuse.java 2012-09-25 22:15:11 UTC (rev 4472)
@@ -21,7 +21,8 @@
*/
package org.teiid.dqp.internal.process;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import java.sql.Connection;
import java.sql.ResultSet;
@@ -35,9 +36,9 @@
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.Mockito;
-import org.mockito.internal.progress.OngoingStubbing;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.DeprecatedOngoingStubbing;
import org.teiid.client.util.ResultsFuture;
import org.teiid.core.util.UnitTestUtil;
import org.teiid.dqp.internal.datamgr.ConnectorManager;
@@ -100,9 +101,9 @@
@Before public void setup() throws DataNotAvailableException, TranslatorException {
execution = Mockito.mock(FakeReusableExecution.class);
ec = null;
- OngoingStubbing stubbing = Mockito.stub(execution.next()).toReturn((List) Arrays.asList((Object)null)).toReturn(null);
+ DeprecatedOngoingStubbing stubbing = Mockito.stub(execution.next()).toReturn((List) Arrays.asList((Object)null)).toReturn(null);
for (int i = 1; i < EXEC_COUNT; i++) {
- stubbing.toReturn((List<Object>) Arrays.asList((Object)null)).toReturn(null);
+ stubbing.toReturn(Arrays.asList((Object)null)).toReturn(null);
}
Mockito.doAnswer(new Answer<Void>() {
@Override
13 years, 6 months
teiid SVN: r4471 - in trunk: build/kits/jboss-as7/docs/teiid and 14 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2012-09-25 14:58:05 -0400 (Tue, 25 Sep 2012)
New Revision: 4471
Modified:
trunk/api/src/main/java/org/teiid/language/SQLConstants.java
trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html
trunk/client/src/main/java/org/teiid/jdbc/TeiidSQLException.java
trunk/engine/src/main/java/org/teiid/query/eval/Evaluator.java
trunk/engine/src/main/java/org/teiid/query/optimizer/ProcedurePlanner.java
trunk/engine/src/main/java/org/teiid/query/processor/proc/CreateCursorResultSetInstruction.java
trunk/engine/src/main/java/org/teiid/query/processor/proc/ErrorInstruction.java
trunk/engine/src/main/java/org/teiid/query/processor/proc/IfInstruction.java
trunk/engine/src/main/java/org/teiid/query/processor/proc/LoopInstruction.java
trunk/engine/src/main/java/org/teiid/query/processor/proc/ProcedurePlan.java
trunk/engine/src/main/java/org/teiid/query/processor/proc/Program.java
trunk/engine/src/main/java/org/teiid/query/processor/proc/ProgramInstruction.java
trunk/engine/src/main/java/org/teiid/query/processor/proc/WhileInstruction.java
trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateProcedureResolver.java
trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
trunk/engine/src/main/java/org/teiid/query/sql/navigator/PreOrPostOrderNavigator.java
trunk/engine/src/main/java/org/teiid/query/sql/proc/Block.java
trunk/engine/src/main/java/org/teiid/query/sql/proc/ExceptionExpression.java
trunk/engine/src/main/java/org/teiid/query/sql/proc/RaiseStatement.java
trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java
trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
trunk/engine/src/main/resources/org/teiid/query/i18n.properties
trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java
trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcErrors.java
trunk/engine/src/test/java/org/teiid/query/resolver/TestProcedureResolving.java
Log:
TEIID-1386 refinement to exception handling. changed syntax slightly and added an exception handler to a block
Modified: trunk/api/src/main/java/org/teiid/language/SQLConstants.java
===================================================================
--- trunk/api/src/main/java/org/teiid/language/SQLConstants.java 2012-09-25 18:56:07 UTC (rev 4470)
+++ trunk/api/src/main/java/org/teiid/language/SQLConstants.java 2012-09-25 18:58:05 UTC (rev 4471)
@@ -128,6 +128,7 @@
public static final String INDEX = "INDEX"; //$NON-NLS-1$
public static final String EXCEPTION = "EXCEPTION"; //$NON-NLS-1$
public static final String RAISE = "RAISE"; //$NON-NLS-1$
+ public static final String CHAIN = "CHAIN"; //$NON-NLS-1$
}
public interface Reserved {
Modified: trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html
===================================================================
--- trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html 2012-09-25 18:56:07 UTC (rev 4470)
+++ trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html 2012-09-25 18:58:05 UTC (rev 4471)
@@ -56,7 +56,6 @@
<li>TEIID-2184 to be consistent with the rest of Teiid's logic the system functions dayName and monthName will return values from the default locale, rather than only the English names. Use the system property org.teiid.enDateNames true to revert to the pre-8.2 behavior.
<li>TEIID-2187 the CONSTRAINT keyword is not correctly used in table DDL. It should be replaced with a comma from scripts to be compatible with 8.2. If desired, 8.2 now supports the CONSTRAINT keyword to provide a name for each constraint.
<li>TEIID-2181 system tables no longer contain valid OIDs. That responsibility has moved to the pg_catalog.
- <li>TEIID-1386 assignment statements and stored procedure invocations assigning a return value will no longer allow non-quoted non-reserved identifiers as left hand side variables. The workaround is to use a quoted variable name if you are using a non-reserved word as a variable name.
<li>TEIID-1386 the SQLState and errorCode reported by a TeiidSQLException will typically be from the top level nested SQLException. If there is also a nested TeiidException, the TeiidSQLException.teiidCode will be set to the TeiidException.getCode value and the TeiidSQLException.errorCode will be set
to the integer suffix of the teiidCode if possible.
</ul>
Modified: trunk/client/src/main/java/org/teiid/jdbc/TeiidSQLException.java
===================================================================
--- trunk/client/src/main/java/org/teiid/jdbc/TeiidSQLException.java 2012-09-25 18:56:07 UTC (rev 4470)
+++ trunk/client/src/main/java/org/teiid/jdbc/TeiidSQLException.java 2012-09-25 18:58:05 UTC (rev 4471)
@@ -102,7 +102,7 @@
if (exception instanceof SQLException) {
return new TeiidSQLException((SQLException) exception, message, true);
}
- String sqlState = SQLStates.DEFAULT;
+ String sqlState = null;
int errorCode = 0;
SQLException se = ExceptionUtil.getExceptionOfType(exception, SQLException.class);
if (se != null && se.getSQLState() != null) {
@@ -125,8 +125,13 @@
}
}
}
- exception = findRootException(exception);
- sqlState = determineSQLState(exception, sqlState);
+ if (sqlState == null) {
+ exception = findRootException(exception);
+ sqlState = determineSQLState(exception, sqlState);
+ }
+ if (sqlState == null) {
+ sqlState = SQLStates.DEFAULT;
+ }
TeiidSQLException tse = new TeiidSQLException(origException, message, sqlState, errorCode);
tse.teiidCode = code;
return tse;
Modified: trunk/engine/src/main/java/org/teiid/query/eval/Evaluator.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/eval/Evaluator.java 2012-09-25 18:56:07 UTC (rev 4470)
+++ trunk/engine/src/main/java/org/teiid/query/eval/Evaluator.java 2012-09-25 18:58:05 UTC (rev 4471)
@@ -59,7 +59,6 @@
import org.teiid.core.types.basic.StringToSQLXMLTransform;
import org.teiid.core.util.EquivalenceUtil;
import org.teiid.jdbc.TeiidSQLException;
-import org.teiid.jdbc.TeiidSQLWarning;
import org.teiid.language.Like.MatchMode;
import org.teiid.query.QueryPlugin;
import org.teiid.query.function.FunctionDescriptor;
@@ -685,12 +684,7 @@
if (ee.getParent() != null) {
parent = (Exception) internalEvaluate(ee.getParent(), tuple);
}
- Exception result = null;
- if (ee.isWarning()) {
- result = new TeiidSQLWarning(msg, sqlState, errorCode!=null?errorCode:0, parent);
- } else {
- result = new TeiidSQLException(parent, msg, sqlState, errorCode!=null?errorCode:0);
- }
+ Exception result = new TeiidSQLException(parent, msg, sqlState, errorCode!=null?errorCode:0);
result.setStackTrace(SourceWarning.EMPTY_STACK_TRACE);
return result;
}
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/ProcedurePlanner.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/ProcedurePlanner.java 2012-09-25 18:56:07 UTC (rev 4470)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/ProcedurePlanner.java 2012-09-25 18:58:05 UTC (rev 4471)
@@ -23,6 +23,7 @@
package org.teiid.query.optimizer;
import java.util.LinkedHashMap;
+import java.util.List;
import java.util.Map;
import org.teiid.api.exception.query.QueryMetadataException;
@@ -132,7 +133,29 @@
programBlock.setLabel(block.getLabel());
// plan each statement in the block
- for (Statement statement : block.getStatements()) {
+ planStatements(parentProcCommand, block.getStatements(), metadata, debug, idGenerator,
+ capFinder, analysisRecord, context, programBlock);
+
+ if (block.getExceptionGroup() != null) {
+ programBlock.setExceptionGroup(block.getExceptionGroup());
+ if (block.getExceptionStatements() != null) {
+ Program exceptionBlock = new Program(false);
+ planStatements(parentProcCommand, block.getExceptionStatements(), metadata, debug, idGenerator,
+ capFinder, analysisRecord, context, exceptionBlock);
+ programBlock.setExceptionProgram(exceptionBlock);
+ }
+ }
+
+ return programBlock;
+ }
+
+ private void planStatements(CreateProcedureCommand parentProcCommand,
+ List<Statement> stmts, QueryMetadataInterface metadata, boolean debug,
+ IDGenerator idGenerator, CapabilitiesFinder capFinder,
+ AnalysisRecord analysisRecord, CommandContext context,
+ Program programBlock) throws QueryPlannerException,
+ QueryMetadataException, TeiidComponentException {
+ for (Statement statement : stmts) {
Object instruction = planStatement(parentProcCommand, statement, metadata, debug, idGenerator, capFinder, analysisRecord, context);
if(instruction instanceof ProgramInstruction){
programBlock.addInstruction((ProgramInstruction)instruction);
@@ -144,10 +167,8 @@
}
}
}
+ }
- return programBlock;
- }
-
/**
* <p> Plan a {@link Statement} object, depending on the type of the statement construct the appropriate
* {@link ProgramInstruction} return it to added to a {@link Program}. If the statement references a
@@ -198,8 +219,9 @@
Expression asigExpr = res.getExpression();
error.setExpression(asigExpr);
+ error.setWarning(res.isWarning());
if(debug) {
- analysisRecord.println("\tERROR STATEMENT:\n" + statement); //$NON-NLS-1$
+ analysisRecord.println("\tRAISE STATEMENT:\n" + statement); //$NON-NLS-1$
}
break;
}
Modified: trunk/engine/src/main/java/org/teiid/query/processor/proc/CreateCursorResultSetInstruction.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/proc/CreateCursorResultSetInstruction.java 2012-09-25 18:56:07 UTC (rev 4470)
+++ trunk/engine/src/main/java/org/teiid/query/processor/proc/CreateCursorResultSetInstruction.java 2012-09-25 18:58:05 UTC (rev 4471)
@@ -26,7 +26,6 @@
import static org.teiid.query.analysis.AnalysisRecord.*;
-import java.util.List;
import java.util.Map;
import org.teiid.client.plan.PlanNode;
@@ -104,9 +103,4 @@
return plan;
}
- @Override
- public void getChildPlans(List<ProcessorPlan> plans) {
- plans.add(this.plan);
- }
-
}
Modified: trunk/engine/src/main/java/org/teiid/query/processor/proc/ErrorInstruction.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/proc/ErrorInstruction.java 2012-09-25 18:56:07 UTC (rev 4470)
+++ trunk/engine/src/main/java/org/teiid/query/processor/proc/ErrorInstruction.java 2012-09-25 18:58:05 UTC (rev 4471)
@@ -24,14 +24,11 @@
import static org.teiid.query.analysis.AnalysisRecord.*;
-import java.sql.SQLWarning;
-
-import org.teiid.client.ProcedureErrorInstructionException;
import org.teiid.client.plan.PlanNode;
import org.teiid.core.TeiidComponentException;
import org.teiid.core.TeiidProcessingException;
+import org.teiid.jdbc.TeiidSQLException;
import org.teiid.logging.LogManager;
-import org.teiid.query.QueryPlugin;
import org.teiid.query.sql.symbol.Expression;
@@ -42,6 +39,7 @@
public class ErrorInstruction extends ProgramInstruction {
private Expression expression;
+ private boolean warning;
/**
* Constructor for DeclareInstruction.
@@ -52,6 +50,10 @@
public void setExpression(Expression expression) {
this.expression = expression;
}
+
+ public void setWarning(boolean warning) {
+ this.warning = warning;
+ }
/**
* @see org.teiid.query.processor.proc.ProgramInstruction#clone()
@@ -59,29 +61,33 @@
public ErrorInstruction clone() {
ErrorInstruction clone = new ErrorInstruction();
clone.expression = expression;
+ clone.warning = warning;
return clone;
}
public String toString() {
- return "RAISE ERROR INSTRUCTION: " + expression; //$NON-NLS-1$
+ return "RAISE " + (warning?"WARNING":"ERROR") +" INSTRUCTION: " + expression; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
public PlanNode getDescriptionProperties() {
- PlanNode node = new PlanNode("RAISE ERROR"); //$NON-NLS-1$
+ PlanNode node = new PlanNode("RAISE " + (warning?"WARNING":"ERROR")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
node.addProperty(PROP_EXPRESSION, this.expression.toString());
return node;
}
@Override
public void process(ProcedurePlan env) throws TeiidComponentException,
- TeiidProcessingException {
+ TeiidProcessingException, TeiidSQLException {
Object value = env.evaluateExpression(expression);
- LogManager.logTrace(org.teiid.logging.LogConstants.CTX_DQP, "Processing ErrorInstruction with the value :", value); //$NON-NLS-1$
- if (value instanceof SQLWarning) {
- env.getContext().addWarning((Exception)value);
- return;
- }
- throw new ProcedureErrorInstructionException(QueryPlugin.Event.TEIID30167, (Exception) value);
+ LogManager.logTrace(org.teiid.logging.LogConstants.CTX_DQP, "Processing RAISE with the value :", value); //$NON-NLS-1$
+ if (warning) {
+ env.getContext().addWarning((Exception)value);
+ return;
+ }
+ if (value == null) {
+ throw new TeiidProcessingException();
+ }
+ throw TeiidSQLException.create((Exception)value);
}
}
\ No newline at end of file
Modified: trunk/engine/src/main/java/org/teiid/query/processor/proc/IfInstruction.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/proc/IfInstruction.java 2012-09-25 18:56:07 UTC (rev 4470)
+++ trunk/engine/src/main/java/org/teiid/query/processor/proc/IfInstruction.java 2012-09-25 18:58:05 UTC (rev 4471)
@@ -24,14 +24,11 @@
import static org.teiid.query.analysis.AnalysisRecord.*;
-import java.util.List;
-
import org.teiid.client.plan.PlanNode;
import org.teiid.common.buffer.BlockedException;
import org.teiid.core.TeiidComponentException;
import org.teiid.core.TeiidProcessingException;
import org.teiid.logging.LogManager;
-import org.teiid.query.processor.ProcessorPlan;
import org.teiid.query.sql.lang.Criteria;
@@ -118,10 +115,10 @@
* Returns a deep clone
*/
public IfInstruction clone(){
- Program cloneIf = (Program) this.ifProgram.clone();
+ Program cloneIf = this.ifProgram.clone();
Program cloneElse = null;
if(elseProgram != null) {
- cloneElse = (Program) this.elseProgram.clone();
+ cloneElse = this.elseProgram.clone();
}
IfInstruction clone = new IfInstruction(this.condition, cloneIf, cloneElse);
return clone;
@@ -141,12 +138,4 @@
return props;
}
- @Override
- public void getChildPlans(List<ProcessorPlan> plans) {
- ifProgram.getChildPlans(plans);
- if (elseProgram != null) {
- elseProgram.getChildPlans(plans);
- }
- }
-
}
Modified: trunk/engine/src/main/java/org/teiid/query/processor/proc/LoopInstruction.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/proc/LoopInstruction.java 2012-09-25 18:56:07 UTC (rev 4470)
+++ trunk/engine/src/main/java/org/teiid/query/processor/proc/LoopInstruction.java 2012-09-25 18:58:05 UTC (rev 4471)
@@ -122,10 +122,4 @@
procEnv.removeResults(rsName);
}
- @Override
- public void getChildPlans(List<ProcessorPlan> plans) {
- super.getChildPlans(plans);
- this.loopProgram.getChildPlans(plans);
- }
-
}
Modified: trunk/engine/src/main/java/org/teiid/query/processor/proc/ProcedurePlan.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/proc/ProcedurePlan.java 2012-09-25 18:56:07 UTC (rev 4470)
+++ trunk/engine/src/main/java/org/teiid/query/processor/proc/ProcedurePlan.java 2012-09-25 18:58:05 UTC (rev 4471)
@@ -37,6 +37,7 @@
import org.teiid.api.exception.query.QueryMetadataException;
import org.teiid.api.exception.query.QueryValidatorException;
+import org.teiid.client.ProcedureErrorInstructionException;
import org.teiid.client.plan.PlanNode;
import org.teiid.client.xa.XATransactionException;
import org.teiid.common.buffer.BlockedException;
@@ -56,6 +57,7 @@
import org.teiid.dqp.service.TransactionService;
import org.teiid.dqp.service.TransactionContext.Scope;
import org.teiid.events.EventDistributor;
+import org.teiid.jdbc.TeiidSQLException;
import org.teiid.logging.LogConstants;
import org.teiid.logging.LogManager;
import org.teiid.query.QueryPlugin;
@@ -69,11 +71,13 @@
import org.teiid.query.processor.QueryProcessor;
import org.teiid.query.processor.RegisterRequestParameter;
import org.teiid.query.processor.relational.SubqueryAwareEvaluator;
+import org.teiid.query.resolver.command.UpdateProcedureResolver;
import org.teiid.query.sql.ProcedureReservedWords;
import org.teiid.query.sql.lang.Command;
import org.teiid.query.sql.lang.Criteria;
import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.sql.symbol.Expression;
+import org.teiid.query.sql.symbol.GroupSymbol;
import org.teiid.query.sql.util.VariableContext;
import org.teiid.query.tempdata.TempTableStore;
import org.teiid.query.util.CommandContext;
@@ -357,21 +361,61 @@
this.pop(true);
continue;
}
- if (inst instanceof RepeatedInstruction) {
- LogManager.logTrace(org.teiid.logging.LogConstants.CTX_DQP, "Executing repeated instruction", inst); //$NON-NLS-1$
- RepeatedInstruction loop = (RepeatedInstruction)inst;
- if (loop.testCondition(this)) {
- LogManager.logTrace(org.teiid.logging.LogConstants.CTX_DQP, "Passed condition, executing program " + loop.getNestedProgram()); //$NON-NLS-1$
- inst.process(this);
- this.push(loop.getNestedProgram());
- continue;
- }
- LogManager.logTrace(org.teiid.logging.LogConstants.CTX_DQP, "Exiting repeated instruction", inst); //$NON-NLS-1$
- loop.postInstruction(this);
- } else {
- LogManager.logTrace(org.teiid.logging.LogConstants.CTX_DQP, "Executing instruction", inst); //$NON-NLS-1$
- inst.process(this);
- }
+ try {
+ if (inst instanceof RepeatedInstruction) {
+ LogManager.logTrace(org.teiid.logging.LogConstants.CTX_DQP, "Executing repeated instruction", inst); //$NON-NLS-1$
+ RepeatedInstruction loop = (RepeatedInstruction)inst;
+ if (loop.testCondition(this)) {
+ LogManager.logTrace(org.teiid.logging.LogConstants.CTX_DQP, "Passed condition, executing program " + loop.getNestedProgram()); //$NON-NLS-1$
+ inst.process(this);
+ this.push(loop.getNestedProgram());
+ continue;
+ }
+ LogManager.logTrace(org.teiid.logging.LogConstants.CTX_DQP, "Exiting repeated instruction", inst); //$NON-NLS-1$
+ loop.postInstruction(this);
+ } else {
+ LogManager.logTrace(org.teiid.logging.LogConstants.CTX_DQP, "Executing instruction", inst); //$NON-NLS-1$
+ inst.process(this);
+ }
+ } catch (Exception e) {
+ if (e instanceof BlockedException) {
+ throw (BlockedException)e;
+ }
+ while (program.getExceptionGroup() == null) {
+ this.pop(false);
+ if (this.programs.empty()) {
+ //reached the top without a handler, so throw
+ if (e instanceof RuntimeException) {
+ throw (RuntimeException)e;
+ }
+ if (e instanceof TeiidComponentException) {
+ throw (TeiidComponentException)e;
+ }
+ if (e instanceof TeiidProcessingException) {
+ throw (TeiidProcessingException)e;
+ }
+ throw new ProcedureErrorInstructionException(QueryPlugin.Event.TEIID30167, e);
+ }
+ program = peek();
+ }
+ //assign variables
+ if (program.getExceptionProgram() == null) {
+ this.pop(true);
+ continue;
+ }
+ Program exceptionProgram = program.getExceptionProgram();
+ exceptionProgram.setStartedTxn(program.startedTxn());
+ this.pop(null); //all the current program to go out of scope
+ this.push(exceptionProgram);
+ TeiidSQLException tse = TeiidSQLException.create(e);
+ GroupSymbol gs = new GroupSymbol(program.getExceptionGroup());
+ this.currentVarContext.setValue(exceptionSymbol(gs, 0), tse.getSQLState());
+ this.currentVarContext.setValue(exceptionSymbol(gs, 1), tse.getErrorCode());
+ this.currentVarContext.setValue(exceptionSymbol(gs, 2), tse.getTeiidCode());
+ this.currentVarContext.setValue(exceptionSymbol(gs, 3), tse);
+ this.currentVarContext.setValue(exceptionSymbol(gs, 4), tse.getCause());
+ continue;
+ }
program.incrementProgramCounter();
}
@@ -381,6 +425,12 @@
return lastTupleSource;
}
+ private ElementSymbol exceptionSymbol(GroupSymbol gs, int pos) {
+ ElementSymbol es = UpdateProcedureResolver.exceptionGroup.get(pos).clone();
+ es.setGroupSymbol(gs);
+ return es;
+ }
+
public void close()
throws TeiidComponentException {
if (!this.cursorStates.isEmpty()) {
@@ -409,7 +459,7 @@
}
public ProcessorPlan clone(){
- ProcedurePlan plan = new ProcedurePlan((Program)originalProgram.clone());
+ ProcedurePlan plan = new ProcedurePlan(originalProgram.clone());
plan.setOutputElements(this.getOutputElements());
plan.setParams(params);
plan.setOutParams(outParams);
@@ -565,13 +615,13 @@
* @throws TeiidComponentException
* @throws XATransactionException
*/
- public void pop(boolean success) throws TeiidComponentException {
+ public void pop(Boolean success) throws TeiidComponentException {
Program program = this.programs.pop();
if (this.currentVarContext.getParentContext() != null) {
this.currentVarContext = this.currentVarContext.getParentContext();
}
program.getTempTableStore().removeTempTables();
- if (program.startedTxn() && this.blockContext != null) {
+ if (success != null && program.startedTxn() && this.blockContext != null) {
TransactionService ts = this.getContext().getTransactionServer();
TransactionContext tc = this.blockContext;
this.blockContext = null;
Modified: trunk/engine/src/main/java/org/teiid/query/processor/proc/Program.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/proc/Program.java 2012-09-25 18:56:07 UTC (rev 4470)
+++ trunk/engine/src/main/java/org/teiid/query/processor/proc/Program.java 2012-09-25 18:58:05 UTC (rev 4471)
@@ -26,7 +26,6 @@
import java.util.List;
import org.teiid.client.plan.PlanNode;
-import org.teiid.query.processor.ProcessorPlan;
import org.teiid.query.sql.proc.Statement.Labeled;
import org.teiid.query.tempdata.TempTableStore;
import org.teiid.query.tempdata.TempTableStore.TransactionMode;
@@ -45,6 +44,8 @@
private String label;
private TempTableStore tempTables;
private boolean startedTxn;
+ private String exceptionGroup;
+ private Program exceptionProgram;
/**
* Constructor for Program.
@@ -149,7 +150,7 @@
/**
* Produces a deep clone.
*/
- public Object clone(){
+ public Program clone(){
Program program = new Program(atomic);
program.counter = this.counter;
@@ -161,12 +162,18 @@
program.programInstructions = clonedInstructions;
}
program.label = label;
+ program.exceptionGroup = this.exceptionGroup;
+ if (this.exceptionProgram != null) {
+ program.exceptionProgram = this.exceptionProgram.clone();
+ }
return program;
}
public PlanNode getDescriptionProperties() {
PlanNode props = new PlanNode("Program"); //$NON-NLS-1$
-
+ if (label != null) {
+ props.addProperty("Label", label); //$NON-NLS-1$
+ }
if(this.programInstructions != null) {
for (int i = 0; i < programInstructions.size(); i++) {
ProgramInstruction inst = programInstructions.get(i);
@@ -174,6 +181,13 @@
props.addProperty("Instruction " + i, childProps); //$NON-NLS-1$
}
}
+
+ if (this.exceptionGroup != null) {
+ props.addProperty("EXCEPTION GROUP", this.exceptionGroup); //$NON-NLS-1$
+ if (this.exceptionProgram != null) {
+ props.addProperty("EXCEPTION HANDLER", this.exceptionProgram.getDescriptionProperties()); //$NON-NLS-1$
+ }
+ }
return props;
}
@@ -207,7 +221,12 @@
StringBuilder str = new StringBuilder();
programToString(str);
-
+ if (exceptionGroup != null) {
+ str.append("\nEXCEPTION ").append(exceptionGroup).append("\n"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ if (exceptionProgram != null) {
+ exceptionProgram.programToString(str);
+ }
return "PROGRAM counter " + this.counter + "\n" + str.toString(); //$NON-NLS-1$ //$NON-NLS-2$
}
@@ -248,11 +267,21 @@
buffer.append(counterStr + line + "\n"); //$NON-NLS-1$
}
-
- void getChildPlans(List<ProcessorPlan> plans) {
- for (ProgramInstruction instruction : programInstructions) {
- instruction.getChildPlans(plans);
- }
- }
+
+ public void setExceptionGroup(String exceptionGroup) {
+ this.exceptionGroup = exceptionGroup;
+ }
+
+ public void setExceptionProgram(Program exceptionBlock) {
+ this.exceptionProgram = exceptionBlock;
+ }
+
+ public String getExceptionGroup() {
+ return exceptionGroup;
+ }
+
+ public Program getExceptionProgram() {
+ return exceptionProgram;
+ }
}
Modified: trunk/engine/src/main/java/org/teiid/query/processor/proc/ProgramInstruction.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/proc/ProgramInstruction.java 2012-09-25 18:56:07 UTC (rev 4470)
+++ trunk/engine/src/main/java/org/teiid/query/processor/proc/ProgramInstruction.java 2012-09-25 18:58:05 UTC (rev 4471)
@@ -22,12 +22,10 @@
package org.teiid.query.processor.proc;
-import java.util.List;
-
import org.teiid.client.plan.PlanNode;
import org.teiid.core.TeiidComponentException;
import org.teiid.core.TeiidProcessingException;
-import org.teiid.query.processor.ProcessorPlan;
+import org.teiid.jdbc.TeiidSQLException;
/**
@@ -50,19 +48,12 @@
* in turn manipulate the running program. A typical instruction should simply {@link
* Program#incrementProgramCounter increment} the program counter of the current program, but specialized
* instructions may add sub programs to the stack or not increment the counter (so that they are executed again.)
+ * @throws TeiidSQLException
*/
public abstract void process(ProcedurePlan env)
- throws TeiidComponentException, TeiidProcessingException;
+ throws TeiidComponentException, TeiidProcessingException, TeiidSQLException;
/**
- * Finds all nested plans and returns them.
- * @return List of ProcessorPlan
- * @since 4.2
- */
- public void getChildPlans(List<ProcessorPlan> plans) {
- }
-
- /**
* Override Object.clone() to make the method public. This method
* simply calls super.clone(), deferring to the default shallow
* cloning. Some ProcessorInstruction subclasses may need to
Modified: trunk/engine/src/main/java/org/teiid/query/processor/proc/WhileInstruction.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/proc/WhileInstruction.java 2012-09-25 18:56:07 UTC (rev 4470)
+++ trunk/engine/src/main/java/org/teiid/query/processor/proc/WhileInstruction.java 2012-09-25 18:58:05 UTC (rev 4471)
@@ -26,12 +26,9 @@
import static org.teiid.query.analysis.AnalysisRecord.*;
-import java.util.List;
-
import org.teiid.client.plan.PlanNode;
import org.teiid.core.TeiidComponentException;
import org.teiid.core.TeiidProcessingException;
-import org.teiid.query.processor.ProcessorPlan;
import org.teiid.query.sql.lang.Criteria;
@@ -73,7 +70,7 @@
* Returns a deep clone
*/
public WhileInstruction clone(){
- return new WhileInstruction((Program)this.whileProgram.clone(), this.condition, this.label);
+ return new WhileInstruction(this.whileProgram.clone(), this.condition, this.label);
}
public String toString() {
@@ -104,9 +101,4 @@
public void postInstruction(ProcedurePlan procEnv) throws TeiidComponentException {
}
- @Override
- public void getChildPlans(List<ProcessorPlan> plans) {
- whileProgram.getChildPlans(plans);
- }
-
}
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateProcedureResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateProcedureResolver.java 2012-09-25 18:56:07 UTC (rev 4470)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateProcedureResolver.java 2012-09-25 18:58:05 UTC (rev 4471)
@@ -35,6 +35,7 @@
import org.teiid.core.TeiidComponentException;
import org.teiid.core.types.DataTypeManager;
import org.teiid.language.SQLConstants;
+import org.teiid.language.SQLConstants.NonReserved;
import org.teiid.logging.LogManager;
import org.teiid.query.QueryPlugin;
import org.teiid.query.metadata.SupportConstants;
@@ -71,6 +72,21 @@
List<StatementNode> children;
}
+ public static final List<ElementSymbol> exceptionGroup;
+ static {
+ ElementSymbol es1 = new ElementSymbol("STATE"); //$NON-NLS-1$
+ es1.setType(DataTypeManager.DefaultDataClasses.STRING);
+ ElementSymbol es2 = new ElementSymbol("ERRORCODE"); //$NON-NLS-1$
+ es2.setType(DataTypeManager.DefaultDataClasses.INTEGER);
+ ElementSymbol es3 = new ElementSymbol("TEIIDCODE"); //$NON-NLS-1$
+ es3.setType(DataTypeManager.DefaultDataClasses.STRING);
+ ElementSymbol es4 = new ElementSymbol(NonReserved.EXCEPTION);
+ es4.setType(Exception.class);
+ ElementSymbol es5 = new ElementSymbol(NonReserved.CHAIN);
+ es5.setType(Exception.class);
+ exceptionGroup = Arrays.asList(es1, es2, es3, es4, es5);
+ }
+
/**
* @see org.teiid.query.resolver.CommandResolver#resolveCommand(org.teiid.query.sql.lang.Command, TempMetadataAdapter, boolean)
*/
@@ -145,6 +161,24 @@
for (Statement statement : block.getStatements()) {
resolveStatement(command, statement, externalGroups, variables, metadata, sn);
}
+
+ if (block.getExceptionGroup() != null) {
+ //create a new variable and metadata context for this block so that discovered metadata is not visible else where
+ store = metadata.getMetadataStore().clone();
+ metadata = new TempMetadataAdapter(metadata.getMetadata(), store);
+ externalGroups = new GroupContext(externalGroups, null);
+
+ //create a new variables group for this block
+ variables = ProcedureContainerResolver.addScalarGroup(ProcedureReservedWords.VARIABLES, store, externalGroups, new LinkedList<Expression>());
+ isValidGroup(metadata, block.getExceptionGroup());
+
+ if (block.getExceptionStatements() != null) {
+ ProcedureContainerResolver.addScalarGroup(block.getExceptionGroup(), store, externalGroups, exceptionGroup, false);
+ for (Statement statement : block.getExceptionStatements()) {
+ resolveStatement(command, statement, externalGroups, variables, metadata, sn);
+ }
+ }
+ }
}
private void resolveStatement(CreateProcedureCommand command, Statement statement, GroupContext externalGroups, GroupSymbol variables, TempMetadataAdapter metadata, StatementNode sn)
@@ -208,12 +242,7 @@
//this could be the last select statement, set the projected symbol
//on the virtual procedure command
if (subCommand.returnsResultSet() && sn != null) {
- updateDynamicAs(sn);
-
- sn.cs = cmdStmt;
- if (sn.children != null) {
- sn.children.clear();
- }
+ clearReturnableStatement(sn, cmdStmt);
}
break;
@@ -254,6 +283,9 @@
exprStmt.setExpression(ResolverUtil.convertExpression(exprStmt.getExpression(), varTypeName, metadata));
if (statement.getType() == Statement.TYPE_ERROR) {
ResolverVisitor.checkException(exprStmt.getExpression());
+ if (!((RaiseStatement)statement).isWarning()) {
+ clearReturnableStatement(sn, null);
+ }
}
}
break;
@@ -270,15 +302,7 @@
LoopStatement loopStmt = (LoopStatement) statement;
String groupName = loopStmt.getCursorName();
- if (metadata.getMetadataStore().getTempGroupID(groupName) != null) {
- throw new QueryResolverException(QueryPlugin.Event.TEIID30124, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30124));
- }
-
- //check - cursor name should not start with #
- if(GroupSymbol.isTempGroupName(loopStmt.getCursorName())){
- String errorMsg = QueryPlugin.Util.getString("ResolveVariablesVisitor.reserved_word_for_temporary_used", loopStmt.getCursorName()); //$NON-NLS-1$
- throw new QueryResolverException(QueryPlugin.Event.TEIID30125, errorMsg);
- }
+ isValidGroup(metadata, groupName);
Command cmd = loopStmt.getCommand();
resolveEmbeddedCommand(metadata, externalGroups, cmd);
List<Expression> symbols = cmd.getProjectedSymbols();
@@ -295,6 +319,28 @@
}
}
+ private void clearReturnableStatement(StatementNode sn,
+ CommandStatement cmdStmt) {
+ updateDynamicAs(sn);
+
+ sn.cs = cmdStmt;
+ if (sn.children != null) {
+ sn.children.clear();
+ }
+ }
+
+ private void isValidGroup(TempMetadataAdapter metadata, String groupName)
+ throws QueryResolverException {
+ if (metadata.getMetadataStore().getTempGroupID(groupName) != null) {
+ throw new QueryResolverException(QueryPlugin.Event.TEIID30124, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30124, groupName));
+ }
+
+ //check - cursor name should not start with #
+ if(GroupSymbol.isTempGroupName(groupName)){
+ throw new QueryResolverException(QueryPlugin.Event.TEIID30125, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30125, groupName));
+ }
+ }
+
private void updateDynamicAs(StatementNode sn) {
if (sn.cs != null && sn.cs.getCommand().getType() == Command.TYPE_DYNAMIC) {
DynamicCommand dynamicCommand = (DynamicCommand)sn.cs.getCommand();
Modified: trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java 2012-09-25 18:56:07 UTC (rev 4470)
+++ trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java 2012-09-25 18:58:05 UTC (rev 4471)
@@ -242,20 +242,27 @@
private Block rewriteBlock(Block block)
throws TeiidComponentException, TeiidProcessingException{
List<Statement> statements = block.getStatements();
- Iterator<Statement> stmtIter = statements.iterator();
+ List<Statement> newStmts = rewriteStatements(statements);
+ block.setStatements(newStmts);
+ if (block.getExceptionStatements() != null) {
+ block.setExceptionStatements(rewriteStatements(block.getExceptionStatements()));
+ }
+ return block;
+ }
+ private List<Statement> rewriteStatements(List<Statement> statements)
+ throws TeiidComponentException, TeiidProcessingException {
+ Iterator<Statement> stmtIter = statements.iterator();
+
List<Statement> newStmts = new ArrayList<Statement>(statements.size());
// plan each statement in the block
while(stmtIter.hasNext()) {
Statement stmnt = stmtIter.next();
rewriteStatement(stmnt, newStmts);
}
+ return newStmts;
+ }
- block.setStatements(newStmts);
-
- return block;
- }
-
private void rewriteStatement(Statement statement, List<Statement> newStmts)
throws TeiidComponentException, TeiidProcessingException{
Modified: trunk/engine/src/main/java/org/teiid/query/sql/navigator/PreOrPostOrderNavigator.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/navigator/PreOrPostOrderNavigator.java 2012-09-25 18:56:07 UTC (rev 4470)
+++ trunk/engine/src/main/java/org/teiid/query/sql/navigator/PreOrPostOrderNavigator.java 2012-09-25 18:58:05 UTC (rev 4471)
@@ -103,6 +103,7 @@
public void visit(Block obj) {
preVisitVisitor(obj);
visitNodes(obj.getStatements());
+ visitNodes(obj.getExceptionStatements());
postVisitVisitor(obj);
}
public void visit(BranchingStatement obj) {
Modified: trunk/engine/src/main/java/org/teiid/query/sql/proc/Block.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/proc/Block.java 2012-09-25 18:56:07 UTC (rev 4470)
+++ trunk/engine/src/main/java/org/teiid/query/sql/proc/Block.java 2012-09-25 18:58:05 UTC (rev 4471)
@@ -27,6 +27,7 @@
import org.teiid.core.util.EquivalenceUtil;
import org.teiid.core.util.StringUtil;
+import org.teiid.query.sql.LanguageObject;
import org.teiid.query.sql.LanguageVisitor;
import org.teiid.query.sql.ProcedureReservedWords;
import org.teiid.query.sql.lang.Command;
@@ -46,6 +47,9 @@
private List<Statement> statements;
private boolean atomic;
private String label;
+
+ private String exceptionGroup;
+ private List<Statement> exceptionStatements;
/**
* Constructor for Block.
@@ -92,11 +96,15 @@
* @param statement The <code>Statement</code> to be added to the block
*/
public void addStatement(Statement statement) {
+ addStatement(statement, false);
+ }
+
+ public void addStatement(Statement statement, boolean exception) {
if (statement instanceof AssignmentStatement) {
AssignmentStatement stmt = (AssignmentStatement)statement;
Command cmd = stmt.getCommand();
if (cmd != null) {
- statements.add(new CommandStatement(cmd));
+ internalAddStatement(new CommandStatement(cmd), exception);
stmt.setCommand(null);
stmt.setExpression(null);
if (stmt.getVariable().getShortName().equalsIgnoreCase(ProcedureReservedWords.ROWCOUNT)
@@ -107,8 +115,19 @@
stmt.setExpression(new ElementSymbol(fullName));
}
}
- statements.add(statement);
+ internalAddStatement(statement, exception);
}
+
+ private void internalAddStatement(Statement statement, boolean exception) {
+ if (exception) {
+ if (this.exceptionStatements == null) {
+ exceptionStatements = new ArrayList<Statement>();
+ }
+ exceptionStatements.add(statement);
+ } else {
+ statements.add(statement);
+ }
+ }
// =========================================================================
// P R O C E S S I N G M E T H O D S
@@ -125,9 +144,11 @@
public Block clone() {
Block copy = new Block();
copy.setAtomic(atomic);
- for (Statement statement : statements) {
- copy.addStatement((Statement)statement.clone());
+ copy.statements = LanguageObject.Util.deepClone(statements, Statement.class);
+ if (exceptionStatements != null) {
+ copy.exceptionStatements = LanguageObject.Util.deepClone(exceptionStatements, Statement.class);
}
+ copy.exceptionGroup = this.exceptionGroup;
copy.setLabel(label);
return copy;
}
@@ -154,7 +175,9 @@
// Compare the statements on the block
return this.atomic == other.atomic
&& StringUtil.equalsIgnoreCase(label, other.label)
- && EquivalenceUtil.areEqual(getStatements(), other.getStatements());
+ && EquivalenceUtil.areEqual(getStatements(), other.getStatements())
+ && EquivalenceUtil.areEqual(exceptionGroup, exceptionGroup)
+ && EquivalenceUtil.areEqual(exceptionStatements, exceptionStatements);
}
/**
@@ -188,5 +211,21 @@
public int getType() {
return Statement.TYPE_COMPOUND;
}
+
+ public String getExceptionGroup() {
+ return exceptionGroup;
+ }
+
+ public void setExceptionGroup(String exceptionGroup) {
+ this.exceptionGroup = exceptionGroup;
+ }
+
+ public List<Statement> getExceptionStatements() {
+ return exceptionStatements;
+ }
+
+ public void setExceptionStatements(List<Statement> exceptionStatements) {
+ this.exceptionStatements = exceptionStatements;
+ }
}// END CLASS
Modified: trunk/engine/src/main/java/org/teiid/query/sql/proc/ExceptionExpression.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/proc/ExceptionExpression.java 2012-09-25 18:56:07 UTC (rev 4470)
+++ trunk/engine/src/main/java/org/teiid/query/sql/proc/ExceptionExpression.java 2012-09-25 18:58:05 UTC (rev 4471)
@@ -36,7 +36,6 @@
private Expression sqlState;
private Expression errorCode;
private Expression parent;
- private boolean warning;
@Override
public Class<?> getType() {
@@ -58,13 +57,12 @@
return EquivalenceUtil.areEqual(message, other.message)
&& EquivalenceUtil.areEqual(sqlState, other.sqlState)
&& EquivalenceUtil.areEqual(errorCode, other.errorCode)
- && EquivalenceUtil.areEqual(parent, other.parent)
- && warning == other.warning;
+ && EquivalenceUtil.areEqual(parent, other.parent);
}
@Override
public int hashCode() {
- return HashCodeUtil.hashCode(warning?0:1, message, sqlState, errorCode);
+ return HashCodeUtil.hashCode(0, message, sqlState, errorCode);
}
@Override
@@ -75,7 +73,6 @@
@Override
public ExceptionExpression clone() {
ExceptionExpression clone = new ExceptionExpression();
- clone.warning = this.warning;
if (this.message != null) {
clone.message = (Expression) this.message.clone();
}
@@ -123,23 +120,12 @@
this.parent = parent;
}
- public boolean isWarning() {
- return warning;
- }
-
- public void setWarning(boolean warning) {
- this.warning = warning;
- }
-
@Override
public void acceptVisitor(LanguageVisitor visitor) {
visitor.visit(this);
}
public String getDefaultSQLState() {
- if (isWarning()) {
- return "01000";
- }
return "50001";
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/proc/RaiseStatement.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/proc/RaiseStatement.java 2012-09-25 18:56:07 UTC (rev 4470)
+++ trunk/engine/src/main/java/org/teiid/query/sql/proc/RaiseStatement.java 2012-09-25 18:58:05 UTC (rev 4471)
@@ -35,6 +35,7 @@
public class RaiseStatement extends Statement implements ExpressionStatement {
private Expression expression;
+ private boolean warning;
public RaiseStatement() {
}
@@ -46,6 +47,11 @@
public RaiseStatement(Expression message) {
expression = message;
}
+
+ public RaiseStatement(Expression message, boolean warning) {
+ expression = message;
+ this.warning = warning;
+ }
public void acceptVisitor(LanguageVisitor visitor) {
visitor.visit(this);
@@ -65,7 +71,7 @@
@Override
public RaiseStatement clone() {
- return new RaiseStatement((Expression) this.expression.clone());
+ return new RaiseStatement((Expression) this.expression.clone(), warning);
}
@Override
@@ -84,12 +90,20 @@
RaiseStatement other = (RaiseStatement)obj;
- return other.expression.equals(this.expression);
+ return other.expression.equals(this.expression) && this.warning == other.warning;
}
@Override
public Class<?> getExpectedType() {
return DataTypeManager.DefaultDataClasses.OBJECT;
}
+
+ public boolean isWarning() {
+ return warning;
+ }
+
+ public void setWarning(boolean warning) {
+ this.warning = warning;
+ }
} // END CLASS
\ No newline at end of file
Modified: trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java 2012-09-25 18:56:07 UTC (rev 4470)
+++ trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java 2012-09-25 18:58:05 UTC (rev 4471)
@@ -47,6 +47,7 @@
import org.teiid.query.sql.lang.TextTable.TextColumn;
import org.teiid.query.sql.lang.XMLTable.XMLColumn;
import org.teiid.query.sql.proc.*;
+import org.teiid.query.sql.proc.BranchingStatement.BranchingMode;
import org.teiid.query.sql.proc.Statement.Labeled;
import org.teiid.query.sql.symbol.*;
import org.teiid.query.sql.symbol.AggregateSymbol.Type;
@@ -1376,7 +1377,21 @@
append(ATOMIC);
}
append("\n"); //$NON-NLS-1$
- Iterator<Statement> stmtIter = statements.iterator();
+ addStatements(statements);
+ if (obj.getExceptionGroup() != null) {
+ append(NonReserved.EXCEPTION);
+ append(SPACE);
+ outputDisplayName(obj.getExceptionGroup());
+ append("\n"); //$NON-NLS-1$
+ if (obj.getExceptionStatements() != null) {
+ addStatements(obj.getExceptionStatements());
+ }
+ }
+ append(END);
+ }
+
+ private void addStatements(List<Statement> statements) {
+ Iterator<Statement> stmtIter = statements.iterator();
while (stmtIter.hasNext()) {
// Add each statement
addTabs(1);
@@ -1384,8 +1399,7 @@
append("\n"); //$NON-NLS-1$
}
addTabs(0);
- append(END);
- }
+ }
private void addLabel(Labeled obj) {
if (obj.getLabel() != null) {
@@ -1464,17 +1478,17 @@
public void visit( RaiseStatement obj ) {
append(NonReserved.RAISE);
append(SPACE);
+ if (obj.isWarning()) {
+ append(SQLWARNING);
+ append(SPACE);
+ }
visitNode(obj.getExpression());
append(";"); //$NON-NLS-1$
}
@Override
public void visit(ExceptionExpression exceptionExpression) {
- if (exceptionExpression.isWarning()) {
- append(SQLWARNING);
- } else {
- append(SQLEXCEPTION);
- }
+ append(SQLEXCEPTION);
append(SPACE);
visitNode(exceptionExpression.getMessage());
if (exceptionExpression.getSqlState() != null) {
@@ -1490,7 +1504,7 @@
}
if (exceptionExpression.getParent() != null) {
append(SPACE);
- append(NonReserved.EXCEPTION);
+ append(NonReserved.CHAIN);
append(SPACE);
append(exceptionExpression.getParent());
}
@@ -1525,7 +1539,7 @@
append(") "); //$NON-NLS-1$
append(AS);
append(" "); //$NON-NLS-1$
- append(obj.getCursorName());
+ outputDisplayName(obj.getCursorName());
append("\n"); //$NON-NLS-1$
addTabs(0);
visitNode(obj.getBlock());
Modified: trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
===================================================================
--- trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2012-09-25 18:56:07 UTC (rev 4470)
+++ trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2012-09-25 18:58:05 UTC (rev 4471)
@@ -457,6 +457,7 @@
| <VARIADIC: "variadic">
| <EXCEPTION: "exception">
| <RAISE: "raise">
+| <CHAIN: "chain">
}
/*
@@ -564,7 +565,7 @@
|<TO_BYTES>|<TIMESTAMPADD>|<TIMESTAMPDIFF>|<QUERYSTRING>|<NAMESPACE>|<RESULT>|<INDEX>|<ACCESSPATTERN>|<AUTO_INCREMENT>|<WELLFORMED>|<SQL_TSI_FRAC_SECOND>
|<SQL_TSI_SECOND>|<SQL_TSI_MINUTE>|<SQL_TSI_HOUR>|<SQL_TSI_DAY>|<SQL_TSI_WEEK>|<SQL_TSI_MONTH>|<SQL_TSI_QUARTER>|<SQL_TSI_YEAR>|<TEXTTABLE>|<ARRAYTABLE>
|<SELECTOR>|<SKIP_KEYWORD>|<WIDTH>|<PASSING>|<NAME>|<ENCODING>|<COLUMNS>|<DELIMITER>|<QUOTE>|<HEADER>|<NULLS>|<OBJECTTABLE>
- |<VERSION>|<INCLUDING>|<EXCLUDING>|<XMLDECLARATION>|<VARIADIC>|<RAISE>|<EXCEPTION>)
+ |<VERSION>|<INCLUDING>|<EXCLUDING>|<XMLDECLARATION>|<VARIADIC>|<RAISE>|<EXCEPTION>|<CHAIN>)
{
return getToken(0);
}
@@ -910,12 +911,14 @@
RaiseStatement raiseStatement(ParseInfo info) :
{
Expression err = null;
+ boolean warning = false;
}
{
<RAISE>
+ [<SQLWARNING> {warning = true;}]
err = exceptionReference(info)
{
- return new RaiseStatement(err);
+ return new RaiseStatement(err, warning);
}
}
@@ -949,22 +952,20 @@
Expression sqlState = null;
Expression errCode = null;
Expression parent = null;
- boolean warning = false;
}
{
- (<SQLWARNING> {warning=true;}|<SQLEXCEPTION>)
+ <SQLEXCEPTION>
err = commonValueExpression(info)
[<SQLSTATE> sqlState = commonValueExpression(info)
[<COMMA> errCode = commonValueExpression(info)]
]
- [<EXCEPTION> parent = exceptionReference(info)]
+ [<CHAIN> parent = exceptionReference(info)]
{
ExceptionExpression ee = new ExceptionExpression();
ee.setMessage(err);
ee.setSqlState(sqlState);
ee.setErrorCode(errCode);
ee.setParent(parent);
- ee.setWarning(warning);
return ee;
}
}
@@ -1013,7 +1014,7 @@
Statement stmt = null;
}
{
- (stmt = assignStatement(info) |
+ (LOOKAHEAD(2) stmt = assignStatement(info) |
stmt = sqlStatement(info) |
stmt = errorStatement(info) |
stmt = raiseStatement(info) |
@@ -1036,15 +1037,24 @@
Statement stmt = null;
Block block = new Block();
Boolean atomic = null;
+ String eId = null;
}
{
<BEGIN> [[<NOT> {atomic = Boolean.FALSE;}] <ATOMIC> {if (atomic == null) {atomic = Boolean.TRUE;}}]
- (
+ (LOOKAHEAD(2)
stmt = statement(info)
{
- block.addStatement(stmt);
+ block.addStatement(stmt, false);
}
)*
+ [<EXCEPTION> eId = id() {block.setExceptionGroup(validateAlias(eId));}
+ (
+ stmt = statement(info)
+ {
+ block.addStatement(stmt, true);
+ }
+ )*
+ ]
<END>
{
if (atomic != null) {
@@ -1200,13 +1210,13 @@
Statement assignStatement(ParseInfo info) :
{
LanguageObject value = null;
- Token var = null;
+ String var = null;
ElementSymbol elementID = null;
}
{
- var = <ID>
+ var = id()
{
- elementID = new ElementSymbol(normalizeId(var.image));
+ elementID = new ElementSymbol(var);
}
[<COLON>]<EQ>
(value = assignStatementOperand(info) |
Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2012-09-25 18:56:07 UTC (rev 4470)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2012-09-25 18:58:05 UTC (rev 4471)
@@ -210,7 +210,7 @@
ERR.015.012.0062 = Elements cannot appear more than once in a SET or USING clause. The following elements are duplicated: {0}
ERR.015.012.0063 = Multiple failures occurred during validation:
ERR.015.012.0064 = Validation succeeded
-TEIID30124=Nested Loop can not use the same cursor name as that of its parent.
+TEIID30124=Loop cursor or exception group name {0} already exists.
ERR.015.012.0067 = No scalar subqueries are allowed in the SELECT with no FROM clause.
ERR.015.012.0069 = INTO clause can not be used in XML query.
@@ -673,7 +673,7 @@
QueryResolver.invalid_xpath=Invalid xpath value: {0}
TEIID30066=The definition for {0} does not have the correct number of projected symbols. Expected {1}, but was {2}.
QueryResolver.wrong_view_symbol_type=The definition for {0} has the wrong type for column {1}. Expected {2}, but was {3}.
-ResolveVariablesVisitor.reserved_word_for_temporary_used=Cursor names cannot begin with "#" as that indicates the name of a temporary table: {0}.
+TEIID30125=Cursor or exception group names cannot begin with "#" as that indicates the name of a temporary table: {0}.
SimpleQueryResolver.materialized_table_not_used=The query against {0} did not use materialization table {1} due to the use of OPTION NOCACHE.
SimpleQueryResolver.cache_hint_used=Loading materialized view {1} for view {0} using cache hint {2}.
SimpleQueryResolver.procedure_cache_used=Procedure caching will be used for {0}.
Modified: trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java 2012-09-25 18:56:07 UTC (rev 4470)
+++ trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java 2012-09-25 18:58:05 UTC (rev 4471)
@@ -3021,12 +3021,11 @@
@Test public void testRaiseErrorStatement() throws Exception {
ExceptionExpression ee = new ExceptionExpression();
ee.setMessage(new Constant("Test only"));
- ee.setWarning(true);
ee.setSqlState(new Constant("100"));
ee.setParent(new ElementSymbol("e"));
- RaiseStatement errStmt = new RaiseStatement(ee);
+ RaiseStatement errStmt = new RaiseStatement(ee, true);
- helpStmtTest("RAISE SQLWARNING 'Test only' SQLSTATE '100' EXCEPTION e;", "RAISE SQLWARNING 'Test only' SQLSTATE '100' EXCEPTION e;", //$NON-NLS-1$ //$NON-NLS-2$
+ helpStmtTest("RAISE SQLWARNING SQLEXCEPTION 'Test only' SQLSTATE '100' chain e;", "RAISE SQLWARNING SQLEXCEPTION 'Test only' SQLSTATE '100' CHAIN e;", //$NON-NLS-1$ //$NON-NLS-2$
errStmt);
}
@@ -5270,5 +5269,17 @@
@Test public void testTextTableNegativeWidth() {
helpException("SELECT * from texttable(null columns x string width -1) as x");
}
+
+ @Test public void testBlockExceptionHandling() throws ParseException {
+ CommandStatement cmdStmt = new CommandStatement(new Query(new Select(Arrays.asList(new MultipleElementSymbol())), new From(Arrays.asList(new UnaryFromClause(new GroupSymbol("x")))), null, null, null));
+ AssignmentStatement assigStmt = new AssignmentStatement(new ElementSymbol("a"), new Constant(new Integer(1))); //$NON-NLS-1$
+ RaiseStatement errStmt = new RaiseStatement(new Constant("My Error")); //$NON-NLS-1$
+ Block b = new Block();
+ b.setExceptionGroup("g");
+ b.addStatement(cmdStmt);
+ b.addStatement(assigStmt);
+ b.addStatement(errStmt, true);
+ helpStmtTest("BEGIN\nselect * from x;\na = 1;\nexception e\nERROR 'My Error';\nEND", "BEGIN\nSELECT * FROM x;\na = 1;\nEXCEPTION e\nRAISE SQLEXCEPTION 'My Error';\nEND", b); //$NON-NLS-1$
+ }
}
Modified: trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcErrors.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcErrors.java 2012-09-25 18:56:07 UTC (rev 4470)
+++ trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcErrors.java 2012-09-25 18:58:05 UTC (rev 4471)
@@ -25,10 +25,12 @@
import static org.junit.Assert.*;
import static org.teiid.query.processor.proc.TestProcedureProcessor.*;
+import java.util.Arrays;
+import java.util.List;
+
import org.junit.Test;
import org.teiid.core.TeiidProcessingException;
import org.teiid.jdbc.TeiidSQLException;
-import org.teiid.jdbc.TeiidSQLWarning;
import org.teiid.query.metadata.TransformationMetadata;
import org.teiid.query.processor.HardcodedDataManager;
import org.teiid.query.processor.ProcessorPlan;
@@ -39,7 +41,7 @@
@Test public void testInvalidException() throws Exception {
String ddl =
- "create virtual procedure vproc (x integer) returns integer as begin declare object e = sqlwarning 'hello'; raise e; raise sqlexception 'hello world' sqlstate 'abc', 1 exception e; end;";
+ "create virtual procedure vproc (x integer) returns integer as begin declare object e = sqlexception 'hello'; raise e; raise sqlexception 'hello world' sqlstate 'abc', 1 chain e; end;";
try {
TestProcedureResolving.createMetadata(ddl);
fail();
@@ -50,7 +52,7 @@
@Test public void testExceptionAndWarning() throws Exception {
String ddl =
- "create virtual procedure vproc (x integer) returns integer as begin declare exception e = sqlwarning 'hello'; raise e; raise sqlexception 'hello world' sqlstate 'abc', 1 exception e; end;";
+ "create virtual procedure vproc (x integer) returns integer as begin declare exception e = sqlexception 'hello'; raise sqlwarning e; raise sqlexception 'hello world' sqlstate 'abc', 1 chain e; end;";
TransformationMetadata tm = TestProcedureResolving.createMetadata(ddl);
String sql = "call vproc(1)"; //$NON-NLS-1$
@@ -63,7 +65,7 @@
helpTestProcess(plan, null, dataManager, tm);
fail();
} catch (TeiidProcessingException e) {
- TeiidSQLWarning tsw = (TeiidSQLWarning) plan.getContext().getAndClearWarnings().get(0);
+ TeiidSQLException tsw = (TeiidSQLException) plan.getContext().getAndClearWarnings().get(0);
assertEquals("hello", tsw.getMessage());
assertEquals(e.getCause().getCause(), tsw);
@@ -74,5 +76,28 @@
}
}
+
+ @Test public void testExceptionHandling() throws Exception {
+ String ddl =
+ "create virtual procedure vproc (x integer) returns integer as begin " +
+ "raise sqlexception 'hello world' sqlstate 'abc', 1;" +
+ "exception e " +
+ "raise sqlwarning sqlexception 'caught' chain e.exception; " +
+ "\"return\" = 1;"+
+ "end;";
+ TransformationMetadata tm = TestProcedureResolving.createMetadata(ddl);
+
+ String sql = "call vproc(1)"; //$NON-NLS-1$
+
+ ProcessorPlan plan = getProcedurePlan(sql, tm);
+
+ HardcodedDataManager dataManager = new HardcodedDataManager(tm);
+
+ helpTestProcess(plan, new List[] {Arrays.asList(1)}, dataManager, tm);
+
+ TeiidSQLException tse = (TeiidSQLException)plan.getContext().getAndClearWarnings().get(0);
+ assertEquals("caught", tse.getMessage());
+ assertEquals("hello world", tse.getCause().getMessage());
+ }
}
Modified: trunk/engine/src/test/java/org/teiid/query/resolver/TestProcedureResolving.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/resolver/TestProcedureResolving.java 2012-09-25 18:56:07 UTC (rev 4470)
+++ trunk/engine/src/test/java/org/teiid/query/resolver/TestProcedureResolving.java 2012-09-25 18:58:05 UTC (rev 4471)
@@ -807,7 +807,7 @@
String userUpdateStr = "UPDATE vm1.g1 SET e1='x'"; //$NON-NLS-1$
helpFailUpdateProcedure(proc.toString(), userUpdateStr,
- Table.TriggerEvent.UPDATE, "TEIID30124 Nested Loop can not use the same cursor name as that of its parent."); //$NON-NLS-1$
+ Table.TriggerEvent.UPDATE, "TEIID30124 Loop cursor or exception group name loopCursor already exists."); //$NON-NLS-1$
}
@Test public void testTempGroupElementShouldNotBeResolable() {
@@ -978,7 +978,7 @@
//cursor starts with "#" Defect14924
@Test public void testVirtualProcedureInvalid1() throws Exception {
- helpResolveException("EXEC pm1.vsp32()",RealMetadataFactory.example1Cached(), "TEIID30125 Cursor names cannot begin with \"#\" as that indicates the name of a temporary table: #mycursor."); //$NON-NLS-1$ //$NON-NLS-2$
+ helpResolveException("EXEC pm1.vsp32()",RealMetadataFactory.example1Cached(), "TEIID30125 Cursor or exception group names cannot begin with \"#\" as that indicates the name of a temporary table: #mycursor."); //$NON-NLS-1$ //$NON-NLS-2$
}
@Test public void testVirtualProcedureWithOrderBy() throws Exception {
@@ -1002,7 +1002,7 @@
}
@Test public void testLoopRedefinition2() throws Exception {
- helpResolveException("EXEC pm1.vsp11()", RealMetadataFactory.example1Cached(), "TEIID30124 Nested Loop can not use the same cursor name as that of its parent."); //$NON-NLS-1$ //$NON-NLS-2$
+ helpResolveException("EXEC pm1.vsp11()", RealMetadataFactory.example1Cached(), "TEIID30124 Loop cursor or exception group name mycursor already exists."); //$NON-NLS-1$ //$NON-NLS-2$
}
@Test public void testVariableResolutionWithIntervening() throws Exception {
13 years, 6 months
teiid SVN: r4470 - trunk/engine/src/main/java/org/teiid/query/validator.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2012-09-25 14:56:07 -0400 (Tue, 25 Sep 2012)
New Revision: 4470
Modified:
trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java
Log:
TEIID-2222 fix for npe with dyanmic sql in trigger
Modified: trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java 2012-09-25 18:19:53 UTC (rev 4469)
+++ trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java 2012-09-25 18:56:07 UTC (rev 4470)
@@ -408,10 +408,12 @@
public void visit(CreateProcedureCommand obj) {
//check that the procedure does not contain references to itself
- if (GroupCollectorVisitor.getGroups(obj,true).contains(obj.getVirtualGroup())) {
- handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.Procedure_has_group_self_reference"),obj); //$NON-NLS-1$
- }
- this.createProc = obj;
+ if (obj.getUpdateType() == null) {
+ if (GroupCollectorVisitor.getGroups(obj,true).contains(obj.getVirtualGroup())) {
+ handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.Procedure_has_group_self_reference"),obj); //$NON-NLS-1$
+ }
+ this.createProc = obj;
+ }
}
public void visit(CompoundCriteria obj) {
13 years, 6 months
teiid SVN: r4469 - in trunk/engine/src: main/java/org/teiid/query/processor/proc and 3 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2012-09-25 14:19:53 -0400 (Tue, 25 Sep 2012)
New Revision: 4469
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/TriggerActionPlanner.java
trunk/engine/src/main/java/org/teiid/query/processor/proc/ExecDynamicSqlInstruction.java
trunk/engine/src/main/java/org/teiid/query/processor/proc/LoopInstruction.java
trunk/engine/src/main/java/org/teiid/query/resolver/command/InsertResolver.java
trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateResolver.java
trunk/engine/src/main/java/org/teiid/query/sql/proc/CreateProcedureCommand.java
trunk/engine/src/test/java/org/teiid/query/processor/TestTriggerActions.java
Log:
TEIID-2222 fix for npe with dyanmic sql in trigger
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/TriggerActionPlanner.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/TriggerActionPlanner.java 2012-09-25 13:13:39 UTC (rev 4468)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/TriggerActionPlanner.java 2012-09-25 18:19:53 UTC (rev 4469)
@@ -97,7 +97,10 @@
ProcessorPlan queryPlan = QueryOptimizer.optimizePlan(query, metadata, idGenerator, capFinder, analysisRecord, context);
result.setQueryPlan(queryPlan);
result.setLookupMap(RelationalNode.createLookupMap(query.getProjectedSymbols()));
- ProcedurePlan rowProcedure = (ProcedurePlan)QueryOptimizer.optimizePlan(new CreateProcedureCommand(ta.getBlock()), metadata, idGenerator, capFinder, analysisRecord, context);
+ CreateProcedureCommand command = new CreateProcedureCommand(ta.getBlock());
+ command.setVirtualGroup(ta.getView());
+ command.setUpdateType(userCommand.getClass().getSimpleName());
+ ProcedurePlan rowProcedure = (ProcedurePlan)QueryOptimizer.optimizePlan(command, metadata, idGenerator, capFinder, analysisRecord, context);
result.setRowProcedure(rowProcedure);
return result;
}
Modified: trunk/engine/src/main/java/org/teiid/query/processor/proc/ExecDynamicSqlInstruction.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/proc/ExecDynamicSqlInstruction.java 2012-09-25 13:13:39 UTC (rev 4468)
+++ trunk/engine/src/main/java/org/teiid/query/processor/proc/ExecDynamicSqlInstruction.java 2012-09-25 18:19:53 UTC (rev 4469)
@@ -255,7 +255,11 @@
localContext.getFlattenedContextMap(variableMap);
Map<ElementSymbol, Expression> nameValueMap = new HashMap<ElementSymbol, Expression>(variableMap.size());
for (Map.Entry<ElementSymbol, Object> entry : variableMap.entrySet()) {
- nameValueMap.put(entry.getKey(), new Constant(entry.getValue(), entry.getKey().getType()));
+ if (entry.getValue() instanceof Expression) {
+ nameValueMap.put(entry.getKey(), (Expression) entry.getValue());
+ } else {
+ nameValueMap.put(entry.getKey(), new Constant(entry.getValue(), entry.getKey().getType()));
+ }
}
return nameValueMap;
}
@@ -312,7 +316,11 @@
// do a recursion check
// Add group to recursion stack
CommandContext context = procEnv.getContext();
- context.pushCall(parentProcCommand.getVirtualGroup().getName());
+ if (parentProcCommand.getUpdateType() != null) {
+ context.pushCall(parentProcCommand.getUpdateType() + " " + parentProcCommand.getVirtualGroup()); //$NON-NLS-1$
+ } else {
+ context.pushCall(parentProcCommand.getVirtualGroup().toString());
+ }
}
/**
Modified: trunk/engine/src/main/java/org/teiid/query/processor/proc/LoopInstruction.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/proc/LoopInstruction.java 2012-09-25 13:13:39 UTC (rev 4468)
+++ trunk/engine/src/main/java/org/teiid/query/processor/proc/LoopInstruction.java 2012-09-25 18:19:53 UTC (rev 4469)
@@ -73,7 +73,9 @@
elements = new ArrayList<ElementSymbol>(schema.size());
for(int i=0; i< schema.size(); i++){
Expression element = (Expression)schema.get(i);
- elements.add(new ElementSymbol(rsName + "." + Symbol.getShortName(element))); //$NON-NLS-1$
+ ElementSymbol e = new ElementSymbol(rsName + Symbol.SEPARATOR + Symbol.getShortName(element));
+ e.setType(element.getType());
+ elements.add(e);
}
}
for(int i=0; i< elements.size(); i++){
@@ -86,7 +88,7 @@
*/
public LoopInstruction clone(){
ProcessorPlan clonedPlan = this.plan.clone();
- return new LoopInstruction((Program)this.loopProgram.clone(), this.rsName, clonedPlan, label);
+ return new LoopInstruction(this.loopProgram.clone(), this.rsName, clonedPlan, label);
}
public String toString() {
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/command/InsertResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/command/InsertResolver.java 2012-09-25 13:13:39 UTC (rev 4468)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/command/InsertResolver.java 2012-09-25 18:19:53 UTC (rev 4469)
@@ -254,12 +254,13 @@
valIter = insert.getValues().iterator();
}
while (varIter.hasNext()) {
- ElementSymbol varSymbol = varIter.next().clone();
-
+ ElementSymbol next = varIter.next();
+ ElementSymbol varSymbol = next.clone();
varSymbol.getGroupSymbol().setName(ProcedureReservedWords.CHANGING);
+ varSymbol.setType(DataTypeManager.DefaultDataClasses.BOOLEAN);
result.put(varSymbol, new Constant(Boolean.TRUE));
if (!changingOnly) {
- varSymbol = varSymbol.clone();
+ varSymbol = next.clone();
varSymbol.getGroupSymbol().setName(SQLConstants.Reserved.NEW);
result.put(varSymbol, (Expression)valIter.next());
}
@@ -271,13 +272,14 @@
Iterator<ElementSymbol> defaultIter = insertElmnts.iterator();
while(defaultIter.hasNext()) {
- ElementSymbol varSymbol = defaultIter.next().clone();
+ ElementSymbol next = varIter.next();
+ ElementSymbol varSymbol = next.clone();
varSymbol.getGroupSymbol().setName(ProcedureReservedWords.CHANGING);
+ varSymbol.setType(DataTypeManager.DefaultDataClasses.BOOLEAN);
result.put(varSymbol, new Constant(Boolean.FALSE));
-
if (!changingOnly) {
Expression value = ResolverUtil.getDefault(varSymbol, metadata);
- varSymbol = varSymbol.clone();
+ varSymbol = next.clone();
varSymbol.getGroupSymbol().setName(SQLConstants.Reserved.NEW);
result.put(varSymbol, value);
}
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateResolver.java 2012-09-25 13:13:39 UTC (rev 4468)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateResolver.java 2012-09-25 18:19:53 UTC (rev 4469)
@@ -33,6 +33,7 @@
import org.teiid.api.exception.query.QueryMetadataException;
import org.teiid.api.exception.query.QueryResolverException;
import org.teiid.core.TeiidComponentException;
+import org.teiid.core.types.DataTypeManager;
import org.teiid.language.SQLConstants;
import org.teiid.query.metadata.QueryMetadataInterface;
import org.teiid.query.metadata.TempMetadataAdapter;
@@ -103,9 +104,10 @@
for (Entry<ElementSymbol, Expression> entry : changing.entrySet()) {
ElementSymbol leftSymbol = entry.getKey().clone();
leftSymbol.getGroupSymbol().setName(ProcedureReservedWords.CHANGING);
+ leftSymbol.setType(DataTypeManager.DefaultDataClasses.BOOLEAN);
result.put(leftSymbol, new Constant(Boolean.TRUE));
if (!changingOnly) {
- leftSymbol = leftSymbol.clone();
+ leftSymbol = entry.getKey().clone();
leftSymbol.getGroupSymbol().setName(SQLConstants.Reserved.NEW);
result.put(leftSymbol, entry.getValue());
}
@@ -119,6 +121,7 @@
while(defaultIter.hasNext()) {
ElementSymbol varSymbol = defaultIter.next().clone();
varSymbol.getGroupSymbol().setName(ProcedureReservedWords.CHANGING);
+ varSymbol.setType(DataTypeManager.DefaultDataClasses.BOOLEAN);
result.put(varSymbol, new Constant(Boolean.FALSE));
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/proc/CreateProcedureCommand.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/proc/CreateProcedureCommand.java 2012-09-25 13:13:39 UTC (rev 4468)
+++ trunk/engine/src/main/java/org/teiid/query/sql/proc/CreateProcedureCommand.java 2012-09-25 18:19:53 UTC (rev 4469)
@@ -54,6 +54,8 @@
private GroupSymbol virtualGroup;
+ private String updateType;
+
/**
* Constructor for CreateUpdateProcedureCommand.
*/
@@ -138,6 +140,7 @@
if (this.virtualGroup != null) {
copy.virtualGroup = this.virtualGroup.clone();
}
+ copy.updateType = this.updateType;
this.copyMetadataState(copy);
return copy;
}
@@ -234,4 +237,12 @@
this.virtualGroup = virtualGroup;
}
+ public void setUpdateType(String updateType) {
+ this.updateType = updateType;
+ }
+
+ public String getUpdateType() {
+ return updateType;
+ }
+
} // END CLASS
Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestTriggerActions.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/TestTriggerActions.java 2012-09-25 13:13:39 UTC (rev 4468)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestTriggerActions.java 2012-09-25 18:19:53 UTC (rev 4469)
@@ -29,6 +29,7 @@
import java.util.List;
import org.junit.Test;
+import org.teiid.api.exception.query.QueryProcessingException;
import org.teiid.metadata.Table;
import org.teiid.query.metadata.TransformationMetadata;
import org.teiid.query.optimizer.TestOptimizer;
@@ -60,7 +61,7 @@
CommandContext context = createCommandContext();
BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
ProcessorPlan plan = TestProcessor.helpGetPlan(TestResolver.helpResolve(sql, metadata), metadata, new DefaultCapabilitiesFinder(caps), context);
- List[] expected = new List[] {Arrays.asList(1)};
+ List<?>[] expected = new List[] {Arrays.asList(1)};
helpProcess(plan, context, dm, expected);
}
@@ -79,10 +80,52 @@
CommandContext context = createCommandContext();
BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
ProcessorPlan plan = TestProcessor.helpGetPlan(TestResolver.helpResolve(sql, metadata), metadata, new DefaultCapabilitiesFinder(caps), context);
- List[] expected = new List[] {Arrays.asList(6)};
+ List<?>[] expected = new List[] {Arrays.asList(6)};
helpProcess(plan, context, dm, expected);
}
+ @Test public void testDynamic() throws Exception {
+ TransformationMetadata metadata = TestUpdateValidator.example1();
+ TestUpdateValidator.createView("select '1' as x, 2 as y", metadata, GX);
+ Table t = metadata.getMetadataStore().getSchemas().get(VM1).getTables().get(GX);
+ t.setDeletePlan("FOR EACH ROW BEGIN ATOMIC END");
+ t.setUpdatePlan("");
+ t.setInsertPlan("FOR EACH ROW BEGIN execute immediate 'delete from gx where gx.x = new.x'; END");
+
+ String sql = "insert into gx (x, y) select e1, e2 from pm1.g1";
+
+ FakeDataManager dm = new FakeDataManager();
+ FakeDataStore.addTable("pm1.g1", dm, metadata);
+ CommandContext context = createCommandContext();
+ BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
+ ProcessorPlan plan = TestProcessor.helpGetPlan(TestResolver.helpResolve(sql, metadata), metadata, new DefaultCapabilitiesFinder(caps), context);
+ List<?>[] expected = new List[] {Arrays.asList(6)};
+ helpProcess(plan, context, dm, expected);
+ }
+
+ @Test public void testDynamicRecursion() throws Exception {
+ TransformationMetadata metadata = TestUpdateValidator.example1();
+ TestUpdateValidator.createView("select 'a' as x, 2 as y", metadata, GX);
+ Table t = metadata.getMetadataStore().getSchemas().get(VM1).getTables().get(GX);
+ t.setDeletePlan("FOR EACH ROW BEGIN ATOMIC insert into gx (x, y) values (old.x, old.y); END");
+ t.setUpdatePlan("");
+ t.setInsertPlan("FOR EACH ROW BEGIN execute immediate 'delete from gx where gx.x = new.x'; END");
+
+ String sql = "insert into gx (x, y) select e1, e2 from pm1.g1";
+
+ FakeDataManager dm = new FakeDataManager();
+ FakeDataStore.addTable("pm1.g1", dm, metadata);
+ CommandContext context = createCommandContext();
+ BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
+ ProcessorPlan plan = TestProcessor.helpGetPlan(TestResolver.helpResolve(sql, metadata), metadata, new DefaultCapabilitiesFinder(caps), context);
+ try {
+ helpProcess(plan, context, dm, null);
+ fail();
+ } catch (QueryProcessingException e) {
+ assertEquals("TEIID30168 Couldn't execute the dynamic SQL command \"EXECUTE IMMEDIATE 'delete from gx where gx.x = new.x'\" with the SQL statement \"'delete from gx where gx.x = new.x'\" due to: TEIID30347 There is a recursive invocation of group 'Insert gx'. Please correct the SQL.", e.getMessage());
+ }
+ }
+
@Test public void testDelete() throws Exception {
TransformationMetadata metadata = TestUpdateValidator.example1();
TestUpdateValidator.createView("select 1 as x, 2 as y", metadata, GX);
@@ -99,7 +142,7 @@
CommandContext context = createCommandContext();
BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
ProcessorPlan plan = TestProcessor.helpGetPlan(TestResolver.helpResolve(sql, metadata), metadata, new DefaultCapabilitiesFinder(caps), context);
- List[] expected = new List[] {Arrays.asList(1)};
+ List<?>[] expected = new List[] {Arrays.asList(1)};
helpProcess(plan, context, dm, expected);
}
@@ -119,7 +162,7 @@
CommandContext context = createCommandContext();
BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
ProcessorPlan plan = TestProcessor.helpGetPlan(TestResolver.helpResolve(sql, metadata), metadata, new DefaultCapabilitiesFinder(caps), context);
- List[] expected = new List[] {Arrays.asList(1)};
+ List<?>[] expected = new List[] {Arrays.asList(1)};
helpProcess(plan, context, dm, expected);
assertEquals("UPDATE pm1.g1 SET e2 = 5 WHERE e2 = 2", dm.getQueries().get(0));
}
@@ -161,7 +204,7 @@
CommandContext context = createCommandContext();
BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
ProcessorPlan plan = TestProcessor.helpGetPlan(TestResolver.helpResolve(sql, metadata), metadata, new DefaultCapabilitiesFinder(caps), context);
- List[] expected = new List[] {Arrays.asList(1)};
+ List<?>[] expected = new List[] {Arrays.asList(1)};
helpProcess(plan, context, dm, expected);
assertEquals("UPDATE pm1.g1 SET e2 = 1 WHERE e2 = 2", dm.getQueries().get(0));
}
13 years, 6 months
teiid SVN: r4468 - trunk/connectors/connector-ws/src/main/rar/META-INF.
by teiid-commits@lists.jboss.org
Author: rareddy
Date: 2012-09-25 09:13:39 -0400 (Tue, 25 Sep 2012)
New Revision: 4468
Modified:
trunk/connectors/connector-ws/src/main/rar/META-INF/ra.xml
Log:
TEIID-1714: Fixing the typo in the previous commit.
Modified: trunk/connectors/connector-ws/src/main/rar/META-INF/ra.xml
===================================================================
--- trunk/connectors/connector-ws/src/main/rar/META-INF/ra.xml 2012-09-25 01:48:29 UTC (rev 4467)
+++ trunk/connectors/connector-ws/src/main/rar/META-INF/ra.xml 2012-09-25 13:13:39 UTC (rev 4468)
@@ -79,7 +79,7 @@
<config-property>
<description>{$display:"Request Timeout",$description:"Timeout for request"}</description>
- <config-property-name>EndPoint</config-property-name>
+ <config-property-name>RequestTimeout</config-property-name>
<config-property-type>java.lang.Long</config-property-type>
</config-property>
13 years, 6 months
teiid SVN: r4467 - in trunk/engine/src: main/java/org/teiid/query/resolver and 10 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2012-09-24 21:48:29 -0400 (Mon, 24 Sep 2012)
New Revision: 4467
Modified:
trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java
trunk/engine/src/main/java/org/teiid/query/resolver/QueryResolver.java
trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateProcedureResolver.java
trunk/engine/src/main/java/org/teiid/query/sql/lang/ProcedureContainer.java
trunk/engine/src/main/java/org/teiid/query/sql/proc/CommandStatement.java
trunk/engine/src/main/java/org/teiid/query/sql/proc/CreateProcedureCommand.java
trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java
trunk/engine/src/main/resources/org/teiid/query/i18n.properties
trunk/engine/src/test/java/org/teiid/query/metadata/TestMetadataValidator.java
trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcedureProcessor.java
trunk/engine/src/test/java/org/teiid/query/resolver/TestAlterResolving.java
trunk/engine/src/test/java/org/teiid/query/sql/proc/TestCreateUpdateProcedureCommand.java
trunk/engine/src/test/java/org/teiid/query/unittest/RealMetadataFactory.java
Log:
TEIID-2226 adding proc rs validation
Modified: trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java 2012-09-24 15:36:49 UTC (rev 4466)
+++ trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java 2012-09-25 01:48:29 UTC (rev 4467)
@@ -535,6 +535,7 @@
TEIID31117,
TEIID31118,
TEIID31119,
- TEIID31120,
+ TEIID31120,
+ TEIID31121,
}
}
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/QueryResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/QueryResolver.java 2012-09-24 15:36:49 UTC (rev 4466)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/QueryResolver.java 2012-09-25 01:48:29 UTC (rev 4467)
@@ -109,6 +109,7 @@
//if the subcommand is virtual stored procedure, it must have the same
//projected symbol as its parent.
cupCommand.setProjectedSymbols(proc.getProjectedSymbols());
+ cupCommand.setResultSetColumns(proc.getResultSetColumns());
}
resolveCommand(command, proc.getGroup(), proc.getType(), metadata.getDesignTimeMetadata());
return command;
@@ -471,8 +472,8 @@
}
public static void validateProjectedSymbols(GroupSymbol virtualGroup,
- List<ElementSymbol> symbols,
- List<Expression> projectedSymbols)
+ List<? extends Expression> symbols,
+ List<? extends Expression> projectedSymbols)
throws QueryValidatorException {
if (symbols.size() != projectedSymbols.size()) {
throw new QueryValidatorException(QueryPlugin.Event.TEIID30066, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30066, virtualGroup, symbols.size(), projectedSymbols.size()));
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateProcedureResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateProcedureResolver.java 2012-09-24 15:36:49 UTC (rev 4466)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateProcedureResolver.java 2012-09-25 01:48:29 UTC (rev 4467)
@@ -22,6 +22,7 @@
package org.teiid.query.resolver.command;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
@@ -64,7 +65,12 @@
/**
*/
public class UpdateProcedureResolver implements CommandResolver {
-
+
+ public static class StatementNode {
+ CommandStatement cs;
+ List<StatementNode> children;
+ }
+
/**
* @see org.teiid.query.resolver.CommandResolver#resolveCommand(org.teiid.query.sql.lang.Command, TempMetadataAdapter, boolean)
*/
@@ -73,7 +79,7 @@
if (command instanceof TriggerAction) {
TriggerAction ta = (TriggerAction)command;
- resolveBlock(new CreateProcedureCommand(), ta.getBlock(), ta.getExternalGroupContexts(), metadata);
+ resolveBlock(new CreateProcedureCommand(), ta.getBlock(), ta.getExternalGroupContexts(), metadata, null);
return;
}
@@ -89,12 +95,42 @@
updateCount.setType(DataTypeManager.DefaultDataClasses.INTEGER);
symbols.add(updateCount);
- ProcedureContainerResolver.addScalarGroup(ProcedureReservedWords.VARIABLES, metadata.getMetadataStore(), externalGroups, symbols);
- resolveBlock(procCommand, procCommand.getBlock(), externalGroups, metadata);
+ ProcedureContainerResolver.addScalarGroup(ProcedureReservedWords.VARIABLES, metadata.getMetadataStore(), externalGroups, symbols);
+ StatementNode sn = new StatementNode();
+ resolveBlock(procCommand, procCommand.getBlock(), externalGroups, metadata, sn);
+
+ //validate the possible returned resultsets
+ if (procCommand.getResultSetColumns() == null || !procCommand.getResultSetColumns().isEmpty()) {
+ setReturnable(procCommand, sn);
+ }
}
+ private void setReturnable(CreateProcedureCommand procCommand, StatementNode sn) {
+ if (sn.cs != null) {
+ sn.cs.setReturnable(true);
+ //this logic is for designer, which want's to populate a resultset from the proc text
+ if (procCommand.getResultSetColumns() == null) {
+ List<? extends Expression> symbols = sn.cs.getCommand().getProjectedSymbols();
+ if (sn.cs.getCommand() instanceof StoredProcedure) {
+ StoredProcedure sp = (StoredProcedure)sn.cs.getCommand();
+ if (sp.isCallableStatement()) {
+ symbols = sp.getResultSetColumns();
+ }
+ }
+ procCommand.setResultSetColumns(symbols);
+ //TODO: what about out parameters
+ procCommand.setProjectedSymbols(symbols);
+ }
+ }
+ if (sn.children != null) {
+ for (StatementNode child : sn.children) {
+ setReturnable(procCommand, child);
+ }
+ }
+ }
+
public void resolveBlock(CreateProcedureCommand command, Block block, GroupContext externalGroups,
- TempMetadataAdapter metadata)
+ TempMetadataAdapter metadata, org.teiid.query.resolver.command.UpdateProcedureResolver.StatementNode sn)
throws QueryResolverException, QueryMetadataException, TeiidComponentException {
LogManager.logTrace(org.teiid.logging.LogConstants.CTX_QUERY_RESOLVER, new Object[]{"Resolving block", block}); //$NON-NLS-1$
@@ -107,11 +143,11 @@
GroupSymbol variables = ProcedureContainerResolver.addScalarGroup(ProcedureReservedWords.VARIABLES, store, externalGroups, new LinkedList<Expression>());
for (Statement statement : block.getStatements()) {
- resolveStatement(command, statement, externalGroups, variables, metadata);
+ resolveStatement(command, statement, externalGroups, variables, metadata, sn);
}
}
- private void resolveStatement(CreateProcedureCommand command, Statement statement, GroupContext externalGroups, GroupSymbol variables, TempMetadataAdapter metadata)
+ private void resolveStatement(CreateProcedureCommand command, Statement statement, GroupContext externalGroups, GroupSymbol variables, TempMetadataAdapter metadata, StatementNode sn)
throws QueryResolverException, QueryMetadataException, TeiidComponentException {
LogManager.logTrace(org.teiid.logging.LogConstants.CTX_QUERY_RESOLVER, new Object[]{"Resolving statement", statement}); //$NON-NLS-1$
@@ -123,9 +159,9 @@
resolveEmbeddedCommand(metadata, externalGroups, container.getCommand());
}
ResolverVisitor.resolveLanguageObject(ifCrit, null, externalGroups, metadata);
- resolveBlock(command, ifStmt.getIfBlock(), externalGroups, metadata);
+ resolveBlock(command, ifStmt.getIfBlock(), externalGroups, metadata, pushChild(sn));
if(ifStmt.hasElseBlock()) {
- resolveBlock(command, ifStmt.getElseBlock(), externalGroups, metadata);
+ resolveBlock(command, ifStmt.getElseBlock(), externalGroups, metadata, pushChild(sn));
}
break;
case Statement.TYPE_COMMAND:
@@ -168,20 +204,17 @@
dynCommand.setAsColumns(command.getProjectedSymbols());
}
}
-
- //don't bother using the metadata when it doesn't matter
- if (command.getResultsCommand() != null && command.getResultsCommand().getType() == Command.TYPE_DYNAMIC) {
- DynamicCommand dynamicCommand = (DynamicCommand)command.getResultsCommand();
- if (!dynamicCommand.isAsClauseSet()) {
- dynamicCommand.setAsColumns(Collections.EMPTY_LIST);
- }
+
+ //this could be the last select statement, set the projected symbol
+ //on the virtual procedure command
+ if (subCommand.returnsResultSet() && sn != null) {
+ updateDynamicAs(sn);
+
+ sn.cs = cmdStmt;
+ if (sn.children != null) {
+ sn.children.clear();
+ }
}
-
- if (subCommand.returnsResultSet()) {
- //this could be the last select statement, set the projected symbol
- //on the virtual procedure command
- command.setResultsCommand(subCommand);
- }
break;
case Statement.TYPE_ERROR:
@@ -231,7 +264,7 @@
resolveEmbeddedCommand(metadata, externalGroups, container.getCommand());
}
ResolverVisitor.resolveLanguageObject(whileCrit, null, externalGroups, metadata);
- resolveBlock(command, whileStmt.getBlock(), externalGroups, metadata);
+ resolveBlock(command, whileStmt.getBlock(), externalGroups, metadata, pushChild(sn));
break;
case Statement.TYPE_LOOP:
LoopStatement loopStmt = (LoopStatement) statement;
@@ -257,11 +290,37 @@
ProcedureContainerResolver.addScalarGroup(groupName, store, externalGroups, symbols, false);
- resolveBlock(command, loopStmt.getBlock(), externalGroups, metadata);
+ resolveBlock(command, loopStmt.getBlock(), externalGroups, metadata, pushChild(sn));
break;
}
}
+ private void updateDynamicAs(StatementNode sn) {
+ if (sn.cs != null && sn.cs.getCommand().getType() == Command.TYPE_DYNAMIC) {
+ DynamicCommand dynamicCommand = (DynamicCommand)sn.cs.getCommand();
+ if (!dynamicCommand.isAsClauseSet()) {
+ dynamicCommand.setAsColumns(Collections.EMPTY_LIST);
+ }
+ }
+ if (sn.children != null) {
+ for (StatementNode child : sn.children) {
+ updateDynamicAs(child);
+ }
+ }
+ }
+
+ private StatementNode pushChild(StatementNode sn) {
+ if (sn != null) {
+ if (sn.children == null) {
+ sn.children = new ArrayList<StatementNode>();
+ }
+ StatementNode child = new StatementNode();
+ sn.children.add(child);
+ sn = child;
+ }
+ return sn;
+ }
+
private boolean isAssignable(TempMetadataAdapter metadata, SPParameter param)
throws TeiidComponentException, QueryMetadataException {
if (!(param.getExpression() instanceof ElementSymbol)) {
Modified: trunk/engine/src/main/java/org/teiid/query/sql/lang/ProcedureContainer.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/lang/ProcedureContainer.java 2012-09-24 15:36:49 UTC (rev 4466)
+++ trunk/engine/src/main/java/org/teiid/query/sql/lang/ProcedureContainer.java 2012-09-25 01:48:29 UTC (rev 4467)
@@ -22,6 +22,8 @@
package org.teiid.query.sql.lang;
+import java.util.List;
+
import org.teiid.query.validator.UpdateValidator.UpdateInfo;
@@ -64,5 +66,9 @@
public void setUpdateInfo(UpdateInfo updateInfo) {
this.updateInfo = updateInfo;
}
+
+ public List getResultSetColumns() {
+ return getProjectedSymbols();
+ }
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/proc/CommandStatement.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/proc/CommandStatement.java 2012-09-24 15:36:49 UTC (rev 4466)
+++ trunk/engine/src/main/java/org/teiid/query/sql/proc/CommandStatement.java 2012-09-25 01:48:29 UTC (rev 4467)
@@ -37,6 +37,7 @@
// the command this statement represents
Command command;
+ private boolean returnable;
/**
* Constructor for CommandStatement.
@@ -87,7 +88,9 @@
* @return Deep clone
*/
public Object clone() {
- return new CommandStatement((Command)this.command.clone());
+ CommandStatement cs = new CommandStatement((Command)this.command.clone());
+ cs.returnable = this.returnable;
+ return cs;
}
/**
@@ -119,5 +122,13 @@
// This hash code relies on the commands hash code
return this.getCommand().hashCode();
}
+
+ public boolean isReturnable() {
+ return returnable;
+ }
+
+ public void setReturnable(boolean returnable) {
+ this.returnable = returnable;
+ }
} // END CLASS
Modified: trunk/engine/src/main/java/org/teiid/query/sql/proc/CreateProcedureCommand.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/proc/CreateProcedureCommand.java 2012-09-24 15:36:49 UTC (rev 4466)
+++ trunk/engine/src/main/java/org/teiid/query/sql/proc/CreateProcedureCommand.java 2012-09-25 01:48:29 UTC (rev 4467)
@@ -22,18 +22,17 @@
package org.teiid.query.sql.proc;
-import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.teiid.core.util.EquivalenceUtil;
import org.teiid.core.util.HashCodeUtil;
+import org.teiid.query.sql.LanguageObject;
import org.teiid.query.sql.LanguageVisitor;
import org.teiid.query.sql.lang.Command;
import org.teiid.query.sql.lang.Query;
-import org.teiid.query.sql.lang.StoredProcedure;
-import org.teiid.query.sql.symbol.GroupSymbol;
import org.teiid.query.sql.symbol.Expression;
+import org.teiid.query.sql.symbol.GroupSymbol;
import org.teiid.query.sql.visitor.SQLStringVisitor;
@@ -51,11 +50,10 @@
private Command userCommand;
private List projectedSymbols;
+ private List resultSetColumns;
private GroupSymbol virtualGroup;
- //command that returns resultset. For virtual procedure only.
- private Command resultsCommand;
/**
* Constructor for CreateUpdateProcedureCommand.
*/
@@ -132,8 +130,11 @@
copy.setBlock(this.block.clone());
}
if (this.projectedSymbols != null) {
- copy.setProjectedSymbols(new ArrayList(this.projectedSymbols));
+ copy.projectedSymbols = LanguageObject.Util.deepClone(this.projectedSymbols, Expression.class);
}
+ if (this.resultSetColumns != null) {
+ copy.resultSetColumns = LanguageObject.Util.deepClone(this.resultSetColumns, Expression.class);
+ }
if (this.virtualGroup != null) {
copy.virtualGroup = this.virtualGroup.clone();
}
@@ -199,21 +200,18 @@
if(this.projectedSymbols != null){
return this.projectedSymbols;
}
- if(this.resultsCommand == null){
- //user may have not entered any query yet
- return Collections.EMPTY_LIST;
- }
- List<? extends Expression> symbols = this.resultsCommand.getProjectedSymbols();
- if (this.resultsCommand instanceof StoredProcedure) {
- StoredProcedure sp = (StoredProcedure)this.resultsCommand;
- if (sp.isCallableStatement()) {
- symbols = sp.getResultSetColumns();
- }
- }
- setProjectedSymbols(symbols);
- return this.projectedSymbols;
+ //user may have not entered any query yet
+ return Collections.EMPTY_LIST;
}
-
+
+ public List getResultSetColumns() {
+ return resultSetColumns;
+ }
+
+ public void setResultSetColumns(List resultSetColumns) {
+ this.resultSetColumns = resultSetColumns;
+ }
+
/**
* @param projSymbols
*/
@@ -221,20 +219,6 @@
projectedSymbols = projSymbols;
}
- /**
- * @return Command
- */
- public Command getResultsCommand() {
- return resultsCommand;
- }
-
- /**
- * @param command
- */
- public void setResultsCommand(Command command) {
- resultsCommand = command;
- }
-
/**
* @see org.teiid.query.sql.lang.Command#areResultsCachable()
*/
Modified: trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java 2012-09-24 15:36:49 UTC (rev 4466)
+++ trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java 2012-09-25 01:48:29 UTC (rev 4467)
@@ -70,6 +70,7 @@
import org.teiid.query.sql.navigator.PreOrderNavigator;
import org.teiid.query.sql.proc.Block;
import org.teiid.query.sql.proc.BranchingStatement;
+import org.teiid.query.sql.proc.CommandStatement;
import org.teiid.query.sql.proc.CreateProcedureCommand;
import org.teiid.query.sql.proc.LoopStatement;
import org.teiid.query.sql.proc.WhileStatement;
@@ -110,13 +111,14 @@
// State during validation
private boolean isXML = false; // only used for Query commands
-
private boolean inQuery;
+ private CreateProcedureCommand createProc;
public void reset() {
super.reset();
this.isXML = false;
this.inQuery = false;
+ this.createProc = null;
}
// ############### Visitor methods for language objects ##################
@@ -409,6 +411,7 @@
if (GroupCollectorVisitor.getGroups(obj,true).contains(obj.getVirtualGroup())) {
handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.Procedure_has_group_self_reference"),obj); //$NON-NLS-1$
}
+ this.createProc = obj;
}
public void visit(CompoundCriteria obj) {
@@ -1465,6 +1468,24 @@
}
@Override
+ public void visit(CommandStatement obj) {
+ if (obj.isReturnable() && this.createProc != null) {
+ List<? extends Expression> symbols = obj.getCommand().getProjectedSymbols();
+ if (obj.getCommand() instanceof StoredProcedure) {
+ StoredProcedure sp = (StoredProcedure)obj.getCommand();
+ if (sp.isCallableStatement()) {
+ symbols = sp.getResultSetColumns();
+ }
+ }
+ try {
+ QueryResolver.validateProjectedSymbols(createProc.getVirtualGroup(), createProc.getResultSetColumns(), symbols);
+ } catch (QueryValidatorException e) {
+ handleValidationError(QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31121, createProc.getVirtualGroup(), obj, e.getMessage()), obj);
+ }
+ }
+ }
+
+ @Override
public void visit(BranchingStatement obj) {
boolean matchedLabel = false;
boolean inLoop = false;
Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2012-09-24 15:36:49 UTC (rev 4466)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2012-09-25 01:48:29 UTC (rev 4467)
@@ -1033,6 +1033,7 @@
TEIID31115=Function based index {1} expression {0} is not deterministic.
TEIID31116=Function based index {1} expression {0} could not be resolved: {2}
TEIID31120=An exception may only be chained to another exception. {0} is not valid.
+TEIID31121=The expected result set of the procedure {0} does not match the result set from returnable statement {1} - {2}
SQLParser.proc_type_conflict=Result type {1} conflicts with return type {2} for procedure {0}
SQLParser.param_out=Procedure {0} RESULT param {1} must be of type OUT.
Modified: trunk/engine/src/test/java/org/teiid/query/metadata/TestMetadataValidator.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/metadata/TestMetadataValidator.java 2012-09-24 15:36:49 UTC (rev 4466)
+++ trunk/engine/src/test/java/org/teiid/query/metadata/TestMetadataValidator.java 2012-09-25 01:48:29 UTC (rev 4467)
@@ -350,4 +350,15 @@
report = new MetadataValidator().validate(this.vdb, this.store);
assertTrue(printError(report), report.hasItems());
}
+
+ @Test public void testResultSet() throws Exception {
+ String ddl = "create virtual procedure vproc (x integer) returns table (y integer) as begin if (x = 1) select 1; else select 1, 2; end;";
+ buildModel("pm1", true, this.vdb, this.store, ddl);
+
+ buildTransformationMetadata();
+
+ ValidatorReport report = new ValidatorReport();
+ report = new MetadataValidator().validate(this.vdb, this.store);
+ assertTrue(printError(report), report.hasItems());
+ }
}
Modified: trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcedureProcessor.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcedureProcessor.java 2012-09-24 15:36:49 UTC (rev 4466)
+++ trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcedureProcessor.java 2012-09-25 01:48:29 UTC (rev 4467)
@@ -30,7 +30,7 @@
import org.junit.Test;
import org.mockito.Mockito;
-import org.teiid.api.exception.query.QueryMetadataException;
+import org.teiid.api.exception.query.QueryPlannerException;
import org.teiid.api.exception.query.QueryProcessingException;
import org.teiid.api.exception.query.QueryValidatorException;
import org.teiid.client.metadata.ParameterInfo;
@@ -629,7 +629,7 @@
// Create expected results
List[] expected = new List[] {
- Arrays.asList(1)};
+ Arrays.asList("1")};
helpTestProcess(plan, expected, dataMgr, metadata);
}
@@ -804,13 +804,11 @@
helpTestProcess(plan, expected, dataMgr, metadata);
}
- private void addProc(TransformationMetadata metadata, String query)
- throws QueryMetadataException {
+ private void addProc(TransformationMetadata metadata, String query) {
addProc(metadata, "sq2", query, new String[] { "e1" }, new String[] { DataTypeManager.DefaultDataTypes.STRING }, new String[0], new String[0]);
}
- private void addProc(TransformationMetadata metadata, String name, String query, String[] rsCols, String[] rsTypes, String[] params, String[] paramTypes)
- throws QueryMetadataException {
+ private void addProc(TransformationMetadata metadata, String name, String query, String[] rsCols, String[] rsTypes, String[] params, String[] paramTypes) {
Schema pm1 = metadata.getMetadataStore().getSchema("PM1"); //$NON-NLS-1$
pm1.getProcedures().remove(name.toUpperCase());
ColumnSet<Procedure> rs2 = RealMetadataFactory.createResultSet("rs1", rsCols, rsTypes);
@@ -837,7 +835,7 @@
procedure.append("IF (mycursor.e2>5) \n"); //$NON-NLS-1$
procedure.append("VARIABLES.e2_total=VARIABLES.e2_total+mycursor.e2;\n"); //$NON-NLS-1$
procedure.append("END\n"); //$NON-NLS-1$
- procedure.append("SELECT VARIABLES.e2_total;\n"); //$NON-NLS-1$
+ procedure.append("SELECT cast(VARIABLES.e2_total as string);\n"); //$NON-NLS-1$
procedure.append("END"); //$NON-NLS-1$
addProc(metadata, procedure.toString());
@@ -850,10 +848,10 @@
//Create expected results
List[] expected = new List[] {
- Arrays.asList(new Object[] { Integer.valueOf(66)}),
+ Arrays.asList(new Object[] { "66"}),
};
helpTestProcess(plan, expected, dataMgr, metadata);
- }
+ }
@Test public void testDynamicCommandWithParameter() throws Exception {
TransformationMetadata metadata = RealMetadataFactory.example1();
@@ -919,7 +917,7 @@
TransformationMetadata metadata = RealMetadataFactory.example1();
addProc(metadata, "sq2", "CREATE VIRTUAL PROCEDURE BEGIN\n" //$NON-NLS-1$ //$NON-NLS-2$
- + "declare object VARIABLES.x; execute string 'SELECT xmlelement(name elem, x)'; select 1; END", new String[] { "e1", "e2" }
+ + "declare object VARIABLES.x; execute string 'SELECT xmlelement(name elem, x)'; select '1', 2; END", new String[] { "e1", "e2" }
, new String[] { DataTypeManager.DefaultDataTypes.STRING, DataTypeManager.DefaultDataTypes.INTEGER }, new String[] {"in"}, new String[] {DataTypeManager.DefaultDataTypes.STRING});
String userUpdateStr = "EXEC pm1.sq2('First')"; //$NON-NLS-1$
@@ -995,7 +993,7 @@
"TEIID30168 Couldn't execute the dynamic SQL command \"EXECUTE IMMEDIATE 'EXEC pm1.sq2(''First'')' AS e1 string, e2 integer\" with the SQL statement \"'EXEC pm1.sq2(''First'')'\" due to: TEIID30347 There is a recursive invocation of group 'pm1.sq2'. Please correct the SQL.", metadata); //$NON-NLS-1$
}
- @Test public void testDynamicCommandIncorrectProjectSymbolCount() throws Exception {
+ @Test(expected=QueryPlannerException.class) public void testDynamicCommandIncorrectProjectSymbolCount() throws Exception {
//Tests dynamic query with incorrect number of elements
TransformationMetadata metadata = RealMetadataFactory.example1();
@@ -1009,11 +1007,7 @@
String userUpdateStr = "EXEC pm1.sq2('test')"; //$NON-NLS-1$
- FakeDataManager dataMgr = exampleDataManager(metadata);
-
- ProcessorPlan plan = getProcedurePlan(userUpdateStr, metadata);
-
- helpTestProcessFailure(plan, dataMgr, "TEIID30168 Couldn't execute the dynamic SQL command \"EXECUTE IMMEDIATE 'EXEC pm1.sq1(''First'')' AS e1 string, e2 integer\" with the SQL statement \"'EXEC pm1.sq1(''First'')'\" due to: The dynamic sql string contains an incorrect number of elements.", metadata); //$NON-NLS-1$
+ getProcedurePlan(userUpdateStr, metadata);
}
@Test public void testDynamicCommandPositional() throws Exception {
@@ -1106,7 +1100,7 @@
TransformationMetadata metadata = RealMetadataFactory.example1();
addProc(metadata, "sq2", "CREATE VIRTUAL PROCEDURE BEGIN\n" //$NON-NLS-1$ //$NON-NLS-2$
- + "execute string 'select e1,e2 from pm5.g3' as e1 string, e2 integer INTO #temp; select * from #temp; END", new String[] { "e1", "e2"}, new String[] { DataTypeManager.DefaultDataTypes.STRING, DataTypeManager.DefaultDataTypes.SHORT}, new String[0], new String[0]); //$NON-NLS-1$
+ + "execute string 'select e1,e2 from pm5.g3' as e1 string, e2 integer INTO #temp; select * from #temp; END", new String[] { "e1", "e2"}, new String[] { DataTypeManager.DefaultDataTypes.STRING, DataTypeManager.DefaultDataTypes.INTEGER}, new String[0], new String[0]); //$NON-NLS-1$
String userUpdateStr = "EXEC pm1.sq2()"; //$NON-NLS-1$
@@ -1210,7 +1204,7 @@
procedure.append("select e1 into #temp from pm1.g1;\n"); //$NON-NLS-1$
procedure.append("VARIABLES.e2_total=select count(*) from #temp;\n"); //$NON-NLS-1$
procedure.append("END\n"); //$NON-NLS-1$
- procedure.append("SELECT VARIABLES.e2_total;\n"); //$NON-NLS-1$
+ procedure.append("SELECT cast(VARIABLES.e2_total as string);\n"); //$NON-NLS-1$
procedure.append("END"); //$NON-NLS-1$
addProc(metadata, procedure.toString());
@@ -1223,7 +1217,7 @@
//Create expected results
List[] expected = new List[] {
- Arrays.asList(new Object[] { Integer.valueOf(3)}),
+ Arrays.asList("3"),
};
helpTestProcess(plan, expected, dataMgr, metadata);
}
@@ -1244,7 +1238,7 @@
procedure.append("BEGIN\n"); //$NON-NLS-1$
procedure.append("e2_total=e2_total+mycursor.x;"); //$NON-NLS-1$
procedure.append("END\n"); //$NON-NLS-1$
- procedure.append("SELECT VARIABLES.e2_total;\n"); //$NON-NLS-1$
+ procedure.append("SELECT cast(VARIABLES.e2_total as string);\n"); //$NON-NLS-1$
procedure.append("END"); //$NON-NLS-1$
addProc(metadata, procedure.toString());
@@ -1257,7 +1251,7 @@
//Create expected results
List[] expected = new List[] {
- Arrays.asList(new Object[] { Integer.valueOf(76)}),
+ Arrays.asList("76"),
};
helpTestProcess(plan, expected, dataMgr, metadata);
}
@@ -1312,7 +1306,7 @@
procedure.append("BEGIN\n"); //$NON-NLS-1$
procedure.append("create local temporary table t1 (e1 integer);\n"); //$NON-NLS-1$
procedure.append("create local temporary table T1 (e1 integer);\n"); //$NON-NLS-1$
- procedure.append("SELECT e1 from t1;\n"); //$NON-NLS-1$
+ procedure.append("SELECT cast(e1 as string) from t1;\n"); //$NON-NLS-1$
procedure.append("END"); //$NON-NLS-1$
addProc(metadata, procedure.toString());
@@ -1339,7 +1333,7 @@
procedure.append("select e1 into t1 from pm1.g1;\n"); //$NON-NLS-1$
procedure.append("drop table t1;\n"); //$NON-NLS-1$
procedure.append("drop table t1;\n"); //$NON-NLS-1$
- procedure.append("SELECT 1;\n"); //$NON-NLS-1$
+ procedure.append("SELECT '1';\n"); //$NON-NLS-1$
procedure.append("END"); //$NON-NLS-1$
addProc(metadata, procedure.toString());
@@ -1350,7 +1344,7 @@
ProcessorPlan plan = getProcedurePlan(userUpdateStr, metadata);
- helpTestProcess(plan, new List[] {Arrays.asList(1)}, dataMgr, metadata);
+ helpTestProcess(plan, new List[] {Arrays.asList("1")}, dataMgr, metadata);
}
/**
@@ -1504,7 +1498,7 @@
.append("insert into #temp (e1) values (convert(rand() * 1000, integer));\n") //$NON-NLS-1$
.append("x = x + 1;\n") //$NON-NLS-1$
.append("END\n") //$NON-NLS-1$
- .append("SELECT * FROM #TEMP;\n") //$NON-NLS-1$
+ .append("SELECT cast(e1 as string) FROM #TEMP;\n") //$NON-NLS-1$
.append("END"); //$NON-NLS-1$
QueryMetadataInterface metadata = createProcedureMetadata(procedure.toString());
@@ -1517,11 +1511,11 @@
helpTestProcess(plan, new List[] {
- Arrays.asList(new Object[] {Integer.valueOf(240)}),
- Arrays.asList(new Object[] {Integer.valueOf(637)})}, dataMgr, metadata);
+ Arrays.asList("240"),
+ Arrays.asList("637")}, dataMgr, metadata);
}
- private QueryMetadataInterface createProcedureMetadata(String procedure) throws QueryMetadataException {
+ private QueryMetadataInterface createProcedureMetadata(String procedure) {
TransformationMetadata metadata = RealMetadataFactory.example1();
addProc(metadata, "sq1", procedure, new String[] { "e1" }, new String[] { DataTypeManager.DefaultDataTypes.STRING }, new String[0], new String[0]);
return metadata;
@@ -1589,7 +1583,7 @@
ColumnSet<Procedure> rs2 = RealMetadataFactory.createResultSet("pm1.rs2", new String[] { "e1" }, new String[] { DataTypeManager.DefaultDataTypes.XML }); //$NON-NLS-1$ //$NON-NLS-2$
ProcedureParameter rs2p2 = RealMetadataFactory.createParameter("input", ParameterInfo.IN, DataTypeManager.DefaultDataTypes.INTEGER); //$NON-NLS-1$
QueryNode sq2n1 = new QueryNode("CREATE VIRTUAL PROCEDURE BEGIN\n" //$NON-NLS-1$ //$NON-NLS-2$
- + "declare integer VARIABLES.x = proc.input; declare xml y = SELECT * FROM xmltest.doc9 WHERE context(SupplierID, OrderID)=x OR OrderID='2'; select convert(y, string); END"); //$NON-NLS-1$
+ + "declare integer VARIABLES.x = proc.input; declare xml y = SELECT * FROM xmltest.doc9 WHERE context(SupplierID, OrderID)=x OR OrderID='2'; select y; END"); //$NON-NLS-1$
Procedure sq2 = RealMetadataFactory.createVirtualProcedure("proc", pm1, Arrays.asList(rs2p2), sq2n1); //$NON-NLS-1$
sq2.setResultSet(rs2);
@@ -1734,7 +1728,7 @@
procedure += " statement. */ "; //$NON-NLS-1$
procedure += " VARIABLES.var1 = L1.BCol3;\n"; //$NON-NLS-1$
procedure += " END\n"; //$NON-NLS-1$
- procedure += " SELECT VARIABLES.Var1 AS e1;\n"; //$NON-NLS-1$
+ procedure += " SELECT cast(VARIABLES.Var1 as string) AS e1;\n"; //$NON-NLS-1$
procedure += "END\n"; //$NON-NLS-1$
QueryMetadataInterface metadata = createProcedureMetadata(procedure);
@@ -1742,7 +1736,7 @@
FakeDataManager dataMgr = exampleDataManager(metadata);
ProcessorPlan plan = getProcedurePlan(userQuery, metadata);
- List[] expected = new List[] {Arrays.asList(new Object[] {Integer.valueOf(3)})};
+ List[] expected = new List[] {Arrays.asList("3")};
helpTestProcess(plan, expected, dataMgr, metadata);
}
@@ -1776,7 +1770,8 @@
" " + sql + ";" + //$NON-NLS-1$ //$NON-NLS-2$
"END"; //$NON-NLS-1$
- QueryMetadataInterface metadata = createProcedureMetadata(proc);
+ TransformationMetadata metadata = RealMetadataFactory.example1();
+ addProc(metadata, "sq1", proc, new String[] { "e1", "e2", "e3", "e4" }, new String[] { DataTypeManager.DefaultDataTypes.STRING, DataTypeManager.DefaultDataTypes.STRING, DataTypeManager.DefaultDataTypes.INTEGER, DataTypeManager.DefaultDataTypes.INTEGER }, new String[0], new String[0]);
String userQuery = "SELECT * FROM (EXEC pm1.sq1()) as proc"; //$NON-NLS-1$
FakeDataManager dataMgr = exampleDataManager2(metadata);
ProcessorPlan plan = getProcedurePlan(userQuery, metadata);
@@ -1822,7 +1817,8 @@
" " + sql + ";" + //$NON-NLS-1$ //$NON-NLS-2$
"END"; //$NON-NLS-1$
- QueryMetadataInterface metadata = createProcedureMetadata(proc);
+ TransformationMetadata metadata = RealMetadataFactory.example1();
+ addProc(metadata, "sq1", proc, new String[] { "e1", "e2", "e3", "e4" }, new String[] { DataTypeManager.DefaultDataTypes.STRING, DataTypeManager.DefaultDataTypes.STRING, DataTypeManager.DefaultDataTypes.INTEGER, DataTypeManager.DefaultDataTypes.INTEGER }, new String[0], new String[0]);
String userQuery = "SELECT * FROM (EXEC pm1.sq1()) as proc"; //$NON-NLS-1$
FakeDataManager dataMgr = exampleDataManager2(metadata);
ProcessorPlan plan = getProcedurePlan(userQuery, metadata, TestOptimizer.getGenericFinder());
@@ -1860,7 +1856,7 @@
"BEGIN " + //$NON-NLS-1$
" create local temporary table t1 (e1 string);\n" + //$NON-NLS-1$
" select e1 into t1 from pm1.g1;\n" + //$NON-NLS-1$
- " select e2 from (exec pm1.sq2((select max(e1) from t1))) x;\n" + //$NON-NLS-1$
+ " select cast(e2 as string) from (exec pm1.sq2((select max(e1) from t1))) x;\n" + //$NON-NLS-1$
"END"; //$NON-NLS-1$
QueryMetadataInterface metadata = createProcedureMetadata(proc);
@@ -1869,7 +1865,7 @@
ProcessorPlan plan = getProcedurePlan(userQuery, metadata, TestOptimizer.getGenericFinder());
List[] expected = new List[] {
- Arrays.asList( 51 ),
+ Arrays.asList( "51" ),
};
helpTestProcess(plan, expected, dataMgr, metadata);
}
@@ -1909,7 +1905,7 @@
procedure.append("exec pm1.sq2(in1 || 'foo');\n"); //$NON-NLS-1$
procedure.append("END"); //$NON-NLS-1$
- addProc(metadata, "sq1", procedure.toString(), new String[] { "e1" }, new String[] { DataTypeManager.DefaultDataTypes.STRING }, new String[] {"in1"}, new String[] {DataTypeManager.DefaultDataTypes.INTEGER});
+ addProc(metadata, "sq1", procedure.toString(), new String[] { "e1", "e2" }, new String[] { DataTypeManager.DefaultDataTypes.STRING, DataTypeManager.DefaultDataTypes.INTEGER }, new String[] {"in1"}, new String[] {DataTypeManager.DefaultDataTypes.INTEGER});
String userUpdateStr = "EXEC pm1.sq1(1)"; //$NON-NLS-1$
Modified: trunk/engine/src/test/java/org/teiid/query/resolver/TestAlterResolving.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/resolver/TestAlterResolving.java 2012-09-24 15:36:49 UTC (rev 4466)
+++ trunk/engine/src/test/java/org/teiid/query/resolver/TestAlterResolving.java 2012-09-25 01:48:29 UTC (rev 4467)
@@ -30,6 +30,7 @@
import org.teiid.query.sql.lang.AlterTrigger;
import org.teiid.query.sql.lang.AlterView;
import org.teiid.query.sql.lang.Query;
+import org.teiid.query.sql.proc.CommandStatement;
import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.unittest.RealMetadataFactory;
@@ -44,7 +45,7 @@
@Test public void testAlterProcedure() {
AlterProcedure alterProc = (AlterProcedure) helpResolve("alter procedure MMSP5 as begin select param1; end", RealMetadataFactory.exampleBQTCached());
assertNotNull(alterProc.getTarget().getMetadataID());
- Query q = (Query)alterProc.getDefinition().getResultsCommand();
+ Query q = (Query)((CommandStatement)alterProc.getDefinition().getBlock().getStatements().get(0)).getCommand();
assertTrue(((ElementSymbol)q.getSelect().getSymbol(0)).isExternalReference());
}
Modified: trunk/engine/src/test/java/org/teiid/query/sql/proc/TestCreateUpdateProcedureCommand.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/sql/proc/TestCreateUpdateProcedureCommand.java 2012-09-24 15:36:49 UTC (rev 4466)
+++ trunk/engine/src/test/java/org/teiid/query/sql/proc/TestCreateUpdateProcedureCommand.java 2012-09-25 01:48:29 UTC (rev 4467)
@@ -22,27 +22,18 @@
package org.teiid.query.sql.proc;
-import junit.framework.TestCase;
+import static org.junit.Assert.*;
+import org.junit.Test;
import org.teiid.core.util.UnitTestUtil;
-import org.teiid.query.resolver.TestResolver;
-import org.teiid.query.sql.lang.StoredProcedure;
-import org.teiid.query.unittest.RealMetadataFactory;
/**
*
* @author gchadalavadaDec 9, 2002
*/
-@SuppressWarnings("nls")
-public class TestCreateUpdateProcedureCommand extends TestCase {
+public class TestCreateUpdateProcedureCommand {
- // ################################## FRAMEWORK ################################
-
- public TestCreateUpdateProcedureCommand(String name) {
- super(name);
- }
-
// ################################## TEST HELPERS ################################
public static final CreateProcedureCommand sample1() {
@@ -59,7 +50,7 @@
// ################################## ACTUAL TESTS ################################
- public void testGetBlock() {
+ @Test public void testGetBlock() {
CreateProcedureCommand b1 = sample1();
assertTrue("Incorrect Block on command", b1.getBlock().equals(TestBlock.sample1())); //$NON-NLS-1$
}
@@ -99,12 +90,4 @@
UnitTestUtil.helpTestEquivalence(0, s1, s2);
}
- public void testProjectedSymbols() {
- CreateProcedureCommand cupc = new CreateProcedureCommand();
- StoredProcedure sp = (StoredProcedure)TestResolver.helpResolve("call TEIIDSP9(p1=>1, p2=>?)", RealMetadataFactory.exampleBQTCached());
- sp.setCallableStatement(true);
- cupc.setResultsCommand(sp);
- assertEquals(1, cupc.getProjectedSymbols().size());
- }
-
}
Modified: trunk/engine/src/test/java/org/teiid/query/unittest/RealMetadataFactory.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/unittest/RealMetadataFactory.java 2012-09-24 15:36:49 UTC (rev 4466)
+++ trunk/engine/src/test/java/org/teiid/query/unittest/RealMetadataFactory.java 2012-09-25 01:48:29 UTC (rev 4467)
@@ -1105,14 +1105,14 @@
QueryNode sq16n1 = new QueryNode("CREATE VIRTUAL PROCEDURE BEGIN INSERT INTO pm1.g1 ( e1, e2 ) VALUES( 1, 2 ); END"); //$NON-NLS-1$ //$NON-NLS-2$
createVirtualProcedure("sq16", pm1, null, sq16n1); //$NON-NLS-1$
- ColumnSet<Procedure> rs19 = createResultSet("pm1.rs19", new String[] { "xml" }, new String[] { DataTypeManager.DefaultDataTypes.STRING }); //$NON-NLS-1$ //$NON-NLS-2$
+ ColumnSet<Procedure> rs19 = createResultSet("pm1.rs19", new String[] { "xml" }, new String[] { DataTypeManager.DefaultDataTypes.XML }); //$NON-NLS-1$ //$NON-NLS-2$
QueryNode sq17n1 = new QueryNode("CREATE VIRTUAL PROCEDURE BEGIN SELECT * FROM xmltest.doc1; END"); //$NON-NLS-1$ //$NON-NLS-2$
Procedure sq17 = createVirtualProcedure("sq17", pm1, null, sq17n1); //$NON-NLS-1$
sq17.setResultSet(rs19);
createStoredProcedure("sp3", pm1, null); //$NON-NLS-1$ //$NON-NLS-2$
- ColumnSet<Procedure> rs20 = createResultSet("pm1.rs20", new String[] { "xml" }, new String[] { DataTypeManager.DefaultDataTypes.STRING }); //$NON-NLS-1$ //$NON-NLS-2$
+ ColumnSet<Procedure> rs20 = createResultSet("pm1.rs20", new String[] { "xml" }, new String[] { DataTypeManager.DefaultDataTypes.XML }); //$NON-NLS-1$ //$NON-NLS-2$
QueryNode sq18n1 = new QueryNode("CREATE VIRTUAL PROCEDURE BEGIN SELECT * FROM xmltest.doc1; END"); //$NON-NLS-1$ //$NON-NLS-2$
Procedure sq18 = createVirtualProcedure("sq18", pm1, null, sq18n1); //$NON-NLS-1$
sq18.setResultSet(rs20);
@@ -1238,7 +1238,7 @@
QueryNode vspqn24 = new QueryNode("CREATE VIRTUAL PROCEDURE BEGIN SELECT e1, e2 INTO #temptable FROM pm1.g1; SELECT #temptable.e1 FROM #temptable WHERE #temptable.e2=15; END"); //$NON-NLS-1$ //$NON-NLS-2$
Procedure vsp24 = createVirtualProcedure("vsp24", pm1, null, vspqn24); //$NON-NLS-1$
- vsp24.setResultSet(vspp4());
+ vsp24.setResultSet(vsprs1());
QueryNode vspqn25 = new QueryNode("CREATE VIRTUAL PROCEDURE BEGIN SELECT e1 INTO #temptable FROM pm1.g1 WHERE e1 ='no match'; SELECT e1 FROM #temptable; END"); //$NON-NLS-1$ //$NON-NLS-2$
Procedure vsp25 = createVirtualProcedure("vsp25", pm1, null, vspqn25); //$NON-NLS-1$
@@ -1283,7 +1283,7 @@
Procedure vsp41 = createVirtualProcedure("vsp41", pm1, null, vspqn41); //$NON-NLS-1$
vsp41.setResultSet(vsprs1());
- QueryNode vspqn37 = new QueryNode("CREATE VIRTUAL PROCEDURE BEGIN DECLARE integer x; VARIABLES.x=5; INSERT INTO vm1.g1(e2) values(VARIABLES.x); SELECT ROWCOUNT; END"); //$NON-NLS-1$ //$NON-NLS-2$
+ QueryNode vspqn37 = new QueryNode("CREATE VIRTUAL PROCEDURE BEGIN DECLARE integer x; VARIABLES.x=5; INSERT INTO vm1.g1(e2) values(VARIABLES.x); SELECT cast(ROWCOUNT as string); END"); //$NON-NLS-1$ //$NON-NLS-2$
Procedure vsp37 = createVirtualProcedure("vsp37", pm1, null, vspqn37); //$NON-NLS-1$
vsp37.setResultSet(vsprs1());
@@ -1467,7 +1467,7 @@
ProcedureParameter vspp55 = createParameter("param1", ParameterInfo.IN, DataTypeManager.DefaultDataTypes.INTEGER); //$NON-NLS-1$
QueryNode vspqn55 = new QueryNode("CREATE VIRTUAL PROCEDURE BEGIN select e1, param1 as a from vm1.g1; END"); //$NON-NLS-1$ //$NON-NLS-2$
Procedure vsp55 = createVirtualProcedure("vsp55", pm1, Arrays.asList( vspp55 ), vspqn55); //$NON-NLS-1$
- vsp55.setResultSet(vsprs1());
+ vsp55.setResultSet(vspp4());
QueryNode vspqn56 = new QueryNode("CREATE VIRTUAL PROCEDURE BEGIN SELECT * INTO #temptable FROM pm1.g1; SELECT #temptable.e1 FROM #temptable; END"); //$NON-NLS-1$ //$NON-NLS-2$
Procedure vsp56 = createVirtualProcedure("vsp56", pm1, null, vspqn56); //$NON-NLS-1$
13 years, 6 months
teiid SVN: r4466 - in trunk: build/kits/jboss-as7/docs/teiid and 26 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2012-09-24 11:36:49 -0400 (Mon, 24 Sep 2012)
New Revision: 4466
Added:
trunk/engine/src/main/java/org/teiid/query/sql/proc/ExceptionExpression.java
trunk/engine/src/main/java/org/teiid/query/sql/proc/RaiseStatement.java
trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcErrors.java
Removed:
trunk/engine/src/main/java/org/teiid/query/sql/proc/RaiseErrorStatement.java
Modified:
trunk/api/src/main/java/org/teiid/language/SQLConstants.java
trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html
trunk/client/src/main/java/org/teiid/client/ProcedureErrorInstructionException.java
trunk/client/src/main/java/org/teiid/client/SourceWarning.java
trunk/client/src/main/java/org/teiid/client/util/ExceptionUtil.java
trunk/client/src/main/java/org/teiid/jdbc/TeiidSQLException.java
trunk/client/src/main/java/org/teiid/jdbc/TeiidSQLWarning.java
trunk/client/src/test/java/org/teiid/jdbc/TestSQLException.java
trunk/engine/src/main/java/org/teiid/dqp/internal/process/DataTierTupleSource.java
trunk/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java
trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java
trunk/engine/src/main/java/org/teiid/query/eval/Evaluator.java
trunk/engine/src/main/java/org/teiid/query/metadata/DDLMetadataRepository.java
trunk/engine/src/main/java/org/teiid/query/metadata/SystemMetadata.java
trunk/engine/src/main/java/org/teiid/query/optimizer/ProcedurePlanner.java
trunk/engine/src/main/java/org/teiid/query/parser/QueryParser.java
trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java
trunk/engine/src/main/java/org/teiid/query/processor/proc/ErrorInstruction.java
trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateProcedureResolver.java
trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverVisitor.java
trunk/engine/src/main/java/org/teiid/query/sql/LanguageVisitor.java
trunk/engine/src/main/java/org/teiid/query/sql/navigator/PreOrPostOrderNavigator.java
trunk/engine/src/main/java/org/teiid/query/sql/proc/DeclareStatement.java
trunk/engine/src/main/java/org/teiid/query/sql/visitor/ExpressionMappingVisitor.java
trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java
trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
trunk/engine/src/main/resources/org/teiid/query/i18n.properties
trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestDQPCoreRequestHandling.java
trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestDataTierManager.java
trunk/engine/src/test/java/org/teiid/query/metadata/TestDDLStringVisitor.java
trunk/engine/src/test/java/org/teiid/query/parser/TestDDLParser.java
trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java
trunk/engine/src/test/java/org/teiid/query/sql/proc/TestRaiseErrorStatement.java
trunk/engine/src/test/java/org/teiid/query/sql/visitor/TestSQLStringVisitor.java
trunk/jboss-integration/src/test/java/org/teiid/jboss/rest/TestRestWebArchiveBuilder.java
Log:
TEIID-1386 initial changes to exception handling. the error statement is superseded by a more general raise statement
Modified: trunk/api/src/main/java/org/teiid/language/SQLConstants.java
===================================================================
--- trunk/api/src/main/java/org/teiid/language/SQLConstants.java 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/api/src/main/java/org/teiid/language/SQLConstants.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -126,6 +126,8 @@
public static final String XMLDECLARATION = "XMLDECLARATION"; //$NON-NLS-1$
public static final String VARIADIC = "VARIADIC"; //$NON-NLS-1$
public static final String INDEX = "INDEX"; //$NON-NLS-1$
+ public static final String EXCEPTION = "EXCEPTION"; //$NON-NLS-1$
+ public static final String RAISE = "RAISE"; //$NON-NLS-1$
}
public interface Reserved {
Modified: trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html
===================================================================
--- trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html 2012-09-24 15:36:49 UTC (rev 4466)
@@ -38,6 +38,7 @@
<li>TEIID-2181 <b>System query performance</b> - system queries are now indexed on case-insensitive schema/table name columns.
<li>TEIID-2086 <b>Transactional results caching</b> - the result set cache is now transactional by default.
<li>TEIID-2210 <b>Object Translator</b> - the translator-object can support Infinispan Cache and other Map type caches. See OBJECTTABLE for executing queries against this translator.
+ <li>TEIID-1386 <b>Procedure exception handling</b> - the Teiid procedure language now supports exception handling and emitting SQLWarnings. See the Reference for syntax and usage.
</ul>
<h2><a name="Compatibility">Compatibility Issues</a></h2>
@@ -55,6 +56,9 @@
<li>TEIID-2184 to be consistent with the rest of Teiid's logic the system functions dayName and monthName will return values from the default locale, rather than only the English names. Use the system property org.teiid.enDateNames true to revert to the pre-8.2 behavior.
<li>TEIID-2187 the CONSTRAINT keyword is not correctly used in table DDL. It should be replaced with a comma from scripts to be compatible with 8.2. If desired, 8.2 now supports the CONSTRAINT keyword to provide a name for each constraint.
<li>TEIID-2181 system tables no longer contain valid OIDs. That responsibility has moved to the pg_catalog.
+ <li>TEIID-1386 assignment statements and stored procedure invocations assigning a return value will no longer allow non-quoted non-reserved identifiers as left hand side variables. The workaround is to use a quoted variable name if you are using a non-reserved word as a variable name.
+ <li>TEIID-1386 the SQLState and errorCode reported by a TeiidSQLException will typically be from the top level nested SQLException. If there is also a nested TeiidException, the TeiidSQLException.teiidCode will be set to the TeiidException.getCode value and the TeiidSQLException.errorCode will be set
+ to the integer suffix of the teiidCode if possible.
</ul>
<h4>from 8.0</h4>
Modified: trunk/client/src/main/java/org/teiid/client/ProcedureErrorInstructionException.java
===================================================================
--- trunk/client/src/main/java/org/teiid/client/ProcedureErrorInstructionException.java 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/client/src/main/java/org/teiid/client/ProcedureErrorInstructionException.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -50,7 +50,7 @@
super(message);
}
- public ProcedureErrorInstructionException(BundleUtil.Event event, String message) {
- super(event, message);
+ public ProcedureErrorInstructionException(BundleUtil.Event event, Exception parent) {
+ super(event, parent);
}
}
Modified: trunk/client/src/main/java/org/teiid/client/SourceWarning.java
===================================================================
--- trunk/client/src/main/java/org/teiid/client/SourceWarning.java 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/client/src/main/java/org/teiid/client/SourceWarning.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -34,7 +34,7 @@
public class SourceWarning extends TeiidException {
- private static final StackTraceElement[] EMPTY_STACK_TRACE = new StackTraceElement[0];
+ public static final StackTraceElement[] EMPTY_STACK_TRACE = new StackTraceElement[0];
private String modelName = "UNKNOWN"; // variable stores the name of the model for the atomic query //$NON-NLS-1$
private String connectorBindingName = "UNKNOWN"; // variable stores name of the connector binding //$NON-NLS-1$
private boolean partialResults;
Modified: trunk/client/src/main/java/org/teiid/client/util/ExceptionUtil.java
===================================================================
--- trunk/client/src/main/java/org/teiid/client/util/ExceptionUtil.java 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/client/src/main/java/org/teiid/client/util/ExceptionUtil.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -31,11 +31,10 @@
public class ExceptionUtil {
- @SuppressWarnings("unchecked")
public static <T extends Throwable> T getExceptionOfType(Throwable ex, Class<T> cls) {
while (ex != null) {
if (cls.isAssignableFrom(ex.getClass())) {
- return (T)ex;
+ return cls.cast(ex);
}
if (ex.getCause() == ex) {
break;
Modified: trunk/client/src/main/java/org/teiid/jdbc/TeiidSQLException.java
===================================================================
--- trunk/client/src/main/java/org/teiid/jdbc/TeiidSQLException.java 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/client/src/main/java/org/teiid/jdbc/TeiidSQLException.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -47,6 +47,7 @@
public class TeiidSQLException extends SQLException {
private static final long serialVersionUID = 3672305321346173922L;
+ private String teiidCode;
/**
* No-arg constructor required by Externalizable semantics.
@@ -70,8 +71,8 @@
return create(exception, exception.getMessage());
}
- public TeiidSQLException(Throwable ex, String reason, String sqlState) {
- super(reason, sqlState); // passing the message to the super class constructor.
+ public TeiidSQLException(Throwable ex, String reason, String sqlState, int errorCode) {
+ super(reason, sqlState, errorCode); // passing the message to the super class constructor.
initCause(ex);
}
@@ -94,23 +95,41 @@
public static TeiidSQLException create(Throwable exception, String message) {
message = getMessage(exception, message);
Throwable origException = exception;
- if (exception instanceof TeiidSQLException) {
- if (message.equals(exception.getMessage())) {
- return (TeiidSQLException) exception;
- }
+ if (exception instanceof TeiidSQLException
+ && message.equals(exception.getMessage())) {
+ return (TeiidSQLException) exception;
}
if (exception instanceof SQLException) {
return new TeiidSQLException((SQLException) exception, message, true);
}
String sqlState = SQLStates.DEFAULT;
+ int errorCode = 0;
+ SQLException se = ExceptionUtil.getExceptionOfType(exception, SQLException.class);
+ if (se != null && se.getSQLState() != null) {
+ sqlState = se.getSQLState();
+ errorCode = se.getErrorCode();
+ }
TeiidException te = ExceptionUtil.getExceptionOfType(exception, TeiidException.class);
+ String code = null;
if (te != null && te.getCode() != null) {
- sqlState = te.getCode();
- } else {
- exception = findRootException(exception);
- sqlState = determineSQLState(exception, sqlState);
+ code = te.getCode();
+ if (errorCode == 0) {
+ String intPart = code;
+ if (code.startsWith("TEIID")) { //$NON-NLS-1$
+ intPart = code.substring(5);
+ }
+ try {
+ errorCode = Integer.valueOf(intPart);
+ } catch (NumberFormatException e) {
+
+ }
+ }
}
- return new TeiidSQLException(origException, message, sqlState);
+ exception = findRootException(exception);
+ sqlState = determineSQLState(exception, sqlState);
+ TeiidSQLException tse = new TeiidSQLException(origException, message, sqlState, errorCode);
+ tse.teiidCode = code;
+ return tse;
}
/**
@@ -228,4 +247,8 @@
public boolean isUsageErrorState() {
return SQLStates.isUsageErrorState(getSQLState());
}
+
+ public String getTeiidCode() {
+ return teiidCode;
+ }
}
\ No newline at end of file
Modified: trunk/client/src/main/java/org/teiid/jdbc/TeiidSQLWarning.java
===================================================================
--- trunk/client/src/main/java/org/teiid/jdbc/TeiidSQLWarning.java 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/client/src/main/java/org/teiid/jdbc/TeiidSQLWarning.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -74,6 +74,10 @@
this.modelName = modelName;
}
+ public TeiidSQLWarning(String reason, String sqlState, int errorCode, Throwable ex) {
+ super(reason, sqlState, errorCode, ex);
+ }
+
/**
*
* @return the source name or null if the warning is not associated with a source
Modified: trunk/client/src/test/java/org/teiid/jdbc/TestSQLException.java
===================================================================
--- trunk/client/src/test/java/org/teiid/jdbc/TestSQLException.java 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/client/src/test/java/org/teiid/jdbc/TestSQLException.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -214,17 +214,18 @@
assertEquals(exception.getNextException().getNextException().getMessage(), nested.getMessage());
}
public static enum Event implements BundleUtil.Event {
- T21,
+ TEIID21,
}
- @Test public void testCodeAsSQLState() {
+ @Test public void testCodeAsVendorCode() {
- TeiidException sqlexception = new TeiidException(Event.T21, "foo"); //$NON-NLS-1$
+ TeiidException sqlexception = new TeiidException(Event.TEIID21, "foo"); //$NON-NLS-1$
String message = "top level message"; //$NON-NLS-1$
TeiidSQLException exception = TeiidSQLException.create(sqlexception, message);
- assertEquals(sqlexception.getCode(), exception.getSQLState());
+ assertEquals(sqlexception.getCode(), exception.getTeiidCode());
+ assertEquals(21, exception.getErrorCode());
}
}
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/DataTierTupleSource.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/DataTierTupleSource.java 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/DataTierTupleSource.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -543,7 +543,7 @@
if (response.getWarnings() != null) {
for (Exception warning : response.getWarnings()) {
SourceWarning sourceFailure = new SourceWarning(this.aqr.getModelName(), aqr.getConnectorName(), warning, partial);
- workItem.addSourceFailureDetails(sourceFailure);
+ this.aqr.getCommandContext().addWarning(sourceFailure);
}
}
if (response.getFinalRow() >= 0) {
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -36,7 +36,6 @@
import org.teiid.client.RequestMessage;
import org.teiid.client.ResultsMessage;
-import org.teiid.client.SourceWarning;
import org.teiid.client.RequestMessage.ShowPlan;
import org.teiid.client.lob.LobChunk;
import org.teiid.client.metadata.ParameterInfo;
@@ -155,8 +154,6 @@
*/
private Throwable processingException;
private Map<AtomicRequestID, DataTierTupleSource> connectorInfo = Collections.synchronizedMap(new HashMap<AtomicRequestID, DataTierTupleSource>(4));
- // This exception contains details of all the atomic requests that failed when query is run in partial results mode.
- private List<TeiidException> warnings = new LinkedList<TeiidException>();
private volatile boolean doneProducingBatches;
private volatile boolean isClosed;
private volatile boolean isCanceled;
@@ -719,19 +716,7 @@
// set final row
response.setFinalRow(finalRowCount);
- // send any warnings with the response object
- List<Throwable> responseWarnings = new ArrayList<Throwable>();
- if (this.processor != null) {
- List<Exception> currentWarnings = processor.getAndClearWarnings();
- if (currentWarnings != null) {
- responseWarnings.addAll(currentWarnings);
- }
- }
- synchronized (warnings) {
- responseWarnings.addAll(this.warnings);
- this.warnings.clear();
- }
- response.setWarnings(responseWarnings);
+ setWarnings(response);
// If it is stored procedure, set parameters
if (originalCommand instanceof StoredProcedure) {
@@ -751,6 +736,18 @@
receiver.receiveResults(response);
return result;
}
+
+ private void setWarnings(ResultsMessage response) {
+ // send any warnings with the response object
+ List<Throwable> responseWarnings = new ArrayList<Throwable>();
+ if (this.processor != null) {
+ List<Exception> currentWarnings = processor.getAndClearWarnings();
+ if (currentWarnings != null) {
+ responseWarnings.addAll(currentWarnings);
+ }
+ }
+ response.setWarnings(responseWarnings);
+ }
public ResultsMessage createResultsMessage(List<? extends List<?>> batch, List<? extends Expression> columnSymbols) {
String[] columnNames = new String[columnSymbols.size()];
@@ -801,6 +798,7 @@
if (isCanceled) {
exception = addCancelCode(exception);
}
+ setWarnings(response);
response.setException(exception);
setAnalysisRecords(response);
receiver.receiveResults(response);
@@ -927,16 +925,6 @@
connectorInfo.put(atomicRequestId, connInfo);
}
- /**
- * <p>This method add information to the warning on the work item for the given
- * <code>RequestID</code>. This method is called from <code>DataTierManager</code></p>
- */
- public void addSourceFailureDetails(SourceWarning details) {
- synchronized (warnings) {
- this.warnings.add(details);
- }
- }
-
boolean isCanceled() {
return isCanceled;
}
@@ -969,10 +957,6 @@
return this.connectorInfo.get(id);
}
- public List<TeiidException> getWarnings() {
- return warnings;
- }
-
@Override
public String toString() {
return this.requestID.toString();
Modified: trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -534,6 +534,7 @@
TEIID31116,
TEIID31117,
TEIID31118,
- TEIID31119,
+ TEIID31119,
+ TEIID31120,
}
}
Modified: trunk/engine/src/main/java/org/teiid/query/eval/Evaluator.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/eval/Evaluator.java 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/engine/src/main/java/org/teiid/query/eval/Evaluator.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -48,6 +48,7 @@
import org.teiid.api.exception.query.ExpressionEvaluationException;
import org.teiid.api.exception.query.FunctionExecutionException;
+import org.teiid.client.SourceWarning;
import org.teiid.common.buffer.BlockedException;
import org.teiid.core.ComponentNotFoundException;
import org.teiid.core.TeiidComponentException;
@@ -57,6 +58,8 @@
import org.teiid.core.types.XMLType.Type;
import org.teiid.core.types.basic.StringToSQLXMLTransform;
import org.teiid.core.util.EquivalenceUtil;
+import org.teiid.jdbc.TeiidSQLException;
+import org.teiid.jdbc.TeiidSQLWarning;
import org.teiid.language.Like.MatchMode;
import org.teiid.query.QueryPlugin;
import org.teiid.query.function.FunctionDescriptor;
@@ -66,6 +69,7 @@
import org.teiid.query.processor.ProcessorDataManager;
import org.teiid.query.sql.LanguageObject;
import org.teiid.query.sql.lang.*;
+import org.teiid.query.sql.proc.ExceptionExpression;
import org.teiid.query.sql.symbol.*;
import org.teiid.query.sql.symbol.XMLNamespaces.NamespaceItem;
import org.teiid.query.sql.util.ValueIterator;
@@ -658,11 +662,39 @@
result[i] = internalEvaluate(exprs.get(i), tuple);
}
return new ArrayImpl(result);
+ } else if (expression instanceof ExceptionExpression) {
+ return evaluate(tuple, (ExceptionExpression)expression);
} else {
throw new TeiidComponentException(QueryPlugin.Event.TEIID30329, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30329, expression.getClass().getName()));
}
}
+ private Object evaluate(List<?> tuple, ExceptionExpression ee)
+ throws ExpressionEvaluationException, BlockedException,
+ TeiidComponentException {
+ String msg = (String) internalEvaluate(ee.getMessage(), tuple);
+ String sqlState = ee.getDefaultSQLState();
+ if (ee.getSqlState() != null) {
+ sqlState = (String) internalEvaluate(ee.getSqlState(), tuple);
+ }
+ Integer errorCode = null;
+ if (ee.getErrorCode() != null) {
+ errorCode = (Integer) internalEvaluate(ee.getErrorCode(), tuple);
+ }
+ Exception parent = null;
+ if (ee.getParent() != null) {
+ parent = (Exception) internalEvaluate(ee.getParent(), tuple);
+ }
+ Exception result = null;
+ if (ee.isWarning()) {
+ result = new TeiidSQLWarning(msg, sqlState, errorCode!=null?errorCode:0, parent);
+ } else {
+ result = new TeiidSQLException(parent, msg, sqlState, errorCode!=null?errorCode:0);
+ }
+ result.setStackTrace(SourceWarning.EMPTY_STACK_TRACE);
+ return result;
+ }
+
private Object evaluateXMLParse(List<?> tuple, final XMLParse xp) throws ExpressionEvaluationException, BlockedException, TeiidComponentException {
Object value = internalEvaluate(xp.getExpression(), tuple);
if (value == null) {
Modified: trunk/engine/src/main/java/org/teiid/query/metadata/DDLMetadataRepository.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/metadata/DDLMetadataRepository.java 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/DDLMetadataRepository.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -21,10 +21,10 @@
*/
package org.teiid.query.metadata;
+import org.teiid.api.exception.query.QueryParserException;
import org.teiid.core.TeiidRuntimeException;
import org.teiid.metadata.MetadataFactory;
import org.teiid.query.QueryPlugin;
-import org.teiid.query.parser.ParseException;
import org.teiid.query.parser.QueryParser;
import org.teiid.translator.ExecutionFactory;
import org.teiid.translator.TranslatorException;
@@ -36,7 +36,7 @@
public void loadMetadata(MetadataFactory factory, ExecutionFactory executionFactory, Object connectionFactory) throws TranslatorException {
try {
QueryParser.getQueryParser().parseDDL(factory, factory.getRawMetadata());
- } catch (ParseException e) {
+ } catch (QueryParserException e) {
throw new TeiidRuntimeException(QueryPlugin.Event.TEIID30386, e);
}
super.loadMetadata(factory, executionFactory, connectionFactory);
Modified: trunk/engine/src/main/java/org/teiid/query/metadata/SystemMetadata.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/metadata/SystemMetadata.java 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/SystemMetadata.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -34,6 +34,7 @@
import org.teiid.adminapi.impl.ModelMetaData;
import org.teiid.adminapi.impl.VDBMetaData;
+import org.teiid.api.exception.query.QueryParserException;
import org.teiid.core.TeiidRuntimeException;
import org.teiid.core.types.DataTypeManager;
import org.teiid.core.types.DataTypeManager.DefaultDataTypes;
@@ -43,7 +44,6 @@
import org.teiid.metadata.MetadataFactory;
import org.teiid.metadata.MetadataStore;
import org.teiid.metadata.Table;
-import org.teiid.query.parser.ParseException;
import org.teiid.query.parser.QueryParser;
import org.teiid.query.validator.ValidatorReport;
import org.teiid.translator.TranslatorException;
@@ -134,7 +134,7 @@
};
QueryParser.getQueryParser().parseDDL(factory, new InputStreamReader(is, Charset.forName("UTF-8"))); //$NON-NLS-1$
return factory;
- } catch (ParseException e) {
+ } catch (QueryParserException e) {
throw new TeiidRuntimeException(e);
} finally {
try {
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/ProcedurePlanner.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/ProcedurePlanner.java 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/ProcedurePlanner.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -194,7 +194,7 @@
{
ErrorInstruction error = new ErrorInstruction();
instruction = error;
- RaiseErrorStatement res = (RaiseErrorStatement)statement;
+ RaiseStatement res = (RaiseStatement)statement;
Expression asigExpr = res.getExpression();
error.setExpression(asigExpr);
Modified: trunk/engine/src/main/java/org/teiid/query/parser/QueryParser.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/parser/QueryParser.java 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/engine/src/main/java/org/teiid/query/parser/QueryParser.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -356,12 +356,16 @@
return new QueryParserException(QueryPlugin.Util.getString("QueryParser.parsingError", tme.getMessage())); //$NON-NLS-1$
}
- public void parseDDL(MetadataFactory factory, String ddl) throws ParseException {
+ public void parseDDL(MetadataFactory factory, String ddl) throws QueryParserException {
parseDDL(factory, new StringReader(ddl));
}
- public void parseDDL(MetadataFactory factory, Reader ddl) throws ParseException {
- getSqlParser(ddl).parseMetadata(factory);
+ public void parseDDL(MetadataFactory factory, Reader ddl) throws QueryParserException {
+ try {
+ getSqlParser(ddl).parseMetadata(factory);
+ } catch (ParseException e) {
+ throw convertParserException(e);
+ }
HashSet<FunctionMethod> functions = new HashSet<FunctionMethod>();
for (FunctionMethod functionMethod : factory.getSchema().getFunctions().values()) {
if (!functions.add(functionMethod)) {
Modified: trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -64,9 +64,9 @@
return literal;
}
- void convertToParameters(List<Expression> values, StoredProcedure storedProcedure) {
+ void convertToParameters(List<Expression> values, StoredProcedure storedProcedure, int paramIndex) {
for (Expression value : values) {
- SPParameter parameter = new SPParameter(storedProcedure.getParameters().size() + 1, value);
+ SPParameter parameter = new SPParameter(paramIndex++, value);
parameter.setParameterType(SPParameter.IN);
storedProcedure.setParameter(parameter);
}
Modified: trunk/engine/src/main/java/org/teiid/query/processor/proc/ErrorInstruction.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/proc/ErrorInstruction.java 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/engine/src/main/java/org/teiid/query/processor/proc/ErrorInstruction.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -24,6 +24,8 @@
import static org.teiid.query.analysis.AnalysisRecord.*;
+import java.sql.SQLWarning;
+
import org.teiid.client.ProcedureErrorInstructionException;
import org.teiid.client.plan.PlanNode;
import org.teiid.core.TeiidComponentException;
@@ -39,8 +41,6 @@
*/
public class ErrorInstruction extends ProgramInstruction {
- public static final String ERROR_PREFIX = "Procedure error:"; //$NON-NLS-1$
-
private Expression expression;
/**
@@ -76,8 +76,12 @@
public void process(ProcedurePlan env) throws TeiidComponentException,
TeiidProcessingException {
Object value = env.evaluateExpression(expression);
- LogManager.logTrace(org.teiid.logging.LogConstants.CTX_DQP, new Object[] {"Processing RaiseErrorInstruction with the value :", value}); //$NON-NLS-1$
- throw new ProcedureErrorInstructionException(QueryPlugin.Event.TEIID30167, ERROR_PREFIX + (value != null ? value.toString() : "")); //$NON-NLS-1$
+ LogManager.logTrace(org.teiid.logging.LogConstants.CTX_DQP, "Processing ErrorInstruction with the value :", value); //$NON-NLS-1$
+ if (value instanceof SQLWarning) {
+ env.getContext().addWarning((Exception)value);
+ return;
+ }
+ throw new ProcedureErrorInstructionException(QueryPlugin.Event.TEIID30167, (Exception) value);
}
}
\ No newline at end of file
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateProcedureResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateProcedureResolver.java 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateProcedureResolver.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -33,6 +33,7 @@
import org.teiid.client.metadata.ParameterInfo;
import org.teiid.core.TeiidComponentException;
import org.teiid.core.types.DataTypeManager;
+import org.teiid.language.SQLConstants;
import org.teiid.logging.LogManager;
import org.teiid.query.QueryPlugin;
import org.teiid.query.metadata.SupportConstants;
@@ -217,7 +218,10 @@
throw new QueryResolverException(QueryPlugin.Event.TEIID30123, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30123));
}
String varTypeName = DataTypeManager.getDataTypeName(varType);
- exprStmt.setExpression(ResolverUtil.convertExpression(exprStmt.getExpression(), varTypeName, metadata));
+ exprStmt.setExpression(ResolverUtil.convertExpression(exprStmt.getExpression(), varTypeName, metadata));
+ if (statement.getType() == Statement.TYPE_ERROR) {
+ ResolverVisitor.checkException(exprStmt.getExpression());
+ }
}
break;
case Statement.TYPE_WHILE:
@@ -301,11 +305,11 @@
}
variable.setType(DataTypeManager.getDataTypeClass(typeName));
variable.setGroupSymbol(variables);
- TempMetadataID id = new TempMetadataID(variable.getName(), variable.getType());
+ TempMetadataID id = new TempMetadataID(variable.getName(), typeName.equalsIgnoreCase(SQLConstants.NonReserved.EXCEPTION)?Exception.class:variable.getType());
id.setUpdatable(true);
variable.setMetadataID(id);
//TODO: this will cause the variables group to loose it's cache of resolved symbols
- metadata.getMetadataStore().addElementToTempGroup(ProcedureReservedWords.VARIABLES, (ElementSymbol)variable.clone());
+ metadata.getMetadataStore().addElementToTempGroup(ProcedureReservedWords.VARIABLES, variable.clone());
}
private void handleUnresolvableDeclaration(ElementSymbol variable, String description) throws QueryResolverException {
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverVisitor.java 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverVisitor.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -46,10 +46,12 @@
import org.teiid.query.function.FunctionLibrary;
import org.teiid.query.metadata.GroupInfo;
import org.teiid.query.metadata.QueryMetadataInterface;
+import org.teiid.query.metadata.TempMetadataID;
import org.teiid.query.sql.LanguageObject;
import org.teiid.query.sql.LanguageVisitor;
import org.teiid.query.sql.lang.*;
import org.teiid.query.sql.navigator.PostOrderNavigator;
+import org.teiid.query.sql.proc.ExceptionExpression;
import org.teiid.query.sql.symbol.*;
import org.teiid.query.sql.symbol.AggregateSymbol.Type;
import org.teiid.query.sql.symbol.ElementSymbol.DisplayMode;
@@ -405,6 +407,46 @@
}
@Override
+ public void visit(ExceptionExpression obj) {
+ try {
+ if (obj.getErrorCode() != null) {
+ obj.setErrorCode(ResolverUtil.convertExpression(obj.getErrorCode(), DataTypeManager.DefaultDataTypes.INTEGER, metadata));
+ }
+ obj.setMessage(ResolverUtil.convertExpression(obj.getMessage(), DataTypeManager.DefaultDataTypes.STRING, metadata));
+ if (obj.getSqlState() != null) {
+ obj.setSqlState(ResolverUtil.convertExpression(obj.getSqlState(), DataTypeManager.DefaultDataTypes.STRING, metadata));
+ }
+ checkException(obj.getParent());
+ } catch (QueryResolverException e) {
+ handleException(e);
+ }
+ }
+
+ public static void checkException(Expression obj)
+ throws QueryResolverException {
+ if (obj == null || obj instanceof ExceptionExpression) {
+ return;
+ }
+ if (obj instanceof ElementSymbol) {
+ ElementSymbol es = (ElementSymbol)obj;
+ if (!(es.getMetadataID() instanceof TempMetadataID)) {
+ throw new QueryResolverException(QueryPlugin.Event.TEIID31120, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31120, obj));
+ }
+ TempMetadataID tid = (TempMetadataID)es.getMetadataID();
+ if (tid.getType() != Exception.class) {
+ throw new QueryResolverException(QueryPlugin.Event.TEIID31120, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31120, obj));
+ }
+ } else if (obj instanceof Constant) {
+ Constant c = (Constant)obj;
+ if (!(c.getValue() instanceof Exception)) {
+ throw new QueryResolverException(QueryPlugin.Event.TEIID31120, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31120, obj));
+ }
+ } else {
+ throw new QueryResolverException(QueryPlugin.Event.TEIID31120, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31120, obj));
+ }
+ }
+
+ @Override
public void visit(AggregateSymbol obj) {
if (obj.getCondition() != null) {
try {
Modified: trunk/engine/src/main/java/org/teiid/query/sql/LanguageVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/LanguageVisitor.java 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/engine/src/main/java/org/teiid/query/sql/LanguageVisitor.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -110,7 +110,7 @@
visit((AssignmentStatement)obj);
}
public void visit(IfStatement obj) {}
- public void visit(RaiseErrorStatement obj) {}
+ public void visit(RaiseStatement obj) {}
public void visit(BranchingStatement obj) {}
public void visit(WhileStatement obj) {}
public void visit(LoopStatement obj) {}
@@ -145,4 +145,6 @@
public void visit(Array array) {}
public void visit(ObjectTable objectTable) {}
+
+ public void visit(ExceptionExpression obj) {}
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/navigator/PreOrPostOrderNavigator.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/navigator/PreOrPostOrderNavigator.java 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/engine/src/main/java/org/teiid/query/sql/navigator/PreOrPostOrderNavigator.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -310,7 +310,7 @@
visitNode(obj.getOption());
postVisitVisitor(obj);
}
- public void visit(RaiseErrorStatement obj) {
+ public void visit(RaiseStatement obj) {
preVisitVisitor(obj);
visitNode(obj.getExpression());
postVisitVisitor(obj);
@@ -635,6 +635,16 @@
postVisitVisitor(array);
}
+ @Override
+ public void visit(ExceptionExpression exceptionExpression) {
+ preVisitVisitor(exceptionExpression);
+ visitNode(exceptionExpression.getMessage());
+ visitNode(exceptionExpression.getSqlState());
+ visitNode(exceptionExpression.getErrorCode());
+ visitNode(exceptionExpression.getParent());
+ postVisitVisitor(exceptionExpression);
+ }
+
public static void doVisit(LanguageObject object, LanguageVisitor visitor, boolean order) {
doVisit(object, visitor, order, false);
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/proc/DeclareStatement.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/proc/DeclareStatement.java 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/engine/src/main/java/org/teiid/query/sql/proc/DeclareStatement.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -113,9 +113,9 @@
*/
public Object clone() {
if (getValue() == null) {
- return new DeclareStatement((ElementSymbol)this.getVariable().clone(), this.varType);
+ return new DeclareStatement(this.getVariable().clone(), this.varType);
}
- return new DeclareStatement((ElementSymbol)this.getVariable().clone(), this.varType, (Expression)getValue().clone());
+ return new DeclareStatement(this.getVariable().clone(), this.varType, (Expression)getValue().clone());
}
/**
Added: trunk/engine/src/main/java/org/teiid/query/sql/proc/ExceptionExpression.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/proc/ExceptionExpression.java (rev 0)
+++ trunk/engine/src/main/java/org/teiid/query/sql/proc/ExceptionExpression.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -0,0 +1,146 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package org.teiid.query.sql.proc;
+
+import org.teiid.core.types.DataTypeManager;
+import org.teiid.core.util.EquivalenceUtil;
+import org.teiid.core.util.HashCodeUtil;
+import org.teiid.query.sql.LanguageObject;
+import org.teiid.query.sql.LanguageVisitor;
+import org.teiid.query.sql.symbol.Expression;
+import org.teiid.query.sql.visitor.SQLStringVisitor;
+
+public class ExceptionExpression implements Expression, LanguageObject {
+
+ private Expression message;
+ private Expression sqlState;
+ private Expression errorCode;
+ private Expression parent;
+ private boolean warning;
+
+ @Override
+ public Class<?> getType() {
+ return DataTypeManager.DefaultDataClasses.OBJECT;
+ }
+
+ public ExceptionExpression() {
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof ExceptionExpression)) {
+ return false;
+ }
+ ExceptionExpression other = (ExceptionExpression)obj;
+ return EquivalenceUtil.areEqual(message, other.message)
+ && EquivalenceUtil.areEqual(sqlState, other.sqlState)
+ && EquivalenceUtil.areEqual(errorCode, other.errorCode)
+ && EquivalenceUtil.areEqual(parent, other.parent)
+ && warning == other.warning;
+ }
+
+ @Override
+ public int hashCode() {
+ return HashCodeUtil.hashCode(warning?0:1, message, sqlState, errorCode);
+ }
+
+ @Override
+ public String toString() {
+ return SQLStringVisitor.getSQLString(this);
+ }
+
+ @Override
+ public ExceptionExpression clone() {
+ ExceptionExpression clone = new ExceptionExpression();
+ clone.warning = this.warning;
+ if (this.message != null) {
+ clone.message = (Expression) this.message.clone();
+ }
+ if (this.sqlState != null) {
+ clone.sqlState = (Expression) this.sqlState.clone();
+ }
+ if (this.errorCode != null) {
+ clone.errorCode = (Expression) this.errorCode.clone();
+ }
+ if (this.parent != null) {
+ clone.parent = (Expression) this.parent.clone();
+ }
+ return clone;
+ }
+
+ public Expression getErrorCode() {
+ return errorCode;
+ }
+
+ public void setErrorCode(Expression errCode) {
+ this.errorCode = errCode;
+ }
+
+ public Expression getSqlState() {
+ return sqlState;
+ }
+
+ public void setSqlState(Expression sqlState) {
+ this.sqlState = sqlState;
+ }
+
+ public Expression getMessage() {
+ return message;
+ }
+
+ public void setMessage(Expression message) {
+ this.message = message;
+ }
+
+ public Expression getParent() {
+ return parent;
+ }
+
+ public void setParent(Expression parent) {
+ this.parent = parent;
+ }
+
+ public boolean isWarning() {
+ return warning;
+ }
+
+ public void setWarning(boolean warning) {
+ this.warning = warning;
+ }
+
+ @Override
+ public void acceptVisitor(LanguageVisitor visitor) {
+ visitor.visit(this);
+ }
+
+ public String getDefaultSQLState() {
+ if (isWarning()) {
+ return "01000";
+ }
+ return "50001";
+ }
+
+}
Property changes on: trunk/engine/src/main/java/org/teiid/query/sql/proc/ExceptionExpression.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Deleted: trunk/engine/src/main/java/org/teiid/query/sql/proc/RaiseErrorStatement.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/proc/RaiseErrorStatement.java 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/engine/src/main/java/org/teiid/query/sql/proc/RaiseErrorStatement.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -1,102 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA.
- */
-
-package org.teiid.query.sql.proc;
-
-import org.teiid.core.types.DataTypeManager;
-import org.teiid.query.sql.LanguageVisitor;
-import org.teiid.query.sql.symbol.Expression;
-
-
-/**
- * <p> This class represents a error assignment statement in the storedprocedure language.
- * It extends the <code>Statement</code> that could part of a <code>Block</code>. This
- * this object holds and error message.</p>
- */
-public class RaiseErrorStatement extends Statement implements ExpressionStatement {
-
- private Expression expression;
-
- /**
- * Constructor for RaiseErrorStatement.
- */
- public RaiseErrorStatement() {
- super();
- }
-
- /**
- * Constructor for RaiseErrorStatement.
- * @param message The error message
- */
- public RaiseErrorStatement(Expression message) {
- expression = message;
- }
-
- public void acceptVisitor(LanguageVisitor visitor) {
- visitor.visit(this);
- }
-
- public Expression getExpression() {
- return expression;
- }
-
- public void setExpression(Expression expression) {
- this.expression = expression;
- }
-
- /**
- * @see org.teiid.query.sql.proc.AssignmentStatement#getType()
- */
- public int getType() {
- return TYPE_ERROR;
- }
-
- @Override
- public RaiseErrorStatement clone() {
- return new RaiseErrorStatement((Expression) this.expression.clone());
- }
-
- @Override
- public int hashCode() {
- return expression.hashCode();
- }
-
- public boolean equals(Object obj) {
- if (obj == this) {
- return true;
- }
-
- if (!(obj instanceof RaiseErrorStatement)) {
- return false;
- }
-
- RaiseErrorStatement other = (RaiseErrorStatement)obj;
-
- return other.expression.equals(this.expression);
- }
-
- @Override
- public Class<?> getExpectedType() {
- return DataTypeManager.DefaultDataClasses.STRING;
- }
-
-} // END CLASS
\ No newline at end of file
Copied: trunk/engine/src/main/java/org/teiid/query/sql/proc/RaiseStatement.java (from rev 4461, trunk/engine/src/main/java/org/teiid/query/sql/proc/RaiseErrorStatement.java)
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/proc/RaiseStatement.java (rev 0)
+++ trunk/engine/src/main/java/org/teiid/query/sql/proc/RaiseStatement.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -0,0 +1,95 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package org.teiid.query.sql.proc;
+
+import org.teiid.core.types.DataTypeManager;
+import org.teiid.query.sql.LanguageVisitor;
+import org.teiid.query.sql.symbol.Expression;
+
+
+/**
+ * <p> This class represents a error assignment statement in the storedprocedure language.
+ * It extends the <code>Statement</code> that could part of a <code>Block</code>. This
+ * this object holds and error message.</p>
+ */
+public class RaiseStatement extends Statement implements ExpressionStatement {
+
+ private Expression expression;
+
+ public RaiseStatement() {
+ }
+
+ /**
+ * Constructor for RaiseErrorStatement.
+ * @param message The error message
+ */
+ public RaiseStatement(Expression message) {
+ expression = message;
+ }
+
+ public void acceptVisitor(LanguageVisitor visitor) {
+ visitor.visit(this);
+ }
+
+ public Expression getExpression() {
+ return expression;
+ }
+
+ public void setExpression(Expression expression) {
+ this.expression = expression;
+ }
+
+ public int getType() {
+ return TYPE_ERROR;
+ }
+
+ @Override
+ public RaiseStatement clone() {
+ return new RaiseStatement((Expression) this.expression.clone());
+ }
+
+ @Override
+ public int hashCode() {
+ return expression.hashCode();
+ }
+
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+
+ if (!(obj instanceof RaiseStatement)) {
+ return false;
+ }
+
+ RaiseStatement other = (RaiseStatement)obj;
+
+ return other.expression.equals(this.expression);
+ }
+
+ @Override
+ public Class<?> getExpectedType() {
+ return DataTypeManager.DefaultDataClasses.OBJECT;
+ }
+
+} // END CLASS
\ No newline at end of file
Modified: trunk/engine/src/main/java/org/teiid/query/sql/visitor/ExpressionMappingVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/visitor/ExpressionMappingVisitor.java 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/engine/src/main/java/org/teiid/query/sql/visitor/ExpressionMappingVisitor.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -39,6 +39,7 @@
import org.teiid.query.sql.navigator.PreOrPostOrderNavigator;
import org.teiid.query.sql.navigator.PreOrderNavigator;
import org.teiid.query.sql.proc.AssignmentStatement;
+import org.teiid.query.sql.proc.ExceptionExpression;
import org.teiid.query.sql.symbol.*;
@@ -445,4 +446,20 @@
}
}
+ @Override
+ public void visit(ExceptionExpression exceptionExpression) {
+ if (exceptionExpression.getMessage() != null) {
+ exceptionExpression.setMessage(replaceExpression(exceptionExpression.getMessage()));
+ }
+ if (exceptionExpression.getSqlState() != null) {
+ exceptionExpression.setSqlState(replaceExpression(exceptionExpression.getSqlState()));
+ }
+ if (exceptionExpression.getErrorCode() != null) {
+ exceptionExpression.setErrorCode(replaceExpression(exceptionExpression.getErrorCode()));
+ }
+ if (exceptionExpression.getParent() != null) {
+ exceptionExpression.setParent(replaceExpression(exceptionExpression.getParent()));
+ }
+ }
+
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -1461,12 +1461,40 @@
createAssignment(obj);
}
- public void visit( RaiseErrorStatement obj ) {
- append(ERROR);
+ public void visit( RaiseStatement obj ) {
+ append(NonReserved.RAISE);
append(SPACE);
visitNode(obj.getExpression());
append(";"); //$NON-NLS-1$
}
+
+ @Override
+ public void visit(ExceptionExpression exceptionExpression) {
+ if (exceptionExpression.isWarning()) {
+ append(SQLWARNING);
+ } else {
+ append(SQLEXCEPTION);
+ }
+ append(SPACE);
+ visitNode(exceptionExpression.getMessage());
+ if (exceptionExpression.getSqlState() != null) {
+ append(SPACE);
+ append(SQLSTATE);
+ append(SPACE);
+ append(exceptionExpression.getSqlState());
+ if (exceptionExpression.getErrorCode() != null) {
+ append(Tokens.COMMA);
+ append(SPACE);
+ append(exceptionExpression.getErrorCode());
+ }
+ }
+ if (exceptionExpression.getParent() != null) {
+ append(SPACE);
+ append(NonReserved.EXCEPTION);
+ append(SPACE);
+ append(exceptionExpression.getParent());
+ }
+ }
public void visit( BranchingStatement obj ) {
switch (obj.getMode()) {
Modified: trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
===================================================================
--- trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2012-09-24 15:36:49 UTC (rev 4466)
@@ -455,6 +455,8 @@
| <EXCLUDING: "excluding">
| <XMLDECLARATION: "xmldeclaration">
| <VARIADIC: "variadic">
+| <EXCEPTION: "exception">
+| <RAISE: "raise">
}
/*
@@ -562,7 +564,7 @@
|<TO_BYTES>|<TIMESTAMPADD>|<TIMESTAMPDIFF>|<QUERYSTRING>|<NAMESPACE>|<RESULT>|<INDEX>|<ACCESSPATTERN>|<AUTO_INCREMENT>|<WELLFORMED>|<SQL_TSI_FRAC_SECOND>
|<SQL_TSI_SECOND>|<SQL_TSI_MINUTE>|<SQL_TSI_HOUR>|<SQL_TSI_DAY>|<SQL_TSI_WEEK>|<SQL_TSI_MONTH>|<SQL_TSI_QUARTER>|<SQL_TSI_YEAR>|<TEXTTABLE>|<ARRAYTABLE>
|<SELECTOR>|<SKIP_KEYWORD>|<WIDTH>|<PASSING>|<NAME>|<ENCODING>|<COLUMNS>|<DELIMITER>|<QUOTE>|<HEADER>|<NULLS>|<OBJECTTABLE>
- |<VERSION>|<INCLUDING>|<EXCLUDING>|<XMLDECLARATION>|<VARIADIC>)
+ |<VERSION>|<INCLUDING>|<EXCLUDING>|<XMLDECLARATION>|<VARIADIC>|<RAISE>|<EXCEPTION>)
{
return getToken(0);
}
@@ -760,7 +762,7 @@
sourceHint = getSourceHint(t);
}
(command = queryExpression(info) |
- command = storedProcedure(info, new StoredProcedure()) |
+ command = storedProcedure(info, 1) |
command = insert(info) |
command = update(info) |
command = delete(info) |
@@ -885,7 +887,7 @@
description=Raises an error with the given message.
example={code:sql}ERROR 'something went wrong'{code}
*/
-RaiseErrorStatement errorStatement(ParseInfo info) :
+RaiseStatement errorStatement(ParseInfo info) :
{
Expression errMsg = null;
}
@@ -894,12 +896,80 @@
errMsg = expression(info)
{
- RaiseErrorStatement errStmt = new RaiseErrorStatement(errMsg);
- return errStmt;
+ ExceptionExpression ee = new ExceptionExpression();
+ ee.setMessage(errMsg);
+ return new RaiseStatement(ee);
}
}
/*
+name=raise statement
+description=Raises an error or warning with the given message.
+example={code:sql}RAISE SQLEXCEPTION '00A' 'something went wrong'{code}
+*/
+RaiseStatement raiseStatement(ParseInfo info) :
+{
+ Expression err = null;
+}
+{
+ <RAISE>
+ err = exceptionReference(info)
+ {
+ return new RaiseStatement(err);
+ }
+}
+
+/*
+name=exception reference
+description=a reference to an exception
+example={code:sql}SQLEXCEPTION 'something went wrong' SQLSTATE '00X', 2{code}
+*/
+Expression exceptionReference(ParseInfo info) :
+{
+ String id = null;
+ Expression ex;
+}
+{
+ id = id() {return new ElementSymbol(id);}
+ |
+ ex = exception(info)
+ {
+ return ex;
+ }
+}
+
+/*
+name=sql exception
+description=creates a sql exception or warning with the specified message, state, and code
+example={code:sql}SQLEXCEPTION 'something went wrong' SQLSTATE '00X', 2{code}
+*/
+Expression exception(ParseInfo info) :
+{
+ Expression err = null;
+ Expression sqlState = null;
+ Expression errCode = null;
+ Expression parent = null;
+ boolean warning = false;
+}
+{
+ (<SQLWARNING> {warning=true;}|<SQLEXCEPTION>)
+ err = commonValueExpression(info)
+ [<SQLSTATE> sqlState = commonValueExpression(info)
+ [<COMMA> errCode = commonValueExpression(info)]
+ ]
+ [<EXCEPTION> parent = exceptionReference(info)]
+ {
+ ExceptionExpression ee = new ExceptionExpression();
+ ee.setMessage(err);
+ ee.setSqlState(sqlState);
+ ee.setErrorCode(errCode);
+ ee.setParent(parent);
+ ee.setWarning(warning);
+ return ee;
+ }
+}
+
+/*
name=statement
description=A procedure statement.
example={code:sql}IF (x = 5) BEGIN ... END{code}
@@ -943,9 +1013,10 @@
Statement stmt = null;
}
{
- (LOOKAHEAD(3) stmt = assignStatement(info) |
+ (stmt = assignStatement(info) |
stmt = sqlStatement(info) |
stmt = errorStatement(info) |
+ stmt = raiseStatement(info) |
stmt = declareStatement(info) |
stmt = branchingStatement(info)
)
@@ -1101,7 +1172,7 @@
}
{
<DECLARE>
- type = parseDataType()
+ (type = parseDataType() | <EXCEPTION> {type = new ParsedDataType(getToken(0).image);})
var = id()
{
variableID = new ElementSymbol(var);
@@ -1126,19 +1197,28 @@
description=Assigns a variable a value in a procedure.
example={code:sql}x := 'b'{code}
*/
-AssignmentStatement assignStatement(ParseInfo info) :
+Statement assignStatement(ParseInfo info) :
{
LanguageObject value = null;
- String var = null;
+ Token var = null;
ElementSymbol elementID = null;
}
{
- var = id()
+ var = <ID>
{
- elementID = new ElementSymbol(var);
+ elementID = new ElementSymbol(normalizeId(var.image));
}
[<COLON>]<EQ>
- value = assignStatementOperand(info)
+ (value = assignStatementOperand(info) |
+ value = storedProcedure(info, 2) {
+ StoredProcedure storedProcedure = (StoredProcedure)value;
+ SPParameter parameter = new SPParameter(1, SPParameter.RETURN_VALUE, "return"); //$NON-NLS-1$
+ parameter.setExpression(elementID);
+ storedProcedure.setParameter(parameter);
+ storedProcedure.setCalledWithReturn(true);
+ return new CommandStatement(storedProcedure);
+ }
+ )
{
if (value instanceof Expression) {
@@ -1160,15 +1240,14 @@
LanguageObject value = null;
}
{
-
(
LOOKAHEAD(<INSERT><INTO>) (value = insert(info)) | //deprecated
value = update(info) | //deprecated
value = delete(info) | //deprecated
- LOOKAHEAD(expression(info)) (value = expression(info)) |
- value = queryExpression(info) //deprecated should be a scalar subquery
+ LOOKAHEAD(1) value = expression(info) |
+ value = queryExpression(info) | //deprecated should be a scalar subquery
+ value = exception(info)
)
-
{
return value;
}
@@ -1180,33 +1259,18 @@
*/
CommandStatement sqlStatement(ParseInfo info) :
{
- CommandStatement cmdStmt = null;
Command cmd = null;
String var = null;
ElementSymbol elementID = null;
StoredProcedure storedProcedure = null;
}
{
- (LOOKAHEAD(2) (cmd = userCommand(info)) |
- cmd = dynamicCommand(info) |
- (
- var = id()
- {
- storedProcedure = new StoredProcedure();
- elementID = new ElementSymbol(var);
- SPParameter parameter = new SPParameter(1, SPParameter.RETURN_VALUE, "return"); //$NON-NLS-1$
- parameter.setExpression(elementID);
- storedProcedure.setParameter(parameter);
- storedProcedure.setCalledWithReturn(true);
- }
- [<COLON>]<EQ>
- cmd = storedProcedure(info, storedProcedure)
- )
+ (LOOKAHEAD(2) cmd = userCommand(info) |
+ cmd = dynamicCommand(info)
)
{
- cmdStmt = new CommandStatement(cmd);
- return cmdStmt;
+ return new CommandStatement(cmd);
}
}
@@ -1409,7 +1473,7 @@
//parameters
[<LPAREN>
- [values = expressionList(info) { convertToParameters(values, storedProcedure); }]
+ [values = expressionList(info) { convertToParameters(values, storedProcedure, parameterIndex); }]
<RPAREN>
]
<RBRACE>
@@ -1429,11 +1493,12 @@
description=Executes the procedure with the given parameters.
example={code:sql}CALL proc('a', 1){code}
*/
-StoredProcedure storedProcedure(ParseInfo info, StoredProcedure storedProcedure) :
+StoredProcedure storedProcedure(ParseInfo info, int startIndex) :
{
String procName = null;
Option option = null;
List<Expression> values = null;
+ StoredProcedure storedProcedure = new StoredProcedure();
}
{
(
@@ -1448,9 +1513,9 @@
(
LOOKAHEAD(2)
- executeNamedParams(info, storedProcedure)
+ executeNamedParams(info, storedProcedure, startIndex)
|
- [values = expressionList(info) { convertToParameters(values, storedProcedure); }]
+ [values = expressionList(info) { convertToParameters(values, storedProcedure, startIndex); }]
)
<RPAREN>
@@ -1470,12 +1535,11 @@
description=A list of named parameters.
example={code:sql}param1 => 'x', param2 => 1{code}
*/
-void executeNamedParams(ParseInfo info, StoredProcedure storedProcedure) :
+void executeNamedParams(ParseInfo info, StoredProcedure storedProcedure, int parameterIndex) :
{
String name = null;
Expression value = null;
SPParameter parameter = null;
- int parameterIndex = 1;
}
{
{
@@ -2788,7 +2852,7 @@
]
lparen = <LPAREN>
( command = queryExpression(info) |
- command = storedProcedure(info, new StoredProcedure()) )
+ command = storedProcedure(info, 1) )
<RPAREN>
[<AS>]
aliasID = id()
@@ -3033,7 +3097,7 @@
<LPAREN>
( subquery = queryExpression(info) |
(
- proc = storedProcedure(info, new StoredProcedure()) //deprecated
+ proc = storedProcedure(info, 1) //deprecated
)
{
subquery = new Query(new Select(Arrays.asList(new MultipleElementSymbol())), new From(Arrays.asList(new SubqueryFromClause("x", proc))), null, null, null);
Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2012-09-24 15:36:49 UTC (rev 4466)
@@ -1032,6 +1032,7 @@
TEIID31114=Function based index {1} expression {0} cannot contain subqueries.
TEIID31115=Function based index {1} expression {0} is not deterministic.
TEIID31116=Function based index {1} expression {0} could not be resolved: {2}
+TEIID31120=An exception may only be chained to another exception. {0} is not valid.
SQLParser.proc_type_conflict=Result type {1} conflicts with return type {2} for procedure {0}
SQLParser.param_out=Procedure {0} RESULT param {1} must be of type OUT.
Modified: trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestDQPCoreRequestHandling.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestDQPCoreRequestHandling.java 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestDQPCoreRequestHandling.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -119,21 +119,6 @@
addRequest(rm, r0, requestID, null, null);
}
- public void testWarnings1() {
- DQPCore rm = new DQPCore();
- rm.setTransactionService(new FakeTransactionService());
- RequestMessage r0 = new RequestMessage("foo"); //$NON-NLS-1$
- RequestID requestID = new RequestID(SESSION_STRING, 1);
-
- RequestWorkItem workItem = addRequest(rm, r0, requestID, null, null);
-
- workItem.addSourceFailureDetails(getSourceFailures("Model1", "Binding1", "Warning1")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- workItem.addSourceFailureDetails(getSourceFailures("Model2", "Binding2", "Warning2")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- workItem.addSourceFailureDetails(getSourceFailures("Model3", "Binding3", "Warning3")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-
- assertEquals(3, workItem.getWarnings().size());
- }
-
static RequestWorkItem addRequest(DQPCore rm,
RequestMessage requestMsg,
RequestID id,
Modified: trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestDataTierManager.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestDataTierManager.java 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestDataTierManager.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -124,6 +124,7 @@
AtomicRequestMessage request = new AtomicRequestMessage(original, workContext, nodeId);
request.setCommand(command);
request.setConnectorName("FakeConnectorID"); //$NON-NLS-1$
+ request.setCommandContext(context);
return request;
}
@@ -187,8 +188,9 @@
assertEquals(10, pullTuples(info, 10));
assertNotNull(workItem.getConnectorRequest(info.getAtomicRequestMessage().getAtomicRequestID()));
assertNull(info.nextTuple());
- assertEquals(1, workItem.getWarnings().size());
- SourceWarning warning = (SourceWarning) workItem.getWarnings().get(0);
+ List<Exception> warnings = context.getAndClearWarnings();
+ assertEquals(1, warnings.size());
+ SourceWarning warning = (SourceWarning) warnings.get(0);
assertFalse(warning.isPartialResultsError());
info.closeSource();
assertNull(workItem.getConnectorRequest(info.getAtomicRequestMessage().getAtomicRequestID()));
@@ -229,7 +231,7 @@
for (int i = 0; i < 10; i++) {
try {
assertNull(info.nextTuple());
- SourceWarning warning = (SourceWarning) workItem.getWarnings().get(0);
+ SourceWarning warning = (SourceWarning) context.getAndClearWarnings().get(0);
assertTrue(warning.isPartialResultsError());
return;
} catch (BlockedException e) {
Modified: trunk/engine/src/test/java/org/teiid/query/metadata/TestDDLStringVisitor.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/metadata/TestDDLStringVisitor.java 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/engine/src/test/java/org/teiid/query/metadata/TestDDLStringVisitor.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -29,12 +29,12 @@
import java.util.Properties;
import org.junit.Test;
+import org.teiid.api.exception.query.QueryParserException;
import org.teiid.metadata.Column;
import org.teiid.metadata.MetadataFactory;
import org.teiid.metadata.Schema;
import org.teiid.metadata.Table;
import org.teiid.metadata.BaseColumn.NullType;
-import org.teiid.query.parser.ParseException;
import org.teiid.query.parser.TestDDLParser;
@SuppressWarnings("nls")
@@ -243,7 +243,7 @@
helpTest(ddl, expected);
}
- private void helpTest(String ddl, String expected) throws ParseException {
+ private void helpTest(String ddl, String expected) throws QueryParserException {
Schema s = TestDDLParser.helpParse(ddl, "model").getSchema();
String metadataDDL = DDLStringVisitor.getDDLString(s, null, null);
assertEquals(expected, metadataDDL);
Modified: trunk/engine/src/test/java/org/teiid/query/parser/TestDDLParser.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/parser/TestDDLParser.java 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/engine/src/test/java/org/teiid/query/parser/TestDDLParser.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -29,6 +29,7 @@
import org.junit.Test;
import org.teiid.adminapi.impl.ModelMetaData;
import org.teiid.adminapi.impl.VDBMetaData;
+import org.teiid.api.exception.query.QueryParserException;
import org.teiid.metadata.*;
import org.teiid.metadata.BaseColumn.NullType;
import org.teiid.query.metadata.MetadataValidator;
@@ -116,7 +117,7 @@
assertEquals("hello", e6.getDefaultValue());
}
- @Test(expected=ParseException.class)
+ @Test(expected=QueryParserException.class)
public void testDuplicatePrimarykey() throws Exception {
String ddl = "CREATE FOREIGN TABLE G1( e1 integer primary key, e2 varchar primary key)";
MetadataStore mds = new MetadataStore();
@@ -214,7 +215,7 @@
assertEquals(table.getColumns().subList(1, 3), table.getAccessPatterns().get(1).getColumns());
}
- @Test(expected=ParseException.class)
+ @Test(expected=QueryParserException.class)
public void testWrongPrimarykey() throws Exception {
String ddl = "CREATE FOREIGN TABLE G1( e1 integer, e2 varchar, PRIMARY KEY (e3))";
@@ -339,7 +340,7 @@
assertEquals(fk.getPrimaryKey().getColumns(), s.getSchema("model").getTable("G1").getColumns());
}
- @Test(expected=ParseException.class)
+ @Test(expected=QueryParserException.class)
public void testTableWithPlan() throws Exception {
String ddl = "CREATE foreign table G1 as select 1";
MetadataStore mds = new MetadataStore();
@@ -513,7 +514,7 @@
assertEquals("boolean", fm.getInputParameters().get(0).getType());
}
- @Test(expected=ParseException.class) public void testInvalidFunctionBody() throws Exception {
+ @Test(expected=QueryParserException.class) public void testInvalidFunctionBody() throws Exception {
String ddl = "CREATE FUNCTION SourceFunc(flag boolean) RETURNS varchar AS SELECT 'a';";
Schema s = helpParse(ddl, "model").getSchema();
@@ -522,7 +523,7 @@
assertTrue( fm.getInputParameters().get(0).isVarArg());
}
- @Test(expected=ParseException.class) public void testInvalidProcedureBody() throws Exception {
+ @Test(expected=QueryParserException.class) public void testInvalidProcedureBody() throws Exception {
String ddl = "CREATE FOREIGN PROCEDURE SourceFunc(flag boolean) RETURNS varchar AS SELECT 'a';";
Schema s = helpParse(ddl, "model").getSchema();
@@ -650,7 +651,7 @@
assertEquals("http://teiid.org", mf.getNamespaces().get("teiid"));
}
- public static MetadataFactory helpParse(String ddl, String model) throws ParseException {
+ public static MetadataFactory helpParse(String ddl, String model) throws QueryParserException {
MetadataFactory mf = new MetadataFactory(null, 1, model, getDataTypes(), new Properties(), null);
QueryParser.getQueryParser().parseDDL(mf, ddl);
return mf;
Modified: trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -3010,12 +3010,26 @@
}
@Test public void testErrorStatement() throws Exception {
- RaiseErrorStatement errStmt = new RaiseErrorStatement(new Constant("Test only")); //$NON-NLS-1$
+ ExceptionExpression ee = new ExceptionExpression();
+ ee.setMessage(new Constant("Test only"));
+ RaiseStatement errStmt = new RaiseStatement(ee);
- helpStmtTest("ERROR 'Test only';", "ERROR 'Test only';", //$NON-NLS-1$ //$NON-NLS-2$
+ helpStmtTest("ERROR 'Test only';", "RAISE SQLEXCEPTION 'Test only';", //$NON-NLS-1$ //$NON-NLS-2$
errStmt);
}
+ @Test public void testRaiseErrorStatement() throws Exception {
+ ExceptionExpression ee = new ExceptionExpression();
+ ee.setMessage(new Constant("Test only"));
+ ee.setWarning(true);
+ ee.setSqlState(new Constant("100"));
+ ee.setParent(new ElementSymbol("e"));
+ RaiseStatement errStmt = new RaiseStatement(ee);
+
+ helpStmtTest("RAISE SQLWARNING 'Test only' SQLSTATE '100' EXCEPTION e;", "RAISE SQLWARNING 'Test only' SQLSTATE '100' EXCEPTION e;", //$NON-NLS-1$ //$NON-NLS-2$
+ errStmt);
+ }
+
@Test public void testIfStatement() throws Exception {
ElementSymbol a = new ElementSymbol("a"); //$NON-NLS-1$
String shortType = new String("short"); //$NON-NLS-1$
Added: trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcErrors.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcErrors.java (rev 0)
+++ trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcErrors.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -0,0 +1,78 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package org.teiid.query.processor.proc;
+
+import static org.junit.Assert.*;
+import static org.teiid.query.processor.proc.TestProcedureProcessor.*;
+
+import org.junit.Test;
+import org.teiid.core.TeiidProcessingException;
+import org.teiid.jdbc.TeiidSQLException;
+import org.teiid.jdbc.TeiidSQLWarning;
+import org.teiid.query.metadata.TransformationMetadata;
+import org.teiid.query.processor.HardcodedDataManager;
+import org.teiid.query.processor.ProcessorPlan;
+import org.teiid.query.resolver.TestProcedureResolving;
+
+@SuppressWarnings("nls")
+public class TestProcErrors {
+
+ @Test public void testInvalidException() throws Exception {
+ String ddl =
+ "create virtual procedure vproc (x integer) returns integer as begin declare object e = sqlwarning 'hello'; raise e; raise sqlexception 'hello world' sqlstate 'abc', 1 exception e; end;";
+ try {
+ TestProcedureResolving.createMetadata(ddl);
+ fail();
+ } catch (RuntimeException e) {
+ assertEquals("TEIID31080 View test.vproc validation error: QueryResolverException-TEIID31120 An exception may only be chained to another exception. e is not valid.", e.getMessage());
+ }
+ }
+
+ @Test public void testExceptionAndWarning() throws Exception {
+ String ddl =
+ "create virtual procedure vproc (x integer) returns integer as begin declare exception e = sqlwarning 'hello'; raise e; raise sqlexception 'hello world' sqlstate 'abc', 1 exception e; end;";
+ TransformationMetadata tm = TestProcedureResolving.createMetadata(ddl);
+
+ String sql = "call vproc(1)"; //$NON-NLS-1$
+
+ ProcessorPlan plan = getProcedurePlan(sql, tm);
+
+ HardcodedDataManager dataManager = new HardcodedDataManager(tm);
+
+ try {
+ helpTestProcess(plan, null, dataManager, tm);
+ fail();
+ } catch (TeiidProcessingException e) {
+ TeiidSQLWarning tsw = (TeiidSQLWarning) plan.getContext().getAndClearWarnings().get(0);
+ assertEquals("hello", tsw.getMessage());
+
+ assertEquals(e.getCause().getCause(), tsw);
+ TeiidSQLException tse = (TeiidSQLException)e.getCause();
+ assertEquals("hello world", tse.getMessage());
+ assertEquals("abc", tse.getSQLState());
+ assertEquals(1, tse.getErrorCode());
+ }
+
+ }
+
+}
Property changes on: trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcErrors.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Modified: trunk/engine/src/test/java/org/teiid/query/sql/proc/TestRaiseErrorStatement.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/sql/proc/TestRaiseErrorStatement.java 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/engine/src/test/java/org/teiid/query/sql/proc/TestRaiseErrorStatement.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -23,7 +23,7 @@
package org.teiid.query.sql.proc;
import org.teiid.core.util.UnitTestUtil;
-import org.teiid.query.sql.proc.RaiseErrorStatement;
+import org.teiid.query.sql.proc.RaiseStatement;
import org.teiid.query.sql.symbol.Constant;
import junit.framework.*;
@@ -43,32 +43,32 @@
// ################################## TEST HELPERS ################################
- public static final RaiseErrorStatement sample1() {
- return new RaiseErrorStatement(new Constant("a")); //$NON-NLS-1$
+ public static final RaiseStatement sample1() {
+ return new RaiseStatement(new Constant("a")); //$NON-NLS-1$
}
- public static final RaiseErrorStatement sample2() {
- return new RaiseErrorStatement(new Constant("b")); //$NON-NLS-1$
+ public static final RaiseStatement sample2() {
+ return new RaiseStatement(new Constant("b")); //$NON-NLS-1$
}
// ################################## ACTUAL TESTS ################################
public void testSelfEquivalence(){
- RaiseErrorStatement s1 = sample1();
+ RaiseStatement s1 = sample1();
int equals = 0;
UnitTestUtil.helpTestEquivalence(equals, s1, s1);
}
public void testEquivalence(){
- RaiseErrorStatement s1 = sample1();
- RaiseErrorStatement s1a = sample1();
+ RaiseStatement s1 = sample1();
+ RaiseStatement s1a = sample1();
int equals = 0;
UnitTestUtil.helpTestEquivalence(equals, s1, s1a);
}
public void testNonEquivalence(){
- RaiseErrorStatement s1 = sample1();
- RaiseErrorStatement s2 = sample2();
+ RaiseStatement s1 = sample1();
+ RaiseStatement s2 = sample2();
int equals = -1;
UnitTestUtil.helpTestEquivalence(equals, s1, s2);
}
Modified: trunk/engine/src/test/java/org/teiid/query/sql/visitor/TestSQLStringVisitor.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/sql/visitor/TestSQLStringVisitor.java 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/engine/src/test/java/org/teiid/query/sql/visitor/TestSQLStringVisitor.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -44,7 +44,7 @@
import org.teiid.query.sql.proc.CommandStatement;
import org.teiid.query.sql.proc.CreateProcedureCommand;
import org.teiid.query.sql.proc.DeclareStatement;
-import org.teiid.query.sql.proc.RaiseErrorStatement;
+import org.teiid.query.sql.proc.RaiseStatement;
import org.teiid.query.sql.symbol.*;
import org.teiid.query.unittest.RealMetadataFactory;
import org.teiid.translator.TypeFacility;
@@ -1341,13 +1341,13 @@
}
@Test public void testRaiseErrorStatement() {
- RaiseErrorStatement errStmt = new RaiseErrorStatement(new Constant("My Error")); //$NON-NLS-1$
- helpTest(errStmt, "ERROR 'My Error';"); //$NON-NLS-1$
+ RaiseStatement errStmt = new RaiseStatement(new Constant("My Error")); //$NON-NLS-1$
+ helpTest(errStmt, "RAISE 'My Error';"); //$NON-NLS-1$
}
@Test public void testRaiseErrorStatementWithExpression() {
- RaiseErrorStatement errStmt = new RaiseErrorStatement(new ElementSymbol("a")); //$NON-NLS-1$
- helpTest(errStmt, "ERROR a;"); //$NON-NLS-1$
+ RaiseStatement errStmt = new RaiseStatement(new ElementSymbol("a")); //$NON-NLS-1$
+ helpTest(errStmt, "RAISE a;"); //$NON-NLS-1$
}
@Test public void testAssignmentStatement1() {
@@ -1393,12 +1393,12 @@
d1.setGroup(new GroupSymbol("g")); //$NON-NLS-1$
CommandStatement cmdStmt = new CommandStatement(d1);
AssignmentStatement assigStmt = new AssignmentStatement(new ElementSymbol("a"), new Constant(new Integer(1))); //$NON-NLS-1$
- RaiseErrorStatement errStmt = new RaiseErrorStatement(new Constant("My Error")); //$NON-NLS-1$
+ RaiseStatement errStmt = new RaiseStatement(new Constant("My Error")); //$NON-NLS-1$
Block b = new Block();
b.addStatement(cmdStmt);
b.addStatement(assigStmt);
b.addStatement(errStmt);
- helpTest(b, "BEGIN\nDELETE FROM g;\na = 1;\nERROR 'My Error';\nEND"); //$NON-NLS-1$
+ helpTest(b, "BEGIN\nDELETE FROM g;\na = 1;\nRAISE 'My Error';\nEND"); //$NON-NLS-1$
}
@Test public void testCreateUpdateProcedure1() {
@@ -1406,13 +1406,13 @@
d1.setGroup(new GroupSymbol("g")); //$NON-NLS-1$
CommandStatement cmdStmt = new CommandStatement(d1);
AssignmentStatement assigStmt = new AssignmentStatement(new ElementSymbol("a"), new Constant(new Integer(1))); //$NON-NLS-1$
- RaiseErrorStatement errStmt = new RaiseErrorStatement(new Constant("My Error")); //$NON-NLS-1$
+ RaiseStatement errStmt = new RaiseStatement(new Constant("My Error")); //$NON-NLS-1$
Block b = new Block();
b.addStatement(cmdStmt);
b.addStatement(assigStmt);
b.addStatement(errStmt);
CreateProcedureCommand cup = new CreateProcedureCommand(b);
- helpTest(cup, "CREATE VIRTUAL PROCEDURE\nBEGIN\nDELETE FROM g;\na = 1;\nERROR 'My Error';\nEND"); //$NON-NLS-1$
+ helpTest(cup, "CREATE VIRTUAL PROCEDURE\nBEGIN\nDELETE FROM g;\na = 1;\nRAISE 'My Error';\nEND"); //$NON-NLS-1$
}
@Test public void testCreateUpdateProcedure2() {
@@ -1420,13 +1420,13 @@
d1.setGroup(new GroupSymbol("g")); //$NON-NLS-1$
CommandStatement cmdStmt = new CommandStatement(d1);
AssignmentStatement assigStmt = new AssignmentStatement(new ElementSymbol("a"), new Constant(new Integer(1))); //$NON-NLS-1$
- RaiseErrorStatement errStmt = new RaiseErrorStatement(new Constant("My Error")); //$NON-NLS-1$
+ RaiseStatement errStmt = new RaiseStatement(new Constant("My Error")); //$NON-NLS-1$
Block b = new Block();
b.addStatement(cmdStmt);
b.addStatement(assigStmt);
b.addStatement(errStmt);
CreateProcedureCommand cup = new CreateProcedureCommand(b);
- helpTest(cup, "CREATE VIRTUAL PROCEDURE\nBEGIN\nDELETE FROM g;\na = 1;\nERROR 'My Error';\nEND"); //$NON-NLS-1$
+ helpTest(cup, "CREATE VIRTUAL PROCEDURE\nBEGIN\nDELETE FROM g;\na = 1;\nRAISE 'My Error';\nEND"); //$NON-NLS-1$
}
@Test public void testCreateUpdateProcedure3() {
@@ -1434,13 +1434,13 @@
d1.setGroup(new GroupSymbol("g")); //$NON-NLS-1$
CommandStatement cmdStmt = new CommandStatement(d1);
AssignmentStatement assigStmt = new AssignmentStatement(new ElementSymbol("a"), new Constant(new Integer(1))); //$NON-NLS-1$
- RaiseErrorStatement errStmt = new RaiseErrorStatement(new Constant("My Error")); //$NON-NLS-1$
+ RaiseStatement errStmt = new RaiseStatement(new Constant("My Error")); //$NON-NLS-1$
Block b = new Block();
b.addStatement(cmdStmt);
b.addStatement(assigStmt);
b.addStatement(errStmt);
CreateProcedureCommand cup = new CreateProcedureCommand(b);
- helpTest(cup, "CREATE VIRTUAL PROCEDURE\nBEGIN\nDELETE FROM g;\na = 1;\nERROR 'My Error';\nEND"); //$NON-NLS-1$
+ helpTest(cup, "CREATE VIRTUAL PROCEDURE\nBEGIN\nDELETE FROM g;\na = 1;\nRAISE 'My Error';\nEND"); //$NON-NLS-1$
}
@Test public void testSubqueryCompareCriteria1() {
Modified: trunk/jboss-integration/src/test/java/org/teiid/jboss/rest/TestRestWebArchiveBuilder.java
===================================================================
--- trunk/jboss-integration/src/test/java/org/teiid/jboss/rest/TestRestWebArchiveBuilder.java 2012-09-23 18:36:52 UTC (rev 4465)
+++ trunk/jboss-integration/src/test/java/org/teiid/jboss/rest/TestRestWebArchiveBuilder.java 2012-09-24 15:36:49 UTC (rev 4466)
@@ -21,28 +21,24 @@
*/
package org.teiid.jboss.rest;
+import static org.junit.Assert.*;
+
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.util.ArrayList;
-import java.util.Map;
-import java.util.Properties;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import org.junit.Test;
-import static org.junit.Assert.*;
import org.teiid.adminapi.impl.ModelMetaData;
import org.teiid.adminapi.impl.VDBMetaData;
import org.teiid.adminapi.impl.VDBMetadataParser;
import org.teiid.core.util.UnitTestUtil;
-import org.teiid.metadata.Datatype;
import org.teiid.metadata.MetadataFactory;
import org.teiid.metadata.MetadataStore;
import org.teiid.query.metadata.QueryMetadataInterface;
-import org.teiid.query.metadata.SystemMetadata;
import org.teiid.query.metadata.TransformationMetadata;
-import org.teiid.query.parser.ParseException;
-import org.teiid.query.parser.QueryParser;
+import org.teiid.query.parser.TestDDLParser;
import org.teiid.query.unittest.RealMetadataFactory;
@SuppressWarnings("nls")
@@ -53,7 +49,7 @@
VDBMetaData vdb = VDBMetadataParser.unmarshell(new FileInputStream(UnitTestUtil.getTestDataFile("sample-vdb.xml")));
MetadataStore ms = new MetadataStore();
for (ModelMetaData model: vdb.getModelMetaDatas().values()) {
- MetadataFactory mf = buildMetadataFactory(model.getSchemaText(), model.getName());
+ MetadataFactory mf = TestDDLParser.helpParse(model.getSchemaText(), model.getName());
ms.addSchema(mf.getSchema());
}
@@ -80,14 +76,4 @@
}
}
-
- public MetadataFactory buildMetadataFactory(String ddl, String model) throws ParseException {
- MetadataFactory mf = new MetadataFactory(null, 1, model, getDataTypes(), new Properties(), null);
- new QueryParser().parseDDL(mf, ddl);
- return mf;
- }
-
- static Map<String, Datatype> getDataTypes() {
- return SystemMetadata.getInstance().getRuntimeTypeMap();
- }
}
13 years, 6 months
teiid SVN: r4465 - trunk/client/src/main/java/org/teiid/jdbc.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2012-09-23 14:36:52 -0400 (Sun, 23 Sep 2012)
New Revision: 4465
Modified:
trunk/client/src/main/java/org/teiid/jdbc/ResultSetImpl.java
Log:
TEIID-2224 TEIID-2225 fixing positioning hangs and adding an available method
Modified: trunk/client/src/main/java/org/teiid/jdbc/ResultSetImpl.java
===================================================================
--- trunk/client/src/main/java/org/teiid/jdbc/ResultSetImpl.java 2012-09-21 19:08:02 UTC (rev 4464)
+++ trunk/client/src/main/java/org/teiid/jdbc/ResultSetImpl.java 2012-09-23 18:36:52 UTC (rev 4465)
@@ -60,19 +60,10 @@
import org.teiid.jdbc.BatchResults.Batch;
import org.teiid.jdbc.BatchResults.BatchFetcher;
-
-/**
- * <p>
- * The MMResultSet is the way query results are returned to the requesting
- * client based upon a query given to the server. This abstract class that
- * implements java.sql.ResultSet. This class represents access to results
- * produced by any of the classes on the driver.
- * </p>
- */
-
-public class ResultSetImpl extends WrapperImpl implements ResultSet, BatchFetcher {
+public class ResultSetImpl extends WrapperImpl implements TeiidResultSet, BatchFetcher {
private static Logger logger = Logger.getLogger("org.teiid.jdbc"); //$NON-NLS-1$
-
+ private static AsynchPositioningException ape = new AsynchPositioningException();
+
private static final int BEFORE_FIRST_ROW = 0;
// the object which was last read from Results
@@ -99,6 +90,11 @@
private int fetchSize;
private Map<String, Integer> columnMap;
+
+ //blocking operations that throw positioning errors are recoverable if we attempt to honor the
+ //results requested
+ private ResultsFuture<ResultsMessage> asynchResults;
+ boolean asynch;
/**
* Constructor.
@@ -275,7 +271,7 @@
if(column < 1 || column > columnCount) {
throw new IllegalArgumentException(JDBCPlugin.Util.getString("ResultsImpl.Invalid_col_index", column)); //$NON-NLS-1$
}
- List cursorRow = batchResults.getCurrentRow();
+ List<?> cursorRow = batchResults.getCurrentRow();
if (cursorRow == null) {
throw new TeiidSQLException(JDBCPlugin.Util.getString("ResultsImpl.The_cursor_is_not_on_a_valid_row._1")); //$NON-NLS-1$
@@ -334,7 +330,7 @@
* @return List of Object values in current row
* @throws SQLException if an access error occurs.
*/
- public List getCurrentRecord() throws SQLException {
+ public List<?> getCurrentRecord() throws SQLException {
checkClosed();
return batchResults.getCurrentRow();
}
@@ -359,6 +355,12 @@
checkClosed();
try {
ResultsFuture<ResultsMessage> results = submitRequestBatch(beginRow);
+ if (asynch && !results.isDone()) {
+ synchronized (this) {
+ asynchResults = results;
+ }
+ throw ape;
+ }
ResultsMessage currentResultMsg = getResults(results);
return processBatch(currentResultMsg);
} catch (InterruptedException e) {
@@ -372,10 +374,19 @@
private ResultsFuture<ResultsMessage> submitRequestBatch(int beginRow)
throws TeiidSQLException {
+ ResultsFuture<ResultsMessage> results;
+ if (asynch) {
+ synchronized (this) {
+ if (this.asynchResults != null) {
+ results = this.asynchResults;
+ this.asynchResults = null;
+ return results;
+ }
+ }
+ }
if (logger.isLoggable(Level.FINER)) {
logger.finer("requestBatch requestID: " + requestID + " beginRow: " + beginRow ); //$NON-NLS-1$ //$NON-NLS-2$
}
- ResultsFuture<ResultsMessage> results;
try {
results = statement.getDQP().processCursorRequest(requestID, beginRow, fetchSize);
} catch (TeiidProcessingException e) {
@@ -421,6 +432,13 @@
return batchResults.hasNext(getOffset() + 1, true);
}
+ @Override
+ public int available() throws SQLException {
+ int current = batchResults.getCurrentRowNumber();
+ int highest = batchResults.getHighestRowNumber();
+ return highest - current - getOffset();
+ }
+
protected int getOffset() {
return parameters > 0 ? 1 : 0;
}
13 years, 6 months
teiid SVN: r4464 - in trunk: client/src/main/resources/org/teiid/jdbc and 2 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2012-09-21 15:08:02 -0400 (Fri, 21 Sep 2012)
New Revision: 4464
Added:
trunk/client/src/main/java/org/teiid/jdbc/AsynchPositioningException.java
trunk/client/src/main/java/org/teiid/jdbc/TeiidResultSet.java
Modified:
trunk/client/src/main/java/org/teiid/jdbc/JDBCPlugin.java
trunk/client/src/main/java/org/teiid/jdbc/NonBlockingRowProcessor.java
trunk/client/src/main/resources/org/teiid/jdbc/i18n.properties
trunk/client/src/test/java/org/teiid/jdbc/TestResultSet.java
trunk/test-integration/common/src/test/java/org/teiid/systemmodel/TestSystemVirtualModel.java
Log:
TEIID-2224 fixing positioning hangs and adding an available method
Added: trunk/client/src/main/java/org/teiid/jdbc/AsynchPositioningException.java
===================================================================
--- trunk/client/src/main/java/org/teiid/jdbc/AsynchPositioningException.java (rev 0)
+++ trunk/client/src/main/java/org/teiid/jdbc/AsynchPositioningException.java 2012-09-21 19:08:02 UTC (rev 4464)
@@ -0,0 +1,33 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package org.teiid.jdbc;
+
+public class AsynchPositioningException extends TeiidSQLException {
+
+ private static final long serialVersionUID = 4965087364648306848L;
+
+ public AsynchPositioningException() {
+ super(JDBCPlugin.Util.gs(JDBCPlugin.Event.TEIID20030));
+ }
+
+}
Property changes on: trunk/client/src/main/java/org/teiid/jdbc/AsynchPositioningException.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Modified: trunk/client/src/main/java/org/teiid/jdbc/JDBCPlugin.java
===================================================================
--- trunk/client/src/main/java/org/teiid/jdbc/JDBCPlugin.java 2012-09-21 19:07:25 UTC (rev 4463)
+++ trunk/client/src/main/java/org/teiid/jdbc/JDBCPlugin.java 2012-09-21 19:08:02 UTC (rev 4464)
@@ -58,6 +58,7 @@
TEIID20023,
TEIID20027,
TEIID20028,
- TEIID20029
+ TEIID20029,
+ TEIID20030
}
}
Modified: trunk/client/src/main/java/org/teiid/jdbc/NonBlockingRowProcessor.java
===================================================================
--- trunk/client/src/main/java/org/teiid/jdbc/NonBlockingRowProcessor.java 2012-09-21 19:07:25 UTC (rev 4463)
+++ trunk/client/src/main/java/org/teiid/jdbc/NonBlockingRowProcessor.java 2012-09-21 19:08:02 UTC (rev 4464)
@@ -27,6 +27,7 @@
import java.util.logging.Logger;
import org.teiid.client.util.ResultsFuture;
+import org.teiid.core.TeiidRuntimeException;
/**
* Handles the future processing logic and makes the appropriate calls to the callback
@@ -52,6 +53,7 @@
return;
}
final ResultSetImpl resultSet = stmt.getResultSet();
+ resultSet.asynch = true;
Runnable rowProcessor = new Runnable() {
@Override
public void run() {
@@ -109,6 +111,9 @@
} catch (Exception e) {
onException(e);
return false;
+ } catch (Throwable t) {
+ onException(new TeiidRuntimeException(t));
+ return false;
}
}
@@ -116,7 +121,7 @@
if (e instanceof ExecutionException) {
ExecutionException ee = (ExecutionException)e;
if (ee.getCause() instanceof Exception) {
- e = (Exception)ee.getCause();
+ e = (Exception) ee.getCause();
}
}
try {
Added: trunk/client/src/main/java/org/teiid/jdbc/TeiidResultSet.java
===================================================================
--- trunk/client/src/main/java/org/teiid/jdbc/TeiidResultSet.java (rev 0)
+++ trunk/client/src/main/java/org/teiid/jdbc/TeiidResultSet.java 2012-09-21 19:08:02 UTC (rev 4464)
@@ -0,0 +1,40 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package org.teiid.jdbc;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+public interface TeiidResultSet extends ResultSet {
+
+ /**
+ * Returns an estimate of the minimum number of rows that can be read (after the current)
+ * without blocking or the end of the ResultSet is reached.
+ *
+ * @return an estimate of the minimum number of rows that can be read (after the current)
+ * without blocking or the end of the ResultSet is reached.
+ * @exception SQLException if the statement is closed or another error condition occurs.
+ */
+ int available() throws SQLException;
+
+}
Property changes on: trunk/client/src/main/java/org/teiid/jdbc/TeiidResultSet.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Modified: trunk/client/src/main/resources/org/teiid/jdbc/i18n.properties
===================================================================
--- trunk/client/src/main/resources/org/teiid/jdbc/i18n.properties 2012-09-21 19:07:25 UTC (rev 4463)
+++ trunk/client/src/main/resources/org/teiid/jdbc/i18n.properties 2012-09-21 19:08:02 UTC (rev 4464)
@@ -173,4 +173,5 @@
unexpected_element=Unexpected Element {0} encountered, expecting one of {1}
ambigious_gss_selection=Either configure "java.security.krb5.conf" property or combination of "java.security.krb5.realm" and "java.security.krb5.kdc" properties. Not both.
no_gss_selection=No KRB5 configuration found. Either configure "java.security.krb5.conf" property or combination of "java.security.krb5.realm" and "java.security.krb5.kdc" properties.
-TEIID20029={0} value outside of 32-bit value range. Please set the system property org.teiid.longDatesTimes to true to avoid this error.
\ No newline at end of file
+TEIID20029={0} value outside of 32-bit value range. Please set the system property org.teiid.longDatesTimes to true to avoid this error.
+TEIID20030=The position cannot be set by a blocking call in asynch mode as the results have not yet been formed.
\ No newline at end of file
Modified: trunk/client/src/test/java/org/teiid/jdbc/TestResultSet.java
===================================================================
--- trunk/client/src/test/java/org/teiid/jdbc/TestResultSet.java 2012-09-21 19:07:25 UTC (rev 4463)
+++ trunk/client/src/test/java/org/teiid/jdbc/TestResultSet.java 2012-09-21 19:08:02 UTC (rev 4464)
@@ -35,8 +35,6 @@
import java.util.Calendar;
import java.util.List;
import java.util.TimeZone;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeoutException;
import org.junit.Test;
import org.mockito.Mockito;
@@ -50,7 +48,9 @@
@SuppressWarnings("nls")
public class TestResultSet {
- /** test next() without walking through */
+ private static final int BATCH_SIZE = 400;
+
+ /** test next() without walking through */
@Test public void testNext1() throws SQLException {
ResultSet cs = helpExecuteQuery();
assertEquals(" Actual doesn't match with expected. ", new Integer(0), new Integer(cs.getRow())); //$NON-NLS-1$
@@ -59,12 +59,13 @@
/** test next() with walking through all the rows and compare records */
@Test public void testNext2() throws SQLException {
- List[] expected = TestAllResultsImpl.exampleResults1(1000);
+ List<?>[] expected = TestAllResultsImpl.exampleResults1(1000);
ResultSetImpl cs = helpExecuteQuery();
int i=0;
while(cs.next()) {
assertEquals(" Actual doesn't match with expected. ", expected[i], cs.getCurrentRecord()); //$NON-NLS-1$
+ assertEquals((i < 800?BATCH_SIZE:200) - (i%BATCH_SIZE) - 1, cs.available());
i++;
}
@@ -204,7 +205,7 @@
/** walk all way through from the end back to first row */
@Test public void testPrevious1() throws SQLException {
ResultSetImpl cs = helpExecuteQuery();
- List[] expected = TestAllResultsImpl.exampleResults1(1000);
+ List<?>[] expected = TestAllResultsImpl.exampleResults1(1000);
while(cs.next()) {
//System.out.println(" rs.next == " + cs.getCurrentRecord());
}
@@ -236,7 +237,7 @@
@Test public void testPrevious3() throws Exception {
//large batch size
ResultSetImpl cs = helpExecuteQuery(600, 10000, ResultSet.TYPE_SCROLL_INSENSITIVE);
- List[] expected = TestAllResultsImpl.exampleResults1(10000);
+ List<?>[] expected = TestAllResultsImpl.exampleResults1(10000);
while(cs.next()) {
}
// cursor is after the last row. getRow() should return 0 when not on a valid row
@@ -256,7 +257,7 @@
@Test public void testPrevious4() throws Exception {
//small batch size
ResultSetImpl cs = helpExecuteQuery(50, 1000, ResultSet.TYPE_SCROLL_INSENSITIVE);
- List[] expected = TestAllResultsImpl.exampleResults1(1000);
+ List<?>[] expected = TestAllResultsImpl.exampleResults1(1000);
while(cs.next()) {
//System.out.println(" rs.next == " + cs.getCurrentRecord());
}
@@ -578,9 +579,9 @@
// check result set metadata
// expected column info.
- List columnName = getBQTRSMetaData1a();
- List columnType = getBQTRSMetaData1b();
- List columnTypeName = getBQTRSMetaData1c();
+ List<String> columnName = getBQTRSMetaData1a();
+ List<Integer> columnType = getBQTRSMetaData1b();
+ List<String> columnTypeName = getBQTRSMetaData1c();
ResultSetMetaData rm = cs.getMetaData();
assertNotNull(rm);
@@ -731,13 +732,13 @@
private ResultSetImpl helpExecuteQuery() {
try {
- return helpExecuteQuery(400, 1000, ResultSet.TYPE_SCROLL_INSENSITIVE);
+ return helpExecuteQuery(BATCH_SIZE, 1000, ResultSet.TYPE_SCROLL_INSENSITIVE);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
- private ResultSetImpl helpExecuteQuery(int fetchSize, int totalResults, int cursorType) throws SQLException, TeiidProcessingException, InterruptedException, ExecutionException, TimeoutException {
+ private ResultSetImpl helpExecuteQuery(int fetchSize, int totalResults, int cursorType) throws SQLException, TeiidProcessingException {
StatementImpl statement = createMockStatement(cursorType);
return TestAllResultsImpl.helpTestBatching(statement, fetchSize, Math.min(fetchSize, totalResults), totalResults);
}
@@ -755,22 +756,22 @@
////////////////////////Expected Results////////////////
/** column name */
- private List getBQTRSMetaData1a() {
- List results = new ArrayList();
+ private List<String> getBQTRSMetaData1a() {
+ List<String> results = new ArrayList<String>();
results.add("IntKey"); //$NON-NLS-1$
return results;
}
/** column type */
- private List getBQTRSMetaData1b() {
- List results = new ArrayList();
- results.add(new Integer(Types.INTEGER));
+ private List<Integer> getBQTRSMetaData1b() {
+ List<Integer> results = new ArrayList<Integer>();
+ results.add(Types.INTEGER);
return results;
}
/** column type name*/
- private List getBQTRSMetaData1c() {
- List results = new ArrayList();
+ private List<String> getBQTRSMetaData1c() {
+ List<String> results = new ArrayList<String>();
results.add("integer"); //$NON-NLS-1$
return results;
}
Modified: trunk/test-integration/common/src/test/java/org/teiid/systemmodel/TestSystemVirtualModel.java
===================================================================
--- trunk/test-integration/common/src/test/java/org/teiid/systemmodel/TestSystemVirtualModel.java 2012-09-21 19:07:25 UTC (rev 4463)
+++ trunk/test-integration/common/src/test/java/org/teiid/systemmodel/TestSystemVirtualModel.java 2012-09-21 19:08:02 UTC (rev 4464)
@@ -39,9 +39,11 @@
import org.teiid.client.util.ResultsFuture;
import org.teiid.core.util.UnitTestUtil;
import org.teiid.jdbc.AbstractMMQueryTestCase;
+import org.teiid.jdbc.AsynchPositioningException;
import org.teiid.jdbc.FakeServer;
import org.teiid.jdbc.RequestOptions;
import org.teiid.jdbc.StatementCallback;
+import org.teiid.jdbc.TeiidResultSet;
import org.teiid.jdbc.TeiidStatement;
import org.teiid.jdbc.TestMMDatabaseMetaData;
@@ -161,11 +163,24 @@
Statement stmt = this.internalConnection.createStatement();
TeiidStatement ts = stmt.unwrap(TeiidStatement.class);
final ResultsFuture<Integer> result = new ResultsFuture<Integer>();
- ts.submitExecute("select * from SYS.Schemas", new StatementCallback() {
+ ts.submitExecute("select * from SYS.columns a, sys.tables b", new StatementCallback() {
int rowCount;
@Override
public void onRow(Statement s, ResultSet rs) {
rowCount++;
+ try {
+ if (!rs.isLast()) {
+ assertTrue(rs.unwrap(TeiidResultSet.class).available() > 0);
+ }
+ } catch (AsynchPositioningException e) {
+ try {
+ assertEquals(0, rs.unwrap(TeiidResultSet.class).available());
+ } catch (SQLException e1) {
+ result.getResultsReceiver().exceptionOccurred(e1);
+ }
+ } catch (SQLException e) {
+ result.getResultsReceiver().exceptionOccurred(e);
+ }
}
@Override
@@ -178,7 +193,7 @@
result.getResultsReceiver().receiveResults(rowCount);
}
}, new RequestOptions());
- assertEquals(4, result.get().intValue());
+ assertEquals(7905, result.get().intValue());
}
@Test public void testAsynchContinuous() throws Exception {
13 years, 6 months
teiid SVN: r4463 - trunk/connectors/translator-object/src/main/java/org/teiid/translator/object.
by teiid-commits@lists.jboss.org
Author: van.halbert
Date: 2012-09-21 15:07:25 -0400 (Fri, 21 Sep 2012)
New Revision: 4463
Removed:
trunk/connectors/translator-object/src/main/java/org/teiid/translator/object/SearchStrategy.java
trunk/connectors/translator-object/src/main/java/org/teiid/translator/object/SelectProjections.java
Log:
TEIID-2210 cleanup, not sure how these 2 classes reappeared.
Deleted: trunk/connectors/translator-object/src/main/java/org/teiid/translator/object/SearchStrategy.java
===================================================================
--- trunk/connectors/translator-object/src/main/java/org/teiid/translator/object/SearchStrategy.java 2012-09-21 14:49:55 UTC (rev 4462)
+++ trunk/connectors/translator-object/src/main/java/org/teiid/translator/object/SearchStrategy.java 2012-09-21 19:07:25 UTC (rev 4463)
@@ -1,20 +0,0 @@
-package org.teiid.translator.object;
-
-import java.util.List;
-
-import org.teiid.language.Select;
-import org.teiid.translator.TranslatorException;
-import org.teiid.translator.object.SelectProjections;
-
-/**
- * Each SearchStrategy implementation is based on the data source language specifics for searching its cache.
- *
- * @author vhalbert
- *
- */
-public interface SearchStrategy {
-
- public List<Object> performSearch(Select command, SelectProjections projections,
- ObjectExecutionFactory factory, Object connection) throws TranslatorException;
-
-}
Deleted: trunk/connectors/translator-object/src/main/java/org/teiid/translator/object/SelectProjections.java
===================================================================
--- trunk/connectors/translator-object/src/main/java/org/teiid/translator/object/SelectProjections.java 2012-09-21 14:49:55 UTC (rev 4462)
+++ trunk/connectors/translator-object/src/main/java/org/teiid/translator/object/SelectProjections.java 2012-09-21 19:07:25 UTC (rev 4463)
@@ -1,118 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA.
- */
-package org.teiid.translator.object;
-
-import java.util.List;
-
-import org.teiid.language.Command;
-import org.teiid.language.NamedTable;
-import org.teiid.language.Select;
-import org.teiid.language.TableReference;
-import org.teiid.metadata.ForeignKey;
-import org.teiid.metadata.Table;
-
-/**
- * The SelectProjections is responsible for parsing the select attributes from
- * the {@link Command command} into usable information for translating result
- * objects into rows.
- *
- * @author vhalbert
- *
- */
-public class SelectProjections {
-
- private boolean isRootTableInSelect = false;
-
- private Table rootTable = null;
-
- private String rootClassName = null;
-
- private SelectProjections(String rootClassName) {
- this.rootClassName = rootClassName;
- }
-
- public static SelectProjections create(ObjectExecutionFactory factory) {
- return new SelectProjections(factory.getRootClassName());
- }
-
- public String getRootTableName() {
- return this.rootTable.getName();
- }
-
- public String getRootNodePrimaryKeyColumnName() {
- if (this.rootTable.getPrimaryKey() != null) {
- return this.rootTable.getPrimaryKey().getColumns().get(0).getName();
- }
- return null;
- }
-
- public boolean isRootTableInFrom() {
- return this.isRootTableInSelect;
- }
-
- public void parse(Select query) {
- Table roottable = null;
-
- List<TableReference> tables = query.getFrom();
- Table lastGroup = null;
- for (TableReference t : tables) {
- if (t instanceof NamedTable) {
- lastGroup = ((NamedTable) t).getMetadataObject();
- if (lastGroup.getNameInSource().equals(rootClassName)) {
- roottable = lastGroup;
- this.isRootTableInSelect = true;
- break;
- }
- }
- }
- // still need to find the roottable, even though its not part of the
- // query
- if (!this.isRootTableInSelect) {
- roottable = determineRootTable(lastGroup);
- }
-
- this.rootTable = roottable;
-
- }
-
- private Table determineRootTable(Table t) {
- if (t == null)
- return null;
-
- if (t.getForeignKeys() != null && !t.getForeignKeys().isEmpty()) {
- List<ForeignKey> fks = t.getForeignKeys();
- for (ForeignKey fk : fks) {
- if (fk.getPrimaryKey() != null
- && fk.getPrimaryKey().getParent() != t) {
- return determineRootTable(fk.getPrimaryKey().getParent());
- }
- }
- }
-
- return t;
- }
-
- protected void cleanup() {
- rootTable = null;
-
- }
-}
13 years, 6 months