mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-08 20:24:46 +00:00
HHH-13778: @OrderBy
handling using SQL AST
- initial work - Antlr grammar, parse tree visitation and building OrderByFragment (translation) tree - fixed bug in HQL parsing - was building an unnecessary HqlLexer instance
This commit is contained in:
parent
8c671d98d0
commit
8600058784
@ -289,9 +289,10 @@ test {
|
|||||||
|
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// Custom Antlr v4 Plugin
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// - the Gradle-supplied Antlr plugin attempts to simultaneously support
|
||||||
// Custom Antlr v4 Plugin (to work with Gradle 3)
|
// multiple versions of Antlr which leads to many difficulties. this custom
|
||||||
|
// plugin provides dedicated and simplified support for Antlr v4
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
baseAntlrInputPath = 'src/main/antlr'
|
baseAntlrInputPath = 'src/main/antlr'
|
||||||
@ -354,6 +355,7 @@ class Antlr4GenerationTask extends DefaultTask {
|
|||||||
static final String HQL_PCKG = 'org.hibernate.query.hql.internal'
|
static final String HQL_PCKG = 'org.hibernate.query.hql.internal'
|
||||||
static final String IMPORT_SQL_PCKG = 'org.hibernate.tool.hbm2ddl.grammar'
|
static final String IMPORT_SQL_PCKG = 'org.hibernate.tool.hbm2ddl.grammar'
|
||||||
static final String GRAPH_PCKG = 'org.hibernate.graph.internal.parse'
|
static final String GRAPH_PCKG = 'org.hibernate.graph.internal.parse'
|
||||||
|
static final String ORDER_PCKG = 'org.hibernate.grammars.ordering'
|
||||||
|
|
||||||
List<GrammarDescriptor> grammarDescriptors = [
|
List<GrammarDescriptor> grammarDescriptors = [
|
||||||
new GrammarDescriptor( HQL_PCKG, 'HqlLexer' ),
|
new GrammarDescriptor( HQL_PCKG, 'HqlLexer' ),
|
||||||
@ -361,7 +363,9 @@ class Antlr4GenerationTask extends DefaultTask {
|
|||||||
new GrammarDescriptor( IMPORT_SQL_PCKG, 'SqlStatementLexer' ),
|
new GrammarDescriptor( IMPORT_SQL_PCKG, 'SqlStatementLexer' ),
|
||||||
new GrammarDescriptor( IMPORT_SQL_PCKG, 'SqlStatementParser' ),
|
new GrammarDescriptor( IMPORT_SQL_PCKG, 'SqlStatementParser' ),
|
||||||
new GrammarDescriptor( GRAPH_PCKG, 'GraphLanguageLexer' ),
|
new GrammarDescriptor( GRAPH_PCKG, 'GraphLanguageLexer' ),
|
||||||
new GrammarDescriptor( GRAPH_PCKG, 'GraphLanguageParser' )
|
new GrammarDescriptor( GRAPH_PCKG, 'GraphLanguageParser' ),
|
||||||
|
new GrammarDescriptor( ORDER_PCKG, 'OrderingLexer' ),
|
||||||
|
new GrammarDescriptor( ORDER_PCKG, 'OrderingParser' )
|
||||||
]
|
]
|
||||||
|
|
||||||
@InputFiles
|
@InputFiles
|
||||||
|
@ -1,97 +0,0 @@
|
|||||||
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
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.hibernate.sql.ordering.antlr;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Antlr grammar for rendering <tt>ORDER_BY</tt> trees as described by the {@link OrderByFragmentParser}
|
|
||||||
|
|
||||||
* @author Steve Ebersole
|
|
||||||
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
|
||||||
*/
|
|
||||||
class GeneratedOrderByFragmentRenderer extends TreeParser;
|
|
||||||
|
|
||||||
options {
|
|
||||||
importVocab=OrderByTemplate;
|
|
||||||
buildAST=false;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// the buffer to which we write the resulting SQL.
|
|
||||||
private StringBuilder buffer = new StringBuilder();
|
|
||||||
|
|
||||||
protected void out(String text) {
|
|
||||||
buffer.append( text );
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void out(AST ast) {
|
|
||||||
buffer.append( ast.getText() );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ String getRenderedFragment() {
|
|
||||||
return buffer.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation note: This is just a stub. OrderByFragmentRenderer contains the effective implementation.
|
|
||||||
*/
|
|
||||||
protected String renderOrderByElement(String expression, String collation, String order, String nulls) {
|
|
||||||
throw new UnsupportedOperationException("Concrete ORDER BY renderer should override this method.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
orderByFragment
|
|
||||||
: #(
|
|
||||||
ORDER_BY sortSpecification ( {out(", ");} sortSpecification)*
|
|
||||||
)
|
|
||||||
;
|
|
||||||
|
|
||||||
sortSpecification { String sortKeySpec = null; String collSpec = null; String ordSpec = null; String nullOrd = null; }
|
|
||||||
: #(
|
|
||||||
SORT_SPEC sortKeySpec=sortKeySpecification (collSpec=collationSpecification)? (ordSpec=orderingSpecification)? (nullOrd=nullOrdering)?
|
|
||||||
{ out( renderOrderByElement( sortKeySpec, collSpec, ordSpec, nullOrd ) ); }
|
|
||||||
)
|
|
||||||
;
|
|
||||||
|
|
||||||
sortKeySpecification returns [String sortKeyExp = null]
|
|
||||||
: #(SORT_KEY s:sortKey) { sortKeyExp = #s.getText(); }
|
|
||||||
;
|
|
||||||
|
|
||||||
sortKey
|
|
||||||
: IDENT
|
|
||||||
;
|
|
||||||
|
|
||||||
collationSpecification returns [String collSpecExp = null]
|
|
||||||
: c:COLLATE { collSpecExp = "collate " + #c.getText(); }
|
|
||||||
;
|
|
||||||
|
|
||||||
orderingSpecification returns [String ordSpecExp = null]
|
|
||||||
: o:ORDER_SPEC { ordSpecExp = #o.getText(); }
|
|
||||||
;
|
|
||||||
|
|
||||||
nullOrdering returns [String nullOrdExp = null]
|
|
||||||
: n:NULL_ORDER { nullOrdExp = #n.getText(); }
|
|
||||||
;
|
|
@ -1,469 +0,0 @@
|
|||||||
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
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.hibernate.sql.ordering.antlr;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Antlr grammar for dealing with <tt>order-by</tt> mapping fragments.
|
|
||||||
|
|
||||||
* @author Steve Ebersole
|
|
||||||
*/
|
|
||||||
class GeneratedOrderByFragmentParser extends Parser;
|
|
||||||
|
|
||||||
options
|
|
||||||
{
|
|
||||||
exportVocab=OrderByTemplate;
|
|
||||||
buildAST=true;
|
|
||||||
k=3;
|
|
||||||
}
|
|
||||||
|
|
||||||
tokens
|
|
||||||
{
|
|
||||||
// synthetic tokens
|
|
||||||
ORDER_BY;
|
|
||||||
SORT_SPEC;
|
|
||||||
ORDER_SPEC;
|
|
||||||
NULL_ORDER;
|
|
||||||
SORT_KEY;
|
|
||||||
EXPR_LIST;
|
|
||||||
DOT;
|
|
||||||
IDENT_LIST;
|
|
||||||
COLUMN_REF;
|
|
||||||
|
|
||||||
COLLATE="collate";
|
|
||||||
ASCENDING="asc";
|
|
||||||
DESCENDING="desc";
|
|
||||||
NULLS="nulls";
|
|
||||||
FIRST;
|
|
||||||
LAST;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Method for logging execution trace information.
|
|
||||||
*
|
|
||||||
* @param msg The trace message.
|
|
||||||
*/
|
|
||||||
@org.hibernate.internal.build.AllowSysOut
|
|
||||||
protected void trace(String msg) {
|
|
||||||
System.out.println( msg );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract a node's text.
|
|
||||||
*
|
|
||||||
* @param ast The node
|
|
||||||
*
|
|
||||||
* @return The text.
|
|
||||||
*/
|
|
||||||
protected final String extractText(AST ast) {
|
|
||||||
// for some reason, within AST creation blocks "[]" I am sometimes unable to refer to the AST.getText() method
|
|
||||||
// using #var (the #var is not interpreted as the rule's output AST).
|
|
||||||
return ast.getText();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process the given node as a quote identifier. These need to be quoted in the dialect-specific way.
|
|
||||||
*
|
|
||||||
* @param ident The quoted-identifier node.
|
|
||||||
*
|
|
||||||
* @return The processed node.
|
|
||||||
*
|
|
||||||
* @see org.hibernate.dialect.Dialect#quote
|
|
||||||
*/
|
|
||||||
protected AST quotedIdentifier(AST ident) {
|
|
||||||
return ident;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process the given node as a quote string.
|
|
||||||
*
|
|
||||||
* @param ident The quoted string. This is used from within function param recognition, and represents a
|
|
||||||
* SQL-quoted string.
|
|
||||||
*
|
|
||||||
* @return The processed node.
|
|
||||||
*/
|
|
||||||
protected AST quotedString(AST ident) {
|
|
||||||
return ident;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A check to see if the text of the given node represents a known function name.
|
|
||||||
*
|
|
||||||
* @param ast The node whose text we want to check.
|
|
||||||
*
|
|
||||||
* @return True if the node's text is a known function name, false otherwise.
|
|
||||||
*
|
|
||||||
* @see org.hibernate.dialect.function.SQLFunctionRegistry
|
|
||||||
*/
|
|
||||||
protected boolean isFunctionName(AST ast) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process the given node as a function.
|
|
||||||
*
|
|
||||||
* @param The node representing the function invocation (including parameters as subtree components).
|
|
||||||
*
|
|
||||||
* @return The processed node.
|
|
||||||
*/
|
|
||||||
protected AST resolveFunction(AST ast) {
|
|
||||||
return ast;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process the given node as an IDENT. May represent either a column reference or a property reference.
|
|
||||||
*
|
|
||||||
* @param ident The node whose text represents either a column or property reference.
|
|
||||||
*
|
|
||||||
* @return The processed node.
|
|
||||||
*/
|
|
||||||
protected AST resolveIdent(AST ident) {
|
|
||||||
return ident;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allow post processing of each <tt>sort specification</tt>
|
|
||||||
*
|
|
||||||
* @param The grammar-built sort specification subtree.
|
|
||||||
*
|
|
||||||
* @return The processed sort specification subtree.
|
|
||||||
*/
|
|
||||||
protected AST postProcessSortSpecification(AST sortSpec) {
|
|
||||||
return sortSpec;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Main recognition rule for this grammar
|
|
||||||
*/
|
|
||||||
orderByFragment { trace("orderByFragment"); }
|
|
||||||
: sortSpecification ( COMMA! sortSpecification )* {
|
|
||||||
#orderByFragment = #( [ORDER_BY, "order-by"], #orderByFragment );
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recognition rule for what ANSI SQL terms the <tt>sort specification</tt>, which is essentially each thing upon which
|
|
||||||
* the results should be sorted.
|
|
||||||
*/
|
|
||||||
sortSpecification { trace("sortSpecification"); }
|
|
||||||
: sortKey (collationSpecification)? (orderingSpecification)? (nullOrdering)? {
|
|
||||||
#sortSpecification = #( [SORT_SPEC, "{sort specification}"], #sortSpecification );
|
|
||||||
#sortSpecification = postProcessSortSpecification( #sortSpecification );
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recognition rule for what ANSI SQL terms the <tt>sort key</tt> which is the expression (column, function, etc) upon
|
|
||||||
* which to base the sorting.
|
|
||||||
*/
|
|
||||||
sortKey! { trace("sortKey"); }
|
|
||||||
: e:expression {
|
|
||||||
#sortKey = #( [SORT_KEY, "sort key"], #e );
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recognition rule what this grammar recognizes as valid <tt>sort key</tt>.
|
|
||||||
*/
|
|
||||||
expression! { trace("expression"); }
|
|
||||||
: HARD_QUOTE qi:IDENT HARD_QUOTE {
|
|
||||||
#expression = quotedIdentifier( #qi );
|
|
||||||
}
|
|
||||||
| ( IDENT (DOT IDENT)* OPEN_PAREN ) => f:functionCall {
|
|
||||||
#expression = #f;
|
|
||||||
}
|
|
||||||
| p:simplePropertyPath {
|
|
||||||
#expression = resolveIdent( #p );
|
|
||||||
}
|
|
||||||
| i:IDENT {
|
|
||||||
if ( isFunctionName( #i ) ) {
|
|
||||||
#expression = resolveFunction( #i );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
#expression = resolveIdent( #i );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Intended for use as a syntactic predicate to determine whether an IDENT represents a known SQL function name.
|
|
||||||
*/
|
|
||||||
functionCallCheck! { trace("functionCallCheck"); }
|
|
||||||
: IDENT (DOT IDENT)* OPEN_PAREN { true }?
|
|
||||||
;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recognition rule for a function call
|
|
||||||
*/
|
|
||||||
functionCall! { trace("functionCall"); }
|
|
||||||
: fn:functionName OPEN_PAREN pl:functionParameterList CLOSE_PAREN {
|
|
||||||
#functionCall = #( [IDENT, extractText( #fn )], #pl );
|
|
||||||
#functionCall = resolveFunction( #functionCall );
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A function-name is an IDENT followed by zero or more (DOT IDENT) sequences
|
|
||||||
*/
|
|
||||||
functionName {
|
|
||||||
trace("functionName");
|
|
||||||
StringBuilder buffer = new StringBuilder();
|
|
||||||
}
|
|
||||||
: i:IDENT { buffer.append( i.getText() ); }
|
|
||||||
( DOT i2:IDENT { buffer.append( '.').append( i2.getText() ); } )* {
|
|
||||||
#functionName = #( [IDENT,buffer.toString()] );
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recognition rule used to "wrap" all function parameters into an EXPR_LIST node
|
|
||||||
*/
|
|
||||||
functionParameterList { trace("functionParameterList"); }
|
|
||||||
: functionParameter ( COMMA! functionParameter )* {
|
|
||||||
#functionParameterList = #( [EXPR_LIST, "{param list}"], #functionParameterList );
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recognized function parameters.
|
|
||||||
*/
|
|
||||||
functionParameter { trace("functionParameter"); }
|
|
||||||
: expression
|
|
||||||
| NUM_DOUBLE
|
|
||||||
| NUM_FLOAT
|
|
||||||
| NUM_INT
|
|
||||||
| NUM_LONG
|
|
||||||
| QUOTED_STRING {
|
|
||||||
#functionParameter = quotedString( #functionParameter );
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recognition rule for what ANSI SQL terms the <tt>collation specification</tt> used to allow specifying that sorting for
|
|
||||||
* the given {@link #sortSpecification} be treated within a specific character-set.
|
|
||||||
*/
|
|
||||||
collationSpecification! { trace("collationSpecification"); }
|
|
||||||
: c:COLLATE cn:collationName {
|
|
||||||
#collationSpecification = #( [COLLATE, extractText( #cn )] );
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The collation name wrt {@link #collationSpecification}. Namely, the character-set.
|
|
||||||
*/
|
|
||||||
collationName { trace("collationSpecification"); }
|
|
||||||
: IDENT
|
|
||||||
;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recognition rule for what ANSI SQL terms the <tt>ordering specification</tt>; <tt>ASCENDING</tt> or
|
|
||||||
* <tt>DESCENDING</tt>.
|
|
||||||
*/
|
|
||||||
orderingSpecification! { trace("orderingSpecification"); }
|
|
||||||
: ( "asc" | "ascending" ) {
|
|
||||||
#orderingSpecification = #( [ORDER_SPEC, "asc"] );
|
|
||||||
}
|
|
||||||
| ( "desc" | "descending") {
|
|
||||||
#orderingSpecification = #( [ORDER_SPEC, "desc"] );
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recognition rule for what SQL-2003 terms the <tt>null ordering</tt>; <tt>NULLS FIRST</tt> or
|
|
||||||
* <tt>NULLS LAST</tt>.
|
|
||||||
*/
|
|
||||||
nullOrdering! { trace("nullOrdering"); }
|
|
||||||
: NULLS n:nullPrecedence {
|
|
||||||
#nullOrdering = #( [NULL_ORDER, extractText( #n )] );
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
nullPrecedence { trace("nullPrecedence"); }
|
|
||||||
: IDENT {
|
|
||||||
if ( "first".equalsIgnoreCase( #nullPrecedence.getText() ) ) {
|
|
||||||
#nullPrecedence.setType( FIRST );
|
|
||||||
}
|
|
||||||
else if ( "last".equalsIgnoreCase( #nullPrecedence.getText() ) ) {
|
|
||||||
#nullPrecedence.setType( LAST );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new SemanticException( "Expecting 'first' or 'last', but found '" + #nullPrecedence.getText() + "' as null ordering precedence." );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A simple-property-path is an IDENT followed by one or more (DOT IDENT) sequences
|
|
||||||
*/
|
|
||||||
simplePropertyPath {
|
|
||||||
trace("simplePropertyPath");
|
|
||||||
StringBuilder buffer = new StringBuilder();
|
|
||||||
}
|
|
||||||
: i:IDENT { buffer.append( i.getText() ); }
|
|
||||||
( DOT i2:IDENT { buffer.append( '.').append( i2.getText() ); } )+ {
|
|
||||||
#simplePropertyPath = #( [IDENT,buffer.toString()] );
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
// **** LEXER ******************************************************************
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Lexer for the <tt>order-by</tt> fragment parser
|
|
||||||
|
|
||||||
* @author Steve Ebersole
|
|
||||||
* @author Joshua Davis
|
|
||||||
*/
|
|
||||||
class GeneratedOrderByLexer extends Lexer;
|
|
||||||
|
|
||||||
options {
|
|
||||||
exportVocab=OrderByTemplate;
|
|
||||||
testLiterals = false;
|
|
||||||
k=2;
|
|
||||||
charVocabulary='\u0000'..'\uFFFE'; // Allow any char but \uFFFF (16 bit -1, ANTLR's EOF character)
|
|
||||||
caseSensitive = false;
|
|
||||||
caseSensitiveLiterals = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- Keywords --
|
|
||||||
|
|
||||||
OPEN_PAREN: '(';
|
|
||||||
CLOSE_PAREN: ')';
|
|
||||||
|
|
||||||
COMMA: ',';
|
|
||||||
|
|
||||||
HARD_QUOTE: '`';
|
|
||||||
|
|
||||||
IDENT options { testLiterals=true; }
|
|
||||||
: ID_START_LETTER ( ID_LETTER )*
|
|
||||||
;
|
|
||||||
|
|
||||||
protected
|
|
||||||
ID_START_LETTER
|
|
||||||
: '_'
|
|
||||||
| '$'
|
|
||||||
| 'a'..'z'
|
|
||||||
| '\u0080'..'\ufffe' // HHH-558 : Allow unicode chars in identifiers
|
|
||||||
;
|
|
||||||
|
|
||||||
protected
|
|
||||||
ID_LETTER
|
|
||||||
: ID_START_LETTER
|
|
||||||
| '0'..'9'
|
|
||||||
;
|
|
||||||
|
|
||||||
QUOTED_STRING
|
|
||||||
: '\'' ( (ESCqs)=> ESCqs | ~'\'' )* '\''
|
|
||||||
;
|
|
||||||
|
|
||||||
protected
|
|
||||||
ESCqs
|
|
||||||
:
|
|
||||||
'\'' '\''
|
|
||||||
;
|
|
||||||
|
|
||||||
//--- From the Java example grammar ---
|
|
||||||
// a numeric literal
|
|
||||||
NUM_INT
|
|
||||||
{boolean isDecimal=false; Token t=null;}
|
|
||||||
: '.' {_ttype = DOT;}
|
|
||||||
( ('0'..'9')+ (EXPONENT)? (f1:FLOAT_SUFFIX {t=f1;})?
|
|
||||||
{
|
|
||||||
if (t != null && t.getText().toUpperCase().indexOf('F')>=0)
|
|
||||||
{
|
|
||||||
_ttype = NUM_FLOAT;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_ttype = NUM_DOUBLE; // assume double
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)?
|
|
||||||
| ( '0' {isDecimal = true;} // special case for just '0'
|
|
||||||
( ('x')
|
|
||||||
( // hex
|
|
||||||
// the 'e'|'E' and float suffix stuff look
|
|
||||||
// like hex digits, hence the (...)+ doesn't
|
|
||||||
// know when to stop: ambig. ANTLR resolves
|
|
||||||
// it correctly by matching immediately. It
|
|
||||||
// is therefore ok to hush warning.
|
|
||||||
options { warnWhenFollowAmbig=false; }
|
|
||||||
: HEX_DIGIT
|
|
||||||
)+
|
|
||||||
| ('0'..'7')+ // octal
|
|
||||||
)?
|
|
||||||
| ('1'..'9') ('0'..'9')* {isDecimal=true;} // non-zero decimal
|
|
||||||
)
|
|
||||||
( ('l') { _ttype = NUM_LONG; }
|
|
||||||
|
|
||||||
// only check to see if it's a float if looks like decimal so far
|
|
||||||
| {isDecimal}?
|
|
||||||
( '.' ('0'..'9')* (EXPONENT)? (f2:FLOAT_SUFFIX {t=f2;})?
|
|
||||||
| EXPONENT (f3:FLOAT_SUFFIX {t=f3;})?
|
|
||||||
| f4:FLOAT_SUFFIX {t=f4;}
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (t != null && t.getText().toUpperCase() .indexOf('F') >= 0)
|
|
||||||
{
|
|
||||||
_ttype = NUM_FLOAT;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_ttype = NUM_DOUBLE; // assume double
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)?
|
|
||||||
;
|
|
||||||
|
|
||||||
// hexadecimal digit (again, note it's protected!)
|
|
||||||
protected
|
|
||||||
HEX_DIGIT
|
|
||||||
: ('0'..'9'|'a'..'f')
|
|
||||||
;
|
|
||||||
|
|
||||||
// a couple protected methods to assist in matching floating point numbers
|
|
||||||
protected
|
|
||||||
EXPONENT
|
|
||||||
: ('e') ('+'|'-')? ('0'..'9')+
|
|
||||||
;
|
|
||||||
|
|
||||||
protected
|
|
||||||
FLOAT_SUFFIX
|
|
||||||
: 'f'|'d'
|
|
||||||
;
|
|
||||||
|
|
||||||
WS : ( ' '
|
|
||||||
| '\t'
|
|
||||||
| '\r' '\n' { newline(); }
|
|
||||||
| '\n' { newline(); }
|
|
||||||
| '\r' { newline(); }
|
|
||||||
)
|
|
||||||
{$setType(Token.SKIP);} //ignore this token
|
|
||||||
;
|
|
3
hibernate-core/src/main/antlr/org/hibernate/.gitignore
vendored
Normal file
3
hibernate-core/src/main/antlr/org/hibernate/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Ignore the `*.tokens` file generated by Antlr when running its grammar generation tool
|
||||||
|
|
||||||
|
*.tokens
|
@ -0,0 +1,133 @@
|
|||||||
|
lexer grammar OrderingLexer;
|
||||||
|
|
||||||
|
|
||||||
|
@header {
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.grammars.ordering;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// Whitespace -> ignore
|
||||||
|
WS : ( ' ' | '\t' | '\f' | EOL ) -> skip;
|
||||||
|
|
||||||
|
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// fragments and literals
|
||||||
|
|
||||||
|
fragment
|
||||||
|
EOL : [\r\n]+;
|
||||||
|
|
||||||
|
INTEGER_LITERAL : INTEGER_NUMBER ;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
INTEGER_NUMBER : ('0' | '1'..'9' '0'..'9'*) ;
|
||||||
|
|
||||||
|
LONG_LITERAL : INTEGER_NUMBER ('l'|'L');
|
||||||
|
|
||||||
|
BIG_INTEGER_LITERAL : INTEGER_NUMBER ('bi'|'BI') ;
|
||||||
|
|
||||||
|
HEX_LITERAL : '0' ('x'|'X') HEX_DIGIT+ ('l'|'L')? ;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;
|
||||||
|
|
||||||
|
OCTAL_LITERAL : '0' ('0'..'7')+ ('l'|'L')? ;
|
||||||
|
|
||||||
|
FLOAT_LITERAL : FLOATING_POINT_NUMBER ('f'|'F')? ;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
FLOATING_POINT_NUMBER
|
||||||
|
: ('0'..'9')+ '.' ('0'..'9')* EXPONENT?
|
||||||
|
| '.' ('0'..'9')+ EXPONENT?
|
||||||
|
| ('0'..'9')+ EXPONENT
|
||||||
|
| ('0'..'9')+
|
||||||
|
;
|
||||||
|
|
||||||
|
DOUBLE_LITERAL : FLOATING_POINT_NUMBER ('d'|'D') ;
|
||||||
|
|
||||||
|
BIG_DECIMAL_LITERAL : FLOATING_POINT_NUMBER ('bd'|'BD') ;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
EXPONENT : ('e'|'E') ('+'|'-')? ('0'..'9')+ ;
|
||||||
|
|
||||||
|
CHARACTER_LITERAL
|
||||||
|
: '\'' ( ESCAPE_SEQUENCE | ~('\''|'\\') ) '\'' {setText(getText().substring(1, getText().length()-1));}
|
||||||
|
;
|
||||||
|
|
||||||
|
STRING_LITERAL
|
||||||
|
: '"' ( ESCAPE_SEQUENCE | ~('\\'|'"') )* '"' {setText(getText().substring(1, getText().length()-1));}
|
||||||
|
| ('\'' ( ESCAPE_SEQUENCE | ~('\\'|'\'') )* '\'')+ {setText(getText().substring(1, getText().length()-1).replace("''", "'"));}
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
ESCAPE_SEQUENCE
|
||||||
|
: '\\' ('b'|'t'|'n'|'f'|'r'|'\\"'|'\''|'\\')
|
||||||
|
| UNICODE_ESCAPE
|
||||||
|
| OCTAL_ESCAPE
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
OCTAL_ESCAPE
|
||||||
|
: '\\' ('0'..'3') ('0'..'7') ('0'..'7')
|
||||||
|
| '\\' ('0'..'7') ('0'..'7')
|
||||||
|
| '\\' ('0'..'7')
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
UNICODE_ESCAPE
|
||||||
|
: '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// collation
|
||||||
|
COLLATE : [cC] [oO] [lL] [lL] [aA] [tT] [eE];
|
||||||
|
|
||||||
|
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// NULL precedence
|
||||||
|
|
||||||
|
NULLS : 'NULLS' | 'nulls';
|
||||||
|
FIRST : 'FIRST' | 'first';
|
||||||
|
LAST : 'LAST' | 'last';
|
||||||
|
|
||||||
|
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// direction
|
||||||
|
|
||||||
|
ASC : [aA] [sS] [cC] ( [eE] [nN] [dD] [iI] [nN] [gG] )?;
|
||||||
|
DESC : [dD] [eE] [sS] [cC] ( [eE] [nN] [dD] [iI] [nN] [gG] )?;
|
||||||
|
|
||||||
|
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// Identifiers
|
||||||
|
|
||||||
|
IDENTIFIER
|
||||||
|
: ('a'..'z'|'A'..'Z'|'_'|'$'|'\u0080'..'\ufffe')('a'..'z'|'A'..'Z'|'_'|'$'|'0'..'9'|'\u0080'..'\ufffe')*
|
||||||
|
;
|
||||||
|
|
||||||
|
QUOTED_IDENTIFIER
|
||||||
|
: '`' ( ESCAPE_SEQUENCE | ~('\\'|'`') )* '`'
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// general tokens
|
||||||
|
|
||||||
|
OPEN_PAREN : '(';
|
||||||
|
CLOSE_PAREN : ')';
|
||||||
|
|
||||||
|
COMMA : ',';
|
||||||
|
DOT : '.';
|
||||||
|
|
||||||
|
PLUS : '+';
|
||||||
|
MINUS : '-';
|
||||||
|
MULTIPLY : '*';
|
||||||
|
DIVIDE : '/';
|
||||||
|
MODULO : '%';
|
||||||
|
|
@ -0,0 +1,82 @@
|
|||||||
|
parser grammar OrderingParser;
|
||||||
|
|
||||||
|
options {
|
||||||
|
tokenVocab=OrderingLexer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@header {
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.grammars.ordering;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Grammar for parsing order-by fragments.
|
||||||
|
*
|
||||||
|
* @implNote While we could re-use the HQL lexer/parser for order fragment parsing, both the HQL lexer and parser
|
||||||
|
* are way "heavier" than needed here. So we use a simplified lexer and parser that defione just what is needed
|
||||||
|
* to parse the order fragment
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo (6.0) : add hooks for keyword-as-identifier logging like we do for HQL?
|
||||||
|
|
||||||
|
orderByFragment
|
||||||
|
: sortSpecification (COMMA sortSpecification)*
|
||||||
|
;
|
||||||
|
|
||||||
|
sortSpecification
|
||||||
|
: expression collationSpecification? direction? nullsPrecedence?
|
||||||
|
;
|
||||||
|
|
||||||
|
expression
|
||||||
|
: function
|
||||||
|
| identifier
|
||||||
|
| dotIdentifier
|
||||||
|
;
|
||||||
|
|
||||||
|
function
|
||||||
|
: simpleFunction
|
||||||
|
| packagedFunction
|
||||||
|
;
|
||||||
|
|
||||||
|
simpleFunction
|
||||||
|
: identifier functionArguments
|
||||||
|
;
|
||||||
|
|
||||||
|
packagedFunction
|
||||||
|
: dotIdentifier functionArguments
|
||||||
|
;
|
||||||
|
|
||||||
|
functionArguments
|
||||||
|
: OPEN_PAREN expression* CLOSE_PAREN
|
||||||
|
;
|
||||||
|
|
||||||
|
collationSpecification
|
||||||
|
: COLLATE identifier
|
||||||
|
;
|
||||||
|
|
||||||
|
direction
|
||||||
|
: ASC | DESC
|
||||||
|
;
|
||||||
|
|
||||||
|
nullsPrecedence
|
||||||
|
: NULLS (FIRST | LAST)
|
||||||
|
;
|
||||||
|
|
||||||
|
identifier
|
||||||
|
: IDENTIFIER
|
||||||
|
// keyword-as-identifier
|
||||||
|
| FIRST
|
||||||
|
| LAST
|
||||||
|
| ASC
|
||||||
|
| DESC
|
||||||
|
| COLLATE
|
||||||
|
;
|
||||||
|
|
||||||
|
dotIdentifier
|
||||||
|
: IDENTIFIER (DOT IDENTIFIER)+
|
||||||
|
;
|
@ -298,14 +298,26 @@ havingClause
|
|||||||
// ORDER BY clause
|
// ORDER BY clause
|
||||||
|
|
||||||
orderByClause
|
orderByClause
|
||||||
// todo (6.0) : null precedence
|
|
||||||
: ORDER BY sortSpecification (COMMA sortSpecification)*
|
: ORDER BY sortSpecification (COMMA sortSpecification)*
|
||||||
;
|
;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specialized rule for ordered Map and Set `@OrderBy` handling
|
||||||
|
*/
|
||||||
|
orderByFragment
|
||||||
|
: sortSpecification (COMMA sortSpecification)*
|
||||||
|
;
|
||||||
|
|
||||||
sortSpecification
|
sortSpecification
|
||||||
|
// todo (6.0) : null precedence
|
||||||
|
// : sortExpression collationSpecification? orderingSpecification? nullsPrecedence?
|
||||||
: sortExpression collationSpecification? orderingSpecification?
|
: sortExpression collationSpecification? orderingSpecification?
|
||||||
;
|
;
|
||||||
|
|
||||||
|
//nullsPrecedence
|
||||||
|
// : NULLS (FIRST | LAST)
|
||||||
|
// ;
|
||||||
|
|
||||||
sortExpression
|
sortExpression
|
||||||
: identifier
|
: identifier
|
||||||
| INTEGER_LITERAL
|
| INTEGER_LITERAL
|
||||||
|
@ -10,5 +10,4 @@
|
|||||||
*
|
*
|
||||||
* @deprecated (since 6.0) Use Hibernate's mapping model {@link org.hibernate.metamodel.MappingMetamodel}
|
* @deprecated (since 6.0) Use Hibernate's mapping model {@link org.hibernate.metamodel.MappingMetamodel}
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
package org.hibernate.metadata;
|
package org.hibernate.metadata;
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hibernate.type.BasicType;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,4 +33,7 @@ default int getJdbcTypeCount(TypeConfiguration typeConfiguration) {
|
|||||||
default List<JdbcMapping> getJdbcMappings(TypeConfiguration typeConfiguration) {
|
default List<JdbcMapping> getJdbcMappings(TypeConfiguration typeConfiguration) {
|
||||||
return Collections.singletonList( getJdbcMapping() );
|
return Collections.singletonList( getJdbcMapping() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BasicType getBasicType();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -29,4 +29,9 @@ public interface BasicValuedModelPart extends BasicValuedMapping, ModelPart, Fet
|
|||||||
* Get the value converter applied to this model part if any
|
* Get the value converter applied to this model part if any
|
||||||
*/
|
*/
|
||||||
BasicValueConverter getConverter();
|
BasicValueConverter getConverter();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default MappingType getPartMappingType() {
|
||||||
|
return getBasicType();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,8 +56,6 @@ public static Nature fromName(String name) {
|
|||||||
|
|
||||||
Nature getNature();
|
Nature getNature();
|
||||||
|
|
||||||
MappingType getPartTypeDescriptor();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default String getPartName() {
|
default String getPartName() {
|
||||||
return getNature().getName();
|
return getNature().getName();
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.hibernate.metamodel.mapping;
|
package org.hibernate.metamodel.mapping;
|
||||||
|
|
||||||
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
@ -16,4 +18,14 @@ public interface EntityDiscriminatorMapping extends VirtualModelPart, BasicValue
|
|||||||
default String getPartName() {
|
default String getPartName() {
|
||||||
return ROLE_NAME;
|
return ROLE_NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default MappingType getPartMappingType() {
|
||||||
|
return getBasicType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default JavaTypeDescriptor getJavaTypeDescriptor() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,6 +64,12 @@ default JavaTypeDescriptor getJavaTypeDescriptor() {
|
|||||||
return getMappedJavaTypeDescriptor();
|
return getMappedJavaTypeDescriptor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default MappingType getPartMappingType() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// Inheritance
|
// Inheritance
|
||||||
|
|
||||||
|
@ -24,6 +24,11 @@ default JavaTypeDescriptor getJavaTypeDescriptor() {
|
|||||||
return getMappedJavaTypeDescriptor();
|
return getMappedJavaTypeDescriptor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default MappingType getPartMappingType() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the number of attributes defined on this class and any supers
|
* Get the number of attributes defined on this class and any supers
|
||||||
*/
|
*/
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.metamodel.mapping;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public interface MappingTypedModelPart extends ModelPart {
|
||||||
|
MappingType getMappingType();
|
||||||
|
}
|
@ -29,6 +29,8 @@
|
|||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface ModelPart extends MappingModelExpressable {
|
public interface ModelPart extends MappingModelExpressable {
|
||||||
|
MappingType getPartMappingType();
|
||||||
|
|
||||||
JavaTypeDescriptor getJavaTypeDescriptor();
|
JavaTypeDescriptor getJavaTypeDescriptor();
|
||||||
|
|
||||||
String getPartName();
|
String getPartName();
|
||||||
|
@ -27,6 +27,11 @@ public AbstractAttributeMapping(String name, MappingType type, ManagedMappingTyp
|
|||||||
this.declaringType = declaringType;
|
this.declaringType = declaringType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MappingType getPartMappingType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getAttributeName() {
|
public String getAttributeName() {
|
||||||
return name;
|
return name;
|
||||||
|
@ -48,6 +48,11 @@ public AbstractEntityDiscriminatorMapping(
|
|||||||
this.mappingType = mappingType;
|
this.mappingType = mappingType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BasicType getBasicType() {
|
||||||
|
return mappingType;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getContainingTableExpression() {
|
public String getContainingTableExpression() {
|
||||||
return tableExpression;
|
return tableExpression;
|
||||||
|
@ -70,7 +70,7 @@ public Nature getNature() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BasicType getPartTypeDescriptor() {
|
public MappingType getPartMappingType() {
|
||||||
return mapper;
|
return mapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,4 +197,9 @@ public int getJdbcTypeCount(TypeConfiguration typeConfiguration) {
|
|||||||
public List<JdbcMapping> getJdbcMappings(TypeConfiguration typeConfiguration) {
|
public List<JdbcMapping> getJdbcMappings(TypeConfiguration typeConfiguration) {
|
||||||
return Collections.singletonList( getJdbcMapping() );
|
return Collections.singletonList( getJdbcMapping() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BasicType getBasicType() {
|
||||||
|
return mapper;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,6 +67,11 @@ public BasicValuedSingularAttributeMapping(
|
|||||||
this.jdbcMapping = jdbcMapping;
|
this.jdbcMapping = jdbcMapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BasicType getBasicType() {
|
||||||
|
return getMappedTypeDescriptor();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BasicType getMappedTypeDescriptor() {
|
public BasicType getMappedTypeDescriptor() {
|
||||||
return (BasicType) super.getMappedTypeDescriptor();
|
return (BasicType) super.getMappedTypeDescriptor();
|
||||||
|
@ -73,7 +73,7 @@ public BasicValueConverter getConverter() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MappingType getPartTypeDescriptor() {
|
public MappingType getPartMappingType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,4 +188,9 @@ public DomainResult createDomainResult(
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return getClass().getSimpleName() + "(" + collectionDescriptor.getRole() + ")";
|
return getClass().getSimpleName() + "(" + collectionDescriptor.getRole() + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BasicType getBasicType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
|
import org.hibernate.metamodel.mapping.MappingType;
|
||||||
import org.hibernate.metamodel.mapping.ModelPart;
|
import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||||
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
||||||
@ -84,7 +85,7 @@ public EmbeddableMappingType getEmbeddableTypeDescriptor() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EmbeddableMappingType getPartTypeDescriptor() {
|
public MappingType getPartMappingType() {
|
||||||
return getEmbeddableTypeDescriptor();
|
return getEmbeddableTypeDescriptor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,6 +77,11 @@ public EmbeddedIdentifierMappingImpl(
|
|||||||
this.attrColumnNames = attrColumnNames;
|
this.attrColumnNames = attrColumnNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MappingType getPartMappingType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JavaTypeDescriptor getJavaTypeDescriptor() {
|
public JavaTypeDescriptor getJavaTypeDescriptor() {
|
||||||
return getMappedTypeDescriptor().getMappedJavaTypeDescriptor();
|
return getMappedTypeDescriptor().getMappedJavaTypeDescriptor();
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||||
import org.hibernate.metamodel.mapping.EntityAssociationMapping;
|
import org.hibernate.metamodel.mapping.EntityAssociationMapping;
|
||||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
|
import org.hibernate.metamodel.mapping.MappingType;
|
||||||
import org.hibernate.metamodel.mapping.ModelPart;
|
import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||||
import org.hibernate.persister.collection.CollectionPersister;
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
@ -63,7 +64,7 @@ public Nature getNature() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityMappingType getPartTypeDescriptor() {
|
public MappingType getPartMappingType() {
|
||||||
return getEntityMappingType();
|
return getEntityMappingType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
import org.hibernate.mapping.ToOne;
|
import org.hibernate.mapping.ToOne;
|
||||||
import org.hibernate.mapping.Value;
|
import org.hibernate.mapping.Value;
|
||||||
import org.hibernate.metamodel.CollectionClassification;
|
import org.hibernate.metamodel.CollectionClassification;
|
||||||
|
import org.hibernate.metamodel.MappingMetamodel;
|
||||||
import org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping;
|
import org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping;
|
||||||
import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
||||||
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
||||||
@ -63,7 +64,6 @@
|
|||||||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadata;
|
import org.hibernate.metamodel.mapping.StateArrayContributorMetadata;
|
||||||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
|
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
|
||||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||||
import org.hibernate.metamodel.MappingMetamodel;
|
|
||||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||||
import org.hibernate.persister.collection.CollectionPersister;
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
import org.hibernate.persister.collection.SQLLoadableCollection;
|
import org.hibernate.persister.collection.SQLLoadableCollection;
|
||||||
@ -80,12 +80,12 @@
|
|||||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||||
import org.hibernate.sql.results.graph.basic.BasicFetch;
|
|
||||||
import org.hibernate.sql.results.graph.basic.BasicResult;
|
|
||||||
import org.hibernate.sql.results.graph.DomainResult;
|
import org.hibernate.sql.results.graph.DomainResult;
|
||||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||||
import org.hibernate.sql.results.graph.Fetch;
|
import org.hibernate.sql.results.graph.Fetch;
|
||||||
import org.hibernate.sql.results.graph.FetchParent;
|
import org.hibernate.sql.results.graph.FetchParent;
|
||||||
|
import org.hibernate.sql.results.graph.basic.BasicFetch;
|
||||||
|
import org.hibernate.sql.results.graph.basic.BasicResult;
|
||||||
import org.hibernate.type.AssociationType;
|
import org.hibernate.type.AssociationType;
|
||||||
import org.hibernate.type.BasicType;
|
import org.hibernate.type.BasicType;
|
||||||
import org.hibernate.type.CompositeType;
|
import org.hibernate.type.CompositeType;
|
||||||
@ -134,9 +134,19 @@ public PropertyAccess getPropertyAccess() {
|
|||||||
return propertyAccess;
|
return propertyAccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MappingType getPartMappingType() {
|
||||||
|
return getBasicType();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MappingType getMappedTypeDescriptor() {
|
public MappingType getMappedTypeDescriptor() {
|
||||||
return ( (BasicType) entityPersister.getIdentifierType() ).getMappedTypeDescriptor();
|
return getBasicType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BasicType getBasicType() {
|
||||||
|
return (BasicType) entityPersister.getIdentifierType();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -337,6 +347,13 @@ public static EntityIdentifierMapping buildNonEncapsulatedCompositeIdentifierMap
|
|||||||
|
|
||||||
return new EntityIdentifierMapping() {
|
return new EntityIdentifierMapping() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MappingType getPartMappingType() {
|
||||||
|
// non-encapsulated means that the id attributes are directly defined on the entity
|
||||||
|
// - alternatively we could have the type here be the IdClass descriptor
|
||||||
|
return entityPersister;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PropertyAccess getPropertyAccess() {
|
public PropertyAccess getPropertyAccess() {
|
||||||
return propertyAccess;
|
return propertyAccess;
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.engine.FetchStrategy;
|
import org.hibernate.engine.FetchStrategy;
|
||||||
import org.hibernate.engine.FetchTiming;
|
import org.hibernate.engine.FetchTiming;
|
||||||
@ -39,6 +40,7 @@
|
|||||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||||
import org.hibernate.sql.results.graph.Fetch;
|
import org.hibernate.sql.results.graph.Fetch;
|
||||||
import org.hibernate.sql.results.graph.FetchParent;
|
import org.hibernate.sql.results.graph.FetchParent;
|
||||||
|
import org.hibernate.type.BasicType;
|
||||||
import org.hibernate.type.ForeignKeyDirection;
|
import org.hibernate.type.ForeignKeyDirection;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
@ -298,6 +300,11 @@ public List<JdbcMapping> getJdbcMappings(TypeConfiguration typeConfiguration) {
|
|||||||
return Collections.singletonList( jdbcMapping );
|
return Collections.singletonList( jdbcMapping );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BasicType getBasicType() {
|
||||||
|
throw new HibernateException( "Unexpected call to SimpleForeignKeyDescriptor#getBasicType" );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitJdbcTypes(
|
public void visitJdbcTypes(
|
||||||
Consumer<JdbcMapping> action,
|
Consumer<JdbcMapping> action,
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.metamodel.mapping.ordering;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public interface AliasResolver {
|
||||||
|
}
|
@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.metamodel.mapping.ordering;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
|
import org.hibernate.grammars.ordering.OrderingLexer;
|
||||||
|
import org.hibernate.grammars.ordering.OrderingParser;
|
||||||
|
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||||
|
import org.hibernate.metamodel.mapping.ordering.ast.ParseTreeVisitor;
|
||||||
|
import org.hibernate.metamodel.mapping.ordering.ast.SortSpecification;
|
||||||
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
|
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
import org.antlr.v4.runtime.BailErrorStrategy;
|
||||||
|
import org.antlr.v4.runtime.BufferedTokenStream;
|
||||||
|
import org.antlr.v4.runtime.CharStreams;
|
||||||
|
import org.antlr.v4.runtime.ConsoleErrorListener;
|
||||||
|
import org.antlr.v4.runtime.DefaultErrorStrategy;
|
||||||
|
import org.antlr.v4.runtime.atn.PredictionMode;
|
||||||
|
import org.antlr.v4.runtime.misc.ParseCancellationException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Responsible for performing the translation of the order-by fragment associated
|
||||||
|
* with an order set or map.
|
||||||
|
*
|
||||||
|
* @see javax.persistence.OrderBy
|
||||||
|
* @see org.hibernate.annotations.OrderBy
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class OrderByFragmentTranslator {
|
||||||
|
private static final Logger LOG = Logger.getLogger( OrderByFragmentTranslator.class.getName() );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform the translation of the user-supplied fragment, returning the translation.
|
||||||
|
*
|
||||||
|
* @apiNote The important distinction to this split between (1) translating and (2) resolving aliases is that
|
||||||
|
* both happen at different times. This is performed at boot-time while building the CollectionPersister
|
||||||
|
* happens at runtime while loading the described collection
|
||||||
|
*
|
||||||
|
* @return The translation.
|
||||||
|
*/
|
||||||
|
public static OrderByFragment translate(
|
||||||
|
String fragment,
|
||||||
|
PluralAttributeMapping pluralAttributeMapping,
|
||||||
|
TranslationContext context) {
|
||||||
|
LOG.tracef( "Beginning parsing of order-by fragment [%s] : %s", pluralAttributeMapping.getCollectionDescriptor().getRole(), fragment );
|
||||||
|
|
||||||
|
final OrderingParser.OrderByFragmentContext parseTree = buildParseTree( context, fragment );
|
||||||
|
|
||||||
|
final ParseTreeVisitor visitor = new ParseTreeVisitor( pluralAttributeMapping, context );
|
||||||
|
|
||||||
|
final List<SortSpecification> interpretation = visitor.visitOrderByFragment( parseTree );
|
||||||
|
|
||||||
|
throw new NotYetImplementedFor6Exception( OrderByFragmentTranslator.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static OrderingParser.OrderByFragmentContext buildParseTree(TranslationContext context, String fragment) {
|
||||||
|
final OrderingLexer lexer = new OrderingLexer( CharStreams.fromString( fragment ) );
|
||||||
|
|
||||||
|
final OrderingParser parser = new OrderingParser( new BufferedTokenStream( lexer ) );
|
||||||
|
|
||||||
|
// try to use SLL(k)-based parsing first - its faster
|
||||||
|
parser.getInterpreter().setPredictionMode( PredictionMode.SLL );
|
||||||
|
parser.removeErrorListeners();
|
||||||
|
parser.setErrorHandler( new BailErrorStrategy() );
|
||||||
|
|
||||||
|
try {
|
||||||
|
return parser.orderByFragment();
|
||||||
|
}
|
||||||
|
catch ( ParseCancellationException e) {
|
||||||
|
// reset the input token stream and parser state
|
||||||
|
lexer.reset();
|
||||||
|
parser.reset();
|
||||||
|
|
||||||
|
// fall back to LL(k)-based parsing
|
||||||
|
parser.getInterpreter().setPredictionMode( PredictionMode.LL );
|
||||||
|
parser.addErrorListener( ConsoleErrorListener.INSTANCE );
|
||||||
|
parser.setErrorHandler( new DefaultErrorStrategy() );
|
||||||
|
|
||||||
|
return parser.orderByFragment();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the translation result
|
||||||
|
*/
|
||||||
|
public interface OrderByFragment {
|
||||||
|
/**
|
||||||
|
* Inject table aliases into the translated fragment to properly qualify column references, using
|
||||||
|
* the given 'aliasResolver' to determine the the proper table alias to use for each column reference.
|
||||||
|
*
|
||||||
|
* @param aliasResolver The strategy to resolver the proper table alias to use per column
|
||||||
|
*
|
||||||
|
* @return The fully translated and replaced fragment.
|
||||||
|
*/
|
||||||
|
String injectAliases(AliasResolver aliasResolver);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.metamodel.mapping.ordering;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access to information needed while translating a collection's order-by fragment
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public interface TranslationContext {
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.metamodel.mapping.ordering.ast;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
|
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||||
|
import org.hibernate.metamodel.mapping.ordering.TranslationContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class CollectionSubPath implements DomainPath {
|
||||||
|
private final PluralAttributeMapping pluralAttribute;
|
||||||
|
private final ModelPart referenceModelPart;
|
||||||
|
|
||||||
|
public CollectionSubPath(
|
||||||
|
PluralAttributeMapping pluralAttribute,
|
||||||
|
ModelPart referenceModelPart) {
|
||||||
|
this.pluralAttribute = pluralAttribute;
|
||||||
|
this.referenceModelPart = referenceModelPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PluralAttributeMapping getPluralAttribute() {
|
||||||
|
return pluralAttribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DomainPath getLhs() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModelPart getReferenceModelPart() {
|
||||||
|
return referenceModelPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SequencePart resolvePathPart(
|
||||||
|
String name,
|
||||||
|
boolean isTerminal,
|
||||||
|
TranslationContext translationContext) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.metamodel.mapping.ordering.ast;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.mapping.ordering.TranslationContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a column-reference used in an order-by fragment
|
||||||
|
*
|
||||||
|
* @apiNote This is Hibernate-specific feature. For {@link javax.persistence.OrderBy} (JPA)
|
||||||
|
* all path references are expected to be domain paths (attributes).
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class ColumnReference implements SortExpression, SequencePart {
|
||||||
|
private final String columnExpression;
|
||||||
|
|
||||||
|
public ColumnReference(String columnExpression) {
|
||||||
|
this.columnExpression = columnExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getColumnExpression() {
|
||||||
|
return columnExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SequencePart resolvePathPart(
|
||||||
|
String name,
|
||||||
|
boolean isTerminal,
|
||||||
|
TranslationContext translationContext) {
|
||||||
|
throw new UnsupportedOperationException( "ColumnReference cannot be de-referenced" );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.metamodel.mapping.ordering.ast;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
|
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a domain-path (model part path) used in an order-by fragment
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public interface DomainPath extends SortExpression, SequencePart {
|
||||||
|
DomainPath getLhs();
|
||||||
|
|
||||||
|
ModelPart getReferenceModelPart();
|
||||||
|
|
||||||
|
default PluralAttributeMapping getPluralAttribute() {
|
||||||
|
return getLhs().getPluralAttribute();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.metamodel.mapping.ordering.ast;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a function used in an order-by fragment
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class FunctionExpression {
|
||||||
|
private final String name;
|
||||||
|
private final List<SortExpression> arguments;
|
||||||
|
|
||||||
|
public FunctionExpression(String name, int numberOfArguments) {
|
||||||
|
this.name = name;
|
||||||
|
this.arguments = numberOfArguments == 0
|
||||||
|
? Collections.emptyList()
|
||||||
|
: new ArrayList<>( numberOfArguments );
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SortExpression> getArguments() {
|
||||||
|
return arguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addArgument(SortExpression argument) {
|
||||||
|
arguments.add( argument );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.metamodel.mapping.ordering.ast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common contract for all nodes in the order-by fragment AST
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public interface Node {
|
||||||
|
}
|
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.metamodel.mapping.ordering.ast;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
|
import org.hibernate.SortOrder;
|
||||||
|
import org.hibernate.grammars.ordering.OrderingParser;
|
||||||
|
import org.hibernate.grammars.ordering.OrderingParserBaseVisitor;
|
||||||
|
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||||
|
import org.hibernate.metamodel.mapping.ordering.TranslationContext;
|
||||||
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
|
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class ParseTreeVisitor extends OrderingParserBaseVisitor {
|
||||||
|
private static final Logger log = Logger.getLogger( ParseTreeVisitor.class );
|
||||||
|
|
||||||
|
private final PathConsumer pathConsumer;
|
||||||
|
private final TranslationContext translationContext;
|
||||||
|
|
||||||
|
private List<SortSpecification> specifications;
|
||||||
|
|
||||||
|
public ParseTreeVisitor(
|
||||||
|
PluralAttributeMapping pluralAttributeMapping,
|
||||||
|
TranslationContext translationContext) {
|
||||||
|
this.pathConsumer = new PathConsumer( pluralAttributeMapping, translationContext );
|
||||||
|
this.translationContext = translationContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<SortSpecification> visitOrderByFragment(OrderingParser.OrderByFragmentContext parsedFragment) {
|
||||||
|
final List<OrderingParser.SortSpecificationContext> parsedSortSpecifications = parsedFragment.sortSpecification();
|
||||||
|
Objects.requireNonNull( parsedSortSpecifications );
|
||||||
|
|
||||||
|
this.specifications = new ArrayList<>( parsedSortSpecifications.size() );
|
||||||
|
|
||||||
|
for ( OrderingParser.SortSpecificationContext parsedSortSpecification : parsedSortSpecifications ) {
|
||||||
|
visitSortSpecification( parsedSortSpecification );
|
||||||
|
}
|
||||||
|
|
||||||
|
Objects.requireNonNull( specifications );
|
||||||
|
return specifications;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SortSpecification visitSortSpecification(OrderingParser.SortSpecificationContext parsedSpec) {
|
||||||
|
assert parsedSpec != null;
|
||||||
|
assert parsedSpec.expression() != null;
|
||||||
|
|
||||||
|
final SortSpecification result = new SortSpecification( visitExpression( parsedSpec.expression() ) );
|
||||||
|
|
||||||
|
if ( parsedSpec.collationSpecification() != null ) {
|
||||||
|
result.setCollation( parsedSpec.collationSpecification().identifier().getText() );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( parsedSpec.direction() != null ) {
|
||||||
|
if ( parsedSpec.direction().ASC() != null ) {
|
||||||
|
result.setSortOrder( SortOrder.ASCENDING );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo (6.0) : null-precedence (see grammar notes)
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SortExpression visitExpression(OrderingParser.ExpressionContext ctx) {
|
||||||
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String visitCollationSpecification(OrderingParser.CollationSpecificationContext ctx) {
|
||||||
|
throw new IllegalStateException( "Unexpected call to #visitCollationSpecification" );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.metamodel.mapping.ordering.ast;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||||
|
import org.hibernate.metamodel.mapping.ordering.TranslationContext;
|
||||||
|
import org.hibernate.query.hql.internal.BasicDotIdentifierConsumer;
|
||||||
|
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the translation of an individual part of a path in `@OrderBy` translation
|
||||||
|
*
|
||||||
|
* Similar in purpose to {@link org.hibernate.query.hql.spi.DotIdentifierConsumer}, but for `@OrderBy` translation
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class PathConsumer {
|
||||||
|
private static final Logger log = Logger.getLogger( BasicDotIdentifierConsumer.class );
|
||||||
|
|
||||||
|
private final TranslationContext translationContext;
|
||||||
|
|
||||||
|
private final SequencePart rootSequencePart;
|
||||||
|
|
||||||
|
private String pathSoFar;
|
||||||
|
private SequencePart currentPart;
|
||||||
|
|
||||||
|
public PathConsumer(
|
||||||
|
PluralAttributeMapping pluralAttributeMapping, TranslationContext translationContext) {
|
||||||
|
this.translationContext = translationContext;
|
||||||
|
|
||||||
|
this.rootSequencePart = new RootSequencePart( pluralAttributeMapping );
|
||||||
|
}
|
||||||
|
|
||||||
|
public SequencePart getConsumedPart() {
|
||||||
|
return currentPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void consumeIdentifier(String identifier, boolean isBase, boolean isTerminal) {
|
||||||
|
if ( isBase ) {
|
||||||
|
// each time we start a new sequence we need to reset our state
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( pathSoFar == null ) {
|
||||||
|
pathSoFar = identifier;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pathSoFar += ( '.' + identifier );
|
||||||
|
}
|
||||||
|
|
||||||
|
log.tracef(
|
||||||
|
"BasicDotIdentifierHandler#consumeIdentifier( %s, %s, %s ) - %s",
|
||||||
|
identifier,
|
||||||
|
isBase,
|
||||||
|
isTerminal,
|
||||||
|
pathSoFar
|
||||||
|
);
|
||||||
|
|
||||||
|
currentPart = currentPart.resolvePathPart( identifier, isTerminal, translationContext );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void reset() {
|
||||||
|
pathSoFar = null;
|
||||||
|
currentPart = rootSequencePart;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.metamodel.mapping.ordering.ast;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
|
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||||
|
import org.hibernate.metamodel.mapping.ordering.TranslationContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PathPart implementation used to translate the root of a path
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class RootSequencePart implements SequencePart {
|
||||||
|
private final PluralAttributeMapping pluralAttributeMapping;
|
||||||
|
|
||||||
|
public RootSequencePart(PluralAttributeMapping pluralAttributeMapping) {
|
||||||
|
this.pluralAttributeMapping = pluralAttributeMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SequencePart resolvePathPart(
|
||||||
|
String name,
|
||||||
|
boolean isTerminal,
|
||||||
|
TranslationContext translationContext) {
|
||||||
|
// could be a column-reference (isTerminal would have to be true) or a domain-path
|
||||||
|
|
||||||
|
final ModelPart subPart = pluralAttributeMapping.findSubPart( name, null );
|
||||||
|
|
||||||
|
if ( subPart != null ) {
|
||||||
|
return new CollectionSubPath( pluralAttributeMapping, subPart );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( isTerminal ) {
|
||||||
|
// assume a column-reference
|
||||||
|
return new ColumnReference( name );
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new UnexpectedTokenException(
|
||||||
|
"Could not resolve order-by token : " +
|
||||||
|
pluralAttributeMapping.getCollectionDescriptor().getRole() + " -> " + name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.metamodel.mapping.ordering.ast;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.mapping.ordering.TranslationContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an individual identifier in a dot-identifier sequence
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public interface SequencePart {
|
||||||
|
SequencePart resolvePathPart(
|
||||||
|
String name,
|
||||||
|
boolean isTerminal,
|
||||||
|
TranslationContext translationContext);
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.metamodel.mapping.ordering.ast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contract for anything that can be a sort expression
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public interface SortExpression extends Node {
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.metamodel.mapping.ordering.ast;
|
||||||
|
|
||||||
|
import org.hibernate.NullPrecedence;
|
||||||
|
import org.hibernate.SortOrder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An individual sort specification in an order-by fragment
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class SortSpecification implements Node {
|
||||||
|
private final SortExpression sortExpression;
|
||||||
|
|
||||||
|
private String collation;
|
||||||
|
private SortOrder sortOrder;
|
||||||
|
private NullPrecedence nullPrecedence = NullPrecedence.NONE;
|
||||||
|
|
||||||
|
public SortSpecification(SortExpression sortExpression) {
|
||||||
|
this.sortExpression = sortExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SortExpression getSortExpression() {
|
||||||
|
return sortExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCollation() {
|
||||||
|
return collation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCollation(String collation) {
|
||||||
|
this.collation = collation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SortOrder getSortOrder() {
|
||||||
|
return sortOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSortOrder(SortOrder sortOrder) {
|
||||||
|
this.sortOrder = sortOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NullPrecedence getNullPrecedence() {
|
||||||
|
return nullPrecedence;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNullPrecedence(NullPrecedence nullPrecedence) {
|
||||||
|
this.nullPrecedence = nullPrecedence;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.metamodel.mapping.ordering.ast;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.mapping.ManagedMappingType;
|
||||||
|
import org.hibernate.metamodel.mapping.MappingTypedModelPart;
|
||||||
|
import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
|
import org.hibernate.metamodel.mapping.ordering.TranslationContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class SubDomainPath implements DomainPath {
|
||||||
|
private final DomainPath lhs;
|
||||||
|
private final ModelPart referencedModelPart;
|
||||||
|
|
||||||
|
public SubDomainPath(DomainPath lhs, ModelPart referencedModelPart) {
|
||||||
|
this.lhs = lhs;
|
||||||
|
this.referencedModelPart = referencedModelPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DomainPath getLhs() {
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModelPart getReferenceModelPart() {
|
||||||
|
return referencedModelPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SequencePart resolvePathPart(
|
||||||
|
String name,
|
||||||
|
boolean isTerminal,
|
||||||
|
TranslationContext translationContext) {
|
||||||
|
if ( referencedModelPart.getPartMappingType() instanceof ManagedMappingType ) {
|
||||||
|
final ManagedMappingType partMappingType = (ManagedMappingType) referencedModelPart.getPartMappingType();
|
||||||
|
final ModelPart subPart = partMappingType.findSubPart( name, null );
|
||||||
|
if ( subPart == null ) {
|
||||||
|
throw new UnexpectedTokenException(
|
||||||
|
"Could not resolve path token : " +
|
||||||
|
referencedModelPart + " -> " + name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new SubDomainPath( this, subPart );
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new UnexpectedTokenException(
|
||||||
|
"Domain path of type `" + referencedModelPart.getPartMappingType() +
|
||||||
|
"` -> `" + name + "`"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.metamodel.mapping.ordering.ast;
|
||||||
|
|
||||||
|
import org.hibernate.HibernateException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class UnexpectedTokenException extends HibernateException {
|
||||||
|
public UnexpectedTokenException(String message) {
|
||||||
|
super( message );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Support for set and map ordering
|
||||||
|
*
|
||||||
|
* @see javax.persistence.OrderBy
|
||||||
|
* @see org.hibernate.annotations.OrderBy
|
||||||
|
*/
|
||||||
|
package org.hibernate.metamodel.mapping.ordering;
|
@ -28,11 +28,12 @@ public class HqlParseTreeBuilder {
|
|||||||
*/
|
*/
|
||||||
public static final HqlParseTreeBuilder INSTANCE = new HqlParseTreeBuilder();
|
public static final HqlParseTreeBuilder INSTANCE = new HqlParseTreeBuilder();
|
||||||
|
|
||||||
public HqlParser generateHqlParser(String hql) {
|
public HqlLexer buildHqlLexer(String hql) {
|
||||||
// Build the lexer
|
return new HqlLexer( CharStreams.fromString( hql ) );
|
||||||
HqlLexer hqlLexer = new HqlLexer( CharStreams.fromString( hql ) );
|
}
|
||||||
|
|
||||||
// Build the parser...
|
public HqlParser buildHqlParser(String hql, HqlLexer hqlLexer) {
|
||||||
|
// Build the parser
|
||||||
return new HqlParser( new CommonTokenStream( hqlLexer ) ) {
|
return new HqlParser( new CommonTokenStream( hqlLexer ) ) {
|
||||||
@Override
|
@Override
|
||||||
protected void logUseOfReservedWordAsIdentifier(Token token) {
|
protected void logUseOfReservedWordAsIdentifier(Token token) {
|
||||||
@ -42,4 +43,9 @@ protected void logUseOfReservedWordAsIdentifier(Token token) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HqlParser buildHqlParser(String hql) {
|
||||||
|
// Build the lexer
|
||||||
|
return buildHqlParser( hql, buildHqlLexer( hql ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
import org.hibernate.query.sqm.tree.SqmStatement;
|
import org.hibernate.query.sqm.tree.SqmStatement;
|
||||||
|
|
||||||
import org.antlr.v4.runtime.BailErrorStrategy;
|
import org.antlr.v4.runtime.BailErrorStrategy;
|
||||||
import org.antlr.v4.runtime.CharStreams;
|
|
||||||
import org.antlr.v4.runtime.ConsoleErrorListener;
|
import org.antlr.v4.runtime.ConsoleErrorListener;
|
||||||
import org.antlr.v4.runtime.DefaultErrorStrategy;
|
import org.antlr.v4.runtime.DefaultErrorStrategy;
|
||||||
import org.antlr.v4.runtime.atn.PredictionMode;
|
import org.antlr.v4.runtime.atn.PredictionMode;
|
||||||
@ -64,10 +63,10 @@ public SqmStatement translate(String query) {
|
|||||||
|
|
||||||
private HqlParser.StatementContext parseHql(String hql) {
|
private HqlParser.StatementContext parseHql(String hql) {
|
||||||
// Build the lexer
|
// Build the lexer
|
||||||
final HqlLexer hqlLexer = new HqlLexer( CharStreams.fromString( hql ) );
|
final HqlLexer hqlLexer = HqlParseTreeBuilder.INSTANCE.buildHqlLexer( hql );
|
||||||
|
|
||||||
// first, ask Antlr to build the parse tree
|
// Build the parse tree
|
||||||
final HqlParser hqlParser = HqlParseTreeBuilder.INSTANCE.generateHqlParser( hql );
|
final HqlParser hqlParser = HqlParseTreeBuilder.INSTANCE.buildHqlParser( hql, hqlLexer );
|
||||||
|
|
||||||
// try to use SLL(k)-based parsing first - its faster
|
// try to use SLL(k)-based parsing first - its faster
|
||||||
hqlParser.getInterpreter().setPredictionMode( PredictionMode.SLL );
|
hqlParser.getInterpreter().setPredictionMode( PredictionMode.SLL );
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
import org.hibernate.engine.FetchStrategy;
|
import org.hibernate.engine.FetchStrategy;
|
||||||
import org.hibernate.engine.FetchTiming;
|
import org.hibernate.engine.FetchTiming;
|
||||||
|
import org.hibernate.metamodel.mapping.MappingType;
|
||||||
import org.hibernate.query.NavigablePath;
|
import org.hibernate.query.NavigablePath;
|
||||||
import org.hibernate.sql.results.graph.AssemblerCreationState;
|
import org.hibernate.sql.results.graph.AssemblerCreationState;
|
||||||
import org.hibernate.sql.results.graph.BiDirectionalFetch;
|
import org.hibernate.sql.results.graph.BiDirectionalFetch;
|
||||||
@ -97,6 +98,11 @@ public String getPartName() {
|
|||||||
return fetchable.getFetchableName();
|
return fetchable.getFetchableName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MappingType getPartMappingType() {
|
||||||
|
return fetchable.getPartMappingType();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JavaTypeDescriptor getJavaTypeDescriptor() {
|
public JavaTypeDescriptor getJavaTypeDescriptor() {
|
||||||
return fetchable.getJavaTypeDescriptor();
|
return fetchable.getJavaTypeDescriptor();
|
||||||
|
@ -32,6 +32,11 @@ public interface BasicType<T> extends Type, BasicDomainType<T>, MappingType, Bas
|
|||||||
*/
|
*/
|
||||||
String[] getRegistrationKeys();
|
String[] getRegistrationKeys();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default BasicType getBasicType() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default MappingType getMappedTypeDescriptor() {
|
default MappingType getMappedTypeDescriptor() {
|
||||||
return this;
|
return this;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user