[teiid-commits] teiid SVN: r4301 - in trunk: engine/src/main/java/org/teiid/query/parser and 4 other directories.

teiid-commits at lists.jboss.org teiid-commits at lists.jboss.org
Tue Aug 7 09:41:49 EDT 2012


Author: shawkins
Date: 2012-08-07 09:41:48 -0400 (Tue, 07 Aug 2012)
New Revision: 4301

Modified:
   trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html
   trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java
   trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
   trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java
   trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java
   trunk/test-integration/common/src/test/java/org/teiid/jdbc/TestDynamicImportedMetaData.java
Log:
TEIID-2113 adding additional doc features and minor parsing improvements

Modified: trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html
===================================================================
--- trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html	2012-08-06 20:18:00 UTC (rev 4300)
+++ trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html	2012-08-07 13:41:48 UTC (rev 4301)
@@ -32,6 +32,8 @@
   <LI>TEIID-2105 <B>Improved VDB loading</B> - vdb loading logic was refined to make administration easier.  ExecutionFactory now has is/setSourceRequiredForMetadata() to indicate whether a source connection is needed for the getMetadata call.
   <LI>TEIID-1598 <B>Translator Result Caching</B> - translators can interact with the result set caching facility via a CacheDirective.  See the Developer's Guide for more.
   <LI>TEIID-2077 <B>Result reuse</B> - the engine will automatically detect if the same source query is used multiple times in a plan and reuse the result rather than issuing another query.
+  <LI>TEIID-2113 <B>Misc parser improvements</B> - the parser will now accept the LATERAL keyword for defining a LATERAL join (previously we just used the TABLE keyword), unary negation is now supported i.e. -col1, the FOR keyword is optional for TEXTAGG,
+and the BNF documentation was dramatically improved. 
 </UL>
 
 <h2><a name="Compatibility">Compatibility Issues</a></h2>

Modified: trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java	2012-08-06 20:18:00 UTC (rev 4300)
+++ trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java	2012-08-07 13:41:48 UTC (rev 4301)
@@ -45,6 +45,7 @@
 import org.teiid.query.sql.lang.ExistsCriteria.SubqueryHint;
 import org.teiid.query.sql.proc.Block;
 import org.teiid.query.sql.proc.Statement;
+import org.teiid.query.sql.symbol.Expression;
 import org.teiid.query.sql.symbol.GroupSymbol;
 import org.teiid.translator.TranslatorException;
 
@@ -54,6 +55,21 @@
 	
 	public static final boolean DECIMAL_AS_DOUBLE = PropertiesUtils.getBooleanProperty(System.getProperties(), "org.teiid.decimalAsDouble", false); //$NON-NLS-1$
 	
+	String prependSign(String sign, String literal) {
+		if (sign != null && sign.charAt(0) == '-') {
+			return sign + literal;
+		}
+		return literal;
+	}
+	
+	void convertToParameters(List<Expression> values, StoredProcedure storedProcedure) {
+		for (Expression value : values) {
+			SPParameter parameter = new SPParameter(storedProcedure.getParameters().size() + 1, value);
+			parameter.setParameterType(SPParameter.IN);
+			storedProcedure.setParameter(parameter);
+		}
+	}
+	
 	String matchesAny(String arg, String ... expected) {
 		for (String string : expected) {
 			if (string.equalsIgnoreCase(arg)) {

Modified: trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
===================================================================
--- trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj	2012-08-06 20:18:00 UTC (rev 4300)
+++ trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj	2012-08-07 13:41:48 UTC (rev 4301)
@@ -16,6 +16,7 @@
 import java.math.BigInteger;
 import java.util.*;
 import org.teiid.core.types.*;
+import org.teiid.core.util.StringUtil;
 import org.teiid.query.QueryPlugin;
 import org.teiid.query.sql.LanguageObject;
 import org.teiid.query.sql.lang.*;
@@ -413,7 +414,6 @@
 |   <FIRST: "first">
 |   <LAST: "last">
 |   <NEXT: "next">
-|   <FN: "fn">
 |   <SUBSTRING: "substring">
 |   <EXTRACT: "extract">
 |   <TO_CHARS: "to_chars">
@@ -444,7 +444,6 @@
 |   <PASSING: "passing">
 |   <NAME: "name">
 |   <ENCODING: "encoding">
-|   <OJ: "oj">
 |   <COLUMNS: "columns">
 |   <DELIMITER: "delimiter">
 |   <QUOTE: "quote">
@@ -452,33 +451,55 @@
 |   <NULLS: "nulls">
 
 }
+/*
+name=all in group identifier
+*/
+TOKEN : { < ALL_IN_GROUP: <ID> <PERIOD> <STAR> > }
+/*
+name=identifier
+*/
+TOKEN : { < ID: <QUOTED_ID> (<PERIOD> <QUOTED_ID>)* > }
+TOKEN : { < #QUOTED_ID: <ID_PART> | ("\"" (("\"\"") | ~["\""] )+ "\"") >  }     
+TOKEN : { < #ID_PART: (("@" | "#" | <LETTER>) (<LETTER> | "_" | <DIGIT>)*) > }
+/*
+name=escaped function
+*/
+TOKEN : { < ESCAPEDFUNCTION: "{" "fn" > }
+/*
+name=escaped join
+*/
+TOKEN : { < ESCAPEDJOIN: "{" "oj" > }
+/*
+name=escaped type
+*/
+TOKEN : { < ESCAPEDTYPE: "{" ("d" | "t" | "ts" | "b") > }
+/*
+name=decimal numeric literal
+*/
+TOKEN : { < DECIMALVAL: (<DIGIT>)* <PERIOD> <UNSIGNEDINTEGER> > }
+/*
+name=approximate numeric literal
+*/
+TOKEN : { < FLOATVAL: <DIGIT> <PERIOD> <UNSIGNEDINTEGER> 
+				["e", "E"] (<PLUS>|<MINUS>)? <UNSIGNEDINTEGER> > }
+/*
+name=string literal
+*/				
+TOKEN : { < STRINGVAL: (("N"|"E")? "'" ( ("''") | ~["'"] )* "'") > }
+TOKEN : { < #LETTER: (["a"-"z","A"-"Z"] | ["\u0153"-"\ufffd"]) > }
+TOKEN : { < #DIGIT: ["0"-"9"] > }
+/*
+name=unsigned integer literal
+*/
+TOKEN : { < UNSIGNEDINTEGER: (<DIGIT>)+ > }
+/*
+name=binary string literal
+*/
+TOKEN : { < BINARYSTRINGVAL: ("X"|"x" "'" ( <HEXIT><HEXIT> )+ "'") > }
+TOKEN : { < #HEXIT: (["a"-"f","A"-"F"] | <DIGIT> ) > }
 
-TOKEN : /* User variables and literals */
+TOKEN :
 {
-    < ALL_IN_GROUP: <ID> <PERIOD> <STAR> >
-
-|   < ID: <QUOTED_ID> (<PERIOD> <QUOTED_ID>)* >
-|	< #QUOTED_ID: <ID_PART> | ("\"" (("\"\"") | ~["\""] )+ "\"") >           
-|   < #ID_PART: (("@" | "#" | <LETTER>) (<LETTER> | "_" | <DIGIT>)*) >               
-
-| 	< DATETYPE: "{" "d" >
-| 	< TIMETYPE: "{" "t" >
-| 	< TIMESTAMPTYPE: "{" "ts" >
-| 	< BOOLEANTYPE: "{" "b" >
-|   < POS_REF: ["$"] (<DIGIT>)+ >
-|	< INTEGERVAL: (<MINUS>)?(<DIGIT>)+ >
-|   < DECIMALVAL: (<MINUS>)? (<DIGIT>)* <PERIOD> (<DIGIT>)+ >
-|   < FLOATVAL: (<MINUS>)? <DIGIT> <PERIOD> (<DIGIT>)+ 
-				["e", "E"] (["+","-"])? (<DIGIT>)+  >
-|   < STRINGVAL: (("N"|"E")? "'" ( ("''") | ~["'"] )* "'") >
-|	< #LETTER: (["a"-"z","A"-"Z"] | ["\u0153"-"\ufffd"]) >
-|	< #DIGIT: ["0"-"9"] >
-|   < BINARYSTRINGVAL: ("X"|"x" "'" ( <HEXIT><HEXIT> )+ "'") >
-|	< #HEXIT: (["a"-"f","A"-"F"] | <DIGIT> ) >
-}
-
-TOKEN : /* Punctuation */
-{
 	<COMMA: ",">
 |	<PERIOD: ".">
 |	<LPAREN: "(">
@@ -505,30 +526,42 @@
 |	<CONCAT_OP: "||">
 }
 
-//----------------------------------------------------
-//----------------------------------------------------
-
+/*
+name=string
+description=A string literal value.  Use '' to escape ' in the string.  
+example={code:sql}'a string'{code}\n{code:sql}'it''s a string'{code}
+*/
 String stringVal() :
 {
 	Token t = null;	
 }
 {
-  	(t = <STRINGVAL>)
+  	t = <STRINGVAL>
   	{
   		return normalizeStringLiteral(t.image);
   	}
 }
 
+/*
+name=non-reserved identifier
+description=Allows non-reserved keywords to be parsed as identifiers  
+example=SELECT *COUNT* FROM ...
+*/
 Token nonReserved() :
 {
 }
 {
-    (<INSTEAD>|<VIEW>|<ENABLED>|<DISABLED>|<KEY>|<SERIAL>|<TEXTAGG>|<COUNT>|<ROW_NUMBER>|<RANK>|<DENSE_RANK>|<SUM>|<AVG>|<MIN>|<MAX>|<EVERY>|<STDDEV_POP>|<STDDEV_SAMP>|<VAR_SAMP>|<VAR_POP>|<DOCUMENT>|<CONTENT>|<TRIM>|<EMPTY>|<ORDINALITY>|<PATH>|<FIRST>|<LAST>|<NEXT>|<FN>|<SUBSTRING>|<EXTRACT>|<TO_CHARS>|<TO_BYTES>|<TIMESTAMPADD>|<TIMESTAMPDIFF>|<QUERYSTRING>|<NAMESPACE>|<RESULT>|<INDEX>|<ACCESSPATTERN>|<AUTO_INCREMENT>|<WELLFORMED>|<SQL_TSI_FRAC_SECOND>|<SQL_TSI_SECOND>|<SQL_TSI_MINUTE>|<SQL_TSI_HOUR>|<SQL_TSI_DAY>|<SQL_TSI_WEEK>|<SQL_TSI_MONTH>|<SQL_TSI_QUARTER>|<SQL_TSI_YEAR>|<TEXTTABLE>|<ARRAYTABLE>|<SELECTOR>|<SKIP_KEYWORD>|<WIDTH>|<PASSING>|<NAME>|<ENCODING>|<OJ>|<COLUMNS>|<DELIMITER>|<QUOTE>|<HEADER>|<NULLS>)
+    (<INSTEAD>|<VIEW>|<ENABLED>|<DISABLED>|<KEY>|<SERIAL>|<TEXTAGG>|<COUNT>|<ROW_NUMBER>|<RANK>|<DENSE_RANK>|<SUM>|<AVG>|<MIN>|<MAX>|<EVERY>|<STDDEV_POP>|<STDDEV_SAMP>|<VAR_SAMP>|<VAR_POP>|<DOCUMENT>|<CONTENT>|<TRIM>|<EMPTY>|<ORDINALITY>|<PATH>|<FIRST>|<LAST>|<NEXT>|<SUBSTRING>|<EXTRACT>|<TO_CHARS>|<TO_BYTES>|<TIMESTAMPADD>|<TIMESTAMPDIFF>|<QUERYSTRING>|<NAMESPACE>|<RESULT>|<INDEX>|<ACCESSPATTERN>|<AUTO_INCREMENT>|<WELLFORMED>|<SQL_TSI_FRAC_SECOND>|<SQL_TSI_SECOND>|<SQL_TSI_MINUTE>|<SQL_TSI_HOUR>|<SQL_TSI_DAY>|<SQL_TSI_WEEK>|<SQL_TSI_MONTH>|<SQL_TSI_QUARTER>|<SQL_TSI_YEAR>|<TEXTTABLE>|<ARRAYTABLE>|<SELECTOR>|<SKIP_KEYWORD>|<WIDTH>|<PASSING>|<NAME>|<ENCODING>|<COLUMNS>|<DELIMITER>|<QUOTE>|<HEADER>|<NULLS>)
     {
     	return getToken(0);
     }	
 }
 
+/*
+name=identifier
+description=Partial or full name of a single entity.
+example={code:sql}tbl.col{code}\n{code:sql}"tbl"."col"{code}
+*/
 String id() :
 {
 }
@@ -539,12 +572,9 @@
   	}
 }
 
-/** 
- * Parse any of several command types - this is the main parser entry point. 
- * @param info instructions to parse the command
- * @return Parsed command
- * @throws ParseException if parsing failed
- */
+/* TODO: createProcedure should not be here, but is due to all of the legacy tests
+unused=true
+*/
 Command command(ParseInfo info) :
 {
 	Command command = null;
@@ -561,6 +591,9 @@
 	}
 }
 
+/*
+unused=true
+*/
 Command designerCommand(ParseInfo info) :
 {
 	Command command = null;
@@ -577,6 +610,11 @@
 	}
 }
 
+/*
+name=create trigger
+description=Creates a trigger action on the given target.
+example={code:sql}CREATE TRIGGER ON vw INSTEAD OF INSERT AS FOR EACH ROW BEGIN ATOMIC ... END{code}
+*/
 Command createTrigger(ParseInfo info) :
 {
   	String target = null;
@@ -598,6 +636,11 @@
 	}
 }
 
+/*
+name=alter
+description=Alter the given target.
+example={code:sql}ALTER VIEW vw AS SELECT col FROM tbl{code}
+*/
 Command alter(ParseInfo info) :
 {
   	String target = null;
@@ -649,6 +692,11 @@
 	)
 }
 
+/*
+name=for each row trigger action
+description=Defines an action to perform on each row.
+example={code:sql}FOR EACH ROW BEGIN ATOMIC ... END{code}
+*/
 TriggerAction forEachRowTriggerAction(ParseInfo info) :
 {
 	Block b = new Block();
@@ -679,6 +727,12 @@
 	}
 }
 
+/*
+name=directly executable statement
+description=A statement that can be executed at runtime.
+example={code:sql}SELECT * FROM tbl{code}
+index=true
+*/
 Command userCommand(ParseInfo info) :
 {
 	Command command = null;
@@ -716,12 +770,11 @@
 	}
 }
 
-/** 
- * Parse drop table command. 
- * @param info instructions to parse the command
- * @return Parsed command
- * @throws ParseException if parsing failed
- */
+/*
+name=drop table
+description=Creates a trigger action on the given target.
+example={code:sql}CREATE TRIGGER ON vw INSTEAD OF INSERT AS FOR EACH ROW BEGIN ATOMIC ... END{code}
+*/
 Command dropTable(ParseInfo info) :
 {
 	Drop drop = new Drop();
@@ -736,12 +789,11 @@
 	}
 }
 	
-/** 
- * Parse create temp table command. 
- * @param info instructions to parse the command
- * @return Parsed command
- * @throws ParseException if parsing failed
- */
+/*
+name=create temporary table
+description=Creates a temporary table.
+example={code:sql}CREATE LOCAL TEMPORARY TABLE tmp (col integer){code}
+*/
 Command createTempTable(ParseInfo info) :
 {
 	Create create = new Create();
@@ -784,6 +836,11 @@
 	}
 }
 
+/*
+name=temporary table element
+description=Defines a temporary table column.
+example={code:sql}col string NOT NULL{code}
+*/
 Column tableElement(ParseInfo info) :
 {
 	String element = null;
@@ -814,10 +871,11 @@
 	 }
 }
 
-/**
- * Parse error statement
- * @throws ParseException if parsing failed
- */
+/*
+name=raise error statement
+description=Raises an error with the given message.
+example={code:sql}ERROR 'something went wrong'{code}
+*/
 RaiseErrorStatement errorStatement(ParseInfo info) :
 {
     Expression errMsg = null;           
@@ -832,10 +890,11 @@
     }
 }
 
-/**
- * Parse statement
- * @throws ParseException if parsing failed
- */
+/*
+name=statement
+description=A procedure statement.
+example={code:sql}IF (x = 5) BEGIN ... END{code}
+*/
 Statement statement(ParseInfo info) :
 {
     Statement stmt = null;
@@ -865,6 +924,11 @@
     }
 }
 
+/*
+name=delimited statement
+description=A procedure statement terminated by ;.
+example={code:sql}SELECT * FROM tbl;{code}
+*/
 Statement delimitedStatement(ParseInfo info) :
 {
     Statement stmt = null;
@@ -882,6 +946,11 @@
 	 }
 }
 
+/*
+name=compound statement
+description=A procedure statement block contained in BEGIN END.
+example={code:sql}BEGIN NOT ATOMIC ... END{code}
+*/
 Block compoundStatement(ParseInfo info) :
 {
     Statement stmt = null;  
@@ -905,10 +974,11 @@
     }
 }        
 
-/**
- * Parse break statement 
- * @throws ParseException if parsing failed
- */
+/*
+name=branching statement
+description=A procedure branching control statement, which typically specifies a label to return control to.
+example={code:sql}BREAK x{code}
+*/
 BranchingStatement branchingStatement(ParseInfo info) :
 {
     BranchingStatement breakStmt = new BranchingStatement();
@@ -930,10 +1000,11 @@
  	}
 } 	
 
-/**
- * Parse while statement 
- * @throws ParseException if parsing failed
- */
+/*
+name=while statement
+description=A procedure while statement that executes until its condition is false.
+example={code:sql}WHILE (var) BEGIN ... END{code}
+*/
 WhileStatement whileStatement(ParseInfo info) :
 {
     WhileStatement whileStmt = null;    
@@ -952,10 +1023,11 @@
     }    
 }    
 
-/**
- * Parse loop statement 
- * @throws ParseException if parsing failed
- */
+/*
+name=loop statement
+description=A procedure loop statement that executes over the given cursor.
+example={code:sql}LOOP ON (SELECT * FROM tbl) AS x BEGIN ... END{code}
+*/
 LoopStatement loopStatement(ParseInfo info) :
 {
     LoopStatement loopStmt = null;    
@@ -978,10 +1050,11 @@
     }    
 }   
 
-/**
- * Parse if statement 
- * @throws ParseException if parsing failed
- */
+/*
+name=if statement
+description=A procedure loop statement that executes over the given cursor.
+example={code:sql}LOOP ON (SELECT * FROM tbl) AS x BEGIN ... END{code}
+*/
 IfStatement ifStatement(ParseInfo info) :
 {
     IfStatement ifStmt = null;    
@@ -1004,21 +1077,22 @@
     }    
 }    
             
-/**
- * Parse declare statement
- * @throws ParseException if parsing failed
- */
+/*
+name=declare statement
+description=A procedure declaration statement that creates a variable and optionally assigns a value.
+example={code:sql}DECLARE STRING x := 'a'{code}
+*/
 DeclareStatement declareStatement(ParseInfo info) :
 {
     DeclareStatement declStmt = null;
     String var = null;    
-    Constant type = null;  
+    ParsedDataType type = null;  
     ElementSymbol variableID = null;
     LanguageObject value = null;
 }
 {
     <DECLARE>
-    type = dataType()
+    type = parseDataType()
     var = id()
     {
         variableID = new ElementSymbol(var);
@@ -1029,19 +1103,20 @@
     
     {
         if (value instanceof Expression) {
-    		return new DeclareStatement(variableID, (String)type.getValue(), (Expression)value);
+    		return new DeclareStatement(variableID, type.type, (Expression)value);
     	}
     	if (value instanceof QueryCommand) {
-    		return new DeclareStatement(variableID, (String)type.getValue(), new ScalarSubquery((QueryCommand)value));
+    		return new DeclareStatement(variableID, type.type, new ScalarSubquery((QueryCommand)value));
     	}
-    	return new DeclareStatement(variableID, (String)type.getValue(), (Command)value);
+    	return new DeclareStatement(variableID, type.type, (Command)value);
     }           
 }
 
-/**
- * Parse assignment statement
- * @throws ParseException if parsing failed
- */
+/*
+name=assignment statement
+description=Assigns a variable a value in a procedure.
+example={code:sql}x := 'b'{code}
+*/
 AssignmentStatement assignStatement(ParseInfo info) :
 {
     LanguageObject value = null;
@@ -1067,11 +1142,10 @@
     }    
 }
 
-/**
- * Parse operand of assignment statement, which can be nested
- * arbitrarily deeply in parentheses.
- * @throws ParseException if parsing failed
- */
+/*
+name=assignment statement operand
+description=A value or command that can be used in an assignment.  {note}All assigments except for expression are deprecated.{note}
+*/
 LanguageObject assignStatementOperand(ParseInfo info) :
 {
     LanguageObject value = null;
@@ -1091,10 +1165,10 @@
     }    
 }
 
-/**
- * Parse sql statement 
- * @throws ParseException if parsing failed
- */
+/*
+name=data statement
+description=A procedure statement that executes a SQL statement.  An update statement can have its update count accessed via the ROWS_UPDATED variable. 
+*/
 CommandStatement sqlStatement(ParseInfo info) :
 {
     CommandStatement cmdStmt = null;
@@ -1127,10 +1201,9 @@
     }   
 }
  
-/**
- * Parse create update procedure command
- * @throws ParseException if parsing failed
- */
+/*
+unused=true
+*/
 CreateProcedureCommand  createProcedure(ParseInfo info) :
 {
     CreateProcedureCommand procCmd = 
@@ -1146,6 +1219,12 @@
     }    
 }   
 
+/*
+name=procedure body definition
+description=Defines a procedure body on a Procedure metadata object.
+example={code:sql}CREATE VIRTUAL PROCEDURE BEGIN ... END{code}
+index=true
+*/
 CreateProcedureCommand  procedureBodyCommand(ParseInfo info) :
 {
     CreateProcedureCommand procCmd = 
@@ -1161,17 +1240,17 @@
     }    
 } 
 
-/**
- * Parse error statement
- * @throws ParseException if parsing failed
- */
+/*
+name=dynamic data statement
+description=A procedure statement that can execute arbitrary sql.
+example={code:sql}EXECUTE IMMEDIATE 'SELECT * FROM tbl' AS x STRING INTO #temp{code}
+*/
 DynamicCommand dynamicCommand(ParseInfo info) :
 {
     Expression sql = null;           
     String groupID = null;
 	GroupSymbol group = null;
 	int updateCount = 0;
-	Token updateToken = null;
 	List<TableFunctionReference.ProjectedColumn> elements = null;
 	SetClauseList using = null;
 	DynamicCommand dcStmt = new DynamicCommand();
@@ -1209,12 +1288,9 @@
 	 }
     ]
     [<UPDATE>
-     ((updateToken = <INTEGERVAL>) 
-     {
-        updateCount = Integer.parseInt(updateToken.image);
-     }
+     (updateCount = intVal()
      |
-     (<STAR>) 
+     <STAR> 
      {	
         updateCount = 2;
      })
@@ -1225,6 +1301,11 @@
     }
 }
 
+/*
+name=set clause list
+description=A list of value assignments.
+example={code:sql}col1 = 'x', col2 = 'y' ...{code}
+*/
 SetClauseList setClauseList(boolean shortName, ParseInfo info) :
 {
 	SetClauseList using = new SetClauseList();
@@ -1254,10 +1335,11 @@
 	}
 }
 
-/**
- * Create elements with datatypes
- * @throws ParseException if parsing failed
- */
+/*
+name=typed element list
+description=A list of typed elements.
+example={code:sql}col1 string, col2 integer ...{code}
+*/
 List<TableFunctionReference.ProjectedColumn> createElementsWithTypes(ParseInfo info) :
 {
 	String element = null;
@@ -1284,15 +1366,21 @@
 	 }
 }
 
+/*
+name=callable statement
+description=A callable statement defined using JDBC escape syntax.
+example={code:sql}{? = CALL proc}{code}
+index=true
+*/
 StoredProcedure callableStatement(ParseInfo info) :
 {
 	StoredProcedure storedProcedure = new StoredProcedure();
 	storedProcedure.setCallableStatement(true);
-	Token call = null;
 	String procName = null;
 	Option option = null;
 	SPParameter parameter = null;
 	int parameterIndex = 1;
+	List<Expression> values = null;
 }
 {
 	<LBRACE>
@@ -1311,10 +1399,7 @@
 	//parameters
 		
 	[<LPAREN>
-		
-	 (
-		  storedProcedure = executeUnnamedParams(info, storedProcedure, parameterIndex)
-	 ) 
+	 [values = expressionList(info) { convertToParameters(values, storedProcedure); }]
 	 <RPAREN>
 	]
 	<RBRACE>			
@@ -1329,15 +1414,16 @@
 	}
 }
 
-
-/**
- * * Parse stored query command
- * @throws ParseException if parsing failed
- */
+/*
+name=call statement
+description=Executes the procedure with the given parameters.
+example={code:sql}CALL proc('a', 1){code}
+*/
 StoredProcedure storedProcedure(ParseInfo info, StoredProcedure storedProcedure) :
 {
 	String procName = null;
 	Option option = null;
+	List<Expression> values = null;
 }
 {
 	(
@@ -1352,9 +1438,9 @@
 		
 		(
 		 LOOKAHEAD(2)
-		 storedProcedure = executeNamedParams(info, storedProcedure)
+		 executeNamedParams(info, storedProcedure)
 		 | 		
-		 storedProcedure = executeUnnamedParams(info, storedProcedure, storedProcedure.getParameters().size() + 1)
+		 [values = expressionList(info) { convertToParameters(values, storedProcedure); }]
 		)
 		
 		<RPAREN>
@@ -1369,43 +1455,13 @@
 	}
 }
 
-/**
- * <p>Parse an exec statement with unnamed parameters</p>
- * @throws ParseException if parsing failed
- */
-StoredProcedure executeUnnamedParams(ParseInfo info, StoredProcedure storedProcedure, int parameterIndex) :
+/*
+name=named parameter list
+description=A list of named parameters.
+example={code:sql}param1 := 'x', param2 := 1{code}
+*/
+void executeNamedParams(ParseInfo info, StoredProcedure storedProcedure) :
 {
-	SPParameter parameter = null;
-    Expression value = null;	
-}
-{
-
-	(value = expression(info)
-		{
-				parameter = new SPParameter(parameterIndex++, value);
-				parameter.setParameterType(SPParameter.IN);
-				storedProcedure.setParameter(parameter);
-		}
-		(	<COMMA>
-			value = expression(info)
-			{
-					parameter = new SPParameter(parameterIndex++, value);
-					parameter.setParameterType(SPParameter.IN);
-					storedProcedure.setParameter(parameter);
-			}
-		)*
-	)?
-	{
-		return storedProcedure;
-	}
-}
-
-/**
- * <p>Parse an exec statement with named parameters</p>
- * @throws ParseException if parsing failed
- */
-StoredProcedure executeNamedParams(ParseInfo info, StoredProcedure storedProcedure) :
-{
 	String name = null;
     Expression value = null;
 	SPParameter parameter = null;
@@ -1438,17 +1494,13 @@
 			}
 		)*
 	)
-	{
-		
-		return storedProcedure;
-	}
 }
 
-/**
- * Parse an INSERT command
- * @return Parsed insert statement
- * @throws ParseException if parsing failed
- */
+/*
+name=insert statement
+description=Inserts values into the given target.
+example={code:sql}INSERT INTO tbl (col1, col2) VALUES ('a', 1){code}
+*/
 Insert insert(ParseInfo info) :
 {
 	Insert insert = new Insert();
@@ -1497,6 +1549,11 @@
 	}
 }
 
+/*
+name=column list
+description=A list of column references.
+example={code:sql}(col1, col2, ...){code}
+*/
 List<ElementSymbol> columnList(boolean validate) :
 {
 	String element = null;
@@ -1526,11 +1583,11 @@
 	}
 }
 
-/**
- * Parse row values - this is a comma separated list of values.
- * @return List of values, never null
- * @throws ParseException if parsing failed
- */
+/*
+name=expression list
+description=A list of expressions.
+example={code:sql}col1, 'a', ...{code}
+*/
 ArrayList<Expression> expressionList(ParseInfo info) :
 {
 	ArrayList<Expression> rowVals = new ArrayList<Expression>(4);
@@ -1552,11 +1609,11 @@
 	}
 }
 
-/**
- * Parse an UPDATE command
- * @return Parsed update statement
- * @throws ParseException if parsing failed
- */
+/*
+name=update statement
+description=Update values in the given target.
+example={code:sql}UPDATE tbl SET (col1 = 'a') WHERE col2 = 1{code}
+*/
 Update update(ParseInfo info) :
 {
 	Update update = new Update();
@@ -1592,12 +1649,11 @@
 	}
 }
 
-
-/**
- * Parse a DELETE command
- * @return Parsed delete statement
- * @throws ParseException if parsing failed
- */
+/*
+name=delete statement
+description=Delete rows from the given target.
+example={code:sql}DELETE FROM tbl WHERE col2 = 1{code}
+*/
 Delete delete(ParseInfo info) :
 {
 	String group = null;
@@ -1622,6 +1678,11 @@
 	}
 }
 
+/*
+name=query expression
+description=A declarative query for data.
+example={code:sql}SELECT * FROM tbl WHERE col2 = 1{code}
+*/
 QueryCommand queryExpression(ParseInfo info) :
 {
 	QueryCommand query = null;
@@ -1648,6 +1709,11 @@
 	}
 }
 
+/*
+name=with list element
+description=A query expression for use in the enclosing query. 
+example={code:sql}X (Y, Z) AS (SELECT 1, 2){code}
+*/
 WithQueryCommand withListElement(ParseInfo info) :
 {
    String name = null;
@@ -1663,6 +1729,11 @@
 	}
 }
 
+/*
+name=query expression body
+description=The body of a query expression, which can optionally be ordered and limited.
+example={code:sql}SELECT * FROM tbl ORDER BY col1 LIMIT 1{code}
+*/
 QueryCommand queryExpressionBody(ParseInfo info) :
 {
     QueryCommand query = null;
@@ -1691,6 +1762,11 @@
     }    
 }
 
+/*
+name=query term
+description=Used to establish INTERSECT precedence.
+example={code:sql}SELECT * FROM tbl{code}\n{code:sql}SELECT * FROM tbl1 INTERSECT SELECT * FROM tbl2{code}
+*/
 QueryCommand queryTerm(ParseInfo info) : 
 {
     QueryCommand query = null;
@@ -1712,6 +1788,11 @@
     }
 }    
 
+/*
+name=query primary
+description=A declarative source of rows.
+example={code:sql}TABLE tbl{code}\n{code:sql}SELECT * FROM tbl1{code}
+*/
 QueryCommand queryPrimary(ParseInfo info) : 
 {
     QueryCommand query = null;
@@ -1733,11 +1814,11 @@
     }
 }    
 
-/**
- * Parse a SELECT query
- * @return Parsed query
- * @throws ParseException if parsing failed
- */
+/*
+name=query
+description=A SELECT query.
+example={code:sql}SELECT col1, max(col2) FROM tbl GROUP BY col1{code}
+*/
 Query query(ParseInfo info) :
 {
 	Select   select         = null;
@@ -1770,6 +1851,11 @@
   	}
 }
 
+/*
+name=into clause
+description=Used to direct the query into a table.  {note}This is deprecated.  Use INSERT INTO with a query expression instead.{note}
+example={code:sql}INTO tbl{code}
+*/
 Into into(ParseInfo info) :
 {
 	String groupID = null;
@@ -1784,18 +1870,10 @@
     }	
 }
 
-/**
- * <p>Parse a SELECT clause.  The select must handle elements, aliased elements
- * (x AS y), group.*, and *.  It also must handle an optional DISTINCT at the
- * beginning of the select list.  It also must handle a scalar subquery expression
- * in parentheses.</p>
- * <p>Example:  "SELECT group.element, group2.element2 AS x, group3.*". </p>
- * <p>Example:  "SELECT *". </p>
- * <p>Example:  "SELECT DISTINCT a, b, c".</p>
- * <p>Example:  "SELECT a, (SELECT b FROM groupC)".</p>
- * <p>Example:  "SELECT a, (SELECT b FROM groupC) as d".</p>
- * @return Parsed select
- * @throws ParseException if parsing failed
+/*
+name=select clause
+description=The columns returned by a query.  Can optionally be distinct.
+example={code:sql}SELECT *{code}\n{code:sql}"SELECT DISTINCT a, b, c{code}
  */
 Select select(ParseInfo info) :
 {
@@ -1823,6 +1901,11 @@
 	}
 }
 
+/*
+name=select sublist
+description=An element in the select clause
+example={code:sql}tbl.*{code}\n{code:sql}tbl.col AS x{code}
+*/
 Expression selectSymbol(ParseInfo info) :
 {
 	Expression symbol = null;	
@@ -1838,6 +1921,11 @@
 	}
 }
 
+/*
+name=select derived column
+description=A select clause item that selects a single column. {note}This is slightly different than a derived column in that the AS keyword is optional.{note}
+example={code:sql}tbl.col AS x{code}
+*/
 Expression selectExpression(ParseInfo info) :
 {
 	Expression expression = null;
@@ -1858,6 +1946,11 @@
 	}
 }
 
+/*
+name=derived column
+description=An optionally named expression.
+example={code:sql}tbl.col AS x{code}
+*/
 DerivedColumn derivedColumn(ParseInfo info) :
 {
 	Expression expression = null;
@@ -1877,6 +1970,11 @@
 	}
 }
 
+/*
+name=all in group 
+description=A select sublist that can select all columns from the given group.
+example={code:sql}tbl.*{code}
+*/
 MultipleElementSymbol allInGroupSymbol() :
 {
 	Token allInGroupToken = null;
@@ -1889,6 +1987,11 @@
 	}
 }
 
+/*
+name=ordered aggreate function
+description=An aggregate function that can optionally be ordered.
+example={code:sql}XMLAGG(col1) ORDER BY col2{code}\n{code:sql}ARRAY_AGG(col1){code}
+*/
 AggregateSymbol orderedAgg(ParseInfo info) :
 {
     Token t = null;
@@ -1909,6 +2012,11 @@
 	}
 }
 
+/*
+name=text aggreate function
+description=An aggregate function for creating separated value clobs.
+example={code:sql}TEXTAGG (col1 as t1, col2 as t2 DELIMITER ',' HEADER){code}
+*/
 AggregateSymbol textAgg(ParseInfo info) :
 {
 	DerivedColumn expression = null;
@@ -1964,6 +2072,11 @@
 	}
 }
 
+/*
+name=standard aggregate function
+description=A standard aggregate function.
+example={code:sql}COUNT(*){code}
+*/
 AggregateSymbol aggregateSymbol(ParseInfo info) :
 {
 	Token func = null;
@@ -2001,6 +2114,11 @@
 	}
 }
 
+/*
+name=analytic aggregate function
+description=An analytic aggregate function.
+example={code:sql}ROW_NUMBER(){code}
+*/
 AggregateSymbol analyticAggregateSymbol(ParseInfo info) :
 {
 	Token func = null;
@@ -2013,7 +2131,11 @@
 	}
 }
 
-
+/*
+name=filter clause
+description=An aggregate filter clause applied prior to accumulating the value.
+example={code:sql}FILTER (WHERE col1='a'){code}
+*/
 Expression filterClause(ParseInfo info) :
 {
 	Expression condition = null;
@@ -2025,16 +2147,11 @@
 	}
 }
 
-/**
- * <p>Parse a FROM.  The from must handle groups, aliased groups or
- * joined groups. This also handles JDBC escape processinf syntax for outer joins.</p>
- * <p>Example:  "FROM a, b". </p>
- * <p>Example:  "FROM a AS x, b as Y". </p>
- * <p>Example:  "FROM a right outer join b, c, d join e".</p>
- * @param from object which is to be updated with the details in the from clause.
- * @return list containing criteria objects.
- * @throws ParseException if parsing failed
- */
+/*
+name=from clause
+description=A query from clause containing a list of table references.
+example={code:sql}FROM a, b{code}\n{code:sql}FROM a right outer join b, c, d join e".</p>{code}
+*/
 From from(ParseInfo info) :
 {
 	FromClause clause = null;
@@ -2061,12 +2178,11 @@
 	}
 }					
 
-/**
- * <p>Parse a join predicate clause, which occurs as an element in the FROM clause.  
- * The join predicate combines two from clauses with a join.</p>
- * @return Join predicate
- * @throws ParseException if parsing failed
- */
+/*
+name=table reference
+description=An optionally escaped joined table.
+example={code:sql}a{code}\n{code:sql}a inner join b{code}
+*/
 FromClause tableReference(ParseInfo info) :
 {
 	FromClause result = null;
@@ -2074,7 +2190,7 @@
 {	
 	(
 		(	
-			<LBRACE> <OJ>
+			<ESCAPEDJOIN>
 			result=joinedTable(info)
 			<RBRACE>
 		) 
@@ -2086,6 +2202,11 @@
 	}
 }	
 
+/*
+name=joined table
+description=A table or join.
+example={code:sql}a{code}\n{code:sql}a inner join b{code}
+*/
 FromClause joinedTable(ParseInfo info) :
 {
 	FromClause result = null;
@@ -2107,6 +2228,11 @@
 	}
 }
 
+/*
+name=cross join
+description=A cross join.
+example={code:sql}a CROSS JOIN b{code}
+*/
 JoinPredicate crossJoin(ParseInfo info) :
 {
 	JoinPredicate result = new JoinPredicate();
@@ -2122,6 +2248,11 @@
 	}
 }
 
+/*
+name=qualified table
+description=An INNER or OUTER join.
+example={code:sql}a inner join b{code}
+*/
 JoinPredicate qualifiedJoin(ParseInfo info) :
 {
 	JoinPredicate result = new JoinPredicate();
@@ -2144,6 +2275,11 @@
 	}
 }
 
+/*
+name=table primary
+description=A single source of rows.
+example={code:sql}a{code}
+*/
 FromClause tablePrimary(ParseInfo info) :
 {
 	FromClause clause = null;
@@ -2175,6 +2311,11 @@
 	}
 }
 
+/*
+name=xml serialize
+description=Serializes an XML value.
+example={code:sql}XMLSERIALIZE(col1 AS CLOB){code}
+*/
 XMLSerialize xmlSerialize(ParseInfo info) :
 {
 	Expression expr = null;
@@ -2202,6 +2343,11 @@
 	}
 }
 
+/*
+name=array table
+description=The ARRAYTABLE table function creates tabular results from arrays.  It can be used as a nested table reference.
+example={code:sql}ARRAYTABLE (col1 COLUMNS x STRING) AS y{code}
+*/
 ArrayTable arrayTable(ParseInfo info) :
 {
 	Expression array = null;
@@ -2223,6 +2369,11 @@
  	}
 }
 
+/*
+name=text table
+description=The TEXTTABLE table function creates tabular results from text.  It can be used as a nested table reference.
+example={code:sql}TEXTTABLE (file COLUMNS x STRING) AS y{code}
+*/
 TextTable textTable(ParseInfo info) :
 {
 	Expression file = null;
@@ -2302,10 +2453,15 @@
  	}
 }
 
+/*
+name=text table column
+description=A text table column.
+example={code:sql}x INTEGER WIDTH 6{code}
+*/
 TextTable.TextColumn textColumn(ParseInfo info):
 {
 	String name = null;
-	Constant datatype = null;
+	ParsedDataType datatype = null;
 	Integer width = null;
 	boolean noTrim = false;
 	String selector = null;
@@ -2313,7 +2469,7 @@
 }
 {
 	name = id()
-	datatype = dataType()
+	datatype = parseDataType()
 	[ 
 	  	<WIDTH>
 	  	width = intVal() 
@@ -2330,13 +2486,18 @@
 	  	position = intVal() 
 	]
 	{
-		TextTable.TextColumn result = new TextTable.TextColumn(validateElementName(name), (String)datatype.getValue(), width, noTrim);
+		TextTable.TextColumn result = new TextTable.TextColumn(validateElementName(name), datatype.type, width, noTrim);
 		result.setSelector(selector);
 		result.setPosition(position);
 		return result;
 	}
 }
 
+/*
+name=xml query
+description=Executes an XQuery to return an XML result.
+example={code:sql}XMLQUERY('<a>...</a>' PASSING doc){code}
+*/
 XMLQuery xmlQuery(ParseInfo info) :
 {
 	String xquery = null;
@@ -2391,6 +2552,11 @@
  	}
 }
 
+/*
+name=xml table
+description=Returns table results by processing an XQuery.
+example={code:sql}XMLTABLE('/a/b' PASSING doc COLUMNS col XML PATH '.') AS X{code}
+*/
 XMLTable xmlTable(ParseInfo info) :
 {
 	String xquery = null;
@@ -2420,7 +2586,6 @@
  	    }
  	  )*
  	]
- 	
  	[
  	  <COLUMNS>
  	  column = xmlColumn(info)
@@ -2447,10 +2612,15 @@
  	}
 }
 
+/*
+name=xml table column
+description=XML table column.
+example={code:sql}y FOR ORDINALITY{code}
+*/
 XMLTable.XMLColumn xmlColumn(ParseInfo info):
 {
 	String name = null;
-	Constant datatype = null;
+	ParsedDataType datatype = null;
 	String path = null;
 	Expression defaultExpr = null;
 }
@@ -2463,7 +2633,7 @@
 	    return new XMLTable.XMLColumn(name); 
 	  }	
 	) | (
-      datatype = dataType()
+      datatype = parseDataType()
       [
 	    <DEFAULT_KEYWORD> defaultExpr = expression(info)
 	  ]
@@ -2471,17 +2641,22 @@
 	    <PATH> path = stringVal()
 	  ]
 	  {
-		return new XMLTable.XMLColumn(name, (String)datatype.getValue(), path, defaultExpr);
+		return new XMLTable.XMLColumn(name, datatype.type, path, defaultExpr);
 	  }
 	))
 }
 
+/*
+name=unsigned integer
+description=An unsigned interger value.
+example={code:sql}12345{code}
+*/
 int intVal() :
 {
 	Token t;
 }
 {
-	t = <INTEGERVAL>
+	t = <UNSIGNEDINTEGER>
 	{
 		try { 
 			return Integer.valueOf(t.image); 				
@@ -2491,12 +2666,11 @@
 	}
 }
 
-
-/**
- * Parse a unary from clause, which is just a single group name and an optional alias.
- * @return Unary from clause containing the group
- * @throws ParseException if parsing failed
- */
+/*
+name=table subquery
+description=A table defined by a subquery.
+example={code:sql}(SELECT * FROM tbl) AS x{code}
+*/
 SubqueryFromClause subqueryFromClause(ParseInfo info) :
 {
     String aliasID = null;
@@ -2506,7 +2680,7 @@
 }
 {	
 	[
-		<TABLE> { table = true; }
+		(<TABLE>|<LATERAL>) { table = true; }
 	]
 	lparen = <LPAREN> 
 	( command = queryExpression(info) |
@@ -2523,11 +2697,11 @@
     }	
 }	
 		
-/**
- * Parse a unary from clause, which is just a single group name and an optional alias.
- * @return Unary from clause containing the group
- * @throws ParseException if parsing failed
- */
+/*
+name=table name
+description=A table named in the FROM clause.
+example={code:sql}tbl AS x{code}
+*/
 UnaryFromClause unaryFromClause(ParseInfo info) :
 {
 	GroupSymbol group = null;
@@ -2550,11 +2724,11 @@
     }	
 }		
 
-/**
- * <p>Parse a WHERE clause.  The where clause holds a criteria.
- * @return Parsed where
- * @throws ParseException if parsing failed
- */
+/*
+name=where clause
+description=Specifies a search condition
+example={code:sql}WHERE x = 'a'{code}
+*/
 Criteria where(ParseInfo info) :
 {
     Criteria criteria = null;
@@ -2568,11 +2742,10 @@
 	}
 }
 
-/**
- * <p>Parse a criteria.  This will parse any criteria expression.</p>
- * @return Parsed criteria
- * @throws ParseException if parsing failed
- */
+/*
+name=condition
+description=A boolean expression.
+*/
 Criteria criteria(ParseInfo info) :
 {
 	Criteria criteria = null;
@@ -2585,11 +2758,10 @@
 	}
 }
 
-/** 
- * <p>Parse a compound logical OR criteria.</p>
- * @return Parsed OR criteria
- * @throws ParseException if parsing failed
- */
+/*
+name=boolean value expression
+description=An optionally ORed boolean expression.
+*/
 Criteria compoundCritOr(ParseInfo info) :
 {
     ArrayList logicList = null;
@@ -2609,11 +2781,10 @@
 	}
 }
 
-/**
- * <p>Parse a compound logical AND criteria.</p>
- * @return Parsed AND criteria
- * @throws ParseException if parsing failed
- */
+/*
+name=boolean term
+description=An optional ANDed boolean factor.
+*/
 Criteria compoundCritAnd(ParseInfo info) :
 {
     ArrayList logicList = null;
@@ -2633,11 +2804,11 @@
 	}
 }
 
-/**
- * <p>Parse a logical NOT criteria.</p>
- * @return Parsed NOT criteria
- * @throws ParseException if parsing failed
- */
+/*
+name=boolean factor
+description=A boolean factor.
+example={code:sql}NOT x = 'a'{code}
+*/
 Criteria notCrit(ParseInfo info) :
 {
     Expression ex = null;
@@ -2662,11 +2833,11 @@
 	}
 }
 
-/**
- * <p>Parse a boolean primary.</p>
- * @return criteria
- * @throws ParseException if parsing failed
- */
+/*
+name=boolean primary
+description=A boolean predicate or simple expression.
+example={code:sql}col LIKE 'a%'{code}
+*/
 Expression booleanPrimary(ParseInfo info) :
 {
     Expression ex = null;
@@ -2692,6 +2863,11 @@
 	}
 }
 
+/*
+name=comparison operator
+description=A comparison operator.
+example={code:sql}={code}
+*/
 Token operator() :
 {
 	Token operator = null;
@@ -2710,12 +2886,11 @@
     }
 }
 
-
-/**
- * <p>Parse a compare criteria.</p>
- * @return Parsed compare criteria
- * @throws ParseException if parsing failed
- */
+/*
+name=comparison predicate
+description=A value comparison.
+example={code:sql}x = 'a'{code}
+*/
 CompareCriteria compareCrit(ParseInfo info, Expression expression) :
 {
     Expression value = null;
@@ -2740,6 +2915,11 @@
 	}
 }
 
+/*
+name=subquery
+description=A subquery.
+example={code:sql}(SELECT * FROM tbl){code}
+*/
 QueryCommand subquery(ParseInfo info) :
 {
     QueryCommand subquery = null;
@@ -2761,24 +2941,11 @@
 	}
 }
 
-Object[] subqueryAndHint(ParseInfo info) :
-{
-    QueryCommand subquery = null;
-    Token lparen = null;
-}
-{
-	{lparen = getToken(1);}
-	subquery = subquery(info)
-	{
-		return new Object[] {subquery, getSubqueryHint(lparen)};
-	}
-}
-
-/** 
- * <p>Parse a subquery compare criteria.</p>
- * @return Parsed subquery compare criteria
- * @throws ParseException if parsing failed
- */
+/*
+name=quantified comparison predicate
+description=A subquery comparison.
+example={code:sql}= ANY (SELECT col FROM tbl){code}
+*/
 SubqueryCompareCriteria subqueryCompareCriteria(ParseInfo info, Expression expression) :
 {
     SubqueryCompareCriteria subqueryCrit = null;
@@ -2816,11 +2983,11 @@
    	}
 }
 
-/**
- * <p>Parse a match criteria. Also parses JDBC escape syntax for match criteria.</p>
- * @return Parsed match criteria
- * @throws ParseException if parsing failed
- */
+/*
+name=match predicate
+description=Matches based upon a pattern.
+example={code:sql}LIKE 'a_'{code}
+*/
 MatchCriteria matchCrit(ParseInfo info, Expression expression) :
 {
     Character esc = null;
@@ -2846,6 +3013,11 @@
    	}
 }
 
+/*
+name=like regex predicate
+description=A regular expression match.
+example={code:sql}LIKE_REGEX 'a.*b'{code}
+*/
 MatchCriteria regexMatchCrit(ParseInfo info, Expression expression) :
 {
 	Expression value = null;
@@ -2863,6 +3035,11 @@
    	}
 }
 
+/*
+name=character
+description=A single character.
+example={code:sql}'a'{code}
+*/
 Character charVal(ParseInfo info, String type) :
 {
 	String escStr = null;
@@ -2877,11 +3054,11 @@
 	}
 }
 
-/**
- * <p>Parse an [NOT] BETWEEN criteria.</p>
- * @return Parsed BETWEEN criteria
- * @throws ParseException if parsing failed
- */
+/*
+name=between predicate
+description=A comparison between two values.
+example={code:sql}BETWEEN 1 AND 5{code}
+*/
 BetweenCriteria betweenCrit(ParseInfo info, Expression expression) :
 {
 	Expression lowerExpression = null, upperExpression = null;
@@ -2901,11 +3078,11 @@
 	}
 }
 
-/**
- * <p>Parse an IS [NOT] NULL criteria.</p>
- * @return Parsed IS NULL criteria
- * @throws ParseException if parsing failed
- */
+/*
+name=is null predicate
+description=A null test.
+example={code:sql}IS NOT NULL{code}
+*/
 IsNullCriteria isNullCrit(ParseInfo info, Expression expression) :
 {
 	boolean negated = false;
@@ -2923,16 +3100,17 @@
 	}
 }
 
-/** 
- * <p>Parse a set criteria.</p>
- * @return Parsed set criteria
- * @throws ParseException if parsing failed
- */
+/*
+name=in predicate
+description=A comparison with multiple values.
+example={code:sql}IN (1, 5){code}
+*/
 AbstractSetCriteria setCrit(ParseInfo info, Expression expression) :
 {
 	Expression value = null;
 	List setList = new ArrayList();
-	Object[] command = null;
+	QueryCommand command = null;
+	ExistsCriteria.SubqueryHint hint = null;
 	boolean negated = false;
 	AbstractSetCriteria criteria = null;
 }
@@ -2940,7 +3118,7 @@
 	[<NOT> {negated = true;}]
 	<IN>
 	(
-		LOOKAHEAD(subquery(info)) (command = subqueryAndHint(info)) |
+		LOOKAHEAD(subquery(info)) { hint = getSubqueryHint(getToken(1)); } (command = subquery(info)) |
 		(
 			<LPAREN>
 			value = commonValueExpression(info)
@@ -2958,8 +3136,8 @@
 	)
 	{
 	    if (command != null) {
-			SubquerySetCriteria ssc = new SubquerySetCriteria(expression, (QueryCommand)command[0]);
-			ssc.setSubqueryHint((ExistsCriteria.SubqueryHint)command[1]);
+			SubquerySetCriteria ssc = new SubquerySetCriteria(expression, command);
+			ssc.setSubqueryHint(hint);
 			criteria = ssc;
 		} else {
 		    criteria = new SetCriteria(expression, setList);
@@ -2969,31 +3147,32 @@
    	}
 }
 
-/** 
- * <p>Parse an exists criteria.</p>
- * @return Parsed exists criteria
- * @throws ParseException if parsing failed
- */
+/*
+name=exists predicate
+description=A test if rows exist.
+example={code:sql}EXISTS (SELECT col FROM tbl){code}
+*/
 ExistsCriteria existsCriteria(ParseInfo info) :
 {
-    Object[] subquery = null;
+    QueryCommand subquery = null;
+    ExistsCriteria.SubqueryHint hint = null;
 }
 {
-	<EXISTS>
-	subquery = subqueryAndHint(info)
+	<EXISTS> { hint = getSubqueryHint(getToken(1)); } 
+	subquery = subquery(info)
 
 	{
-		ExistsCriteria existsCrit = new ExistsCriteria((QueryCommand)subquery[0]);
-		existsCrit.setSubqueryHint((ExistsCriteria.SubqueryHint)subquery[1]);
+		ExistsCriteria existsCrit = new ExistsCriteria(subquery);
+		existsCrit.setSubqueryHint(hint);
 	    return existsCrit;
    	}
 }
 
-/**
- * <p>Parse a GROUP BY clause.  </p>
- * @return Parsed group by
- * @throws ParseException if parsing failed
- */
+/*
+name=group by clause
+description=Defines the grouping columns
+example={code:sql}GROUP BY col1, col2{code}
+*/
 GroupBy groupBy(ParseInfo info) :
 {
 	List<Expression> expressions = null;
@@ -3006,11 +3185,11 @@
 	}
 }
 
-/**
- * <p>Parse a HAVING clause.  </p>
- * @return Parsed having
- * @throws ParseException if parsing failed
- */
+/*
+name=having clause
+description=Search condition applied after grouping.
+example={code:sql}HAVING max(col1) = 5{code}
+*/
 Criteria having(ParseInfo info) :
 {
     Criteria criteria = null;
@@ -3023,12 +3202,11 @@
 	}
 }
 
-	
-/** 
- * <p>Parse an ORDER BY clause.</p>
- * @return Parsed ORDER BY
- * @throws ParseException if parsing failed
- */
+/*
+name=order by clause
+description=Specifices row ordering.
+example={code:sql}ORDER BY x, y DESC{code}
+*/
 OrderBy orderby(ParseInfo info) :
 {
     OrderBy orderby = new OrderBy();
@@ -3051,6 +3229,11 @@
 	}
 }
 
+/*
+name=sort specification
+description=Defines how to sort on a particular expression
+example={code:sql}col1 NULLS FIRST{code}
+*/
 OrderByItem sortSpecification(ParseInfo info) :
 {
     Expression ex = null;
@@ -3070,6 +3253,11 @@
 	}
 }
 
+/*
+name=sort key
+description=A sort expression.
+example={code:sql}col1{code}
+*/
 Expression sortKey(ParseInfo info) :
 {
     Expression ex = null;
@@ -3093,6 +3281,11 @@
     }
 }
 
+/*
+name=integer parameter
+description=A literal integer or parameter reference to an integer.
+example={code:sql}?{code}
+*/
 Expression intParam(ParseInfo info) :
 {
    Integer val = null;
@@ -3107,11 +3300,11 @@
    }
 }
 
-/** 
- * <p>Parse an LIMIT clause.</p>
- * @return Parsed LIMIT
- * @throws ParseException if parsing failed
- */
+/*
+name=limit clause
+description=Limits and/or offsets the resultant rows.
+example={code:sql}LIMIT 2{code}
+*/
 Limit limit(ParseInfo info) :
 {
 	Expression limit = null;
@@ -3140,6 +3333,11 @@
 	}
 }
 
+/*
+name=fetch clause
+description=ANSI limit.
+example={code:sql}FETCH FIRST 1 ROWS ONLY{code}
+*/
 Expression fetchLimit(ParseInfo info) :
 {
     Expression limit = null;
@@ -3154,11 +3352,11 @@
     }
 }
 
-/** 
- * <p>Parse an OPTION clause.</p>
- * @return Parsed OPTION clause
- * @throws ParseException if parsing failed
- */
+/*
+name=option clause
+description=Specifies query options.
+example={code:sql}OPTION MAKEDEP tbl{code}
+*/
 Option option(ParseInfo info) :
 {
 	String id = null;
@@ -3210,11 +3408,11 @@
 	}
 }
 
-/**
- * <p>Parse an expression - made up of literals and functions.</p>
- * @return Expression
- * @throws ParseException if parsing failed
- */
+/*
+name=expression
+description=A value.
+example={code:sql}col1{code}
+*/
 Expression expression(ParseInfo info) :
 {
 	Expression expression = null;
@@ -3229,6 +3427,11 @@
 	}
 }
 
+/*
+name=common value expression
+description=Establishes the precedence of concat.
+example={code:sql}'a' || 'b'{code}
+*/
 Expression commonValueExpression(ParseInfo info) :
 {
 	Expression leftExpression = null;
@@ -3251,11 +3454,10 @@
 	}
 }
 
-/**
- * <p>Parse an expression - made up of literals and functions.</p>
- * @return Expression
- * @throws ParseException if parsing failed
- */
+/*
+name=numeric value expression
+example={code:sql}1 + 2{code}
+*/
 Expression plusExpression(ParseInfo info) :
 {
 	Expression leftExpression = null;
@@ -3265,7 +3467,7 @@
 {
 	(	leftExpression=timesExpression(info)
 		(
-			operator=plusOperator()
+			operator=plusMinus()
 			rightExpression=timesExpression(info)
 			{
 				leftExpression = new Function(operator, new Expression[] { leftExpression, rightExpression });
@@ -3280,30 +3482,26 @@
 	}
 }
 
-/**
- * <p>Parse the add/subtract operators.</p>
- * @return "+" or "-"
- * @throws ParseException if parsing failed
- */
-String plusOperator() :
+/*
+name=plus or minus
+description=The + or - operator.
+example={code:sql}+{code}
+*/
+String plusMinus() :
 {
-	Token operator = null;
 }
 {
-	(	operator = <PLUS> |
-		operator = <MINUS>
-	)
-
+	(<PLUS> | <MINUS>)
 	{
-		return operator.image;
+		return getToken(0).image;
 	}
 }
 
-/**
- * <p>Parse an expression - made up of literals and functions.</p>
- * @return Expression
- * @throws ParseException if parsing failed
- */
+/*
+name=term
+description=A numeric term
+example={code:sql}1 * 2{code}
+*/
 Expression timesExpression(ParseInfo info) :
 {
 	Expression leftExpression = null;
@@ -3328,11 +3526,11 @@
 	}
 }
 
-/**
- * <p>Parse the multiply/divide operator.</p>
- * @return "*" or "/"
- * @throws ParseException if parsing failed
- */
+/*
+name=star or slash
+description=The * or / operator.
+example={code:sql}/{code}
+*/
 String timesOperator() :
 {
 	Token operator = null;
@@ -3347,33 +3545,56 @@
 	}
 }
 
-/**
- * <p>Parse a basic expression.</p>
- * @return Expression
- * @throws ParseException if parsing failed
- */
+/*
+name=value expression primary
+description=A simple value expression.
+example={code:sql}+col1{code}
+*/
 Expression valueExpressionPrimary(ParseInfo info) :
 {
-	Token refToken = null;
+	String strVal = null;
+	Expression ex = null;
+}
+{
+	// Literal
+	(ex=nonNumericLiteral()
+	| [strVal = plusMinus()] 
+	  (ex = unsignedNumericLiteral(strVal)
+	   |
+	   ex = unsignedValueExpressionPrimary(info) {
+	     if (strVal != null && strVal.charAt(0) == '-') {
+	     	ex = new Function("*", new Expression[] { new Constant(-1), ex });
+	     }
+	    }
+	   )
+	 )
+	 {
+		return ex;	 
+	 }  
+}
+
+/*
+name=unsigned value expression primary
+description=An unsigned simple value expression.
+example={code:sql}col1{code}
+*/
+Expression unsignedValueExpressionPrimary(ParseInfo info) :
+{
 	Expression expression = null;
 	Token symbol = null;
-	Constant literal = null;	
 	QueryCommand subquery = null;
-	Integer arrayIndex = null;
+	Integer index = null;
 	Expression condition = null;
 }
 {
         (
 		// Reference
-		refToken=<QMARK>
+		<QMARK> {return new Reference(info.referenceCount++);}
 		|
-		refToken=<POS_REF>
+		(<DOLLAR> index = intVal() {return new Reference(index -1); })
 		|
-		// Literal
-		literal=literal()
-		|
 		// Escaped function
-		(	<LBRACE> <FN>
+		(	<ESCAPEDFUNCTION>
 			expression=function(info)
 			<RBRACE>
 		)
@@ -3390,11 +3611,10 @@
 		((symbol=<ID> {
 				String symbolImage = symbol.image;
 				if(isStringLiteral(symbolImage, info)) {
-				    literal = new Constant(normalizeStringLiteral(symbolImage));
-				    symbol = null;
+				    return new Constant(normalizeStringLiteral(symbolImage));
 				}  
 			} | symbol=nonReserved()) 
-			(<LSBRACE> arrayIndex = intVal() <RSBRACE>)?
+			(<LSBRACE> index = intVal() <RSBRACE>)?
 		)
 		|
 		LOOKAHEAD(subquery(info)) subquery = subquery(info)
@@ -3402,7 +3622,7 @@
 		( <LPAREN> 
  			expression = expression(info)
 		  <RPAREN>
-		  (<LSBRACE> arrayIndex = intVal() <RSBRACE>)?
+		  (<LSBRACE> index = intVal() <RSBRACE>)?
 		)
 		|
 		// Searched CASE expressions
@@ -3413,28 +3633,26 @@
 	)						
 		
 	{
-		if(refToken != null) {
-		    if (refToken.image.charAt(0) == '$') {
-				return new Reference(Integer.parseInt(refToken.image.substring(1)) -1);
-		    }
-			expression = new Reference(info.referenceCount++);
-		} else if(symbol != null) {
+		if(symbol != null) {
 			expression = new ElementSymbol(normalizeId(symbol.image));
-		} else if(literal != null) {
-			expression = literal;		// may be null literal
 		} else if (subquery != null){
 			expression = new ScalarSubquery(subquery);
 		}
 		if (condition != null) {
 			((AggregateSymbol)expression).setCondition(condition);
 		}
-		if (arrayIndex != null) {
-			expression = new Function("array_get", new Expression[] {expression, new Constant(arrayIndex)});		
+		if (index != null) {
+			expression = new Function("array_get", new Expression[] {expression, new Constant(index)});		
 		}
 		return expression;
 	}
 }
 
+/*
+name=window specification
+description=The window specification for an analytical or windowed aggregate function.
+example={code:sql}OVER (PARTION BY col1){code}
+*/
 Expression windowSpecification(Expression agg, ParseInfo info) :
 {
 	List<Expression> partitionList = null;
@@ -3460,11 +3678,11 @@
     }
 }
 
-/**
- * Parse a non-searched CASE expression.
- * @return CaseExpression
- * @throws ParseException if parsing failed
- */
+/*
+name=case expression
+description=If/then/else chain using a common search predicand.
+example={code:sql}CASE col1 WHEN 'a' THEN 1 ELSE 2{code}
+*/
 CaseExpression caseExpression(ParseInfo info) :
 {
 	Expression expression = null, whenExpression = null, thenExpression = null, elseExpression = null;
@@ -3493,11 +3711,11 @@
 	}
 }
 
-/**
- * Parse a searched CASE expression.
- * @return SearchedCaseExpression
- * @throws ParseException if parsing failed
- */
+/*
+name=searched case expression
+description=If/then/else chain using multiple search conditions.
+example={code:sql}CASE WHEN x = 'a' THEN 1 WHEN y = 'b' THEN 2{code}
+*/
 SearchedCaseExpression searchedCaseExpression(ParseInfo info) :
 {
 	Expression thenExpression = null, elseExpression = null;
@@ -3527,11 +3745,11 @@
 	}
 }
 
-/**
- * <p>Parse a function. </p>
- * @return Parsed function
- * @throws ParseException if parsing failed
- */
+/*
+name=function
+description=Calls a scalar function.
+example={code:sql}func('1', col1){code}
+*/
 Expression function(ParseInfo info) :
 {
 	String funcName = null;
@@ -3543,6 +3761,8 @@
 	Boolean distinct = null;
 	OrderBy orderBy = null;
 	Expression condition = null;
+	String literal = null;
+	ParsedDataType type = null;
 }
 {
 	((	funcToken = <CONVERT>
@@ -3552,9 +3772,9 @@
 			args.add(expression);
 		}
 		<COMMA>
-		expression = dataType()	
+		type = parseDataType()	
 		{
-			args.add(expression);
+			args.add(new Constant(type.type));
 		}
 		<RPAREN> 
 	)
@@ -3567,9 +3787,9 @@
 			args.add(expression);
 		} 
 		<AS>
-		expression = dataType()
+		type = parseDataType()
 		{
-			args.add(expression);
+			args.add(new Constant(type.type));
 		}
 		<RPAREN>				
 	)
@@ -3658,9 +3878,9 @@
 			args.add(expression);
 		}
 		<COMMA>
-		expression = stringConstant()
+		literal = stringVal()
 		{
-			args.add(expression);
+			args.add(new Constant(literal));
 		} 
 		<RPAREN>				
 	)
@@ -3717,10 +3937,10 @@
 	| ( funcToken = <XMLPI>
 		<LPAREN>
 		(
-		 [LOOKAHEAD(1) <NAME>] expression = idExpression()
+		 [LOOKAHEAD(1) <NAME>] literal = id()
 		)
 		{
-			args.add(expression);	
+			args.add(new Constant(literal));	
 		}
 		[
 			<COMMA> expression = expression(info)
@@ -3764,17 +3984,11 @@
 	}
 }
 
-Constant stringConstant() :
-{
-	String val = null;
-}
-{
-	val = stringVal()
-	{
-		return new Constant(val);
-	}
-}
-
+/*
+name=xml parse
+description=Parses the given value as XML.
+example={code:sql}XMLPARSE(DOCUMENT doc WELLFORMED){code}
+*/
 XMLParse xmlParse(ParseInfo info) :
 {
 	Expression expr = null;
@@ -3800,6 +4014,11 @@
 	}
 }
 
+/*
+name=querystring function
+description=Produces a URL query string from the given arguments.
+example={code:sql}QUERYSTRING(col1 AS opt, col2 AS val){code}
+*/
 QueryString queryString(ParseInfo info) :
 {
 	Expression path = null;
@@ -3821,6 +4040,11 @@
 	}
 }
 
+/*
+name=xml element
+description=Creates an XML element.
+example={code:sql}XMLELEMENT(NAME "root", child){code}
+*/
 XMLElement xmlElement(ParseInfo info) :
 {
 	String name = null;
@@ -3854,6 +4078,11 @@
 	}
 }	
 
+/*
+name=xml attributes
+description=Creates attributes for the containing element.
+example={code:sql}XMLATTRIBUTES(col1 AS attr1, col2 AS attr2){code}
+*/
 XMLAttributes xmlAttributes(ParseInfo info) :
 {
 	DerivedColumn expression = null;
@@ -3876,6 +4105,11 @@
 	}
 }
 
+/*
+name=xml forest
+description=Produces an element for each derived column.
+example={code:sql}XMLFOREST(col1 AS ELEM1, col2 AS ELEM2){code}
+*/
 XMLForest xmlForest(ParseInfo info) :
 {
 	DerivedColumn expression = null;
@@ -3904,6 +4138,11 @@
 	}
 }		
 		
+/*
+name=xml namespaces
+description=Defines XML namespace URI/prefix combinations
+example={code:sql}XMLNAMESPACES('http://foo' AS foo){code}
+*/
 XMLNamespaces xmlNamespaces(ParseInfo info) :
 {
 	ArrayList namespaces = new ArrayList(2);
@@ -3926,6 +4165,11 @@
 	}
 }
 
+/*
+name=xml namespace element
+description=An xml namespace
+example={code:sql}NO DEFAULT{code}
+*/
 XMLNamespaces.NamespaceItem namespaceItem() :
 {
 	String uri = null;
@@ -3950,82 +4194,64 @@
 	)
 }
 
-Constant idExpression() :
-{
-	String id = null;
-}
-{
-	id = id()
-	{
-		return new Constant(id);
-	}
-}
-
+/*
+name=data type
+description=A data type.
+example={code:sql}STRING{code}
+*/
 ParsedDataType parseDataType() :
 {
 	Token typeToken = null;
-	Token lengthToken = null;
-	Token scaleToken = null; 
+	Integer length = null;
+	Integer scale = null; 
 	boolean precision = true;
 }
 {
 	(
-		(typeToken = <STRING> ([<LPAREN>lengthToken=<INTEGERVAL><RPAREN>]) {precision = false;} ) |
-		(typeToken = <VARCHAR> ([<LPAREN>lengthToken=<INTEGERVAL><RPAREN>]) {precision = false;} ) | 
+		(typeToken = <STRING> ([<LPAREN>length=intVal()<RPAREN>]) {precision = false;} ) |
+		(typeToken = <VARCHAR> ([<LPAREN>length=intVal()<RPAREN>]) {precision = false;} ) | 
 		typeToken = <BOOLEAN> | 
 		typeToken = <BYTE> | 
 		typeToken = <TINYINT> |
 		typeToken = <SHORT> | 
 		typeToken = <SMALLINT> |
-		(typeToken = <CHAR> ([<LPAREN>lengthToken=<INTEGERVAL><RPAREN>]) {precision = false;} ) | 
+		(typeToken = <CHAR> ([<LPAREN>length=intVal()<RPAREN>]) {precision = false;} ) | 
 		typeToken = <INTEGER> | 
 		typeToken = <LONG> | 
 		typeToken = <BIGINT> |
-		(typeToken = <BIGINTEGER> [<LPAREN>lengthToken=<INTEGERVAL><RPAREN>]) | 
+		(typeToken = <BIGINTEGER> [<LPAREN>length=intVal()<RPAREN>]) | 
 		typeToken = <FLOAT> |
 		typeToken = <REAL> | 
 		typeToken = <DOUBLE> | 
-		(typeToken = <BIGDECIMAL> [<LPAREN>lengthToken=<INTEGERVAL>[<COMMA>scaleToken=<INTEGERVAL>]<RPAREN>])|
-		(typeToken = <DECIMAL> [<LPAREN>lengthToken=<INTEGERVAL>[<COMMA>scaleToken=<INTEGERVAL>]<RPAREN>])| 
+		(typeToken = <BIGDECIMAL> [<LPAREN>length=intVal()[<COMMA>scale=intVal()]<RPAREN>])|
+		(typeToken = <DECIMAL> [<LPAREN>length=intVal()[<COMMA>scale=intVal()]<RPAREN>])| 
 		typeToken = <DATE> | 
 		typeToken = <TIME> |
 		typeToken = <TIMESTAMP> |
 		typeToken = <OBJECT> |
-		(typeToken = <BLOB> ([<LPAREN>lengthToken=<INTEGERVAL><RPAREN>]) {precision = false;} )|
-		(typeToken = <CLOB> ([<LPAREN>lengthToken=<INTEGERVAL><RPAREN>]) {precision = false;} )|
-		(typeToken = <VARBINARY> ([<LPAREN>lengthToken=<INTEGERVAL><RPAREN>]) {precision = false;} ) |
+		(typeToken = <BLOB> ([<LPAREN>length=intVal()<RPAREN>]) {precision = false;} )|
+		(typeToken = <CLOB> ([<LPAREN>length=intVal()<RPAREN>]) {precision = false;} )|
+		(typeToken = <VARBINARY> ([<LPAREN>length=intVal()<RPAREN>]) {precision = false;} ) |
 		typeToken = <XML>
 		
 	)
 	
 	{
-		if (scaleToken != null){
-			return new ParsedDataType(typeToken.image, Integer.parseInt(lengthToken.image), Integer.parseInt(scaleToken.image), precision);
+		if (scale != null){
+			return new ParsedDataType(typeToken.image, length, scale, precision);
 		}
-		else if (scaleToken == null && lengthToken != null){
-			return new ParsedDataType(typeToken.image, Integer.parseInt(lengthToken.image), precision);
+		else if (length != null){
+			return new ParsedDataType(typeToken.image, length, precision);
 		}
 		return new ParsedDataType(typeToken.image);
 	}
 }
 
-
-Constant dataType() : 
-{
-	ParsedDataType type = null;
-}
-{
-	type = parseDataType()	
-	{
-		return new Constant(type.type);
-	}
-}
-
-/**
- * Parse an interval type name - used only in TIMESTAMPADD and TIMESTAMPDIFF functions.
- * @return Interval type parsed into a constant string object
- * @throws ParseException if parsing failed
- */
+/*
+name=time interval
+description=A time interval keyword.
+example={code:sql}SQL_TSI_HOUR{code}
+*/
 Constant intervalType() : 
 {
 	Token type = null;
@@ -4046,16 +4272,16 @@
 		return new Constant(type.image);
 	}
 }
-/**
- * <p>Parse a literal - strings must be wrapped in either '' or "".
- * JDBC escape syntax is parsed for Date, Time and Timestamp value.</p>
- * @return Parsed literal
- * @throws ParseException if parsing failed
- */
-Constant literal() :
+
+/*
+name=non numeric literal
+description=An escaped or simple non numeric literal.
+example={code:sql}'a'{code}
+*/
+Constant nonNumericLiteral() :
 {
     Token t = null;
-    String strVal = null;
+    String strVal = "";
     Class escapeType = null;
     Constant constant = null;
 }
@@ -4064,84 +4290,107 @@
 		strVal=stringVal()	{ 
 			constant = new Constant(strVal, DataTypeManager.DefaultDataClasses.STRING);
 		} |
-		
-		t=<INTEGERVAL> 	{ 
+		t=<BINARYSTRINGVAL> { constant = new Constant(new BinaryType(javax.xml.bind.DatatypeConverter.parseHexBinary(t.image.substring(2, t.image.length() - 1))), DataTypeManager.DefaultDataClasses.VARBINARY); } |
+		t=<FALSE>    { constant = new Constant(Boolean.FALSE, DataTypeManager.DefaultDataClasses.BOOLEAN); } |
+		t=<TRUE>     { constant = new Constant(Boolean.TRUE, DataTypeManager.DefaultDataClasses.BOOLEAN); }  |
+        t=<UNKNOWN>  { constant = new Constant(null, DataTypeManager.DefaultDataClasses.BOOLEAN); }       |
+        t=<NULL>     { constant = new Constant(null); }          |
+        
+        ( <ESCAPEDTYPE> { 
+            String image = getToken(0).image; 
+        	if (StringUtil.endsWithIgnoreCase(image, "b")) {
+        		escapeType=DataTypeManager.DefaultDataClasses.BOOLEAN;
+        	} else if (StringUtil.endsWithIgnoreCase(image, "ts")) {
+        		escapeType=DataTypeManager.DefaultDataClasses.TIMESTAMP;
+        	} else if (StringUtil.endsWithIgnoreCase(image, "d")) {
+        		escapeType=DataTypeManager.DefaultDataClasses.DATE;
+        	} else {
+        		escapeType=DataTypeManager.DefaultDataClasses.TIME;
+        	}
+		  } strVal=stringVal() { 
+	        	try {
+	        		constant = new Constant(DataTypeManager.transformValue(strVal, escapeType), escapeType);
+	        	} catch (TransformationException e) {
+	        		throw new ParseException(e.getMessage()); //$NON-NLS-1$
+	        	}
+	        } <RBRACE> ) 
+
+	)
+	{
+		return constant;
+	}
+}
+
+/*
+name=unsigned numeric literal
+description=An unsigned numeric literal value.
+example={code:sql}1.234{code}
+*/
+Constant unsignedNumericLiteral(String strVal) :
+{
+    Token t = null;
+}
+{
+		(t=<UNSIGNEDINTEGER> 	{ 
 			try { 
+			    strVal = prependSign(strVal, t.image);
 				// First try as integer - this should nearly always work
-				constant = new Constant(Integer.valueOf(t.image), DataTypeManager.DefaultDataClasses.INTEGER); 				
+				return new Constant(Integer.valueOf(strVal), DataTypeManager.DefaultDataClasses.INTEGER); 				
 			} catch(NumberFormatException e1) { 
 				try { 
 					// Second try as a long
-					constant = new Constant(Long.valueOf(t.image), DataTypeManager.DefaultDataClasses.LONG);
+					return new Constant(Long.valueOf(strVal), DataTypeManager.DefaultDataClasses.LONG);
 				} catch(NumberFormatException e2) {
 					try {
 						// Third try as a biginteger
-						constant = new Constant(new BigInteger(t.image), DataTypeManager.DefaultDataClasses.BIG_INTEGER);
+						return new Constant(new BigInteger(strVal), DataTypeManager.DefaultDataClasses.BIG_INTEGER);
 					} catch(NumberFormatException e3) {
-						Object[] params = new Object[] { t.image };
+						Object[] params = new Object[] { strVal };
 						throw new ParseException(QueryPlugin.Util.getString("SQLParser.Integer_parse", params)); //$NON-NLS-1$
 					}
 				}
 			}			
-		}	|
-		
-		t=<FLOATVAL>	{ 
+		}	| t=<FLOATVAL>	{ 
+		    strVal = prependSign(strVal, t.image);
 			try { 
-				constant = new Constant(Double.valueOf(t.image), DataTypeManager.DefaultDataClasses.DOUBLE); 
+				return new Constant(Double.valueOf(strVal), DataTypeManager.DefaultDataClasses.DOUBLE); 
 			} catch(NumberFormatException e) {
-				Object[] params = new Object[] { t.image };
+				Object[] params = new Object[] { strVal };
 				throw new ParseException(QueryPlugin.Util.getString("SQLParser.Float_parse", params)); //$NON-NLS-1$
 			}
-		}   |
-		t=<DECIMALVAL>	{ 
+		}  | t=<DECIMALVAL>	{ 
+     		strVal = prependSign(strVal, t.image);
 			try { 
 			    if (DECIMAL_AS_DOUBLE) {
-			    	constant = new Constant(Double.valueOf(t.image), DataTypeManager.DefaultDataClasses.DOUBLE); 
+			    	return new Constant(Double.valueOf(strVal), DataTypeManager.DefaultDataClasses.DOUBLE); 
 				} else {
-			    	constant = new Constant(new java.math.BigDecimal(t.image), DataTypeManager.DefaultDataClasses.BIG_DECIMAL); 
+			    	return new Constant(new java.math.BigDecimal(strVal), DataTypeManager.DefaultDataClasses.BIG_DECIMAL); 
 				}
 			} catch(NumberFormatException e) {
 				Object[] params = new Object[] { t.image };
 				throw new ParseException(QueryPlugin.Util.getString("SQLParser.decimal_parse", params)); //$NON-NLS-1$
 			}
-		}   |
-		t=<BINARYSTRINGVAL> { constant = new Constant(new BinaryType(javax.xml.bind.DatatypeConverter.parseHexBinary(t.image.substring(2, t.image.length() - 1))), DataTypeManager.DefaultDataClasses.VARBINARY); } |
-		t=<FALSE>    { constant = new Constant(Boolean.FALSE, DataTypeManager.DefaultDataClasses.BOOLEAN); } |
-		t=<TRUE>     { constant = new Constant(Boolean.TRUE, DataTypeManager.DefaultDataClasses.BOOLEAN); }  |
-        t=<UNKNOWN>  { constant = new Constant(null, DataTypeManager.DefaultDataClasses.BOOLEAN); }       |
-        t=<NULL>     { constant = new Constant(null); }          |
-        
-        ( (<BOOLEANTYPE>   { escapeType=DataTypeManager.DefaultDataClasses.BOOLEAN; } |
-          <TIMESTAMPTYPE> { escapeType=DataTypeManager.DefaultDataClasses.TIMESTAMP; } | 
-          <DATETYPE>      { escapeType=DataTypeManager.DefaultDataClasses.DATE; } |
-          <TIMETYPE>      { escapeType=DataTypeManager.DefaultDataClasses.TIME; }) strVal=stringVal() { 
-	        	try {
-	        		constant = new Constant(DataTypeManager.transformValue(strVal, escapeType), escapeType);
-	        	} catch (TransformationException e) {
-	        		throw new ParseException(e.getMessage()); //$NON-NLS-1$
-	        	}
-	        } <RBRACE> ) 
-
-	)
-	{
-		return constant;
-	}
+		} )
 }
 
-
-
-/*   
- * DDL specific parser
- */
-
+/*
+unused=true
+*/
  void parseMetadata(MetadataFactory factory) :
 {
 }
 {
-    ddlStmts(factory) [<SEMICOLON>] (ddlStmts(factory) [<SEMICOLON>])*     
+    (ddlStmt(factory))*
+    <EOF>     
 }
 
-void ddlStmts(MetadataFactory factory) :
+/*
+name=ddl statement
+description=A data definition statement.
+example={code:sql}CREATE FOREIGN TABLE X (Y STRING){code}
+index=true
+*/
+void ddlStmt(MetadataFactory factory) :
 {
 	Command command = null; 
 }
@@ -4154,8 +4403,14 @@
 	 	createDDLTrigger(factory, (AlterTrigger)command);
 	 }
 	)
+	[<SEMICOLON>]
 }
 
+/*
+name=option namespace
+description=A namespace used to shorten the full name of an option key.
+example={code:sql}SET NAMESPACE 'http://foo' AS foo{code}
+*/
 void createNameSpace(MetadataFactory factory) :
 {
 	String uri = null;
@@ -4164,14 +4419,15 @@
 { 
 	<SET> <NAMESPACE> uri = stringVal() <AS> prefix = id()
 	{
-		factory.addNamespace(prefix, uri);
+		factory.addNamespace(validateAlias(prefix), uri);
 	}
 }
 
-/**
- * Parse create update procedure command
- * @throws ParseException if parsing failed
- */
+/*
+name=create procedure
+description=Defines a procedure or function invocation.
+example={code:sql}CREATE FOREIGN PROCEDURE proc (param STRING) RETURNS STRING{code}
+*/
 CreateProcedureCommand createDDLProcedure(MetadataFactory factory, ParseInfo info) :
 {
 	boolean virtual = true;
@@ -4234,6 +4490,11 @@
 		}
 }
 
+/*
+name=procedure parameter
+description=A procedure or function parameter
+example={code:sql}OUT x INTEGER{code}
+*/
 void procedureParameter(MetadataFactory factory, Procedure proc) :
 {
 	String name = null;
@@ -4277,25 +4538,23 @@
 	]	
 }
 
+/*
+name=procedure result column
+description=A procedure result column.
+example={code:sql}x INTEGER{code}
+*/
 void procedureRsColumn(MetadataFactory factory, Procedure proc) :
 {
 	String name = null;
-}
-{
-	name = id()
-	procedureColumn(factory, proc, name, true)
-}
-
-void procedureColumn(MetadataFactory factory, Procedure proc, String name, boolean rs) :
-{
 	ParsedDataType type = null;
 	boolean notNull = false;
 	BaseColumn column = null; 
 }
 {
+      name = id()
 	  type = parseDataType()
 	  {
-	  	column = addProcColumn(factory, proc, name, type, rs);
+	  	column = addProcColumn(factory, proc, name, type, true);
 	  }
 	  [<NOT> <NULL> {column.setNullType(Column.NullType.No_Nulls);}]	  
 	  [optionsClause(column, factory)
@@ -4305,6 +4564,11 @@
 	  ]
 }
 
+/*
+name=create table
+description=Defines a table or view.
+example={code:sql}CREATE VIEW vw AS SELECT 1{code}
+*/
 void createTable(MetadataFactory factory) :
 {
 	Table table = null;
@@ -4358,6 +4622,11 @@
 	}
 }
 
+/*
+name=foreign key
+description=Defines the foreign key referential constraint.
+example={code:sql}FOREIGN KEY (a, b) REFERENCES tbl (x, y){code}
+*/
 void foreignKeys(MetadataFactory factory, Table table) :
 {
 	List<String> columnNames = null;
@@ -4393,6 +4662,11 @@
 	]
 }
 
+/*
+name=primary key
+description=Defines the primary key.
+example={code:sql}PRIMARY KEY (a, b){code}
+*/
 void primaryKeys(MetadataFactory factory, Table table) :
 {
 	List<String> columnNames = null;
@@ -4422,6 +4696,11 @@
 	]    
 }
 
+/*
+name=other constraints
+description=Defines ACCESSPATTERN and UNIQUE constraints and INDEXes. 
+example={code:sql}UNIQUE (a){code}
+*/
 void constraints(MetadataFactory factory, Table table) :
 {
 	KeyRecord keyrecord = null;
@@ -4458,6 +4737,11 @@
 	]    
 }
 
+/*
+name=column name list
+description=A list of column names.
+example={code:sql}(a, b){code}
+*/
 ArrayList<String> getColumnNames() :
 {
 	ArrayList list = new ArrayList<String>();
@@ -4480,6 +4764,11 @@
 	 }
 }
 
+/*
+name=table element
+description=Defines a table column.
+example={code:sql}x INTEGER NOT NULL{code}
+*/
 void createColumn(MetadataFactory factory, Table table) :
 {
 	String element = null;
@@ -4548,6 +4837,11 @@
 	 }
 }
 
+/*
+name=options clause
+description=A list of statement options.
+example={code:sql}OPTIONS ('x' 'y', 'a' 'b'){code}
+*/
 void optionsClause(AbstractMetadataRecord record, MetadataFactory factory) :
 {
 }
@@ -4557,28 +4851,28 @@
   <RPAREN> 
 }
 
+/*
+name=option pair
+description=An option key/value pair.
+example={code:sql}'key' 'value'{code}
+*/
 void optionPair(AbstractMetadataRecord record, MetadataFactory factory) :
 {
-	String value = null;
+	Constant value = null;
 	String key = null;
 	Token t = null;
+	String strVal = null;
 }
 {
 	 key = id()
-	 (value = stringVal() 
- 	 |
- 	 t = <INTEGERVAL>
- 	 |
- 	 t = <DECIMALVAL>
- 	 |
- 	 t = <TRUE>
- 	 |
- 	 t = <FALSE>)
+	 (value = nonNumericLiteral()
+	 | [strVal = plusMinus()] value = unsignedNumericLiteral(strVal))
 	 { 
-	 	if (t != null) {
-	 		value = t.image;
+	 	key = resolvePropertyKey(factory, key);
+	 	String val = null;
+	 	if (!value.isNull()) {
+	 		val = value.getValue().toString();
 	 	}
-	 	key = resolvePropertyKey(factory, key);
-	 	record.setProperty(key, value); 
+	 	record.setProperty(key, val); 
 	 } 
 }

Modified: trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java	2012-08-06 20:18:00 UTC (rev 4300)
+++ trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java	2012-08-07 13:41:48 UTC (rev 4301)
@@ -558,7 +558,26 @@
 				 "SELECT (5 + length(concat(a, 'x'))) FROM g",  //$NON-NLS-1$
 				 query);
 	}
+	
+	@Test public void testSignedExpression() {
+		GroupSymbol g = new GroupSymbol("g"); //$NON-NLS-1$
+		From from = new From();
+		from.addGroup(g);
 
+		Function f = new Function("*", new Expression[] {new Constant(-1), new ElementSymbol("x")});
+		Select select = new Select();
+		select.addSymbol(f);
+		select.addSymbol(new ElementSymbol("x"));
+		select.addSymbol(new Constant(5));
+
+		Query query = new Query();
+		query.setSelect(select);
+		query.setFrom(from);
+		helpTest("SELECT -x, +x, +5 FROM g",  //$NON-NLS-1$
+				 "SELECT (-1 * x), x, 5 FROM g",  //$NON-NLS-1$
+				 query);
+	}
+
 	/** SELECT REPLACE(a, 'x', 'y') AS y FROM g */
 	@Test public void testAliasedFunction() {
 		GroupSymbol g = new GroupSymbol("g"); //$NON-NLS-1$
@@ -1472,52 +1491,18 @@
 
 		Select select = new Select();
 		select.addSymbol(new Constant(new Double(1.3e8))); //$NON-NLS-1$
-						
-		Query query = new Query();
-		query.setSelect(select);
-		query.setFrom(from);
-		
-		helpTest("SELECT 1.3e8 FROM a.g1",  //$NON-NLS-1$
-				 "SELECT 1.3E8 FROM a.g1",  //$NON-NLS-1$
-				 query);		    
-	}	
-	
-	/** SELECT -1.3e-6 FROM a.g1 */
-	@Test public void testFloatWithMinusE() {
-		GroupSymbol g = new GroupSymbol("a.g1"); //$NON-NLS-1$
-		From from = new From();
-		from.addGroup(g);
-
-		Select select = new Select();
-		select.addSymbol(new Constant(new Double(-1.3e-6))); //$NON-NLS-1$
-						
-		Query query = new Query();
-		query.setSelect(select);
-		query.setFrom(from);
-		
-		helpTest("SELECT -1.3e-6 FROM a.g1",  //$NON-NLS-1$
-				 "SELECT -1.3E-6 FROM a.g1",  //$NON-NLS-1$
-				 query);		    
-	}	
-	
-	/** SELECT -1.3e+8 FROM a.g1 */
-	@Test public void testFloatWithPlusE() {
-		GroupSymbol g = new GroupSymbol("a.g1"); //$NON-NLS-1$
-		From from = new From();
-		from.addGroup(g);
-
-		Select select = new Select();
 		select.addSymbol(new Constant(new Double(-1.3e+8))); //$NON-NLS-1$
+		select.addSymbol(new Constant(new Double(+1.3e-8))); //$NON-NLS-1$
 						
 		Query query = new Query();
 		query.setSelect(select);
 		query.setFrom(from);
 		
-		helpTest("SELECT -1.3e+8 FROM a.g1",  //$NON-NLS-1$
-				 "SELECT -1.3E8 FROM a.g1",  //$NON-NLS-1$
+		helpTest("SELECT 1.3e8, -1.3e+8, +1.3e-8 FROM a.g1",  //$NON-NLS-1$
+				 "SELECT 1.3E8, -1.3E8, 1.3E-8 FROM a.g1",  //$NON-NLS-1$
 				 query);		    
 	}	
-
+	
     /** SELECT {d'2002-10-02'} FROM m.g1 */
     @Test public void testDateLiteral1() {
         GroupSymbol g = new GroupSymbol("m.g1"); //$NON-NLS-1$
@@ -5232,5 +5217,17 @@
 		Query actualCommand = (Query)QueryParser.getQueryParser().parseCommand("SELECT foo(distinct x, y) over ()", new ParseInfo());
 		assertEquals("SELECT foo(DISTINCT x, y) OVER ()", actualCommand.toString());
     }
+    
+    @Test public void testInvalidLimit() {
+        helpException("SELECT * FROM pm1.g1 LIMIT -5");
+    }
 
+    @Test public void testInvalidLimit_Offset() {
+    	helpException("SELECT * FROM pm1.g1 LIMIT -1, 100");
+    }
+    
+    @Test public void testTextTableNegativeWidth() {        
+        helpException("SELECT * from texttable(null columns x string width -1) as x"); 
+	}
+
 }

Modified: trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java	2012-08-06 20:18:00 UTC (rev 4300)
+++ trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java	2012-08-07 13:41:48 UTC (rev 4301)
@@ -1367,14 +1367,6 @@
     	helpValidate("select group2.e1, group3.e2 from group2, group3 WHERE group2.e0 = group3.e0 OPTION MAKEDEP group2 MAKENOTDEP group2, group3", new String[] {"OPTION MAKEDEP group2 MAKENOTDEP group2, group3"}, exampleMetadata()); //$NON-NLS-1$ //$NON-NLS-2$
     }
     
-    @Test public void testInvalidLimit() {
-        helpValidate("SELECT * FROM pm1.g1 LIMIT -5", new String[] {"LIMIT -5"}, RealMetadataFactory.example1Cached()); //$NON-NLS-1$ //$NON-NLS-2$
-    }
-
-    @Test public void testInvalidLimit_Offset() {
-    	helpValidate("SELECT * FROM pm1.g1 LIMIT -1, 100", new String[] {"LIMIT -1, 100"}, RealMetadataFactory.example1Cached()); //$NON-NLS-1$ //$NON-NLS-2$
-    }
-    
     /**
      * Test case 4237.  This test simulates the way the modeler transformation 
      * panel uses the query resolver and validator to validate a transformation for
@@ -1536,10 +1528,6 @@
         helpValidate(userSql, new String[] {"xpathValue('<?xml version=\"1.0\" encoding=\"utf-8\" ?><a><b><c>test</c></b></a>', '//*[local-name()=''bookName\"]')"}, RealMetadataFactory.exampleBQTCached());
     }
     
-    @Test public void testTextTableNegativeWidth() {        
-        helpValidate("SELECT * from texttable(null columns x string width -1) as x", new String[] {"TEXTTABLE(null COLUMNS x string WIDTH -1) AS x"}, RealMetadataFactory.exampleBQTCached()); 
-	}
-    
     @Test public void testTextTableNoWidth() {        
         helpValidate("SELECT * from texttable(null columns x string width 1, y integer) as x", new String[] {"TEXTTABLE(null COLUMNS x string WIDTH 1, y integer) AS x"}, RealMetadataFactory.exampleBQTCached()); 
 	}

Modified: trunk/test-integration/common/src/test/java/org/teiid/jdbc/TestDynamicImportedMetaData.java
===================================================================
--- trunk/test-integration/common/src/test/java/org/teiid/jdbc/TestDynamicImportedMetaData.java	2012-08-06 20:18:00 UTC (rev 4300)
+++ trunk/test-integration/common/src/test/java/org/teiid/jdbc/TestDynamicImportedMetaData.java	2012-08-07 13:41:48 UTC (rev 4301)
@@ -170,10 +170,9 @@
     	QueryParser.getQueryParser().parseDDL(mf, ddl);
     	MetadataStore ms = mf.asMetadataStore();
     
-    	String ddl2 = "CREATE VIEW stock (symbol string, price bigdecimal) " +
+    	String ddl2 = "CREATE VIEW stock (symbol string, price bigdecimal) OPTIONS (UUID 'uuid')" +
     			"AS select stock.* from (call MarketData.getTextFiles('*.txt')) f, " +
-    			"TEXTTABLE(f.file COLUMNS symbol string, price bigdecimal HEADER) stock " +
-    			"OPTIONS (UUID 'uuid')";    	
+    			"TEXTTABLE(f.file COLUMNS symbol string, price bigdecimal HEADER) stock;";    	
     	MetadataFactory m2 = createMetadataFactory("portfolio", new Properties());
 
     	QueryParser.getQueryParser().parseDDL(m2, ddl2);



More information about the teiid-commits mailing list