[teiid-commits] teiid SVN: r3624 - in trunk: api/src/main/java/org/teiid/translator and 24 other directories.
teiid-commits at lists.jboss.org
teiid-commits at lists.jboss.org
Wed Nov 9 15:06:25 EST 2011
Author: shawkins
Date: 2011-11-09 15:06:24 -0500 (Wed, 09 Nov 2011)
New Revision: 3624
Added:
trunk/engine/src/main/java/org/teiid/query/sql/lang/SourceHint.java
trunk/engine/src/test/java/org/teiid/query/processor/TestSourceHints.java
Modified:
trunk/api/src/main/java/org/teiid/language/visitor/SQLStringVisitor.java
trunk/api/src/main/java/org/teiid/translator/ExecutionContext.java
trunk/common-core/src/main/java/org/teiid/core/util/SqlUtil.java
trunk/common-core/src/test/java/org/teiid/core/util/TestSqlUtil.java
trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/oracle/OracleExecutionFactory.java
trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/oracle/TestOracleTranslator.java
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPSyncQueryExecution.java
trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/ConnectorWorkItem.java
trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/ExecutionContextImpl.java
trunk/engine/src/main/java/org/teiid/dqp/internal/process/DataTierManagerImpl.java
trunk/engine/src/main/java/org/teiid/dqp/internal/process/SessionAwareCache.java
trunk/engine/src/main/java/org/teiid/dqp/message/AtomicRequestMessage.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java
trunk/engine/src/main/java/org/teiid/query/parser/ParseInfo.java
trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java
trunk/engine/src/main/java/org/teiid/query/processor/relational/RelationalPlan.java
trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
trunk/engine/src/main/java/org/teiid/query/sql/lang/Command.java
trunk/engine/src/main/java/org/teiid/query/sql/lang/Delete.java
trunk/engine/src/main/java/org/teiid/query/sql/lang/Insert.java
trunk/engine/src/main/java/org/teiid/query/sql/lang/Update.java
trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java
trunk/engine/src/main/java/org/teiid/query/util/CommandContext.java
trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
trunk/engine/src/test/java/org/teiid/query/optimizer/TestRuleRemoveSorts.java
trunk/engine/src/test/java/org/teiid/query/optimizer/relational/rules/TestRuleAccessPatternValidation.java
trunk/engine/src/test/java/org/teiid/query/optimizer/relational/rules/TestRulePushSelectCriteria.java
trunk/engine/src/test/java/org/teiid/query/parser/TestOptionsAndHints.java
trunk/engine/src/test/java/org/teiid/query/processor/eval/TestExpressionEvaluator.java
trunk/runtime/src/main/java/org/teiid/odbc/ODBCClientRemote.java
trunk/runtime/src/main/java/org/teiid/odbc/ODBCServerRemoteImpl.java
trunk/runtime/src/main/java/org/teiid/transport/PgBackendProtocol.java
trunk/test-integration/common/src/test/java/org/teiid/connector/visitor/util/TestSQLStringVisitor.java
Log:
TEIID-1726 adding the ability to pass source hints through the teiid system
Modified: trunk/api/src/main/java/org/teiid/language/visitor/SQLStringVisitor.java
===================================================================
--- trunk/api/src/main/java/org/teiid/language/visitor/SQLStringVisitor.java 2011-11-09 18:09:23 UTC (rev 3623)
+++ trunk/api/src/main/java/org/teiid/language/visitor/SQLStringVisitor.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -97,6 +97,7 @@
protected static final String UNDEFINED_PARAM = "?"; //$NON-NLS-1$
protected StringBuilder buffer = new StringBuilder();
+ private boolean appendedSourceComment;
/**
* Gets the name of a group or element from the RuntimeMetadata
@@ -230,7 +231,7 @@
public void visit(Delete obj) {
buffer.append(DELETE)
.append(Tokens.SPACE);
- buffer.append(getSourceComment(obj));
+ appendSourceComment(obj);
buffer.append(FROM)
.append(Tokens.SPACE);
append(obj.getTable());
@@ -242,6 +243,14 @@
}
}
+ private void appendSourceComment(Command obj) {
+ if (appendedSourceComment) {
+ return;
+ }
+ appendedSourceComment = true;
+ buffer.append(getSourceComment(obj));
+ }
+
/**
* Take the specified derived group and element short names and determine a
* replacement element name to use instead. Most commonly, this is used to strip
@@ -502,7 +511,7 @@
public void visit(Insert obj) {
buffer.append(INSERT).append(Tokens.SPACE);
- buffer.append(getSourceComment(obj));
+ appendSourceComment(obj);
buffer.append(INTO).append(Tokens.SPACE);
append(obj.getTable());
buffer.append(Tokens.SPACE).append(Tokens.LPAREN);
@@ -725,7 +734,7 @@
append(obj.getWith());
}
buffer.append(SELECT).append(Tokens.SPACE);
- buffer.append(getSourceComment(obj));
+ appendSourceComment(obj);
if (obj.isDistinct()) {
buffer.append(DISTINCT).append(Tokens.SPACE);
}
@@ -851,7 +860,7 @@
public void visit(Update obj) {
buffer.append(UPDATE)
.append(Tokens.SPACE);
- buffer.append(getSourceComment(obj));
+ appendSourceComment(obj);
append(obj.getTable());
buffer.append(Tokens.SPACE)
.append(SET)
@@ -912,7 +921,7 @@
protected void appendSetQuery(SetQuery parent, QueryExpression obj, boolean right) {
if((!(obj instanceof SetQuery) && useParensForSetQueries())
- || (right && ((obj instanceof SetQuery
+ || (!useSelectLimit() && (obj.getLimit() != null || obj.getOrderBy() != null)) || (right && ((obj instanceof SetQuery
&& ((parent.isAll() && !((SetQuery)obj).isAll())
|| parent.getOperation() != ((SetQuery)obj).getOperation())) || obj.getLimit() != null || obj.getOrderBy() != null))) {
buffer.append(Tokens.LPAREN);
Modified: trunk/api/src/main/java/org/teiid/translator/ExecutionContext.java
===================================================================
--- trunk/api/src/main/java/org/teiid/translator/ExecutionContext.java 2011-11-09 18:09:23 UTC (rev 3623)
+++ trunk/api/src/main/java/org/teiid/translator/ExecutionContext.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -100,6 +100,18 @@
* @since 4.2
*/
Serializable getExecutionPayload();
+
+ /**
+ * Get the general hint passed to all executions under the user query.
+ * @return the general hint or null if none was specified
+ */
+ String getGeneralHint();
+
+ /**
+ * Get the hint designated for this source.
+ * @return the source hint or null if none was specified
+ */
+ String getSourceHint();
/**
* Get the identifier for the connection through which
Modified: trunk/common-core/src/main/java/org/teiid/core/util/SqlUtil.java
===================================================================
--- trunk/common-core/src/main/java/org/teiid/core/util/SqlUtil.java 2011-11-09 18:09:23 UTC (rev 3623)
+++ trunk/common-core/src/main/java/org/teiid/core/util/SqlUtil.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -23,9 +23,9 @@
package org.teiid.core.util;
import java.sql.SQLException;
-
import java.sql.SQLFeatureNotSupportedException;
-
+import java.util.TreeSet;
+import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
@@ -36,8 +36,17 @@
public static final char NL_CHAR = StringUtil.Constants.NEW_LINE_CHAR;
public static final char SPACE_CHAR = StringUtil.Constants.SPACE_CHAR;
public static final char TAB_CHAR = StringUtil.Constants.TAB_CHAR;
- private static Pattern PATTERN = Pattern.compile("^([\\s]|(/\\*.*\\*/))*(insert|update|delete|create|drop|(select([\\s]|(/\\*.*\\*/))+.*into([\\s]|(/\\*.*\\*/))+)).*", Pattern.CASE_INSENSITIVE|Pattern.MULTILINE); //$NON-NLS-1$
-
+ private static TreeSet<String> updateKeywords = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
+ static {
+ updateKeywords.add("insert"); //$NON-NLS-1$
+ updateKeywords.add("update"); //$NON-NLS-1$
+ updateKeywords.add("delete"); //$NON-NLS-1$
+ updateKeywords.add("drop"); //$NON-NLS-1$
+ updateKeywords.add("create"); //$NON-NLS-1$
+ }
+ private static Pattern PATTERN = Pattern.compile("^(?:\\s|(?:/\\*.*\\*/))*(\\w*)\\s", Pattern.CASE_INSENSITIVE|Pattern.DOTALL); //$NON-NLS-1$
+ private static Pattern INTO_PATTERN = Pattern.compile("(?:'[^']*')|(\\sinto\\s)", Pattern.CASE_INSENSITIVE|Pattern.DOTALL); //$NON-NLS-1$
+
private SqlUtil() {
super();
}
@@ -52,10 +61,29 @@
* query or an update
*/
public static boolean isUpdateSql(String sql) throws IllegalArgumentException {
- ArgCheck.isNotNull(sql);
- return PATTERN.matcher(sql).matches();
+ String keyWord = getKeyword(sql);
+ return updateKeywords.contains(keyWord);
}
+ public static String getKeyword(String sql) {
+ Matcher matcher = PATTERN.matcher(sql);
+ if (!matcher.find()) {
+ return sql; //shouldn't happen
+ }
+ String keyword = matcher.group(1);
+ if (keyword.equalsIgnoreCase("select")) { //$NON-NLS-1$
+ int end = matcher.end();
+ Matcher intoMatcher = INTO_PATTERN.matcher(sql);
+ while (intoMatcher.find(end)) {
+ if (intoMatcher.group(1) != null) {
+ return "insert"; //$NON-NLS-1$
+ }
+ end = intoMatcher.end();
+ }
+ }
+ return keyword;
+ }
+
public static SQLException createFeatureNotSupportedException() {
return new SQLFeatureNotSupportedException();
}
Modified: trunk/common-core/src/test/java/org/teiid/core/util/TestSqlUtil.java
===================================================================
--- trunk/common-core/src/test/java/org/teiid/core/util/TestSqlUtil.java 2011-11-09 18:09:23 UTC (rev 3623)
+++ trunk/common-core/src/test/java/org/teiid/core/util/TestSqlUtil.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -22,72 +22,71 @@
package org.teiid.core.util;
-import org.teiid.core.util.SqlUtil;
+import static org.junit.Assert.*;
-import junit.framework.TestCase;
-
+import org.junit.Test;
/**
*/
-public class TestSqlUtil extends TestCase {
+public class TestSqlUtil {
- public TestSqlUtil(String name) {
- super(name);
- }
-
public void helpTest(String sql, boolean isUpdate) {
boolean actual = SqlUtil.isUpdateSql(sql);
assertEquals(isUpdate, actual);
}
- public void testSelect() {
+ @Test public void testSelect() {
helpTest("SELECT x FROM y", false); //$NON-NLS-1$
}
- public void testInsert() {
+ @Test public void testInsert() {
helpTest("Insert INTO g (a) VALUES (1)", true); //$NON-NLS-1$
}
- public void testUpdate() {
+ @Test public void testUpdate() {
helpTest("upDate x set a=5", true); //$NON-NLS-1$
}
- public void testDelete() {
+ @Test public void testDelete() {
helpTest("delete FROM x", true); //$NON-NLS-1$
}
- public void testInsertWithWhitespace() {
+ @Test public void testInsertWithWhitespace() {
helpTest("\nINSERT INTO g (a) VALUES (1)", true); //$NON-NLS-1$
}
- public void testExec() {
+ @Test public void testExec() {
helpTest("exec sq1()", false); //$NON-NLS-1$
}
- public void testXquery() {
+ @Test public void testXquery() {
helpTest("<i/>", false); //$NON-NLS-1$
}
- public void testSelectInto1() {
+ @Test public void testSelectInto1() {
helpTest("SELECT x INTO z FROM y", true); //$NON-NLS-1$
}
- public void testSelectInto2() {
+ @Test public void testSelectInto2() {
helpTest("SELECT x, INTOz FROM y", false); //$NON-NLS-1$
}
- public void testSelectInto3() {
+ @Test public void testSelectInto3() {
helpTest("SELECT x into z FROM y", true); //$NON-NLS-1$
}
- public void testSelectInto4() {
+ @Test public void testSelectInto4() {
helpTest("SELECT x into z", true); //$NON-NLS-1$
}
- public void testCreate() {
+ @Test public void testSelectInto5() {
+ helpTest("SELECT x, ' into ' from z", false); //$NON-NLS-1$
+ }
+
+ @Test public void testCreate() {
helpTest(" create table x", true); //$NON-NLS-1$
}
- public void testDrop() {
+ @Test public void testDrop() {
helpTest("/* */ drop table x", true); //$NON-NLS-1$
}
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 2011-11-09 18:09:23 UTC (rev 3623)
+++ trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/oracle/OracleExecutionFactory.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -54,6 +54,8 @@
import org.teiid.language.SQLConstants.Tokens;
import org.teiid.language.SetQuery.Operation;
import org.teiid.language.visitor.CollectorVisitor;
+import org.teiid.logging.LogConstants;
+import org.teiid.logging.LogManager;
import org.teiid.metadata.Column;
import org.teiid.translator.ExecutionContext;
import org.teiid.translator.SourceSystemFunctions;
@@ -66,6 +68,7 @@
import org.teiid.translator.jdbc.ExtractFunctionModifier;
import org.teiid.translator.jdbc.FunctionModifier;
import org.teiid.translator.jdbc.JDBCExecutionFactory;
+import org.teiid.translator.jdbc.JDBCPlugin;
import org.teiid.translator.jdbc.LocateFunctionModifier;
import org.teiid.translator.jdbc.TranslatedCommand;
@@ -79,6 +82,7 @@
private static final String TIMESTAMP_FORMAT = DATETIME_FORMAT + ".FF"; //$NON-NLS-1$
public final static String HINT_PREFIX = "/*+"; //$NON-NLS-1$
+ public static final String HINT_SUFFIX = "*/"; //$NON-NLS-1$
public final static String DUAL = "DUAL"; //$NON-NLS-1$
public final static String ROWNUM = "ROWNUM"; //$NON-NLS-1$
public final static String SEQUENCE = ":SEQUENCE="; //$NON-NLS-1$
@@ -345,17 +349,44 @@
public String getSourceComment(ExecutionContext context, Command command) {
String comment = super.getSourceComment(context, command);
+ boolean usingPayloadComment = false;
if (context != null) {
// Check for db hints
Object payload = context.getExecutionPayload();
if (payload instanceof String) {
String payloadString = (String)payload;
if (payloadString.startsWith(HINT_PREFIX)) {
- comment += payloadString + " "; //$NON-NLS-1$
+ int i = payloadString.indexOf(HINT_SUFFIX);
+ if (i > 0 && payloadString.substring(i + 2).trim().length() == 0) {
+ comment += payloadString + " "; //$NON-NLS-1$
+ usingPayloadComment = true;
+ } else {
+ String msg = JDBCPlugin.Util.getString("OraleExecutionFactory.invalid_hint", "Execution Payload", payloadString); //$NON-NLS-1$ //$NON-NLS-2$
+ context.addWarning(new TranslatorException(msg));
+ LogManager.logWarning(LogConstants.CTX_CONNECTOR, msg);
+ }
}
}
}
+ if (!usingPayloadComment && context != null) {
+ String hint = null;
+ hint = context.getSourceHint();
+ if (hint == null) {
+ hint = context.getGeneralHint();
+ }
+ if (hint != null) {
+ //append a source hint
+ if (!hint.contains(HINT_PREFIX)) {
+ comment += HINT_PREFIX + ' ' + hint + ' ' + HINT_SUFFIX + ' ';
+ } else {
+ String msg = JDBCPlugin.Util.getString("OraleExecutionFactory.invalid_hint", "Source Hint", hint); //$NON-NLS-1$ //$NON-NLS-2$
+ context.addWarning(new TranslatorException(msg));
+ LogManager.logWarning(LogConstants.CTX_CONNECTOR, msg);
+ }
+ }
+ }
+
if (command instanceof Select) {
//
// This simple algorithm determines the hint which will be added to the
Modified: trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/oracle/TestOracleTranslator.java
===================================================================
--- trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/oracle/TestOracleTranslator.java 2011-11-09 18:09:23 UTC (rev 3623)
+++ trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/oracle/TestOracleTranslator.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -77,6 +77,18 @@
helpTestVisitor(getOracleSpecificMetadata(), input, EMPTY_CONTEXT, null, expectedOutput);
}
+ @Test public void testSourceHint() throws Exception {
+ ExecutionContextImpl impl = new FakeExecutionContextImpl();
+ impl.setHint("hello world");
+ helpTestVisitor(getTestVDB(), "select part_name from parts", impl, null, "SELECT /*+ hello world */ g_0.PART_NAME FROM PARTS g_0", true);
+ }
+
+ @Test public void testSourceHint1() throws Exception {
+ ExecutionContextImpl impl = new FakeExecutionContextImpl();
+ impl.setHint("hello world");
+ helpTestVisitor(getTestVDB(), "select part_name from parts union select part_id from parts", impl, null, "SELECT /*+ hello world */ g_1.PART_NAME AS c_0 FROM PARTS g_1 UNION SELECT g_0.PART_ID AS c_0 FROM PARTS g_0", true);
+ }
+
@Test public void testInsertWithSequnce() throws Exception {
helpTestVisitor("insert into smalla (doublenum) values (1)", "INSERT INTO SmallishA (DoubleNum, ID) VALUES (1.0, MYSEQUENCE.nextVal)"); //$NON-NLS-1$ //$NON-NLS-2$
}
@@ -702,6 +714,21 @@
false);
}
+ @Test public void testOracleCommentPayload1() throws Exception {
+ String input = "SELECT part_name, rownum FROM parts"; //$NON-NLS-1$
+ String output = "SELECT PARTS.PART_NAME, ROWNUM FROM PARTS"; //$NON-NLS-1$
+
+ String hint = "/*+ ALL_ROWS */ something else"; //$NON-NLS-1$
+ ExecutionContext context = new ExecutionContextImpl(null, 1, hint, null, "", null, null, null); //$NON-NLS-1$
+
+ helpTestVisitor(getTestVDB(),
+ input,
+ context,
+ null,
+ output,
+ false);
+ }
+
/**
* reproducing this case relies on the name in source for the table being different from
* the name
@@ -788,7 +815,7 @@
@Test public void testRowLimitWithUnionOrderBy() throws Exception {
String input = "(select intkey from bqt1.smalla limit 50, 100) union select intnum from bqt1.smalla order by intkey"; //$NON-NLS-1$
- String output = "SELECT c_0 FROM (SELECT VIEW_FOR_LIMIT.*, ROWNUM ROWNUM_ FROM (SELECT g_1.IntKey AS c_0 FROM SmallA g_1) VIEW_FOR_LIMIT WHERE ROWNUM <= 150) WHERE ROWNUM_ > 50 UNION SELECT g_0.IntNum AS c_0 FROM SmallA g_0 ORDER BY c_0"; //$NON-NLS-1$
+ String output = "(SELECT c_0 FROM (SELECT VIEW_FOR_LIMIT.*, ROWNUM ROWNUM_ FROM (SELECT g_1.IntKey AS c_0 FROM SmallA g_1) VIEW_FOR_LIMIT WHERE ROWNUM <= 150) WHERE ROWNUM_ > 50) UNION SELECT g_0.IntNum AS c_0 FROM SmallA g_0 ORDER BY c_0"; //$NON-NLS-1$
CommandBuilder commandBuilder = new CommandBuilder(RealMetadataFactory.exampleBQTCached());
Command obj = commandBuilder.getCommand(input, true, true);
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 2011-11-09 18:09:23 UTC (rev 3623)
+++ trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPSyncQueryExecution.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -331,9 +331,11 @@
} catch (SizeLimitExceededException e) {
if (resultCount != searchDetails.getCountLimit()) {
String msg = "LDAP Search results exceeded size limit. Results may be incomplete."; //$NON-NLS-1$
+ TranslatorException te = new TranslatorException(e, msg);
if (executionFactory.isExceptionOnSizeLimitExceeded()) {
- throw new TranslatorException(e, msg);
+ 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
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/ConnectorWorkItem.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/ConnectorWorkItem.java 2011-11-09 18:09:23 UTC (rev 3623)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/ConnectorWorkItem.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -98,6 +98,8 @@
Integer.toString(requestID.getNodeID()),
Integer.toString(requestID.getExecutionId())
);
+ this.securityContext.setGeneralHint(message.getGeneralHint());
+ this.securityContext.setHint(message.getHint());
this.securityContext.setUser(requestMsg.getWorkContext().getSubject());
this.securityContext.setBatchSize(this.requestMsg.getFetchSize());
this.securityContext.setSession(requestMsg.getWorkContext().getSession());
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/ExecutionContextImpl.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/ExecutionContextImpl.java 2011-11-09 18:09:23 UTC (rev 3623)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/ExecutionContextImpl.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -69,6 +69,8 @@
private Session session;
private RequestWorkItem worktItem;
private boolean dataAvailable;
+ private String generalHint;
+ private String hint;
public ExecutionContextImpl(String vdbName, int vdbVersion, Serializable executionPayload,
String originalConnectionID, String connectorName, String requestId, String partId, String execCount) {
@@ -237,4 +239,22 @@
dataAvailable = false;
return result;
}
+
+ @Override
+ public String getGeneralHint() {
+ return generalHint;
+ }
+
+ @Override
+ public String getSourceHint() {
+ return hint;
+ }
+
+ public void setGeneralHint(String generalHint) {
+ this.generalHint = generalHint;
+ }
+
+ public void setHint(String hint) {
+ this.hint = hint;
+ }
}
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/DataTierManagerImpl.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/DataTierManagerImpl.java 2011-11-09 18:09:23 UTC (rev 3623)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/DataTierManagerImpl.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -84,6 +84,7 @@
import org.teiid.query.processor.ProcessorDataManager;
import org.teiid.query.sql.lang.Command;
import org.teiid.query.sql.lang.Query;
+import org.teiid.query.sql.lang.SourceHint;
import org.teiid.query.sql.lang.StoredProcedure;
import org.teiid.query.sql.lang.UnaryFromClause;
import org.teiid.query.sql.symbol.Constant;
@@ -192,6 +193,11 @@
}
AtomicRequestMessage aqr = createRequest(context.getProcessorID(), command, modelName, connectorBindingId, nodeID);
+ SourceHint sh = context.getSourceHint();
+ if (sh != null) {
+ aqr.setGeneralHint(sh.getGeneralHint());
+ aqr.setHint(sh.getSourceHint(aqr.getConnectorName()));
+ }
if (limit > 0) {
aqr.setFetchSize(Math.min(limit, aqr.getFetchSize()));
}
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/SessionAwareCache.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/SessionAwareCache.java 2011-11-09 18:09:23 UTC (rev 3623)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/SessionAwareCache.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -227,7 +227,7 @@
private static final long serialVersionUID = 8261905111156764744L;
private String sql;
private VDBKey vdbInfo;
- private ParseInfo pi;
+ private boolean ansiIdentifiers;
private String sessionId;
private String originalSessionId;
private List<Serializable> parameters;
@@ -242,7 +242,7 @@
Assertion.isNotNull(sql);
this.sql = sql;
this.vdbInfo = new VDBKey(vdbName, vdbVersion);
- this.pi = pi;
+ this.ansiIdentifiers = pi.ansiQuotedIdentifiers;
this.originalSessionId = sessionId;
this.originalUserName = userName;
}
@@ -303,14 +303,14 @@
return false;
}
CacheID that = (CacheID)obj;
- return EquivalenceUtil.areEqual(this.pi, that.pi) && this.vdbInfo.equals(that.vdbInfo) && this.sql.equals(that.sql)
+ return ansiIdentifiers == that.ansiIdentifiers && this.vdbInfo.equals(that.vdbInfo) && this.sql.equals(that.sql)
&& EquivalenceUtil.areEqual(this.userName, that.userName)
&& EquivalenceUtil.areEqual(this.sessionId, that.sessionId)
&& EquivalenceUtil.areEqual(this.parameters, that.parameters);
}
public int hashCode() {
- return HashCodeUtil.hashCode(0, vdbInfo, sql, pi, this.userName, sessionId, parameters);
+ return HashCodeUtil.hashCode(0, vdbInfo, sql, this.userName, sessionId, parameters);
}
@Override
Modified: trunk/engine/src/main/java/org/teiid/dqp/message/AtomicRequestMessage.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/message/AtomicRequestMessage.java 2011-11-09 18:09:23 UTC (rev 3623)
+++ trunk/engine/src/main/java/org/teiid/dqp/message/AtomicRequestMessage.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -84,6 +84,8 @@
private boolean serial;
private DQPWorkContext workContext;
+ private String generalHint;
+ private String hint;
public AtomicRequestMessage() {
// This is only to honor the externalizable interface..
@@ -214,5 +216,21 @@
public DQPWorkContext getWorkContext() {
return workContext;
}
+
+ public String getGeneralHint() {
+ return generalHint;
+ }
+
+ public void setGeneralHint(String generalHint) {
+ this.generalHint = generalHint;
+ }
+
+ public String getHint() {
+ return hint;
+ }
+
+ public void setHint(String hint) {
+ this.hint = hint;
+ }
}
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java 2011-11-09 18:09:23 UTC (rev 3623)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -100,6 +100,7 @@
import org.teiid.query.sql.lang.QueryCommand;
import org.teiid.query.sql.lang.Select;
import org.teiid.query.sql.lang.SetQuery;
+import org.teiid.query.sql.lang.SourceHint;
import org.teiid.query.sql.lang.StoredProcedure;
import org.teiid.query.sql.lang.SubqueryContainer;
import org.teiid.query.sql.lang.SubqueryFromClause;
@@ -157,6 +158,7 @@
private QueryMetadataInterface metadata;
private PlanHints hints = new PlanHints();
private Option option;
+ private SourceHint sourceHint;
public ProcessorPlan optimize(
Command command)
@@ -220,7 +222,7 @@
PlanNode plan;
try {
- plan = generatePlan(command);
+ plan = generatePlan(command, true);
} catch (TeiidProcessingException e) {
throw new QueryPlannerException(e, e.getMessage());
}
@@ -259,7 +261,7 @@
result.setWith(withList);
}
result.setOutputElements(topCols);
-
+ result.setSourceHint(sourceHint);
return result;
}
@@ -483,7 +485,10 @@
return plan;
}
- public PlanNode generatePlan(Command cmd) throws TeiidComponentException, TeiidProcessingException {
+ public PlanNode generatePlan(Command cmd, boolean useSourceHint) throws TeiidComponentException, TeiidProcessingException {
+ if (useSourceHint && cmd.getSourceHint() != null && sourceHint == null) {
+ sourceHint = cmd.getSourceHint();
+ }
//cascade the option clause nocache
Option savedOption = option;
option = cmd.getOption();
@@ -564,7 +569,7 @@
if(!usingTriggerAction && command instanceof Insert){
Insert insert = (Insert)command;
if (insert.getQueryExpression() != null) {
- PlanNode plan = generatePlan(insert.getQueryExpression());
+ PlanNode plan = generatePlan(insert.getQueryExpression(), true);
attachLast(sourceNode, plan);
mergeTempMetadata(insert.getQueryExpression(), insert);
projectNode.setProperty(NodeConstants.Info.INTO_GROUP, insert.getGroup());
@@ -699,9 +704,12 @@
} else {
hints.hasSetQuery = true;
SetQuery query = (SetQuery)command;
+ boolean hasSourceHint = sourceHint != null;
PlanNode leftPlan = createQueryPlan( query.getLeftQuery());
PlanNode rightPlan = createQueryPlan( query.getRightQuery());
-
+ if (!hasSourceHint) {
+ sourceHint = null;
+ }
node = NodeFactory.getNewNode(NodeConstants.Types.SET_OP);
node.setProperty(NodeConstants.Info.SET_OPERATION, query.getOperation());
node.setProperty(NodeConstants.Info.USE_ALL, query.isAll());
@@ -848,6 +856,9 @@
if (info != null && info.getPartitionInfo() != null && !info.getPartitionInfo().isEmpty()) {
node.setProperty(NodeConstants.Info.PARTITION_INFO, info.getPartitionInfo());
}
+ if (parent.getType() != NodeConstants.Types.JOIN && nestedCommand.getSourceHint() != null && sourceHint == null) {
+ sourceHint = nestedCommand.getSourceHint();
+ }
addNestedCommand(node, group, nestedCommand, nestedCommand, true);
}
parent.addLastChild(node);
@@ -984,7 +995,7 @@
if (merge) {
mergeTempMetadata(nestedCommand, parentCommand);
- PlanNode childRoot = generatePlan(nestedCommand);
+ PlanNode childRoot = generatePlan(nestedCommand, false);
node.addFirstChild(childRoot);
List<SingleElementSymbol> projectCols = nestedCommand.getProjectedSymbols();
SymbolMap map = SymbolMap.createSymbolMap(group, projectCols, metadata);
Modified: trunk/engine/src/main/java/org/teiid/query/parser/ParseInfo.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/parser/ParseInfo.java 2011-11-09 18:09:23 UTC (rev 3623)
+++ trunk/engine/src/main/java/org/teiid/query/parser/ParseInfo.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -23,25 +23,23 @@
package org.teiid.query.parser;
import java.io.Serializable;
-import java.util.HashMap;
import java.util.Map;
-import org.teiid.query.sql.lang.CacheHint;
+import org.teiid.core.util.PropertiesUtils;
public class ParseInfo implements Serializable{
private static final long serialVersionUID = -7323683731955992888L;
+ private static final boolean ANSI_QUOTED_DEFAULT = PropertiesUtils.getBooleanProperty(System.getProperties(), "org.teiid.ansiQuotedIdentifiers", true); //$NON-NLS-1$
- public Map<String, Integer> nameCounts = new HashMap<String, Integer>();
+ public Map<String, Integer> nameCounts = null;
public int referenceCount = 0;
// treat a double quoted variable as variable instead of string
- public boolean ansiQuotedIdentifiers=Boolean.valueOf(System.getProperty("org.teiid.ansiQuotedIdentifiers", Boolean.TRUE.toString())).booleanValue(); //$NON-NLS-1$
+ public boolean ansiQuotedIdentifiers=ANSI_QUOTED_DEFAULT;
- public CacheHint cacheHint;
-
public ParseInfo() { }
public boolean useAnsiQuotedIdentifiers() {
Modified: trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java 2011-11-09 18:09:23 UTC (rev 3623)
+++ trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -22,6 +22,7 @@
package org.teiid.query.parser;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@@ -40,6 +41,7 @@
import org.teiid.query.sql.lang.Option;
import org.teiid.query.sql.lang.QueryCommand;
import org.teiid.query.sql.lang.SetQuery;
+import org.teiid.query.sql.lang.SourceHint;
import org.teiid.query.sql.lang.ExistsCriteria.SubqueryHint;
import org.teiid.query.sql.proc.Block;
import org.teiid.query.sql.proc.CriteriaSelector;
@@ -207,13 +209,42 @@
if (optToken == null) {
return ""; //$NON-NLS-1$
}
- String hint = optToken.image.substring(2, optToken.image.length() - 2);
+ //handle nested comments
+ String image = optToken.image;
+ while (optToken.specialToken != null) {
+ optToken = optToken.specialToken;
+ image = optToken.image + image;
+ }
+ String hint = image.substring(2, image.length() - 2);
if (hint.startsWith("+")) { //$NON-NLS-1$
hint = hint.substring(1);
}
return hint;
}
+ private static Pattern SOURCE_HINT = Pattern.compile("\\s*sh(?::((?:'[^']*')+))?\\s*", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); //$NON-NLS-1$
+ private static Pattern SOURCE_HINT_ARG = Pattern.compile("\\s*([^:]+):((?:'[^']*')+)", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); //$NON-NLS-1$
+
+ SourceHint getSourceHint(Token t) {
+ String comment = getComment(t);
+ Matcher matcher = SOURCE_HINT.matcher(comment);
+ if (!matcher.find()) {
+ return null;
+ }
+ SourceHint sourceHint = new SourceHint();
+ String generalHint = matcher.group(1);
+ if (generalHint != null) {
+ sourceHint.setGeneralHint(normalizeStringLiteral(generalHint));
+ }
+ int end = matcher.end();
+ matcher = SOURCE_HINT_ARG.matcher(comment);
+ while (matcher.find(end)) {
+ end = matcher.end();
+ sourceHint.setSourceHint(matcher.group(1), normalizeStringLiteral(matcher.group(2)));
+ }
+ return sourceHint;
+ }
+
boolean isNonStrictHint(Token t) {
String[] parts = getComment(t).split("\\s"); //$NON-NLS-1$
for (int i = 0; i < parts.length; i++) {
@@ -294,6 +325,9 @@
} else {
functionType = functionType.toLowerCase();
}
+ if (info.nameCounts == null) {
+ info.nameCounts = new HashMap<String, Integer>();
+ }
Integer num = info.nameCounts.get(functionType);
if (num == null) {
num = 0;
Modified: trunk/engine/src/main/java/org/teiid/query/processor/relational/RelationalPlan.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/relational/RelationalPlan.java 2011-11-09 18:09:23 UTC (rev 3623)
+++ trunk/engine/src/main/java/org/teiid/query/processor/relational/RelationalPlan.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -44,6 +44,7 @@
import org.teiid.query.sql.lang.Create;
import org.teiid.query.sql.lang.Insert;
import org.teiid.query.sql.lang.QueryCommand;
+import org.teiid.query.sql.lang.SourceHint;
import org.teiid.query.sql.lang.WithQueryCommand;
import org.teiid.query.tempdata.TempTableStore;
import org.teiid.query.tempdata.TempTableStore.TransactionMode;
@@ -62,6 +63,7 @@
private QueryProcessor withProcessor;
private TempTableStore tempTableStore;
private boolean multisourceUpdate;
+ private SourceHint sourceHint;
/**
* Constructor for RelationalPlan.
@@ -82,10 +84,21 @@
this.with = with;
}
+ public void setSourceHint(SourceHint sourceHint) {
+ this.sourceHint = sourceHint;
+ }
+
+ public SourceHint getSourceHint() {
+ return sourceHint;
+ }
+
/**
* @see ProcessorPlan#connectDataManager(ProcessorDataManager)
*/
public void initialize(CommandContext context, ProcessorDataManager dataMgr, BufferManager bufferMgr) {
+ if (sourceHint != null && context.getSourceHint() == null) {
+ context.setSourceHint(sourceHint);
+ }
if (this.with != null) {
context = context.clone();
tempTableStore = new TempTableStore(context.getConnectionID(), TransactionMode.NONE);
@@ -207,6 +220,7 @@
public RelationalPlan clone(){
RelationalPlan plan = new RelationalPlan((RelationalNode)root.clone());
+ plan.sourceHint = this.sourceHint;
plan.setOutputElements(outputCols);
if (with != null) {
List<WithQueryCommand> newWith = LanguageObject.Util.deepClone(this.with, WithQueryCommand.class);
Modified: trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java 2011-11-09 18:09:23 UTC (rev 3623)
+++ trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -754,13 +754,6 @@
return true;
}
- /**
- * Converts a group by with expressions into a group by with only element symbols and an inline view
- * @param query
- * @return
- * @throws TeiidProcessingException
- * @throws TeiidComponentException
- */
private Query rewriteGroupBy(Query query) throws TeiidComponentException, TeiidProcessingException {
if (query.getGroupBy() == null) {
rewriteAggs = false;
@@ -880,6 +873,8 @@
try {
List<ElementSymbol> allIntoElements = Util.deepClone(ResolverUtil.resolveElementsInGroup(into.getGroup(), metadata), ElementSymbol.class);
Insert insert = new Insert(into.getGroup(), allIntoElements, Collections.emptyList());
+ insert.setSourceHint(query.getSourceHint());
+ query.setSourceHint(null);
query.setInto(null);
insert.setQueryExpression(query);
return rewriteInsert(correctDatatypes(insert));
Modified: trunk/engine/src/main/java/org/teiid/query/sql/lang/Command.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/lang/Command.java 2011-11-09 18:09:23 UTC (rev 3623)
+++ trunk/engine/src/main/java/org/teiid/query/sql/lang/Command.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -130,6 +130,7 @@
private SymbolMap correlatedReferences;
private CacheHint cacheHint;
+ private SourceHint sourceHint;
/**
* Return type of command to make it easier to build switch statements by command type.
@@ -231,6 +232,7 @@
copy.setOption( (Option) this.getOption().clone() );
}
copy.cacheHint = this.cacheHint;
+ copy.sourceHint = this.sourceHint;
}
/**
@@ -324,6 +326,14 @@
this.cacheHint = cacheHint;
}
+ public SourceHint getSourceHint() {
+ return sourceHint;
+ }
+
+ public void setSourceHint(SourceHint sourceHint) {
+ this.sourceHint = sourceHint;
+ }
+
/**
* Returns a string representation of an instance of this class.
* @return String representation of object
@@ -333,7 +343,8 @@
}
protected boolean sameOptionAndHint(Command cmd) {
- return EquivalenceUtil.areEqual(this.cacheHint, cmd.cacheHint) &&
+ return EquivalenceUtil.areEqual(this.cacheHint, cmd.cacheHint) &&
+ EquivalenceUtil.areEqual(this.cacheHint, cmd.cacheHint) &&
EquivalenceUtil.areEqual(this.option, cmd.option);
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/lang/Delete.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/lang/Delete.java 2011-11-09 18:09:23 UTC (rev 3623)
+++ trunk/engine/src/main/java/org/teiid/query/sql/lang/Delete.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -161,6 +161,7 @@
Delete other = (Delete) obj;
return EquivalenceUtil.areEqual(getGroup(), other.getGroup()) &&
+ sameOptionAndHint(other) &&
EquivalenceUtil.areEqual(getCriteria(), other.getCriteria());
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/lang/Insert.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/lang/Insert.java 2011-11-09 18:09:23 UTC (rev 3623)
+++ trunk/engine/src/main/java/org/teiid/query/sql/lang/Insert.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -223,6 +223,7 @@
return EquivalenceUtil.areEqual(getGroup(), other.getGroup()) &&
EquivalenceUtil.areEqual(getValues(), other.getValues()) &&
EquivalenceUtil.areEqual(getVariables(), other.getVariables()) &&
+ sameOptionAndHint(other) &&
EquivalenceUtil.areEqual(getQueryExpression(), other.getQueryExpression());
}
Added: trunk/engine/src/main/java/org/teiid/query/sql/lang/SourceHint.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/lang/SourceHint.java (rev 0)
+++ trunk/engine/src/main/java/org/teiid/query/sql/lang/SourceHint.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -0,0 +1,74 @@
+/*
+ * 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.lang;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.teiid.core.util.EquivalenceUtil;
+
+public class SourceHint {
+
+ private String generalHint;
+ private Map<String, String> sourceHints;
+
+ public String getGeneralHint() {
+ return generalHint;
+ }
+
+ public void setGeneralHint(String generalHint) {
+ this.generalHint = generalHint;
+ }
+
+ public void setSourceHint(String translatorName, String hint) {
+ if (this.sourceHints == null) {
+ this.sourceHints = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER);
+ }
+ this.sourceHints.put(translatorName, hint);
+ }
+
+ public String getSourceHint(String sourceName) {
+ if (this.sourceHints == null) {
+ return null;
+ }
+ return this.sourceHints.get(sourceName);
+ }
+
+ public Map<String, String> getSourceHints() {
+ return sourceHints;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof SourceHint)) {
+ return false;
+ }
+ SourceHint other = (SourceHint)obj;
+ return EquivalenceUtil.areEqual(generalHint, other.generalHint)
+ && EquivalenceUtil.areEqual(this.sourceHints, other.sourceHints);
+ }
+
+}
Property changes on: trunk/engine/src/main/java/org/teiid/query/sql/lang/SourceHint.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Modified: trunk/engine/src/main/java/org/teiid/query/sql/lang/Update.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/lang/Update.java 2011-11-09 18:09:23 UTC (rev 3623)
+++ trunk/engine/src/main/java/org/teiid/query/sql/lang/Update.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -206,12 +206,9 @@
Update other = (Update) obj;
return
- // Compare the groups
EquivalenceUtil.areEqual(getGroup(), other.getGroup()) &&
- // Compare the changeList by checking to see if
- // both objects contains exactly the same CompareCriteria objects.
getChangeList().equals(other.getChangeList()) &&
- // Compare the criteria clauses
+ sameOptionAndHint(other) &&
EquivalenceUtil.areEqual(getCriteria(), other.getCriteria());
}
@@ -261,12 +258,12 @@
LinkedHashMap<ElementSymbol, Expression> map = new LinkedHashMap<ElementSymbol, Expression>();
- for (Iterator iter = getChangeList().getClauses().iterator(); iter.hasNext();) {
- SetClause setClause = (SetClause)iter.next();
- ElementSymbol symbol = (ElementSymbol)(setClause.getSymbol()).clone();
+ for (Iterator<SetClause> iter = getChangeList().getClauses().iterator(); iter.hasNext();) {
+ SetClause setClause = iter.next();
+ ElementSymbol symbol = setClause.getSymbol().clone();
symbol.setGroupSymbol(new GroupSymbol(ProcedureReservedWords.INPUTS));
map.put( symbol, setClause.getValue() );
- } // for
+ }
return map;
}
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 2011-11-09 18:09:23 UTC (rev 3623)
+++ trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -28,6 +28,7 @@
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import org.teiid.core.types.DataTypeManager;
import org.teiid.core.util.StringUtil;
@@ -78,6 +79,7 @@
import org.teiid.query.sql.lang.SetClauseList;
import org.teiid.query.sql.lang.SetCriteria;
import org.teiid.query.sql.lang.SetQuery;
+import org.teiid.query.sql.lang.SourceHint;
import org.teiid.query.sql.lang.StoredProcedure;
import org.teiid.query.sql.lang.SubqueryCompareCriteria;
import org.teiid.query.sql.lang.SubqueryFromClause;
@@ -347,7 +349,7 @@
beginClause(2);
// Columns clause
- List vars = obj.getVariables();
+ List<ElementSymbol> vars = obj.getVariables();
if (vars != null) {
append("("); //$NON-NLS-1$
registerNodes(vars, 0);
@@ -632,10 +634,10 @@
append(MAKENOTDEP);
append(" "); //$NON-NLS-1$
- Iterator iter = groups.iterator();
+ Iterator<String> iter = groups.iterator();
while (iter.hasNext()) {
- outputDisplayName((String)iter.next());
+ outputDisplayName(iter.next());
if (iter.hasNext()) {
append(", ");//$NON-NLS-1$
@@ -649,10 +651,10 @@
append(NOCACHE);
append(" "); //$NON-NLS-1$
- Iterator iter = groups.iterator();
+ Iterator<String> iter = groups.iterator();
while (iter.hasNext()) {
- outputDisplayName((String)iter.next());
+ outputDisplayName(iter.next());
if (iter.hasNext()) {
append(", ");//$NON-NLS-1$
@@ -777,7 +779,9 @@
public void visit( Query obj ) {
addCacheHint(obj.getCacheHint());
addWithClause(obj);
- visitNode(obj.getSelect());
+ if (obj.getSelect() != null) {
+ visitDirect(obj.getSelect(), obj);
+ }
if (obj.getInto() != null) {
beginClause(1);
@@ -864,23 +868,55 @@
}
public void visit( Select obj ) {
+ visitDirect(obj, null);
+ }
+
+ private void visitDirect(Select obj, Query query) {
append(SELECT);
- if (obj.isDistinct()) {
+
+ if (query != null) {
+ SourceHint sh = query.getSourceHint();
+ if (sh != null) {
+ append(SPACE);
+ append(BEGIN_HINT);
+ append("sh"); //$NON-NLS-1$
+ if (sh.getGeneralHint() != null) {
+ appendSourceHintValue(sh.getGeneralHint());
+ }
+ if (sh.getSourceHints() != null) {
+ for (Map.Entry<String, String> entry : sh.getSourceHints().entrySet()) {
+ append(entry.getKey());
+ appendSourceHintValue(entry.getValue());
+ }
+ }
+ append(END_HINT);
+ }
+ }
+
+ if (obj.isDistinct()) {
append(SPACE);
append(DISTINCT);
}
beginClause(2);
- Iterator iter = obj.getSymbols().iterator();
+ Iterator<SelectSymbol> iter = obj.getSymbols().iterator();
while (iter.hasNext()) {
- SelectSymbol symbol = (SelectSymbol)iter.next();
+ SelectSymbol symbol = iter.next();
visitNode(symbol);
if (iter.hasNext()) {
append(", "); //$NON-NLS-1$
}
}
- }
+ }
+ private void appendSourceHintValue(String sh) {
+ append(Tokens.COLON);
+ append('\'');
+ append(escapeStringValue(sh, "'")); //$NON-NLS-1$
+ append('\'');
+ append(SPACE);
+ }
+
public void visit( SetCriteria obj ) {
// variable
visitNode(obj.getExpression());
@@ -950,8 +986,8 @@
protected void appendSetQuery( SetQuery parent,
QueryCommand obj,
boolean right ) {
- if (right && ((obj instanceof SetQuery
- && ((parent.isAll() && !((SetQuery)obj).isAll()) || parent.getOperation() != ((SetQuery)obj).getOperation())) || obj.getLimit() != null || obj.getOrderBy() != null)) {
+ if (obj.getLimit() != null || obj.getOrderBy() != null || (right && ((obj instanceof SetQuery
+ && ((parent.isAll() && !((SetQuery)obj).isAll()) || parent.getOperation() != ((SetQuery)obj).getOperation()))))) {
append(Tokens.LPAREN);
visitNode(obj);
append(Tokens.RPAREN);
@@ -1415,6 +1451,9 @@
}
}
+ /**
+ * @param level
+ */
protected void addTabs( int level ) {
}
Modified: trunk/engine/src/main/java/org/teiid/query/util/CommandContext.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/util/CommandContext.java 2011-11-09 18:09:23 UTC (rev 3623)
+++ trunk/engine/src/main/java/org/teiid/query/util/CommandContext.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -56,6 +56,7 @@
import org.teiid.query.optimizer.relational.PlanToProcessConverter;
import org.teiid.query.parser.ParseInfo;
import org.teiid.query.processor.QueryProcessor;
+import org.teiid.query.sql.lang.SourceHint;
import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.sql.symbol.Expression;
import org.teiid.query.sql.util.VariableContext;
@@ -133,6 +134,7 @@
private DQPWorkContext dqpWorkContext;
private TransactionContext transactionContext;
private TransactionService transactionService;
+ private SourceHint sourceHint;
}
private GlobalState globalState = new GlobalState();
@@ -629,4 +631,12 @@
globalState.transactionService = transactionService;
}
+ public SourceHint getSourceHint() {
+ return this.globalState.sourceHint;
+ }
+
+ public void setSourceHint(SourceHint hint) {
+ this.globalState.sourceHint = hint;
+ }
+
}
Modified: trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
===================================================================
--- trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2011-11-09 18:09:23 UTC (rev 3623)
+++ trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2011-11-09 20:06:24 UTC (rev 3624)
@@ -38,6 +38,11 @@
PARSER_END(SQLParser)
+TOKEN_MGR_DECLS :
+{
+ int commentNestingDepth;
+}
+
SKIP :
{
" " | "\t" | "\n" | "\r"
@@ -45,16 +50,25 @@
MORE :
{
- "/*" : IN_MULTI_LINE_COMMENT
+ "/*" { commentNestingDepth = 1 ; } : IN_MULTI_LINE_COMMENT
}
<IN_MULTI_LINE_COMMENT>
-SPECIAL_TOKEN :
-{
- <MULTI_LINE_COMMENT: "*/" > : DEFAULT
-}
+MORE :
+{
+ "/*" { commentNestingDepth += 1 ; }
+}
<IN_MULTI_LINE_COMMENT>
+SPECIAL_TOKEN :
+{
+ "*/" {
+ commentNestingDepth -= 1;
+ SwitchTo( commentNestingDepth==0 ? DEFAULT : IN_MULTI_LINE_COMMENT ) ;
+ }
+}
+
+<IN_MULTI_LINE_COMMENT>
MORE :
{
< ~[] >
@@ -596,8 +610,18 @@
Command userCommand(ParseInfo info) :
{
Command command = null;
+ SourceHint sourceHint = null;
}
{
+ {int index = 1;
+ Token t = null;
+ do
+ t = getToken(index++);
+ while (t != null && t.kind == LPAREN);
+ t = getToken(index);
+ if (t != null)
+ sourceHint = getSourceHint(t);
+ }
(command = queryExpression(info) |
command = storedProcedure(info, new StoredProcedure()) |
command = insert(info) |
@@ -609,6 +633,13 @@
command = createTrigger(info)
)
{
+ if (sourceHint != null) {
+ if (command instanceof SetQuery) {
+ ((SetQuery)command).getProjectedQuery().setSourceHint(sourceHint);
+ } else {
+ command.setSourceHint(sourceHint);
+ }
+ }
return command;
}
}
@@ -1590,7 +1621,6 @@
String group = null;
SetClauseList setClauseList = null;
Criteria criteria = null;
- ElementSymbol elementID = null;
Option option = null;
}
{
@@ -1650,9 +1680,6 @@
}
}
-/**
- * Currently just a place holder to keep consistency with the spec
- */
QueryCommand queryExpression(ParseInfo info) :
{
QueryCommand query = null;
Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/TestRuleRemoveSorts.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/optimizer/TestRuleRemoveSorts.java 2011-11-09 18:09:23 UTC (rev 3623)
+++ trunk/engine/src/test/java/org/teiid/query/optimizer/TestRuleRemoveSorts.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -22,17 +22,16 @@
package org.teiid.query.optimizer;
+import org.junit.Test;
import org.teiid.query.optimizer.TestOptimizer.ComparisonMode;
import org.teiid.query.processor.ProcessorPlan;
import org.teiid.query.unittest.RealMetadataFactory;
-import junit.framework.TestCase;
-
-public class TestRuleRemoveSorts extends TestCase {
+public class TestRuleRemoveSorts {
/** Tests an order by in a query transformation */
- public void testRemovedOrderByFromQueryTransform() {
+ @Test public void testRemovedOrderByFromQueryTransform() {
ProcessorPlan plan = TestOptimizer.helpPlan("SELECT e1, e2 FROM vm1.g14", RealMetadataFactory.example1Cached(), //$NON-NLS-1$
new String[] { "SELECT pm3.g1.e1, pm3.g1.e2 FROM pm3.g1"}); //$NON-NLS-1$
@@ -43,7 +42,7 @@
* Tests an order by in a query transformation, where the
* physical model does not support pushing order bys
*/
- public void testRemovedOrderByFromQueryTransform2() {
+ @Test public void testRemovedOrderByFromQueryTransform2() {
ProcessorPlan plan = TestOptimizer.helpPlan("SELECT e, e2 FROM vm1.g8", RealMetadataFactory.example1Cached(), //$NON-NLS-1$
new String[] { "SELECT e1, e2 FROM pm1.g1"}); //$NON-NLS-1$
@@ -69,7 +68,7 @@
* Tests an order by in a query transformation, where the
* query transformation contains a function
*/
- public void testRemovedOrderByFromQueryTransform3() {
+ @Test public void testRemovedOrderByFromQueryTransform3() {
ProcessorPlan plan = TestOptimizer.helpPlan("SELECT e, e2 FROM vm1.g16", RealMetadataFactory.example1Cached(), //$NON-NLS-1$
new String[] { "SELECT e1, e2 FROM pm3.g1"}); //$NON-NLS-1$
@@ -92,7 +91,7 @@
}
/** Tests an order by in a query transformation */
- public void testRemovedOrderByFromQueryTransform4() {
+ @Test public void testRemovedOrderByFromQueryTransform4() {
ProcessorPlan plan = TestOptimizer.helpPlan("SELECT e1, e2 FROM vm1.g13", RealMetadataFactory.example1Cached(), //$NON-NLS-1$
new String[] { "SELECT DISTINCT pm3.g1.e1, pm3.g1.e2, pm3.g1.e3, pm3.g1.e4 FROM pm3.g1"}); //$NON-NLS-1$
@@ -115,7 +114,7 @@
}
/** Order by is not removed */
- public void testOrderByWithLimit() throws Exception {
+ @Test public void testOrderByWithLimit() throws Exception {
ProcessorPlan plan = TestOptimizer.helpPlan("select * from (SELECT e1, e2 FROM pm1.g1 order by e1 limit 10) x", RealMetadataFactory.example1Cached(), //$NON-NLS-1$
new String[] { "SELECT g_0.e1 AS c_0, g_0.e2 AS c_1 FROM pm1.g1 AS g_0 ORDER BY c_0"}, ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$
Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/relational/rules/TestRuleAccessPatternValidation.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/optimizer/relational/rules/TestRuleAccessPatternValidation.java 2011-11-09 18:09:23 UTC (rev 3623)
+++ trunk/engine/src/test/java/org/teiid/query/optimizer/relational/rules/TestRuleAccessPatternValidation.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -85,7 +85,7 @@
//Generate canonical plan
RelationalPlanner p = new RelationalPlanner();
p.initialize(query, null, METADATA, FINDER, null, new CommandContext());
- PlanNode planNode = p.generatePlan(query);
+ PlanNode planNode = p.generatePlan(query, false);
RelationalPlanner planner = new RelationalPlanner();
final RuleStack rules = planner.buildRules();
Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/relational/rules/TestRulePushSelectCriteria.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/optimizer/relational/rules/TestRulePushSelectCriteria.java 2011-11-09 18:09:23 UTC (rev 3623)
+++ trunk/engine/src/test/java/org/teiid/query/optimizer/relational/rules/TestRulePushSelectCriteria.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -73,8 +73,8 @@
RelationalPlanner p = new RelationalPlanner();
CommandContext cc = new CommandContext();
p.initialize(command, null, metadata, null, null, cc);
- PlanNode root = p.generatePlan(command);
- PlanNode child = p.generatePlan(subCommand);
+ PlanNode root = p.generatePlan(command, false);
+ PlanNode child = p.generatePlan(subCommand, false);
PlanNode sourceNode = NodeEditor.findNodePreOrder(root, NodeConstants.Types.SOURCE);
sourceNode.addFirstChild(child);
sourceNode.setProperty(NodeConstants.Info.SYMBOL_MAP, SymbolMap.createSymbolMap(sourceNode.getGroups().iterator().next(), (List<SingleElementSymbol>)child.getFirstChild().getProperty(Info.PROJECT_COLS), metadata));
Modified: trunk/engine/src/test/java/org/teiid/query/parser/TestOptionsAndHints.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/parser/TestOptionsAndHints.java 2011-11-09 18:09:23 UTC (rev 3623)
+++ trunk/engine/src/test/java/org/teiid/query/parser/TestOptionsAndHints.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -425,6 +425,7 @@
option.setNoCache(true);
Criteria crit = new CompareCriteria(new ElementSymbol("b"), CompareCriteria.EQ, new Reference(1)); //$NON-NLS-1$
update.setCriteria(crit);
+ update.setOption(option);
TestParser.helpTest("UPDATE m.g SET a = ? WHERE b = ? OPTION NOCACHE", //$NON-NLS-1$
"UPDATE m.g SET a = ? WHERE b = ? OPTION NOCACHE", //$NON-NLS-1$
update);
@@ -1173,4 +1174,17 @@
assertEquals("SELECT a FROM x /*+ NON_STRICT */ LIMIT 1", QueryParser.getQueryParser().parseCommand(sql, new ParseInfo()).toString()); //$NON-NLS-1$
}
+ @Test public void testNestedComments() throws QueryParserException {
+ String sql = "/*+ /*nested*/ */ SELECT a FROM x limit 1"; //$NON-NLS-1$
+ assertEquals("SELECT a FROM x LIMIT 1", QueryParser.getQueryParser().parseCommand(sql, new ParseInfo()).toString()); //$NON-NLS-1$
+ }
+
+ @Test public void testSourceHint() throws QueryParserException {
+ String sql = "SELECT /*+ sh:'foo' oracle:'leading' */ a FROM x limit 1"; //$NON-NLS-1$
+ assertEquals("SELECT /*+sh:'foo' oracle:'leading' */ a FROM x LIMIT 1", QueryParser.getQueryParser().parseCommand(sql, new ParseInfo()).toString()); //$NON-NLS-1$
+
+ sql = "(SELECT /*+ sh:'foo' oracle:'leading' */ a FROM x limit 1) union all select 1"; //$NON-NLS-1$
+ assertEquals("(SELECT /*+sh:'foo' oracle:'leading' */ a FROM x LIMIT 1) UNION ALL SELECT 1", QueryParser.getQueryParser().parseCommand(sql, new ParseInfo()).toString());
+ }
+
}
Added: trunk/engine/src/test/java/org/teiid/query/processor/TestSourceHints.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/TestSourceHints.java (rev 0)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestSourceHints.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -0,0 +1,108 @@
+/*
+ * 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;
+
+import static org.junit.Assert.*;
+import static org.teiid.query.processor.TestProcessor.*;
+
+import java.util.List;
+
+import org.junit.Test;
+import org.teiid.common.buffer.TupleSource;
+import org.teiid.core.TeiidComponentException;
+import org.teiid.metadata.MetadataStore;
+import org.teiid.metadata.Schema;
+import org.teiid.metadata.Table;
+import org.teiid.query.mapping.relational.QueryNode;
+import org.teiid.query.metadata.TransformationMetadata;
+import org.teiid.query.sql.lang.Command;
+import org.teiid.query.unittest.RealMetadataFactory;
+import org.teiid.query.util.CommandContext;
+
+ at SuppressWarnings("nls")
+public class TestSourceHints {
+
+ @Test public void testUserQueryHint() {
+ String sql = "SELECT /*+ sh:'foo' bar:'leading' */ e1 from pm1.g1 order by e1 limit 1"; //$NON-NLS-1$
+
+ ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached());
+
+ List<?>[] expected = new List[] {};
+ helpProcess(plan, manager("foo", "leading"), expected);
+ }
+
+ @Test public void testHintInView() {
+ MetadataStore metadataStore = new MetadataStore();
+ Schema p1 = RealMetadataFactory.createPhysicalModel("p1", metadataStore); //$NON-NLS-1$
+ Table t1 = RealMetadataFactory.createPhysicalGroup("t", p1); //$NON-NLS-1$
+ RealMetadataFactory.createElements(t1, new String[] {"a", "b" }, new String[] { "string", "string" }); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+
+ Schema v1 = RealMetadataFactory.createVirtualModel("v1", metadataStore); //$NON-NLS-1$
+ QueryNode n1 = new QueryNode("SELECT /*+ sh:'x' */ a as c, b FROM p1.t"); //$NON-NLS-1$ //$NON-NLS-2$
+ Table vt1 = RealMetadataFactory.createVirtualGroup("t1", v1, n1); //$NON-NLS-1$
+ RealMetadataFactory.createElements(vt1, new String[] {"c", "b" }, new String[] { "string", "string" }); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+
+ TransformationMetadata metadata = RealMetadataFactory.createTransformationMetadata(metadataStore, "metadata");
+
+ //top level applies
+ HardcodedDataManager manager = manager("foo", "leading");
+
+ String sql = "SELECT /*+ sh:'foo' bar:'leading' */ c from t1 order by c limit 1"; //$NON-NLS-1$
+ ProcessorPlan plan = helpGetPlan(sql, metadata);
+
+ List<?>[] expected = new List[] {};
+ helpProcess(plan, manager, expected);
+
+ //use the underlying hint
+ manager = manager("x", null);
+ sql = "SELECT c from t1 order by c limit 1"; //$NON-NLS-1$
+ plan = helpGetPlan(sql, metadata);
+ helpProcess(plan, manager, expected);
+
+ //use no hints
+ manager = manager(null, null);
+ sql = "SELECT c from t1 union all select c from t1"; //$NON-NLS-1$
+ plan = helpGetPlan(sql, metadata);
+ helpProcess(plan, manager, expected);
+ }
+
+ private HardcodedDataManager manager(final String general, final String hint) {
+ HardcodedDataManager manager = new HardcodedDataManager() {
+ @Override
+ public TupleSource registerRequest(CommandContext context,
+ Command command, String modelName,
+ String connectorBindingId, int nodeID, int limit)
+ throws TeiidComponentException {
+ if (general == null && hint == null) {
+ assertNull(context.getSourceHint());
+ } else {
+ assertEquals(general, context.getSourceHint().getGeneralHint()); //$NON-NLS-1$
+ assertEquals(hint, context.getSourceHint().getSourceHint("bar")); //$NON-NLS-1$
+ }
+ return CollectionTupleSource.createNullTupleSource();
+ }
+ };
+ return manager;
+ }
+
+}
Property changes on: trunk/engine/src/test/java/org/teiid/query/processor/TestSourceHints.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Modified: trunk/engine/src/test/java/org/teiid/query/processor/eval/TestExpressionEvaluator.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/eval/TestExpressionEvaluator.java 2011-11-09 18:09:23 UTC (rev 3623)
+++ trunk/engine/src/test/java/org/teiid/query/processor/eval/TestExpressionEvaluator.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -42,12 +42,14 @@
import org.teiid.core.types.DataTypeManager;
import org.teiid.query.eval.Evaluator;
import org.teiid.query.function.FunctionDescriptor;
+import org.teiid.query.parser.QueryParser;
import org.teiid.query.processor.FakeDataManager;
import org.teiid.query.processor.ProcessorDataManager;
import org.teiid.query.resolver.TestFunctionResolving;
import org.teiid.query.sql.lang.CollectionValueIterator;
import org.teiid.query.sql.lang.IsNullCriteria;
import org.teiid.query.sql.lang.Query;
+import org.teiid.query.sql.lang.QueryCommand;
import org.teiid.query.sql.lang.SubqueryContainer;
import org.teiid.query.sql.symbol.CaseExpression;
import org.teiid.query.sql.symbol.Constant;
@@ -294,7 +296,7 @@
}
@Test public void testScalarSubqueryFails() throws Exception{
- ScalarSubquery expr = new ScalarSubquery(new Query());
+ ScalarSubquery expr = new ScalarSubquery((QueryCommand) QueryParser.getQueryParser().parseCommand("select x from y"));
ArrayList values = new ArrayList(2);
values.add("a"); //$NON-NLS-1$
values.add("b"); //$NON-NLS-1$
@@ -303,7 +305,7 @@
helpTestWithValueIterator(expr, values, null);
fail("Expected ExpressionEvaluationException but got none"); //$NON-NLS-1$
} catch (ExpressionEvaluationException e) {
- assertEquals("Error Code:ERR.015.006.0058 Message:Unable to evaluate (<undefined>): Error Code:ERR.015.006.0058 Message:The command of this scalar subquery returned more than one value: <undefined>", e.getMessage()); //$NON-NLS-1$
+ assertEquals("Error Code:ERR.015.006.0058 Message:Unable to evaluate (SELECT x FROM y): Error Code:ERR.015.006.0058 Message:The command of this scalar subquery returned more than one value: SELECT x FROM y", e.getMessage()); //$NON-NLS-1$
}
}
Modified: trunk/runtime/src/main/java/org/teiid/odbc/ODBCClientRemote.java
===================================================================
--- trunk/runtime/src/main/java/org/teiid/odbc/ODBCClientRemote.java 2011-11-09 18:09:23 UTC (rev 3623)
+++ trunk/runtime/src/main/java/org/teiid/odbc/ODBCClientRemote.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -80,7 +80,7 @@
void sendMoveCursor(ResultSetImpl rs, int rowCount, ResultsFuture<Integer> results);
- void sendCommandComplete(String sql, int updateCount);
+ void sendCommandComplete(String sql, Integer count);
// CommandComplete (B)
void sendUpdateCount(String sql, int updateCount);
Modified: trunk/runtime/src/main/java/org/teiid/odbc/ODBCServerRemoteImpl.java
===================================================================
--- trunk/runtime/src/main/java/org/teiid/odbc/ODBCServerRemoteImpl.java 2011-11-09 18:09:23 UTC (rev 3623)
+++ trunk/runtime/src/main/java/org/teiid/odbc/ODBCServerRemoteImpl.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -268,7 +268,7 @@
try {
List<PgColInfo> cols = getPgColInfo(stmt.getResultSet().getMetaData());
cursorMap.put(cursorName, new Cursor(cursorName, sql, stmt, null, stmt.getResultSet(), cols));
- client.sendCommandComplete("DECLARE CURSOR", 0); //$NON-NLS-1$
+ client.sendCommandComplete("DECLARE CURSOR", null); //$NON-NLS-1$
completion.getResultsReceiver().receiveResults(0);
} catch (Throwable e) {
completion.getResultsReceiver().exceptionOccurred(e);
@@ -336,7 +336,7 @@
if (cursor != null) {
cursor.rs.close();
cursor.stmt.close();
- this.client.sendCommandComplete("CLOSE CURSOR", 0); //$NON-NLS-1$
+ this.client.sendCommandComplete("CLOSE CURSOR", null); //$NON-NLS-1$
}
}
@@ -941,7 +941,7 @@
String plan_name = m.group(1);
plan_name = SQLParserUtil.normalizeId(plan_name);
closePreparedStatement(plan_name);
- client.sendCommandComplete("DEALLOCATE", 0); //$NON-NLS-1$
+ client.sendCommandComplete("DEALLOCATE", null); //$NON-NLS-1$
results.getResultsReceiver().receiveResults(1);
}
else {
Modified: trunk/runtime/src/main/java/org/teiid/transport/PgBackendProtocol.java
===================================================================
--- trunk/runtime/src/main/java/org/teiid/transport/PgBackendProtocol.java 2011-11-09 18:09:23 UTC (rev 3623)
+++ trunk/runtime/src/main/java/org/teiid/transport/PgBackendProtocol.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -56,6 +56,7 @@
import org.teiid.client.util.ResultsFuture;
import org.teiid.core.util.ObjectConverterUtil;
import org.teiid.core.util.ReflectionHelper;
+import org.teiid.core.util.SqlUtil;
import org.teiid.core.util.StringUtil;
import org.teiid.jdbc.ResultSetImpl;
import org.teiid.jdbc.TeiidSQLException;
@@ -155,7 +156,7 @@
} else {
sendContents();
if (sql != null) {
- sendCommandComplete(sql, 0);
+ sendCommandComplete(sql, rowsSent);
}
result.getResultsReceiver().receiveResults(rowsSent);
processNext = false;
@@ -417,42 +418,28 @@
}
@Override
- public void sendCommandComplete(String sql, int updateCount) {
+ public void sendCommandComplete(String sql, Integer count) {
startMessage('C');
- // TODO remove remarks at the beginning
String tag;
- if (StringUtil.startsWithIgnoreCase(sql, "INSERT")) {
- tag = "INSERT 0 " + updateCount;
- } else if (StringUtil.startsWithIgnoreCase(sql, "DELETE")) {
- tag = "DELETE " + updateCount;
- } else if (StringUtil.startsWithIgnoreCase(sql, "UPDATE")) {
- tag = "UPDATE " + updateCount;
- } else if (StringUtil.startsWithIgnoreCase(sql, "SELECT") || StringUtil.startsWithIgnoreCase(sql, "CALL")) {
- tag = "SELECT";
- } else if (StringUtil.startsWithIgnoreCase(sql, "BEGIN") || StringUtil.startsWithIgnoreCase(sql, "START TRANSACTION")) {
+ if (StringUtil.startsWithIgnoreCase(sql, "BEGIN") || StringUtil.startsWithIgnoreCase(sql, "START TRANSACTION")) {
tag = "BEGIN";
- } else if (StringUtil.startsWithIgnoreCase(sql, "COMMIT")) {
- tag = "COMMIT";
- } else if (StringUtil.startsWithIgnoreCase(sql, "ROLLBACK")) {
- tag = "ROLLBACK";
+ } else if (sql.indexOf(' ') == -1) {
+ //should already be a completion tag
+ tag = sql.toUpperCase();
+ if (count != null) {
+ tag += " " + count;
+ }
} else if (StringUtil.startsWithIgnoreCase(sql, "SET ")) {
tag = "SET";
- } else if (StringUtil.startsWithIgnoreCase(sql, "DECLARE CURSOR")) {
- tag = "DECLARE CURSOR";
- } else if (StringUtil.startsWithIgnoreCase(sql, "CLOSE CURSOR")) {
- tag = "CLOSE CURSOR";
- } else if (StringUtil.startsWithIgnoreCase(sql, "FETCH")) {
- tag = "FETCH "+ updateCount;
- } else if (StringUtil.startsWithIgnoreCase(sql, "MOVE")) {
- tag = "MOVE "+ updateCount;
- } else if (StringUtil.startsWithIgnoreCase(sql, "RELEASE")) {
- tag = "RELEASE "+ updateCount;
- } else if (StringUtil.startsWithIgnoreCase(sql, "SAVEPOINT")) {
- tag = "SAVEPOINT "+ updateCount;
+ } else {
+ tag = SqlUtil.getKeyword(sql).toUpperCase();
+ if (tag.equals("EXEC") || tag.equals("CALL")) {
+ tag = "SELECT";
+ }
+ if (count != null) {
+ tag += " " + count;
+ }
}
- else {
- tag = sql;
- }
writeString(tag);
sendMessage();
}
Modified: trunk/test-integration/common/src/test/java/org/teiid/connector/visitor/util/TestSQLStringVisitor.java
===================================================================
--- trunk/test-integration/common/src/test/java/org/teiid/connector/visitor/util/TestSQLStringVisitor.java 2011-11-09 18:09:23 UTC (rev 3623)
+++ trunk/test-integration/common/src/test/java/org/teiid/connector/visitor/util/TestSQLStringVisitor.java 2011-11-09 20:06:24 UTC (rev 3624)
@@ -352,7 +352,7 @@
}
@Test public void testVisitIUnion1() throws Exception {
- String expected = "SELECT DISTINCT g1.e1, g1.e2, g1.e3, g1.e4 FROM g1, g2 AS myAlias, g3, g4 WHERE 100 >= 200 AND 500 < 600 GROUP BY g1.e1, g1.e2, g1.e3, g1.e4 HAVING 100 >= 200 AND 500 < 600 ORDER BY g1.e1, g1.e2 DESC, g1.e3, g1.e4 DESC UNION (SELECT DISTINCT g1.e1, g1.e2, g1.e3, g1.e4 FROM g1, g2 AS myAlias, g3, g4 WHERE 100 >= 200 AND 500 < 600 GROUP BY g1.e1, g1.e2, g1.e3, g1.e4 HAVING 100 >= 200 AND 500 < 600 ORDER BY g1.e1, g1.e2 DESC, g1.e3, g1.e4 DESC) ORDER BY e1, e2 DESC, e3, e4 DESC";//$NON-NLS-1$
+ String expected = "(SELECT DISTINCT g1.e1, g1.e2, g1.e3, g1.e4 FROM g1, g2 AS myAlias, g3, g4 WHERE 100 >= 200 AND 500 < 600 GROUP BY g1.e1, g1.e2, g1.e3, g1.e4 HAVING 100 >= 200 AND 500 < 600 ORDER BY g1.e1, g1.e2 DESC, g1.e3, g1.e4 DESC) UNION (SELECT DISTINCT g1.e1, g1.e2, g1.e3, g1.e4 FROM g1, g2 AS myAlias, g3, g4 WHERE 100 >= 200 AND 500 < 600 GROUP BY g1.e1, g1.e2, g1.e3, g1.e4 HAVING 100 >= 200 AND 500 < 600 ORDER BY g1.e1, g1.e2 DESC, g1.e3, g1.e4 DESC) ORDER BY e1, e2 DESC, e3, e4 DESC";//$NON-NLS-1$
assertEquals(expected, getString(TestSetQueryImpl.example()));
}
More information about the teiid-commits
mailing list