📄 hql-sql.g
字号:
;aliasedSelectExpr! : #(AS se:selectExpr i:identifier) { setAlias(#se,#i); #aliasedSelectExpr = #se; } ;selectExpr : p:propertyRef { resolveSelectExpression(#p); } | #(ALL ar2:aliasRef) { resolveSelectExpression(#ar2); #selectExpr = #ar2; } | #(OBJECT ar3:aliasRef) { resolveSelectExpression(#ar3); #selectExpr = #ar3; } | con:constructor { processConstructor(#con); } | functionCall | count | collectionFunction // elements() or indices() | literal | arithmeticExpr | query ;count : #(COUNT ( DISTINCT | ALL )? ( aggregateExpr | ROW_STAR ) ) ;constructor { String className = null; } : #(CONSTRUCTOR className=path ( selectExpr | aliasedSelectExpr )* ) ;aggregateExpr : expr //p:propertyRef { resolve(#p); } | collectionFunction ;// Establishes the list of aliases being used by this query.fromClause { // NOTE: This references the INPUT AST! (see http://www.antlr.org/doc/trees.html#Action%20Translation) // the ouput AST (#fromClause) has not been built yet. prepareFromClauseInputTree(#fromClause_in); } : #(f:FROM { pushFromClause(#fromClause,f); handleClauseStart( FROM ); } fromElementList ) ;fromElementList { boolean oldInFrom = inFrom; inFrom = true; } : (fromElement)+ { inFrom = oldInFrom; } ;fromElement! { String p = null; } // A simple class name, alias element. : #(RANGE p=path (a:ALIAS)? (pf:FETCH)? ) { #fromElement = createFromElement(p,a, pf); } | je:joinElement { #fromElement = #je; } // A from element created due to filter compilation | fe:FILTER_ENTITY a3:ALIAS { #fromElement = createFromFilterElement(fe,a3); } ;joinElement! { int j = INNER; } // A from element with a join. This time, the 'path' should be treated as an AST // and resolved (like any path in a WHERE clause). Make sure all implied joins // generated by the property ref use the join type, if it was specified. : #(JOIN (j=joinType { setImpliedJoinType(j); } )? (f:FETCH)? ref:propertyRef (a:ALIAS)? (pf:FETCH)? (with:WITH)? ) { //createFromJoinElement(#ref,a,j,f, pf); createFromJoinElement(#ref,a,j,f, pf, with); setImpliedJoinType(INNER); // Reset the implied join type. } ;// Returns an node type integer that represents the join type// tokens.joinType returns [int j] { j = INNER; } : ( (left:LEFT | right:RIGHT) (outer:OUTER)? ) { if (left != null) j = LEFT_OUTER; else if (right != null) j = RIGHT_OUTER; else if (outer != null) j = RIGHT_OUTER; } | FULL { j = FULL; } | INNER { j = INNER; } ;// Matches a path and returns the normalized string for the path (usually// fully qualified a class name).path returns [String p] { p = "???"; String x = "?x?"; } : a:identifier { p = a.getText(); } | #(DOT x=path y:identifier) { StringBuffer buf = new StringBuffer(); buf.append(x).append(".").append(y.getText()); p = buf.toString(); } ;// Returns a path as a single identifier node.pathAsIdent { String text = "?text?"; } : text=path { #pathAsIdent = #([IDENT,text]); } ;withClause // Note : this is used internally from the HqlSqlWalker to // parse the node recognized with the with keyword earlier. // Done this way because it relies on the join it "qualifies" // already having been processed, which would not be the case // if withClause was simply referenced from the joinElement // rule during recognition... : #(w:WITH { handleClauseStart( WITH ); } b:logicalExpr ) { #withClause = #(w , #b); } ;whereClause : #(w:WHERE { handleClauseStart( WHERE ); } b:logicalExpr ) { // Use the *output* AST for the boolean expression! #whereClause = #(w , #b); } ;logicalExpr : #(AND logicalExpr logicalExpr) | #(OR logicalExpr logicalExpr) | #(NOT logicalExpr) | comparisonExpr ;// TODO: Add any other comparison operators here.comparisonExpr : ( #(EQ exprOrSubquery exprOrSubquery) | #(NE exprOrSubquery exprOrSubquery) | #(LT exprOrSubquery exprOrSubquery) | #(GT exprOrSubquery exprOrSubquery) | #(LE exprOrSubquery exprOrSubquery) | #(GE exprOrSubquery exprOrSubquery) | #(LIKE exprOrSubquery expr ( #(ESCAPE expr) )? ) | #(NOT_LIKE exprOrSubquery expr ( #(ESCAPE expr) )? ) | #(BETWEEN exprOrSubquery exprOrSubquery exprOrSubquery) | #(NOT_BETWEEN exprOrSubquery exprOrSubquery exprOrSubquery) | #(IN exprOrSubquery inRhs ) | #(NOT_IN exprOrSubquery inRhs ) | #(IS_NULL exprOrSubquery) | #(IS_NOT_NULL exprOrSubquery)// | #(IS_TRUE expr)// | #(IS_FALSE expr) | #(EXISTS ( expr | collectionFunctionOrSubselect ) ) ) { prepareLogicOperator( #comparisonExpr ); } ;inRhs : #(IN_LIST ( collectionFunctionOrSubselect | ( (expr)* ) ) ) ;exprOrSubquery : expr | query | #(ANY collectionFunctionOrSubselect) | #(ALL collectionFunctionOrSubselect) | #(SOME collectionFunctionOrSubselect) ; collectionFunctionOrSubselect : collectionFunction | query ; expr : ae:addrExpr [ true ] { resolve(#ae); } // Resolve the top level 'address expression' | #( VECTOR_EXPR (expr)* ) | constant | arithmeticExpr | functionCall // Function call, not in the SELECT clause. | parameter | count // Count, not in the SELECT clause. ;arithmeticExpr : #(PLUS expr expr) { prepareArithmeticOperator( #arithmeticExpr ); } | #(MINUS expr expr) { prepareArithmeticOperator( #arithmeticExpr ); } | #(DIV expr expr) { prepareArithmeticOperator( #arithmeticExpr ); } | #(STAR expr expr) { prepareArithmeticOperator( #arithmeticExpr ); }// | #(CONCAT expr (expr)+ ) { prepareArithmeticOperator( #arithmeticExpr ); } | #(UNARY_MINUS expr) { prepareArithmeticOperator( #arithmeticExpr ); } | caseExpr ;caseExpr : #(CASE { inCase = true; } (#(WHEN logicalExpr expr))+ (#(ELSE expr))?) { inCase = false; } | #(CASE2 { inCase = true; } expr (#(WHEN expr expr))+ (#(ELSE expr))?) { inCase = false; } ;//TODO: I don't think we need this anymore .. how is it different to // maxelements, etc, which are handled by functionCallcollectionFunction : #(e:ELEMENTS {inFunctionCall=true;} p1:propertyRef { resolve(#p1); } ) { processFunction(#e,inSelect); } {inFunctionCall=false;} | #(i:INDICES {inFunctionCall=true;} p2:propertyRef { resolve(#p2); } ) { processFunction(#i,inSelect); } {inFunctionCall=false;} ;functionCall : #(METHOD_CALL {inFunctionCall=true;} pathAsIdent ( #(EXPR_LIST (expr)* ) )? ) { processFunction(#functionCall,inSelect); } {inFunctionCall=false;} | #(AGGREGATE aggregateExpr ) ;constant : literal | NULL | TRUE { processBoolean(#constant); } | FALSE { processBoolean(#constant); } | JAVA_CONSTANT ;literal : NUM_INT { processNumericLiteral( #literal ); } | NUM_LONG { processNumericLiteral( #literal ); } | NUM_FLOAT { processNumericLiteral( #literal ); } | NUM_DOUBLE { processNumericLiteral( #literal ); } | QUOTED_STRING ;identifier : (IDENT | WEIRD_IDENT) ;addrExpr! [ boolean root ] : #(d:DOT lhs:addrExprLhs rhs:propertyName ) { // This gives lookupProperty() a chance to transform the tree // to process collection properties (.elements, etc). #addrExpr = #(#d, #lhs, #rhs); #addrExpr = lookupProperty(#addrExpr,root,false); } | #(i:INDEX_OP lhs2:addrExprLhs rhs2:expr) { #addrExpr = #(#i, #lhs2, #rhs2); processIndex(#addrExpr); } | p:identifier {// #addrExpr = #p;// resolve(#addrExpr); // In many cases, things other than property-refs are recognized // by this addrExpr rule. Some of those I have seen: // 1) select-clause from-aliases // 2) sql-functions if ( isNonQualifiedPropertyRef(#p) ) { #addrExpr = lookupNonQualifiedProperty(#p); } else { resolve(#p); #addrExpr = #p; } } ;addrExprLhs : addrExpr [ false ] ;propertyName : identifier | CLASS | ELEMENTS | INDICES ;propertyRef! : #(d:DOT lhs:propertyRefLhs rhs:propertyName ) { // This gives lookupProperty() a chance to transform the tree to process collection properties (.elements, etc). #propertyRef = #(#d, #lhs, #rhs); #propertyRef = lookupProperty(#propertyRef,false,true); } | p:identifier { // In many cases, things other than property-refs are recognized // by this propertyRef rule. Some of those I have seen: // 1) select-clause from-aliases // 2) sql-functions if ( isNonQualifiedPropertyRef(#p) ) { #propertyRef = lookupNonQualifiedProperty(#p); } else { resolve(#p); #propertyRef = #p; } } ;propertyRefLhs : propertyRef ;aliasRef! : i:identifier { #aliasRef = #([ALIAS_REF,i.getText()]); // Create an ALIAS_REF node instead of an IDENT node. lookupAlias(#aliasRef); } ;parameter! : #(c:COLON a:identifier) { // Create a NAMED_PARAM node instead of (COLON IDENT). #parameter = generateNamedParameter( c, a );// #parameter = #([NAMED_PARAM,a.getText()]);// namedParameter(#parameter); } | #(p:PARAM (n:NUM_INT)?) { if ( n != null ) { // An ejb3-style "positional parameter", which we handle internally as a named-param #parameter = generateNamedParameter( p, n );// #parameter = #([NAMED_PARAM,n.getText()]);// namedParameter(#parameter); } else { #parameter = generatePositionalParameter( p );// #parameter = #([PARAM,"?"]);// positionalParameter(#parameter); } } ;numericInteger : NUM_INT ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -