[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