Author: steve.ebersole(a)jboss.com
Date: 2009-02-09 13:30:53 -0500 (Mon, 09 Feb 2009)
New Revision: 15917
Added:
core/branches/SQL_GEN_REDESIGN/src/main/antlr/hql/resolve.g
Modified:
core/branches/SQL_GEN_REDESIGN/src/main/antlr/hql/normalize.g
core/branches/SQL_GEN_REDESIGN/src/main/antlr/hql/parse.g
core/branches/SQL_GEN_REDESIGN/src/main/antlr/sql/common.g
Log:
HHH-2407 : HQL translation rework ->
HHH-3687 : parse (phase1)
HHH-3688 : normalize (phase2)
Modified: core/branches/SQL_GEN_REDESIGN/src/main/antlr/hql/normalize.g
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/antlr/hql/normalize.g 2009-02-09 11:19:30 UTC
(rev 15916)
+++ core/branches/SQL_GEN_REDESIGN/src/main/antlr/hql/normalize.g 2009-02-09 18:30:53 UTC
(rev 15917)
@@ -63,6 +63,10 @@
tokens {
PROPERTY_REF;
+ INDEXED_COLLECTION_ACCESS_PERSISTER_REF;
+ INDEXED_COLLECTION_ELEMENT_REF;
+ ASSOCIATION_NAME;
+ INDEX_VALUE_CORRELATION;
}
@@ -70,16 +74,27 @@
{
private static Logger log = LoggerFactory.getLogger( GeneratedHqlNormalizer.class );
+ private AST currentFromClause;
+
private int ordinalParamCount = 0;
+ private int statementDepth = 0;
+ protected final int getStatementDepth() {
+ return statementDepth;
+ }
+ protected final boolean isSubquery() {
+ return statementDepth > 1;
+ }
+
+
// persister reference related actions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
protected AST normalizeEntityName(AST node) throws SemanticException {
throw new UnsupportedOperationException( "must be overridden!" );
}
- protected AST normalizeAlias(AST node) {
+ protected final AST normalizeAlias(AST node) {
if ( node != null ) {
return node;
}
@@ -133,6 +148,10 @@
throw new UnsupportedOperationException( "must be overridden!" );
}
+ protected AST normalizeUnqualifiedPropertyReferenceSource(AST propertyName) {
+ throw new UnsupportedOperationException( "must be overridden!" );
+ }
+
protected AST normalizeIndexedRoot(AST alias) {
throw new UnsupportedOperationException( "must be overridden!" );
}
@@ -145,103 +164,109 @@
throw new UnsupportedOperationException( "must be overridden!" );
}
+ protected AST normalizeIntermediateIndexOperation(AST collectionPath, AST selector)
throws SemanticException {
+ throw new UnsupportedOperationException( "must be overridden!" );
+ }
- // Statement node BEGIN/END handling ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ protected AST normalizeTerminalIndexOperation(AST collectionPath, AST selector)
throws SemanticException {
+ throw new UnsupportedOperationException( "must be overridden!" );
+ }
+ protected void applyWithFragment(AST withFragment) {
+ }
+
+
+ // Statement node BEGIN/END handling
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
protected void pushStatement(AST statementNode) {
+ throw new UnsupportedOperationException( "must be overridden!" );
}
protected void popStatement() {
+ throw new UnsupportedOperationException( "must be overridden!" );
}
- // property-path context pushing/popping ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // property-path context pushing/popping
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
protected void pushFromClausePropertyPathContext(AST joinType, AST fetch, AST alias, AST
propertyFetch) {
+ throw new UnsupportedOperationException( "must be overridden!" );
}
protected void popFromClausePropertyPathContext() {
+ throw new UnsupportedOperationException( "must be overridden!" );
}
protected void pushSelectClausePropertyPathContext() {
+ throw new UnsupportedOperationException( "must be overridden!" );
}
protected void popSelectClausePropertyPathContext() {
+ throw new UnsupportedOperationException( "must be overridden!" );
}
protected void pushOnFragmentPropertyPathContext(AST rhsPersisterReference) {
+ throw new UnsupportedOperationException( "must be overridden!" );
}
- protected void popOnFragmentPropertyPathContext() {
+ protected AST popOnFragmentPropertyPathContext() {
+ throw new UnsupportedOperationException( "must be overridden!" );
}
protected void pushWithFragmentPropertyPathContext(AST rhsPersisterReference) {
+ throw new UnsupportedOperationException( "must be overridden!" );
}
protected void popWithFragmentPropertyPathContext() {
+ throw new UnsupportedOperationException( "must be overridden!" );
}
-
-
// function processing
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
protected void startingFunction() {
+ throw new UnsupportedOperationException( "must be overridden!" );
}
protected void endingFunction() {
+ throw new UnsupportedOperationException( "must be overridden!" );
}
-
-
protected void registerSelectItem(AST selectItem) {
+ throw new UnsupportedOperationException( "must be overridden!" );
}
+ private void startQuerySpec(AST querySpecIn) {
+ statementDepth++;
+ applyCollectionFilter(querySpecIn);
+ }
+ private void endQuerySpec(AST querySpec) {
+ postProcessQuery( querySpec );
+ --statementDepth;
+ }
-
-
- protected AST resolveAlias(AST alias) {
- return alias;
- }
-
- /**
- * Validate the operands to the index operator '[]'. Specifically, the
left-hand operand should be a reference
- * to some form of indexed collection (map or list) and the right-hand operand should
be a value expression
- * whose type is the same as the indexed collection's index values.
- *
- * @param collectionPropertyReference The left-hand operand. Should resolve to an
indexed collection
- * @param selector the right-hand operand. Should resolve to a value type compatible
with the collection's
- * index type.
- */
- protected void validateIndexOperationOperands(AST collectionPropertyReference, AST
selector) {
+ protected void applyCollectionFilter(AST querySpecIn) {
+ throw new UnsupportedOperationException( "must be overridden!" );
}
-
- // persister reference handling ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- protected AST buildEntityPersisterReference(AST entityName, AST alias, AST
propertyFetch) {
- return entityName;
- }
-
- protected AST buildAdHocJoinNode(AST persisterReference, AST joinType, AST withFragment)
{
- return persisterReference;
- }
-
- protected void applyWithFragment(AST withFragment) {
- }
-
- protected void injectSelectAlias( AST selectExpression, AST alias) {
+ protected void postProcessQuery(AST query) {
+ throw new UnsupportedOperationException( "must be overridden!" );
}
- protected void registerSelectExpression(AST selectExpression) {
+ protected AST buildRootEntityPersisterReference(AST persisterReferenceNode, AST
entityName, AST alias, AST filter, AST propertyFetch) {
+ AST rtn = #( persisterReferenceNode, entityName, alias, filter );
+ registerPersisterReference( rtn );
+ if ( propertyFetch != null ) {
+ registerPropertyFetchNode( rtn );
+ }
+ return rtn;
}
- protected AST handleSelectedPropertyRef(AST propertyRef) {
- return propertyRef;
+ protected void registerPropertyFetchNode(AST persisterReference) {
+ throw new UnsupportedOperationException( "must be overridden!" );
}
-
}
// Statement rules
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -311,9 +336,9 @@
*/
insertStatement :
#(
- INSERT { pushStatement( #insertStatement ); }
- intoClause
- queryExpression { popStatement(); }
+ i:INSERT { pushStatement( #insertStatement ); }
+ ic:intoClause
+ qe:queryExpression { popStatement(); }
)
;
@@ -373,51 +398,52 @@
queryExpression
;
-querySpec :
- #( QUERY_SPEC selectFrom ( whereClause )? ( groupByClause ( havingClause )? )? )
+querySpec { startQuerySpec(#querySpec_in); } :
+ #( QUERY_SPEC selectFrom ( whereClause )? ( groupByClause ( havingClause )? )? ) {
endQuerySpec(#querySpec); }
;
selectFrom :
- #( SELECT_FROM fromClause (selectClause)? )
+ #( SELECT_FROM fromClause (sc:selectClause)? )
;
// table/persister related rules
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-fromClause :
- #( FROM (persisterSpace)+ )
+fromClause! :
+ #( f:FROM {currentFromClause=#f;} (persisterSpace)+ {currentFromClause=null;} ) {
+ #fromClause = #f;
+ }
;
-persisterSpace :
- #( PERSISTER_SPACE entityPersisterReference ( explicitJoin )* )
+persisterSpace! :
+ #( PERSISTER_SPACE pr:entityPersisterReference {currentFromClause.addChild( #pr );} (
explicitPersisterJoin | explicitPropertyJoin )* )
;
entityPersisterReference! :
- #( epr:ENTITY_PERSISTER_REF en:ENTITY_NAME (a:ALIAS)? (pf:PROP_FETCH)? ) {
-// #entityPersisterReference = buildEntityPersisterReference( en, a, pf );
- AST entityName = normalizeEntityName( #en );
- AST alias = normalizeAlias( #a );
- #entityPersisterReference = #( #epr, entityName, alias, #pf );
- registerPersisterReference( #entityPersisterReference );
+ #( epr:ENTITY_PERSISTER_REF en:ENTITY_NAME a:ALIAS (f:FILTER)? (pf:PROP_FETCH)? ) {
+ #entityPersisterReference = buildRootEntityPersisterReference(
+ #epr,
+ normalizeEntityName( #en ),
+ normalizeAlias( #a ),
+ #f,
+ #pf
+ );
}
;
-explicitJoin :
- explicitPersisterJoin
- | explicitPropertyJoin
-;
-
-explicitPersisterJoin :
+explicitPersisterJoin!:
#(
j:PERSISTER_JOIN (
- CROSS entityPersisterReference
- | qualifiedJoinType e:entityPersisterReference (on:onFragment[#e])?
+ CROSS cjpr:entityPersisterReference {
+ currentFromClause.addChild( #cjpr );
+ }
+ | jt:qualifiedJoinType rhs:entityPersisterReference
{pushOnFragmentPropertyPathContext(#rhs);} on:onFragment {
+ AST lhs = popOnFragmentPropertyPathContext();
+ lhs.addChild( #( #j, #jt, #rhs, #on ) );
+ }
)
- ) {
- #j.setType( JOIN );
- #j.setText( "join" );
- }
+ )
;
explicitPropertyJoin! :
@@ -429,10 +455,8 @@
| INNER
;
-onFragment[ AST rhsPersisterReference ] :
- #( o:ON { pushOnFragmentPropertyPathContext( rhsPersisterReference ); }
sc:searchCondition ) {
- #onFragment = #( o, sc );
- }
+onFragment :
+ #( o:ON sc:searchCondition )
;
withFragment[ AST rhsPropertyReference ] :
@@ -927,7 +951,7 @@
propertyReference :
(unqualifiedPropertyReferenceCheck) => unqualifiedPropertyReference
| pathedPropertyReference
- | indexOperation
+ | terminalIndexOperation
;
/**
@@ -973,7 +997,7 @@
(persisterReferenceAliasCheck) => a:IDENT { #pathedPropertyReferenceSource =
normalizeQualifiedRoot( #a ); }
| (unqualifiedPropertyReferenceCheck) => pr:IDENT { #pathedPropertyReferenceSource
= normalizeUnqualifiedRoot( #pr ); }
| intermediatePathedPropertyReference
- | i:indexOperation { #pathedPropertyReferenceSource = normalizeIndexedRoot( #i ); }
+ | intermediateIndexOperation
;
/**
@@ -986,31 +1010,31 @@
alias:IDENT { isPersisterReferenceAlias( alias ) }?
;
-/**
- * AST construction rule for building AST relating to *known*
- * persister reference aliases. Do not call this rule unless
- * you know for certain (ala, have verified via the persisterReferenceAliasCheck
- * rule or similiar) that the next token is an IDENT representing an
- * alias for a persister reference
- */
-persisterReferenceAlias! :
- alias:IDENT {
- #persisterReferenceAlias = resolveAlias( alias );
- }
-;
-
intermediatePathedPropertyReference! :
#( d:DOT source:pathedPropertyReferenceSource prop:IDENT ) {
#intermediatePathedPropertyReference = normalizePropertyPathIntermediary(
#source, #prop );
}
;
-indexOperation
- : #( i:INDEX_OP coll:collectionPropertyReference selector:indexSelector ) {
- validateIndexOperationOperands( #coll, #selector );
+intermediateIndexOperation! :
+ #( INDEX_OP collection:indexOperationSource selector:indexSelector ) {
+ #intermediateIndexOperation = normalizeIntermediateIndexOperation( #collection,
#selector );
}
- ;
+;
+terminalIndexOperation! :
+ #( INDEX_OP collection:indexOperationSource selector:indexSelector ) {
+ #terminalIndexOperation = normalizeTerminalIndexOperation( #collection, #selector
);
+ }
+;
+
+indexOperationSource :
+ #( DOT pathedPropertyReferenceSource IDENT )
+ | (unqualifiedPropertyReferenceCheck) => pr:IDENT {
+ #indexOperationSource = #( [DOT], normalizeUnqualifiedPropertyReferenceSource(
#pr ), #pr );
+ }
+;
+
indexSelector
: valueExpression
// | literal
Modified: core/branches/SQL_GEN_REDESIGN/src/main/antlr/hql/parse.g
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/antlr/hql/parse.g 2009-02-09 11:19:30 UTC (rev
15916)
+++ core/branches/SQL_GEN_REDESIGN/src/main/antlr/hql/parse.g 2009-02-09 18:30:53 UTC (rev
15917)
@@ -66,7 +66,7 @@
DYNAMIC_INSTANTIATION_ARG;
ENTITY_NAME;
ENTITY_PERSISTER_REF;
- FILTER_ENTITY;
+ FILTER;
GENERIC_FUNCTION;
INDEX_OP;
INSERTABILITY_SPEC;
@@ -258,9 +258,10 @@
// filter rules
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-filterStatement :
+filterStatement[String collectionRole] :
filteredSelectFrom (whereClause)? ( groupByClause ( havingClause )? )?
(orderByClause)? {
- #filterStatement = #( [QUERY,"query"], #filterStatement );
+ AST querySpec = #( [QUERY_SPEC, "filter-query-spec"], [FILTER,
collectionRole], #filterStatement );
+ #filterStatement = #( [QUERY,"query"], querySpec );
}
;
@@ -272,7 +273,7 @@
// Create an artificial token so the 'FROM' can be placed
// before the SELECT in the tree to make tree processing
// simpler.
- #filteredSelectFrom = #( [SELECT_FROM,"SELECT_FROM"], #f, #s );
+ #filteredSelectFrom = #( [SELECT_FROM,"select-from"], #f, #s );
}
;
@@ -372,7 +373,7 @@
*/
sortSpecification :
sortKey (collationSpecification)? (orderingSpecification)? {
- #sortSpecification = #( [SORT_SPEC, "{sort specification}"],
#sortSpecification );
+ #sortSpecification = #( [SORT_SPEC, "sort-specification"],
#sortSpecification );
}
;
@@ -427,7 +428,7 @@
// Create an artificial token so the 'FROM' can be placed
// before the SELECT in the tree to make tree processing
// simpler.
- #selectFrom = #( [SELECT_FROM,"SELECT_FROM"], f, s );
+ #selectFrom = #( [SELECT_FROM,"select-from"], f, s );
}
;
@@ -501,10 +502,10 @@
}
;
-crossJoin :
- CROSS j:JOIN^ {prepareForCrossJoinElements();} mainEntityPersisterReference {
- j.setType( PERSISTER_JOIN );
- j.setText( "persister-join" );
+crossJoin! :
+ c:CROSS j:JOIN {prepareForCrossJoinElements();} rhs:mainEntityPersisterReference {
+ #crossJoin = #( [PERSISTER_JOIN,"persister-join"], #c, rhs );
+ transferTrackingInfo( #j, #crossJoin );
}
;
Added: core/branches/SQL_GEN_REDESIGN/src/main/antlr/hql/resolve.g
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/antlr/hql/resolve.g
(rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/antlr/hql/resolve.g 2009-02-09 18:30:53 UTC
(rev 15917)
@@ -0,0 +1,854 @@
+header {
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ *
+ * Portions of SQL grammar parsing copyright (C) 2003 by Lubos Vnuk. All rights
+ * reserved. These portions are distributed under license by Red Hat Middleware
+ * LLC and are covered by the above LGPL notice. If you redistribute this material,
+ * with or without modification, you must preserve this copyright notice in its
+ * entirety.
+ */
+package org.hibernate.sql.ast.phase.hql.resolve;
+
+import antlr.collections.AST;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.hibernate.sql.ast.DetailedSemanticException;
+}
+
+/**
+ * An Antlr tree parser for "resolving" an HQL AST. Essentially here we are
concerned with creating a generic
+ * SQL AST.
+ *
+ * @author Joshua Davis
+ * @author Steve Ebersole
+ */
+class GeneratedHqlResolver extends TreeParser;
+
+options {
+ importVocab = HqlNormalize;
+ exportVocab = HqlResolve;
+ buildAST = true;
+}
+
+tokens {
+ COLUMN;
+ NAME;
+}
+
+
+{
+ private static Logger log = LoggerFactory.getLogger( GeneratedHqlResolver.class );
+
+ protected AST resolveEntityPersister(AST entityName, AST alias, AST filter) {
+ throw new UnsupportedOperationException( "must be overridden!" );
+ }
+
+ protected AST resolveCollectionPersister(AST collectionRole, AST alias) {
+ throw new UnsupportedOperationException( "must be overridden!" );
+ }
+
+ protected void applyPropertyJoin(AST lhs, AST rhs, AST propertyName, AST joinType,
AST with) {
+ throw new UnsupportedOperationException( "must be overridden!" );
+ }
+
+ protected AST generateIndexValueCondition(AST lhs, AST rhs, AST propertyName, AST
selector ) {
+ throw new UnsupportedOperationException( "must be overridden!" );
+ }
+
+ protected void appendSearchCondition(AST condition, AST container) {
+ if ( container.getFirstChild() == null ) {
+ container.setFirstChild( condition );
+ }
+ else {
+ AST and = #( [AND,"and"], container.getFirstChild() );
+ and.addChild( condition );
+ container.setFirstChild( and );
+ }
+ }
+
+ protected void applyVersionedUpdate(AST updateStatement) {
+ throw new UnsupportedOperationException( "must be overridden!" );
+ }
+
+ protected void postProcessQuery(AST whereClause) {
+ throw new UnsupportedOperationException( "must be overridden!" );
+ }
+
+ protected void startSelectClause() {
+ throw new UnsupportedOperationException( "must be overridden!" );
+ }
+
+ protected void finishSelectClause() {
+ throw new UnsupportedOperationException( "must be overridden!" );
+ }
+
+ protected void startFunction() {
+ throw new UnsupportedOperationException( "must be overridden!" );
+ }
+
+ protected void finishFunction() {
+ throw new UnsupportedOperationException( "must be overridden!" );
+ }
+
+ protected AST resolvePropertyReference(AST persisterAlias, AST propertyName) {
+ throw new UnsupportedOperationException( "must be overridden!" );
+ }
+
+ protected AST resolveAliasReference(AST aliasReference) {
+ throw new UnsupportedOperationException( "must be overridden!" );
+ }
+}
+
+
+// Statement rules
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+/**
+ * The main grammar rule
+ */
+statement :
+ updateStatement
+ | deleteStatement
+ | insertStatement
+ | selectStatement
+;
+
+
+// <tt>UPDATE</tt> statement
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+/**
+ * Recognize an <tt>UPDATE</tt> statement
+ */
+updateStatement :
+ #( u:UPDATE (v:VERSIONED)? en:ENTITY_NAME a:ALIAS setClause (whereClause)? ) {
+ if ( #v != null ) {
+ applyVersionedUpdate( #updateStatement );
+ }
+ }
+;
+
+setClause :
+ #( SET (assignment)+ )
+;
+
+assignment :
+ #( ASSIGNMENT_OP assignmentField newValue )
+;
+
+assignmentField :
+ propertyReference
+;
+
+newValue :
+ valueExpression
+;
+
+
+
+// <tt>DELETE</tt> statement
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+/**
+ * Recognize an HQL <tt>DELETE</tt> statement
+ */
+deleteStatement :
+ #( d:DELETE en:ENTITY_NAME a:ALIAS (whereClause)? )
+;
+
+
+// <tt>INSERT</tt> statement
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+/**
+ * Recognize an HQL <tt>INSERT</tt> statement
+ */
+insertStatement :
+ #( i:INSERT ic:intoClause qe:queryExpression )
+;
+
+intoClause :
+ #( INTO ENTITY_NAME insertabilitySpecification )
+;
+
+insertabilitySpecification :
+ #( INSERTABILITY_SPEC (insertablePropertySpecification)+ )
+;
+
+/**
+ * The property being inserted into.
+ */
+insertablePropertySpecification :
+ IDENT
+;
+
+
+// <tt>SELECT</tt> statement rules
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+/**
+ * Recognize an HQL <tt>SELECT</tt> statement.
+ * <p/>
+ * This corresponds most closely to the <cursor specification> rule in ISO/ANSI
SQL...
+ */
+selectStatement :
+ #( QUERY queryExpression (orderByClause)? )
+;
+
+orderByClause :
+ #( ORDER_BY (sortSpecification)+ )
+;
+
+sortSpecification :
+ #( SORT_SPEC sortKey (collationSpecification)? (orderingSpecification)? )
+;
+
+sortKey :
+ // todo : do we want to explicitly limit these?
+ valueExpression
+;
+
+collationSpecification :
+ COLLATE
+;
+
+orderingSpecification :
+ ORDER_SPEC
+;
+
+queryExpression :
+ querySpec ( ( UNION | INTERSECT | EXCEPT ) (ALL)? querySpec )*
+;
+
+subquery :
+ queryExpression
+;
+
+querySpec! :
+ #( qs:QUERY_SPEC #(SELECT_FROM f:fromClause s:selectClause) (w:whereClause)? (
g:groupByClause ( h:havingClause )? )? ) {
+ #querySpec = #( #qs, #s, #f, #w, #g, #h );
+ postProcessQuery( #querySpec );
+ }
+;
+
+
+selectFrom :
+ #( SELECT_FROM fromClause selectClause )
+;
+
+
+// table/persister related rules
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+fromClause :
+ #( FROM (entityPersisterReference)+ )
+;
+
+persisterReference :
+ entityPersisterReference
+ | collectionPersisterReference
+ | indexedCollectionElementPersisterReference
+;
+
+entityPersisterReference! {
+ AST lhs = null;
+} :
+ #( epr:ENTITY_PERSISTER_REF en:ENTITY_NAME a:ALIAS (f:FILTER)? { lhs =
resolveEntityPersister( #en, #a, #f ); } joins[lhs] ) {
+ #entityPersisterReference = lhs;
+ }
+;
+
+collectionPersisterReference! {
+ AST lhs = null;
+} :
+ #( COLLECTION_PERSISTER_REF cr:COLLECTION_ROLE a:ALIAS { lhs =
resolveCollectionPersister( #cr, #a ); } joins[lhs] ) {
+ #collectionPersisterReference = lhs;
+ }
+;
+
+indexedCollectionElementPersisterReference! {
+ AST lhs = null;
+} :
+ #( INDEXED_COLLECTION_ACCESS_PERSISTER_REF cr:COLLECTION_ROLE a:ALIAS { lhs =
resolveCollectionPersister( #cr, #a ); } indexSelector[lhs] joins[lhs] )
+;
+
+indexSelector[AST lhs] :
+ #( INDEX_VALUE_CORRELATION iv:selectedIndexValue )
+;
+
+selectedIndexValue! :
+ valueExpression
+;
+
+joins[AST lhs] :
+ ( persisterJoin[lhs] | propertyJoin[lhs] )*
+;
+
+persisterJoin![AST lhs] :
+ // NOTE : persister cross joins were mutated into root table references during
normalize.
+ #( PERSISTER_JOIN jt:correlatedJoinType rhs:entityPersisterReference
on:onFragment[lhs,rhs] ) {
+ lhs.addChild( #( [JOIN,"join"], #jt, #rhs, #on ) );
+ }
+;
+
+correlatedJoinType :
+ INNER
+ | LEFT
+ | RIGHT
+;
+
+onFragment[AST rhs, AST lhs] :
+ #( ON searchCondition )
+;
+
+propertyJoin![AST lhs] :
+ #( PROPERTY_JOIN jt:propertyJoinType pn:ASSOCIATION_NAME rhs:persisterReference
(w:withFragment[lhs,#rhs])? ) {
+ applyPropertyJoin( lhs, #rhs, #pn, #jt, #w );
+ }
+;
+
+propertyJoinType:
+ INNER
+ | LEFT
+;
+
+
+withFragment[AST lhs, AST rhs] :
+ #( w:WITH searchCondition )
+;
+
+
+// select clause related rules
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+// todo : we need to tighten down exactly what is allowed in the select clause here...
+// todo : additionally certain nodes need to be interpretted differently when in
select-clause versus other clauses:
+// think of an ALIAS_REF; in select-clause this should be expanded to the full
columns list; elsewhere to just the pk/fk
+
+// actually may need something more like a strategy based on context...
+
+selectClause :
+ #( SELECT {startSelectClause();} (d:DISTINCT)? rootSelectExpression
{finishSelectClause();} )
+;
+
+rootSelectExpression :
+ #( SELECT_LIST explicitSelectList )
+ | #( SELECT_ITEM rootDynamicInstantiation )
+;
+
+explicitSelectList :
+ ( explicitSelectItem )+
+;
+
+explicitSelectItem :
+ #( SELECT_ITEM selectExpression )
+;
+
+selectExpression :
+ valueExpression ( ALIAS )?
+;
+
+rootDynamicInstantiation :
+ #( DYNAMIC_INSTANTIATION dynamicInstantiationArguments )
+;
+
+nestedDynamicInstantiation :
+ #( DYNAMIC_INSTANTIATION dynamicInstantiationArguments (ALIAS)? )
+;
+
+dynamicInstantiationArguments :
+ ( dynamicInstantiationArgument )+
+;
+
+dynamicInstantiationArgument :
+ #( DYNAMIC_INSTANTIATION_ARG ( nestedDynamicInstantiation | selectExpression ) )
+;
+
+
+
+// where clause rules
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+whereClause :
+ #( WHERE searchCondition )
+;
+
+
+
+// group by clause rules
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+groupByClause :
+ #( GROUP_BY groupingSpecification )
+;
+
+groupingSpecification :
+ ( groupingValue )+
+;
+
+groupingValue :
+ valueExpression ( collationSpecification )?
+;
+
+
+
+// having clause related rules
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+havingClause :
+ #( HAVING searchCondition )
+;
+
+
+
+// value/expression recognition rules
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+numericValueExpression :
+ valueExpression
+;
+
+stringValueExpression :
+ characterValueExpression
+;
+
+characterValueExpression :
+ valueExpression
+;
+
+intervalValueExpression :
+ valueExpression
+;
+
+datetimeValueExpression :
+ valueExpression
+;
+
+valueExpression :
+ #( CONCATENATION_OP ARGLIST ( characterValueExpression )+ )
+ | #( UNARY_MINUS numericValueExpression )
+ | #( UNARY_PLUS numericValueExpression )
+ | #( PLUS_SIGN valueExpression valueExpression )
+ | #( MINUS_SIGN valueExpression valueExpression )
+ | #( ASTERISK numericValueExpression numericValueExpression )
+ | #( SOLIDUS numericValueExpression numericValueExpression )
+ | valueExpressionPrimary
+;
+
+valueExpressionPrimary :
+ persisterAliasReference
+ | caseExpression
+ | function
+ | collectionFunction
+ | collectionExpression
+ | literal
+ | parameter
+ | propertyReference
+;
+
+propertyReference! :
+ #( PROPERTY_REF a:ALIAS_REF pn:IDENT ) {
+ #propertyReference = resolvePropertyReference( #a, #pn );
+ }
+;
+
+nonCollectionPropertyReference :
+ pr:propertyReference
+;
+
+collectionPropertyReference :
+ pr:propertyReference
+;
+
+function {
+ startFunction();
+} :
+ ( standardFunction | setFunction ) {
+ finishFunction();
+ }
+;
+
+persisterAliasReference! :
+ a:ALIAS_REF {
+ #persisterAliasReference = resolveAliasReference( #a );
+ }
+;
+
+caseExpression :
+ caseAbbreviation
+ | caseSpecification
+;
+
+caseAbbreviation :
+ #( NULLIF valueExpression valueExpression )
+ | #( COALESCE ( valueExpression )+ )
+;
+
+caseSpecification :
+ simpleCase
+ | searchedCase
+;
+
+simpleCase :
+ #( SIMPLE_CASE valueExpression (simpleCaseWhenClause)+ (elseClause)? END )
+;
+
+simpleCaseWhenClause :
+ #( WHEN valueExpression THEN result )
+;
+
+result :
+ valueExpression
+;
+
+elseClause :
+ #( ELSE result )
+;
+
+searchedCase :
+ #( SEARCHED_CASE (searchedWhenClause)+ (elseClause)? END )
+;
+
+searchedWhenClause :
+ #( WHEN searchCondition THEN valueExpression )
+;
+
+standardFunction :
+ castFunction
+ | concatFunction
+ | substringFunction
+ | trimFunction
+ | upperFunction
+ | lowerFunction
+ | lengthFunction
+ | locateFunction
+ | absFunction
+ | sqrtFunction
+ | modFunction
+ | sizeFunction
+ | indexFunction
+ | currentDateFunction
+ | currentTimeFunction
+ | currentTimestampFunction
+ | extractFunction
+ | positionFunction
+ | charLengthFunction
+ | octetLengthFunction
+ | bitLengthFunction
+;
+
+castFunction :
+ #( CAST valueExpression dataType )
+;
+
+dataType :
+ // todo : temp...
+ IDENT
+;
+
+concatFunction :
+ #( CONCAT (valueExpression)* )
+;
+
+substringFunction :
+ #( SUBSTRING characterValueExpression numericValueExpression
(numericValueExpression)? )
+;
+
+trimFunction :
+ #( TRIM ( LEADING | TRAILING | BOTH ) CHAR_STRING characterValueExpression )
+;
+
+upperFunction :
+ #( UPPER characterValueExpression )
+;
+
+lowerFunction :
+ #( LOWER characterValueExpression )
+;
+
+lengthFunction :
+ #( LENGTH characterValueExpression )
+;
+
+locateFunction :
+ #( LOCATE characterValueExpression characterValueExpression (numericValueExpression)?
)
+;
+
+absFunction :
+ #( ABS numericValueExpression )
+;
+
+sqrtFunction :
+ #( SQRT numericValueExpression )
+;
+
+modFunction :
+ #( MOD numericValueExpression numericValueExpression )
+;
+
+sizeFunction :
+ #( SIZE collectionPropertyReference )
+;
+
+indexFunction :
+ #( INDEX ALIAS_REF )
+;
+
+currentDateFunction :
+ CURRENT_DATE
+;
+
+currentTimeFunction :
+ CURRENT_TIME
+;
+
+currentTimestampFunction :
+ CURRENT_TIMESTAMP
+;
+
+extractFunction :
+ #( EXTRACT extractField FROM extractSource )
+;
+
+extractField :
+ datetimeField
+ | timeZoneField
+;
+
+datetimeField :
+ nonSecondDatetimeField
+ | SECOND
+;
+
+timeZoneField :
+ TIMEZONE_HOUR
+ | TIMEZONE_MINUTE
+;
+
+extractSource :
+ datetimeValueExpression
+;
+
+positionFunction :
+ #( POSITION characterValueExpression characterValueExpression )
+;
+
+charLengthFunction :
+ #( CHAR_LENGTH characterValueExpression )
+ | #( CHARACTER_LENGTH characterValueExpression )
+;
+
+octetLengthFunction :
+ #( OCTET_LENGTH characterValueExpression )
+;
+
+bitLengthFunction :
+ #( BIT_LENGTH characterValueExpression )
+;
+
+setFunction :
+ #( SUM numericValueExpression )
+ | #( AVG numericValueExpression )
+ | #( MAX numericValueExpression )
+ | #( MIN numericValueExpression )
+ | #( COUNT ( ASTERISK | ( ( DISTINCT | ALL )? ( propertyReference | literal ) ) ) )
+;
+
+collectionFunction :
+ #( MAXELEMENT collectionPropertyReference )
+ | #( MAXINDEX collectionPropertyReference )
+ | #( MINELEMENT collectionPropertyReference )
+ | #( MININDEX collectionPropertyReference )
+;
+
+collectionExpression :
+ #( ELEMENTS collectionPropertyReference )
+ #( INDICES collectionPropertyReference )
+;
+
+parameter :
+ PARAM
+ | JPA_PARAM
+ | NAMED_PARAM
+;
+
+
+// literals
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+protected
+literal :
+ javaConstant
+ | numericLiteral
+ | characterLiteral
+ | dateLiteral
+ | timeLiteral
+ | timestampLiteral
+ | intervalLiteral
+;
+
+protected
+javaConstant :
+ JAVA_CONSTANT
+;
+
+protected
+numericLiteral :
+ UNSIGNED_INTEGER
+ | NUM_INT_LITERAL
+ | NUM_LONG_LITERAL
+ | NUM_DOUBLE_LITERAL
+ | NUM_FLOAT_LITERAL
+;
+
+protected
+characterLiteral :
+ CHAR_STRING
+ | NATIONAL_CHAR_STRING_LIT
+ | BIT_STRING_LIT
+ | HEX_STRING_LIT
+;
+
+protected
+dateLiteral :
+// #( DATE CHAR_STRING )
+ #( DATE characterValueExpression )
+;
+
+protected
+timeLiteral :
+// #( TIME CHAR_STRING )
+ #( TIME characterValueExpression )
+;
+
+protected
+timestampLiteral :
+// #( TIMESTAMP CHAR_STRING )
+ #( TIMESTAMP characterValueExpression )
+;
+
+protected
+intervalLiteral :
+ #( INTERVAL ( PLUS_SIGN | MINUS_SIGN )? CHAR_STRING intervalQualifier )
+// #( INTERVAL ( PLUS_SIGN | MINUS_SIGN )? characterValueExpression intervalQualifier
) -- characterValueExpression causes non-determinism with + and -
+;
+
+protected
+intervalQualifier :
+ #( YEAR (precision)? ( TO MONTH )? )
+ | #( MONTH (precision)? )
+ | #( DAY (precision)? ( TO ( HOUR | MINUTE | ( SECOND (scale)? ) ) )? )
+ | #( HOUR (precision)? ( TO ( MINUTE | SECOND (scale)? ) )? )
+ | #( MINUTE (precision)? ( TO SECOND (scale)? )? )
+ | #( SECOND ( precision (scale)? )? )
+;
+
+precision :
+ NUM_INT_LITERAL
+;
+
+scale :
+ NUM_INT_LITERAL
+;
+
+//protected
+//intervalStartField :
+// nonSecondDatetimeField ( LEFT_PAREN UNSIGNED_INTEGER RIGHT_PAREN )?
+//;
+//
+//protected
+//intervalEndField :
+// nonSecondDatetimeField
+// | SECOND ( LEFT_PAREN UNSIGNED_INTEGER RIGHT_PAREN )?
+//;
+
+protected
+nonSecondDatetimeField :
+ YEAR
+ | MONTH
+ | DAY
+ | HOUR
+ | MINUTE
+;
+
+
+
+// Search conditions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+/**
+ * Main logical/conditional rule defining boolean evaluated expressions
+ * <p/>
+ * This first level handles OR expressions
+ */
+searchCondition :
+ #( OR searchCondition searchCondition )
+ | #( AND searchCondition searchCondition )
+ | #( NOT searchCondition )
+ | predicate
+;
+
+predicate :
+ #( EQUALS_OP rowValueConstructor comparativePredicateValue )
+ | #( NOT_EQUALS_OP rowValueConstructor comparativePredicateValue )
+ | #( LESS_THAN_OP rowValueConstructor comparativePredicateValue )
+ | #( LESS_THAN_OR_EQUALS_OP rowValueConstructor comparativePredicateValue )
+ | #( GREATER_THAN_OP rowValueConstructor comparativePredicateValue )
+ | #( GREATER_THAN_OR_EQUALS_OP rowValueConstructor comparativePredicateValue )
+ | #( IS_NULL rowValueConstructor )
+ | #( IS_NOT_NULL rowValueConstructor )
+ | #( LIKE valueExpression valueExpression (escapeSpecification)? )
+ | #( NOT_LIKE valueExpression valueExpression (escapeSpecification)? )
+ | #( BETWEEN rowValueConstructor rowValueConstructor rowValueConstructor )
+ | #( NOT_BETWEEN rowValueConstructor rowValueConstructor rowValueConstructor )
+ | #( IN rowValueConstructor inPredicateValue )
+ | #( NOT_IN rowValueConstructor inPredicateValue )
+ | #( EXISTS (
+ queryExpression
+ | ( ELEMENTS | INDICES ) collectionPropertyReference
+ )
+ )
+;
+
+comparativePredicateValue :
+ rowValueConstructor
+ | ( ( SOME | ALL | ANY ) subquery )
+;
+
+escapeSpecification :
+ #( ESCAPE characterValueExpression )
+;
+
+inPredicateValue :
+ #(
+ IN_LIST (
+ queryExpression
+ | ( valueExpression )+
+ )
+ )
+;
+
+rowValueConstructor :
+ ( LEFT_PAREN ) => ( LEFT_PAREN rowValueConstructorList RIGHT_PAREN )
+ | rowValueConstructorElement
+;
+
+rowValueConstructorElement :
+ valueExpression
+ | NULL
+ | DEFAULT
+;
+
+rowValueConstructorList :
+ rowValueConstructorElement ( COMMA! rowValueConstructorElement )*
+;
Modified: core/branches/SQL_GEN_REDESIGN/src/main/antlr/sql/common.g
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/antlr/sql/common.g 2009-02-09 11:19:30 UTC
(rev 15916)
+++ core/branches/SQL_GEN_REDESIGN/src/main/antlr/sql/common.g 2009-02-09 18:30:53 UTC
(rev 15917)
@@ -36,6 +36,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+
+import org.hibernate.util.StringHelper;
}
/**
@@ -197,6 +199,8 @@
ORDER_BY;
GROUP_BY;
+ ROW_VALUE_CONSTRUCTOR_LIST;
+
// synthetic numeric literal types
NUM_INT_LITERAL;
NUM_LONG_LITERAL;
@@ -235,8 +239,39 @@
{
private static final Logger log = LoggerFactory.getLogger(
CommonHibernateParserSupport.class );
- // Grammar actions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ private int traceDepth = 0;
+ /**
+ * {@inheritDoc}
+ */
+ public void traceIn(String s) throws TokenStreamException {
+ if ( inputState.guessing > 0 ) {
+ return;
+ }
+ String prefix = StringHelper.repeat( "-", (traceDepth++ * 2) ) +
"->";
+ traceExecution( prefix + s );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void traceOut(String s) throws TokenStreamException {
+ if ( inputState.guessing > 0 ) {
+ return;
+ }
+ String prefix = "<-" + StringHelper.repeat( "-", (--traceDepth *
2) );
+ traceExecution( prefix + s );
+ }
+
+ /**
+ * Perform trace logging. Called from both {@link #traceIn} and {@link #traceOut}.
+ *
+ * @param msg The trace string
+ */
+ protected void traceExecution(String msg) {
+ log.trace( msg );
+ }
+
public void showAST(AST ast) {
showAST( ast, "AST" );
}