PL-5590 AST-based QueryTransformer

JPA2 parser and lexer
AST tests fixed
#PL-5590
This commit is contained in:
Eugeny Degtyarjov 2015-07-31 09:12:32 +00:00
parent 65147ef520
commit acf1a3b36b
15 changed files with 26027 additions and 181 deletions

View File

@ -4,8 +4,8 @@
*/
package com.haulmont.cuba.core.sys.jpql;
import com.haulmont.cuba.core.sys.jpql.antlr.JPALexer;
import com.haulmont.cuba.core.sys.jpql.antlr.JPAParser;
import com.haulmont.cuba.core.sys.jpql.antlr2.JPA2Lexer;
import com.haulmont.cuba.core.sys.jpql.antlr2.JPA2Parser;
import org.antlr.runtime.CharStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;
@ -14,37 +14,37 @@ import org.antlr.runtime.tree.CommonTree;
public class Parser {
public static CommonTree parse(String input) throws RecognitionException {
JPAParser parser = createParser(input);
JPAParser.ql_statement_return aReturn = parser.ql_statement();
JPA2Parser parser = createParser(input);
JPA2Parser.ql_statement_return aReturn = parser.ql_statement();
return (CommonTree) aReturn.getTree();
}
public static CommonTree parseWhereClause(String input) throws RecognitionException {
JPAParser parser = createParser(input);
JPAParser.where_clause_return aReturn = parser.where_clause();
JPA2Parser parser = createParser(input);
JPA2Parser.where_clause_return aReturn = parser.where_clause();
return (CommonTree) aReturn.getTree();
}
public static CommonTree parseJoinClause(String join) throws RecognitionException {
JPAParser parser = createParser(join);
JPAParser.join_return aReturn = parser.join();
JPA2Parser parser = createParser(join);
JPA2Parser.join_return aReturn = parser.join();
return (CommonTree) aReturn.getTree();
}
private static JPAParser createParser(String input) {
private static JPA2Parser createParser(String input) {
if (input.contains("~"))
throw new IllegalArgumentException("Input string cannot contain \"~\"");
CharStream cs = new AntlrNoCaseStringStream(input);
JPALexer lexer = new JPALexer(cs);
JPA2Lexer lexer = new JPA2Lexer(cs);
TokenStream tstream = new CommonTokenStream(lexer);
return new JPAParser(tstream);
return new JPA2Parser(tstream);
}
public static CommonTree parseSelectionSource(String input) throws RecognitionException {
JPAParser parser = createParser(input);
JPAParser.identification_variable_or_collection_declaration_return aReturn =
parser.identification_variable_or_collection_declaration();
JPA2Parser parser = createParser(input);
JPA2Parser.identification_variable_declaration_or_collection_member_declaration_return aReturn =
parser.identification_variable_declaration_or_collection_member_declaration();
return (CommonTree) aReturn.getTree();
}
}

View File

@ -5,7 +5,7 @@
package com.haulmont.cuba.core.sys.jpql;
import com.haulmont.cuba.core.sys.jpql.antlr.JPALexer;
import com.haulmont.cuba.core.sys.jpql.antlr2.JPA2Lexer;
import com.haulmont.cuba.core.sys.jpql.model.Entity;
import com.haulmont.cuba.core.sys.jpql.pointer.EntityPointer;
import com.haulmont.cuba.core.sys.jpql.pointer.Pointer;
@ -63,7 +63,7 @@ public class QueryTreeAnalyzer {
}
public PathNode getSelectedPathNode() {
Tree selectedItems = tree.getFirstChildWithType(JPALexer.T_SELECTED_ITEMS);
Tree selectedItems = tree.getFirstChildWithType(JPA2Lexer.T_SELECTED_ITEMS);
boolean isDistinct = "DISTINCT".equalsIgnoreCase(selectedItems.getChild(0).getText());
SelectedItemNode selectedItemNode;
if (isDistinct) {

View File

@ -5,7 +5,7 @@
package com.haulmont.cuba.core.sys.jpql;
import com.haulmont.cuba.core.sys.jpql.antlr.JPALexer;
import com.haulmont.cuba.core.sys.jpql.antlr2.JPA2Lexer;
import com.haulmont.cuba.core.sys.jpql.tree.TreeToQueryCapable;
import org.antlr.runtime.tree.CommonErrorNode;
import org.antlr.runtime.tree.CommonTree;
@ -40,25 +40,25 @@ public class TreeToQuery implements TreeVisitorAction {
if (node.token == null)
return t;
if (node.getType() == JPALexer.HAVING ||
node.parent != null && node.parent.getType() == JPALexer.T_SIMPLE_CONDITION ||
node.parent != null && node.parent.getType() == JPALexer.T_GROUP_BY ||
node.parent != null && node.parent.getType() == JPALexer.T_ORDER_BY && node.getType() != JPALexer.T_ORDER_BY_FIELD ||
node.parent != null && node.parent.getType() == JPALexer.T_CONDITION && node.getType() == JPALexer.LPAREN && node.childIndex - 1 >= 0 && node.parent.getChild(node.childIndex - 1).getType() != JPALexer.LPAREN ||
node.getType() == JPALexer.AND ||
node.parent != null && node.parent.getType() == JPALexer.T_ORDER_BY_FIELD ||
node.getType() == JPALexer.OR ||
node.getType() == JPALexer.DISTINCT && node.childIndex == 0 ||
node.getType() == JPALexer.JOIN ||
node.getType() == JPALexer.LEFT ||
node.getType() == JPALexer.OUTER ||
node.getType() == JPALexer.INNER ||
node.getType() == JPALexer.FETCH
if (node.getType() == JPA2Lexer.HAVING ||
node.parent != null && node.parent.getType() == JPA2Lexer.T_SIMPLE_CONDITION ||
node.parent != null && node.parent.getType() == JPA2Lexer.T_GROUP_BY ||
node.parent != null && node.parent.getType() == JPA2Lexer.T_ORDER_BY && node.getType() != JPA2Lexer.T_ORDER_BY_FIELD ||
node.parent != null && node.parent.getType() == JPA2Lexer.T_CONDITION && node.getType() == JPA2Lexer.LPAREN && node.childIndex - 1 >= 0 && node.parent.getChild(node.childIndex - 1).getType() != JPA2Lexer.LPAREN ||
node.getType() == JPA2Lexer.AND ||
node.parent != null && node.parent.getType() == JPA2Lexer.T_ORDER_BY_FIELD ||
node.getType() == JPA2Lexer.OR ||
node.getType() == JPA2Lexer.DISTINCT && node.childIndex == 0 ||
node.getType() == JPA2Lexer.JOIN ||
node.getType() == JPA2Lexer.LEFT ||
node.getType() == JPA2Lexer.OUTER ||
node.getType() == JPA2Lexer.INNER ||
node.getType() == JPA2Lexer.FETCH
) {
sb.appendSpace();
}
if (node.getType() == JPALexer.T_ORDER_BY_FIELD && node.childIndex - 1 >= 0 && node.parent.getChild(node.childIndex - 1).getType() == JPALexer.T_ORDER_BY_FIELD) {
if (node.getType() == JPA2Lexer.T_ORDER_BY_FIELD && node.childIndex - 1 >= 0 && node.parent.getChild(node.childIndex - 1).getType() == JPA2Lexer.T_ORDER_BY_FIELD) {
sb.appendString(", ");
}
@ -66,11 +66,11 @@ public class TreeToQuery implements TreeVisitorAction {
return ((TreeToQueryCapable) t).treeToQueryPre(sb, invalidNodes);
}
if (node.getType() == JPALexer.T_SELECTED_ITEMS) {
if (node.getType() == JPA2Lexer.T_SELECTED_ITEMS) {
return t;
}
if (node.getType() == JPALexer.T_SOURCES) {
if (node.getType() == JPA2Lexer.T_SOURCES) {
sb.appendString("FROM ");
return t;
}
@ -92,7 +92,7 @@ public class TreeToQuery implements TreeVisitorAction {
if (node.token == null)
return t;
if (node.getType() == JPALexer.DISTINCT || node.getType() == JPALexer.FETCH)
if (node.getType() == JPA2Lexer.DISTINCT || node.getType() == JPA2Lexer.FETCH)
sb.appendSpace();

View File

@ -0,0 +1,477 @@
grammar JPA;
// Alexander Kunkel
// More JPA informations:
// http://www.kunkelgmbh.de/jpa/jpa.html
// 28.11.2009
// Alexander Chevelev
// 15.10.2010
options{
backtrack=true;
output=AST;
}
tokens {
T_SELECTED_ITEMS;
T_SELECTED_ITEM;
T_SOURCES;
T_SOURCE;
T_SELECTED_FIELD;
T_SELECTED_ENTITY;
T_ID_VAR;
T_JOIN_VAR;
T_COLLECTION_MEMBER;
T_QUERY;
T_CONDITION;
T_SIMPLE_CONDITION;
T_PARAMETER;
T_GROUP_BY;
T_ORDER_BY;
T_ORDER_BY_FIELD;
T_AGGREGATE_EXPR;
HAVING = 'HAVING';
ASC = 'ASC';
DESC = 'DESC';
AVG = 'AVG';
MAX = 'MAX';
MIN = 'MIN';
SUM = 'SUM';
COUNT = 'COUNT';
OR = 'OR';
AND = 'AND';
LPAREN = '(';
RPAREN = ')';
DISTINCT = 'DISTINCT';
LEFT = 'LEFT';
OUTER = 'OUTER';
INNER = 'INNER';
JOIN = 'JOIN';
FETCH = 'FETCH';
ORDER = 'ORDER';
GROUP = 'GROUP';
BY = 'BY';
}
@header {
package com.haulmont.cuba.core.sys.jpql.antlr;
import com.haulmont.cuba.core.sys.jpql.tree.QueryNode;
import com.haulmont.cuba.core.sys.jpql.tree.SelectedItemNode;
import com.haulmont.cuba.core.sys.jpql.tree.PathNode;
import com.haulmont.cuba.core.sys.jpql.tree.FromNode;
import com.haulmont.cuba.core.sys.jpql.tree.SelectionSourceNode;
import com.haulmont.cuba.core.sys.jpql.tree.IdentificationVariableNode;
import com.haulmont.cuba.core.sys.jpql.tree.JoinVariableNode;
import com.haulmont.cuba.core.sys.jpql.tree.CollectionMemberNode;
import com.haulmont.cuba.core.sys.jpql.tree.WhereNode;
import com.haulmont.cuba.core.sys.jpql.tree.SimpleConditionNode;
import com.haulmont.cuba.core.sys.jpql.tree.ParameterNode;
import com.haulmont.cuba.core.sys.jpql.tree.GroupByNode;
import com.haulmont.cuba.core.sys.jpql.tree.OrderByNode;
import com.haulmont.cuba.core.sys.jpql.tree.OrderByFieldNode;
import com.haulmont.cuba.core.sys.jpql.tree.AggregateExpressionNode;
}
@lexer::header {
package com.haulmont.cuba.core.sys.jpql.antlr;
}
ql_statement
: select_statement;
select_statement
: sl='SELECT' select_clause from_clause (where_clause)? (groupby_clause)? (having_clause)?(orderby_clause)?
-> ^(T_QUERY<QueryNode>[$sl] (select_clause)? from_clause (where_clause)? (groupby_clause)? (having_clause)? (orderby_clause)?);
from_clause
: fr='FROM' identification_variable_declaration (',' identification_variable_or_collection_declaration)*
-> ^(T_SOURCES<FromNode>[$fr] identification_variable_declaration identification_variable_or_collection_declaration*);
identification_variable_or_collection_declaration
: identification_variable_declaration
| collection_member_declaration -> ^(T_SOURCE<SelectionSourceNode> collection_member_declaration);
identification_variable_declaration
: range_variable_declaration joined_clause*
-> ^(T_SOURCE<SelectionSourceNode> range_variable_declaration joined_clause*);
joined_clause
: join | fetch_join;
range_variable_declaration
: range_variable_declaration_source ('AS')? identification_variable
-> ^(T_ID_VAR<IdentificationVariableNode>[$identification_variable.text] range_variable_declaration_source )
;
range_variable_declaration_source
: abstract_schema_name
| lp='(SELECT' select_clause from_clause (where_clause)? (groupby_clause)? (having_clause)?(orderby_clause)? rp=')'
-> ^(T_QUERY<QueryNode>[$lp, $rp] (select_clause)? from_clause (where_clause)? (groupby_clause)? (having_clause)? (orderby_clause)?)
;
join
: join_spec join_association_path_expression ('AS')? identification_variable
-> ^(T_JOIN_VAR<JoinVariableNode>[$join_spec.text, $identification_variable.text] join_association_path_expression )
;
fetch_join
: join_spec 'FETCH' join_association_path_expression;
join_spec
:(('LEFT') ('OUTER')? | 'INNER' )? 'JOIN';
join_association_path_expression
: identification_variable '.' (field'.')* field?
-> ^(T_SELECTED_FIELD<PathNode>[$identification_variable.text] (field)*)
;
collection_member_declaration
: 'IN''(' path_expression ')' ('AS')? identification_variable
-> ^(T_COLLECTION_MEMBER<CollectionMemberNode>[$identification_variable.text] path_expression )
;
path_expression
: identification_variable '.' (field'.')* (field)?
-> ^(T_SELECTED_FIELD<PathNode>[$identification_variable.text] (field)*)
;
select_clause
: ('DISTINCT')? select_expression (',' select_expression)*
-> ^(T_SELECTED_ITEMS ('DISTINCT')? ^(T_SELECTED_ITEM<SelectedItemNode>[] select_expression)*)
;
select_expression
: path_expression
| aggregate_expression
| identification_variable -> ^(T_SELECTED_ENTITY<PathNode>[$identification_variable.text])
| 'OBJECT' '('identification_variable')'
| constructor_expression;
constructor_expression
: 'NEW' constructor_name '(' constructor_item (',' constructor_item)* ')';
constructor_item
: path_expression | aggregate_expression;
aggregate_expression
: aggregate_expression_function_name '(' ('DISTINCT')? path_expression')'
-> ^(T_AGGREGATE_EXPR<AggregateExpressionNode>[] aggregate_expression_function_name '(' ('DISTINCT')? path_expression')')
| 'COUNT' '(' ('DISTINCT')? identification_variable ')'
-> ^(T_AGGREGATE_EXPR<AggregateExpressionNode>[] 'COUNT' '(' ('DISTINCT')? identification_variable ')');
aggregate_expression_function_name
: 'AVG' | 'MAX' | 'MIN' |'SUM' | 'COUNT';
where_clause
: wh='WHERE' conditional_expression-> ^(T_CONDITION<WhereNode>[$wh] conditional_expression)
| 'WHERE' path_expression -> ^(T_CONDITION<WhereNode>[$wh] path_expression);
groupby_clause
: 'GROUP' 'BY' groupby_item (',' groupby_item)*
-> ^(T_GROUP_BY<GroupByNode>[] 'GROUP' 'BY' groupby_item*)
;
groupby_item
: path_expression | identification_variable;
having_clause
: 'HAVING' conditional_expression;
orderby_clause
: 'ORDER' 'BY' orderby_item (',' orderby_item)*
-> ^(T_ORDER_BY<OrderByNode>[] 'ORDER' 'BY' orderby_item*);
orderby_item
: path_expression ('ASC')?
-> ^(T_ORDER_BY_FIELD<OrderByFieldNode>[] path_expression ('ASC')?)
| path_expression 'DESC'
-> ^(T_ORDER_BY_FIELD<OrderByFieldNode>[] path_expression 'DESC');
subquery
: lp='(SELECT' simple_select_clause subquery_from_clause (where_clause)? (groupby_clause)? (having_clause)? rp=')'
-> ^(T_QUERY<QueryNode>[$lp,$rp] simple_select_clause subquery_from_clause (where_clause)? (groupby_clause)? (having_clause)? );
subquery_from_clause
: fr='FROM' subselect_identification_variable_declaration (',' subselect_identification_variable_declaration)*
-> ^(T_SOURCES<FromNode>[$fr] ^(T_SOURCE<SelectionSourceNode> subselect_identification_variable_declaration)*);
subselect_identification_variable_declaration
: identification_variable_declaration
| association_path_expression ('AS')? identification_variable
| collection_member_declaration;
association_path_expression
: path_expression;
simple_select_clause
: ('DISTINCT')? simple_select_expression
-> ^(T_SELECTED_ITEMS ^(T_SELECTED_ITEM<SelectedItemNode>[] ('DISTINCT')? simple_select_expression));
simple_select_expression
: path_expression
| aggregate_expression
| identification_variable;
conditional_expression
: (conditional_term) ('OR' conditional_term)*;
conditional_term
: (conditional_factor) ('AND' conditional_factor)*;
conditional_factor
: ('NOT')? simple_cond_expression -> ^(T_SIMPLE_CONDITION<SimpleConditionNode>[] ('NOT')? simple_cond_expression)
| '('conditional_expression')';
simple_cond_expression
: comparison_expression
| between_expression
| like_expression
| in_expression
| null_comparison_expression
| empty_collection_comparison_expression
| collection_member_expression
| exists_expression
| date_macro_expression;
date_macro_expression
: date_between_macro_expression
| date_before_macro_expression
| date_after_macro_expression
| date_equals_macro_expression
| date_today_macro_expression;
date_between_macro_expression
: '@BETWEEN' '(' path_expression ',' 'NOW' (('+' | '-') INT_NUMERAL)? ',' 'NOW' (('+' | '-') INT_NUMERAL)? ',' ('YEAR' | 'MONTH' | 'DAY' | 'HOUR' |'MINUTE' | 'SECOND') ')';
date_before_macro_expression
: '@DATEBEFORE' '(' path_expression ',' (path_expression | input_parameter) ')';
date_after_macro_expression
: '@DATEAFTER' '(' path_expression ',' (path_expression | input_parameter) ')';
date_equals_macro_expression
: '@DATEEQUALS' '(' path_expression ',' (path_expression | input_parameter) ')';
date_today_macro_expression
: '@TODAY' '(' path_expression ')';
between_expression
: arithmetic_expression ('NOT')? 'BETWEEN' arithmetic_expression 'AND' arithmetic_expression
| string_expression ('NOT')? 'BETWEEN' string_expression 'AND' string_expression
| datetime_expression ('NOT')? 'BETWEEN' datetime_expression 'AND' datetime_expression;
in_expression
: path_expression ('NOT')? 'IN' in_expression_right_part;
in_expression_right_part
: '(' in_item (',' in_item)* ')'
| subquery;
in_item
: literal
| input_parameter;
like_expression
: string_expression ('NOT')? 'LIKE' (pattern_value | input_parameter)('ESCAPE' ESCAPE_CHARACTER)?;
null_comparison_expression
: (path_expression | input_parameter) 'IS' ('NOT')? 'NULL';
empty_collection_comparison_expression
: path_expression 'IS' ('NOT')? 'EMPTY';
collection_member_expression
: entity_expression ('NOT')? 'MEMBER' ('OF')? path_expression;
exists_expression
: ('NOT')? 'EXISTS' subquery;
all_or_any_expression
: ( 'ALL' | 'ANY' | 'SOME') subquery;
comparison_expression
: string_expression comparison_operator (string_expression | all_or_any_expression)
| boolean_expression ('=' | '<>') (boolean_expression | all_or_any_expression)
| enum_expression ('='|'<>') (enum_expression | all_or_any_expression)
| datetime_expression comparison_operator (datetime_expression | all_or_any_expression)
| entity_expression ('=' | '<>') (entity_expression | all_or_any_expression)
| arithmetic_expression comparison_operator (arithmetic_expression | all_or_any_expression);
comparison_operator
: '='
| '>'
| '>='
| '<'
| '<='
| '<>';
arithmetic_expression
: simple_arithmetic_expression
| subquery;
simple_arithmetic_expression
: (arithmetic_term) (( '+' | '-' ) arithmetic_term)*;
arithmetic_term
: (arithmetic_factor) (( '*' | '/' ) arithmetic_factor)*;
arithmetic_factor
: ( '+' | '-' )? arithmetic_primary;
arithmetic_primary
: path_expression
| numeric_literal
| '('simple_arithmetic_expression')'
| input_parameter
| functions_returning_numerics
| aggregate_expression;
string_expression
: string_primary | subquery;
string_primary
: path_expression
| STRINGLITERAL
| input_parameter
| functions_returning_strings
| aggregate_expression;
datetime_expression
: datetime_primary
| subquery;
datetime_primary
: path_expression
| input_parameter
| functions_returning_datetime
| aggregate_expression;
boolean_expression
: boolean_primary
| subquery;
boolean_primary
: path_expression
| boolean_literal
| input_parameter;
enum_expression
: enum_primary
| subquery;
enum_primary
: path_expression
| enum_literal
| input_parameter;
entity_expression
: path_expression
| simple_entity_expression;
simple_entity_expression
: identification_variable
| input_parameter;
functions_returning_numerics
: 'LENGTH' '('string_primary')'
| 'LOCATE' '('string_primary',' string_primary(',' simple_arithmetic_expression)?')'
| 'ABS' '('simple_arithmetic_expression')'
| 'SQRT' '('simple_arithmetic_expression')'
| 'MOD' '('simple_arithmetic_expression',' simple_arithmetic_expression')'
| 'SIZE' '('path_expression')';
functions_returning_datetime
: 'CURRENT_DATE'
| 'CURRENT_TIME'
| 'CURRENT_TIMESTAMP';
functions_returning_strings
: 'CONCAT' '('string_primary',' string_primary')'
| 'SUBSTRING' '('string_primary','simple_arithmetic_expression',' simple_arithmetic_expression')'
| 'TRIM' '('((trim_specification)? (TRIM_CHARACTER)? 'FROM')? string_primary')'
| 'LOWER' '('string_primary')'
| 'UPPER' '('string_primary')';
trim_specification
: 'LEADING'
| 'TRAILING'
| 'BOTH';
//my
abstract_schema_name
: WORD;
//todo fix pattern value if needed
pattern_value
: WORD;
// my
numeric_literal
: ('0x')? INT_NUMERAL ;
input_parameter
: '?' INT_NUMERAL -> ^(T_PARAMETER<ParameterNode>[] '?' INT_NUMERAL )
| NAMED_PARAMETER -> ^(T_PARAMETER<ParameterNode>[] NAMED_PARAMETER )
| '${' WORD '}' -> ^(T_PARAMETER<ParameterNode>[] '${' WORD '}');
literal
: WORD;
constructor_name
: WORD;
enum_literal
: WORD;
boolean_literal
: 'true'
| 'false';
// my
field
: WORD | 'GROUP';
identification_variable
: WORD;
parameter_name
: WORD ('.' WORD)*;
// Lexical Rules
//fix trim character
TRIM_CHARACTER
: '\'.\'';
STRINGLITERAL
: '\'' (~('\'' | '"') )* '\'' ;
WORD
: ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'$')*;
RUSSIAN_SYMBOLS
: ('\u0400'..'\u04FF'|'\u0500'..'\u052F' ) {if ( 1 == 1) throw new IllegalArgumentException("Incorrect symbol");};
NAMED_PARAMETER
: ':'('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'$')* (('.') ('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'$')+)*;
WS : (' '|'\r'|'\t'|'\u000C'|'\n') {$channel=HIDDEN;}
;
COMMENT
: '/*' .* '*/' {$channel=HIDDEN;};
LINE_COMMENT
: '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;};
ESCAPE_CHARACTER
: '\'' (~('\''|'\\') ) '\'';
INT_NUMERAL
: ('0'..'9')+;

View File

@ -117,49 +117,25 @@ join_association_path_expression
//End : here we have simplified joins
collection_member_declaration
: 'IN''(' collection_valued_path_expression ')' ('AS')? identification_variable
-> ^(T_COLLECTION_MEMBER<CollectionMemberNode>[$identification_variable.text] collection_valued_path_expression );
: 'IN''(' path_expression ')' ('AS')? identification_variable
-> ^(T_COLLECTION_MEMBER<CollectionMemberNode>[$identification_variable.text] path_expression );
qualified_identification_variable
: map_field_identification_variable
| 'ENTRY('identification_variable')';
map_field_identification_variable : 'KEY('identification_variable')' | 'VALUE('identification_variable')';
//todo start : simplify path expression and use PathNode
//Start : here we have simplified paths
path_expression
: identification_variable '.' (field'.')* (field)?
-> ^(T_SELECTED_FIELD<PathNode>[$identification_variable.text] (field)*)
;
single_valued_path_expression
: qualified_identification_variable
| 'TREAT('qualified_identification_variable 'AS' subtype')'
| state_field_path_expression
| single_valued_object_path_expression;
//todo treated path
//End : here we have simplified paths
general_identification_variable
: identification_variable
| map_field_identification_variable;
general_subpath
: simple_subpath
| treated_subpath '.' (single_valued_object_field '.')*;
simple_subpath
: general_identification_variable '.' (single_valued_object_field '.')*
;
treated_subpath
: 'TREAT('general_subpath '.' single_valued_object_field 'AS' subtype ')'
| 'TREAT('general_subpath '.' collection_valued_field 'AS' subtype ')';
state_field_path_expression
: general_subpath state_field;
state_valued_path_expression
: state_field_path_expression
| general_identification_variable;
single_valued_object_path_expression
: general_subpath single_valued_object_field;
collection_valued_path_expression
: general_subpath collection_valued_field;
//todo end
update_clause
: entity_name (('AS')? identification_variable)? 'SET' update_item (',' update_item)*;
update_item
@ -176,37 +152,36 @@ select_clause
select_item
: select_expression (('AS')? result_variable)?;
select_expression
: single_valued_path_expression
: path_expression
| identification_variable -> ^(T_SELECTED_ENTITY<PathNode>[$identification_variable.text])
| scalar_expression
| aggregate_expression
| identification_variable
| 'OBJECT' '('identification_variable')'
| constructor_expression;
constructor_expression
: 'NEW' constructor_name '(' constructor_item (',' constructor_item)* ')';
constructor_item
: single_valued_path_expression
: path_expression
| scalar_expression
| aggregate_expression
| identification_variable;
aggregate_expression
: aggregate_expression_function_name '('(DISTINCT)? state_valued_path_expression')'
-> ^(T_AGGREGATE_EXPR<AggregateExpressionNode>[] aggregate_expression_function_name '(' ('DISTINCT')? state_valued_path_expression')')
: aggregate_expression_function_name '('(DISTINCT)? path_expression')'
-> ^(T_AGGREGATE_EXPR<AggregateExpressionNode>[] aggregate_expression_function_name '(' ('DISTINCT')? path_expression')')
| 'COUNT' '('(DISTINCT)? count_argument ')'
-> ^(T_AGGREGATE_EXPR<AggregateExpressionNode>[] 'COUNT' '(' ('DISTINCT')? count_argument ')')
| function_invocation;
aggregate_expression_function_name
: 'AVG' | 'MAX' | 'MIN' |'SUM' | 'COUNT';
count_argument
: identification_variable | state_valued_path_expression | single_valued_object_path_expression;
: identification_variable | path_expression;
where_clause
: wh='WHERE' conditional_expression-> ^(T_CONDITION<WhereNode>[$wh] conditional_expression);
groupby_clause
: 'GROUP BY' groupby_item (',' groupby_item)*
: 'GROUP' 'BY' groupby_item (',' groupby_item)*
-> ^(T_GROUP_BY<GroupByNode>[] 'GROUP' 'BY' groupby_item*);
groupby_item
: single_valued_path_expression
| identification_variable;
: path_expression | identification_variable;
having_clause
: 'HAVING' conditional_expression;
orderby_clause
@ -218,10 +193,10 @@ orderby_item
| orderby_variable 'DESC'
-> ^(T_ORDER_BY_FIELD<OrderByFieldNode>[] orderby_variable 'DESC');
orderby_variable
: state_field_path_expression | general_identification_variable | result_variable;
: path_expression | general_identification_variable | result_variable;
subquery
: lp='(' simple_select_clause subquery_from_clause (where_clause)? (groupby_clause)? (having_clause)? rp=')'
: lp='(SELECT' simple_select_clause subquery_from_clause (where_clause)? (groupby_clause)? (having_clause)? rp=')'
-> ^(T_QUERY<QueryNode>[$lp,$rp] simple_select_clause subquery_from_clause (where_clause)? (groupby_clause)? (having_clause)? );
subquery_from_clause
: fr='FROM' subselect_identification_variable_declaration (',' subselect_identification_variable_declaration)*
@ -247,10 +222,10 @@ derived_collection_member_declaration
: 'IN' superquery_identification_variable'.'(single_valued_object_field '.')*collection_valued_field;
simple_select_clause
: 'SELECT' ('DISTINCT') simple_select_expression
: ('DISTINCT')? simple_select_expression
-> ^(T_SELECTED_ITEMS ^(T_SELECTED_ITEM<SelectedItemNode>[] ('DISTINCT')? simple_select_expression));
simple_select_expression
: single_valued_path_expression
: path_expression
| scalar_expression
| aggregate_expression
| identification_variable;
@ -280,7 +255,9 @@ simple_cond_expression
| null_comparison_expression
| empty_collection_comparison_expression
| collection_member_expression
| exists_expression;
| exists_expression
| date_macro_expression;
//Start: Here we insert our custom macroses
date_macro_expression
: date_between_macro_expression
@ -310,7 +287,7 @@ between_expression
| string_expression ('NOT')? 'BETWEEN' string_expression 'AND' string_expression
| datetime_expression ('NOT')? 'BETWEEN' datetime_expression 'AND' datetime_expression;
in_expression
: (state_valued_path_expression | type_discriminator) ('NOT')? 'IN'
: (path_expression | type_discriminator) ('NOT')? 'IN'
( '(' in_item (',' in_item)* ')'
| subquery
| collection_valued_input_parameter );
@ -319,14 +296,13 @@ in_item
like_expression
: string_expression ('NOT')? 'LIKE' (pattern_value | input_parameter)('ESCAPE' escape_character)?;
null_comparison_expression
: (single_valued_path_expression | input_parameter) 'IS' ('NOT')? 'NULL';
: (path_expression | input_parameter) 'IS' ('NOT')? 'NULL';
empty_collection_comparison_expression
: collection_valued_path_expression 'IS' ('NOT')? 'EMPTY';
: path_expression 'IS' ('NOT')? 'EMPTY';
collection_member_expression
: entity_or_value_expression ('NOT')? 'MEMBER' ('OF')? collection_valued_path_expression;
: entity_or_value_expression ('NOT')? 'MEMBER' ('OF')? path_expression;
entity_or_value_expression
: single_valued_object_path_expression
| state_field_path_expression
: path_expression
| simple_entity_or_value_expression;
simple_entity_or_value_expression
: identification_variable
@ -342,7 +318,8 @@ comparison_expression
| enum_expression ('='|'<>') (enum_expression | all_or_any_expression)
| datetime_expression comparison_operator (datetime_expression | all_or_any_expression)
| entity_expression ('=' | '<>') (entity_expression | all_or_any_expression)
| entity_type_expression ('=' | '<>') entity_type_expression;
| entity_type_expression ('=' | '<>') entity_type_expression
| arithmetic_expression comparison_operator (arithmetic_expression | all_or_any_expression);
comparison_operator
: '='
@ -360,7 +337,7 @@ arithmetic_term
arithmetic_factor
: (( '+' | '-'))? arithmetic_primary;
arithmetic_primary
: state_valued_path_expression
: path_expression
| numeric_literal
| '('arithmetic_expression')'
| input_parameter
@ -370,7 +347,7 @@ arithmetic_primary
| function_invocation
| subquery;
string_expression
: state_valued_path_expression
: path_expression
| string_literal
| input_parameter
| functions_returning_strings
@ -379,7 +356,7 @@ string_expression
| function_invocation
| subquery;
datetime_expression
: state_valued_path_expression
: path_expression
| input_parameter
| functions_returning_datetime
| aggregate_expression
@ -388,20 +365,20 @@ datetime_expression
| date_time_timestamp_literal
| subquery;
boolean_expression
: state_valued_path_expression
: path_expression
| boolean_literal
| input_parameter
| case_expression
| function_invocation
| subquery;
enum_expression
: state_valued_path_expression
: path_expression
| enum_literal
| input_parameter
| case_expression
| subquery;
entity_expression
: single_valued_object_path_expression
: path_expression
| simple_entity_expression;
simple_entity_expression
: identification_variable
@ -411,14 +388,14 @@ entity_type_expression
| entity_type_literal
| input_parameter;
type_discriminator
: 'TYPE'(general_identification_variable | single_valued_object_path_expression | input_parameter);
: 'TYPE'(general_identification_variable | path_expression | input_parameter);
functions_returning_numerics
: 'LENGTH('string_expression')'
| 'LOCATE(' string_expression',' string_expression(','arithmetic_expression)?')'
| 'ABS('arithmetic_expression')'
| 'SQRT('arithmetic_expression')'
| 'MOD('arithmetic_expression',' arithmetic_expression')'
| 'SIZE('collection_valued_path_expression')'
| 'SIZE('path_expression')'
| 'INDEX('identification_variable')';
functions_returning_datetime
: 'CURRENT_DATE'
@ -436,7 +413,7 @@ function_invocation
: 'FUNCTION('function_name (',' function_arg)* ')';
function_arg
: literal
| state_valued_path_expression
| path_expression
| input_parameter
| scalar_expression;
case_expression
@ -451,7 +428,7 @@ when_clause
simple_case_expression
: 'CASE' case_operand simple_when_clause (simple_when_clause)* 'ELSE' scalar_expression 'END';
case_operand
: state_valued_path_expression
: path_expression
| type_discriminator;
simple_when_clause
: 'WHEN' scalar_expression 'THEN' scalar_expression;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@ package com.haulmont.cuba.core.sys.jpql.transform;
import com.haulmont.cuba.core.global.QueryTransformer;
import com.haulmont.cuba.core.sys.jpql.*;
import com.haulmont.cuba.core.sys.jpql.antlr.JPALexer;
import com.haulmont.cuba.core.sys.jpql.antlr2.JPA2Lexer;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.tree.CommonErrorNode;
import org.antlr.runtime.tree.CommonTree;
@ -117,7 +117,7 @@ public class QueryTransformerAstBased implements QueryTransformer {
EntityReference ref = inferer.infer(queryAnalyzer);
try {
CommonTree statementTree = Parser.parse(statement);
CommonTree whereClause = (CommonTree) statementTree.getFirstChildWithType(JPALexer.T_CONDITION);
CommonTree whereClause = (CommonTree) statementTree.getFirstChildWithType(JPA2Lexer.T_CONDITION);
addWhere(whereClause, ref, true);
} catch (RecognitionException e) {
throw new RuntimeException(e);

View File

@ -6,7 +6,7 @@
package com.haulmont.cuba.core.sys.jpql.transform;
import com.haulmont.cuba.core.sys.jpql.QueryTreeAnalyzer;
import com.haulmont.cuba.core.sys.jpql.antlr.JPALexer;
import com.haulmont.cuba.core.sys.jpql.antlr2.JPA2Lexer;
import com.haulmont.cuba.core.sys.jpql.tree.*;
import org.antlr.runtime.CommonToken;
import org.antlr.runtime.tree.CommonTree;
@ -27,9 +27,9 @@ public class QueryTreeTransformer extends QueryTreeAnalyzer {
public void mixinWhereConditionsIntoTree(CommonTree whereTreeToMixIn) {
CommonTree whereTreeToMixWithin = (CommonTree) tree.getFirstChildWithType(JPALexer.T_CONDITION);
CommonTree whereTreeToMixWithin = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_CONDITION);
if (whereTreeToMixWithin == null) {
FromNode fromNode = (FromNode) tree.getFirstChildWithType(JPALexer.T_SOURCES);
FromNode fromNode = (FromNode) tree.getFirstChildWithType(JPA2Lexer.T_SOURCES);
List<Tree> endingNodes = new ArrayList<Tree>();
int deletionCount = tree.getChildCount() - (fromNode.getChildIndex() + 1);
for (int i = 0; i < deletionCount; i++) {
@ -41,7 +41,7 @@ public class QueryTreeTransformer extends QueryTreeAnalyzer {
}
tree.freshenParentAndChildIndexes();
} else {
CommonTree and = new CommonTree(new CommonToken(JPALexer.AND, "and"));
CommonTree and = new CommonTree(new CommonToken(JPA2Lexer.AND, "and"));
whereTreeToMixWithin.addChild(and);
for (Object o : whereTreeToMixIn.getChildren()) {
CommonTree t = (CommonTree) o;
@ -52,7 +52,7 @@ public class QueryTreeTransformer extends QueryTreeAnalyzer {
}
public void mixinJoinIntoTree(CommonTree joinClause, EntityReference entityRef, boolean renameVariable) {
CommonTree from = (CommonTree) tree.getFirstChildWithType(JPALexer.T_SOURCES);
CommonTree from = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_SOURCES);
for (int i = 0; i < from.getChildCount(); i++) {
SelectionSourceNode sourceNode = (SelectionSourceNode) from.getChild(i);
if (sourceNode.getChild(0) instanceof IdentificationVariableNode) {
@ -74,13 +74,13 @@ public class QueryTreeTransformer extends QueryTreeAnalyzer {
}
public void addSelectionSource(CommonTree selectionSource) {
CommonTree from = (CommonTree) tree.getFirstChildWithType(JPALexer.T_SOURCES);
CommonTree from = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_SOURCES);
from.addChild(selectionSource);
from.freshenParentAndChildIndexes();
}
public void replaceWithCount(EntityReference entityRef) {
Tree selectedItems = tree.getFirstChildWithType(JPALexer.T_SELECTED_ITEMS);
Tree selectedItems = tree.getFirstChildWithType(JPA2Lexer.T_SELECTED_ITEMS);
boolean isDistinct = "DISTINCT".equalsIgnoreCase(selectedItems.getChild(0).getText());
if (!(isDistinct && selectedItems.getChildCount() == 2 ||
selectedItems.getChildCount() == 1))
@ -95,7 +95,7 @@ public class QueryTreeTransformer extends QueryTreeAnalyzer {
selectedItemNode.deleteChild(0);
selectedItemNode.addChild(countNode);
Tree orderBy = tree.getFirstChildWithType(JPALexer.T_ORDER_BY);
Tree orderBy = tree.getFirstChildWithType(JPA2Lexer.T_ORDER_BY);
if (orderBy != null) {
tree.deleteChild(orderBy.getChildIndex());
}
@ -103,18 +103,18 @@ public class QueryTreeTransformer extends QueryTreeAnalyzer {
}
public void replaceOrderBy(PathEntityReference orderingFieldRef, boolean desc) {
CommonTree orderBy = (CommonTree) tree.getFirstChildWithType(JPALexer.T_ORDER_BY);
CommonTree orderBy = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_ORDER_BY);
OrderByFieldNode orderByField;
if (orderBy == null) {
orderByField = new OrderByFieldNode(JPALexer.T_ORDER_BY_FIELD);
orderByField = new OrderByFieldNode(JPA2Lexer.T_ORDER_BY_FIELD);
orderBy = new OrderByNode(JPALexer.T_ORDER_BY);
orderBy.addChild(new CommonTree(new CommonToken(JPALexer.ORDER, "order")));
orderBy.addChild(new CommonTree(new CommonToken(JPALexer.BY, "by")));
orderBy = new OrderByNode(JPA2Lexer.T_ORDER_BY);
orderBy.addChild(new CommonTree(new CommonToken(JPA2Lexer.ORDER, "order")));
orderBy.addChild(new CommonTree(new CommonToken(JPA2Lexer.BY, "by")));
orderBy.addChild(orderByField);
tree.addChild(orderBy);
} else {
orderByField = (OrderByFieldNode) orderBy.getFirstChildWithType(JPALexer.T_ORDER_BY_FIELD);
orderByField = (OrderByFieldNode) orderBy.getFirstChildWithType(JPA2Lexer.T_ORDER_BY_FIELD);
if (orderByField == null)
throw new IllegalStateException("No ordering field found");
@ -130,35 +130,35 @@ public class QueryTreeTransformer extends QueryTreeAnalyzer {
CommonTree lastNode = (CommonTree) pathNode.deleteChild(pathNode.getChildCount() - 1);
String variableName = pathNode.asPathString('_');
PathNode orderingNode = new PathNode(JPALexer.T_SELECTED_FIELD, variableName);
PathNode orderingNode = new PathNode(JPA2Lexer.T_SELECTED_FIELD, variableName);
orderingNode.addDefaultChild(lastNode.getText());
orderByField.addChild(orderingNode);
JoinVariableNode joinNode = new JoinVariableNode(JPALexer.T_JOIN_VAR, "left join", variableName);
JoinVariableNode joinNode = new JoinVariableNode(JPA2Lexer.T_JOIN_VAR, "left join", variableName);
joinNode.addChild(pathNode);
CommonTree from = (CommonTree) tree.getFirstChildWithType(JPALexer.T_SOURCES);
CommonTree from = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_SOURCES);
from.getChild(0).addChild(joinNode); // assumption
} else {
orderByField.addChild(orderingFieldRef.createNode());
}
if (desc) {
orderByField.addChild(new CommonTree(new CommonToken(JPALexer.DESC, "DESC")));
orderByField.addChild(new CommonTree(new CommonToken(JPA2Lexer.DESC, "DESC")));
}
orderByField.freshenParentAndChildIndexes();
}
private AggregateExpressionNode createCountNode(EntityReference ref, boolean distinct) {
AggregateExpressionNode result = new AggregateExpressionNode(JPALexer.T_AGGREGATE_EXPR);
AggregateExpressionNode result = new AggregateExpressionNode(JPA2Lexer.T_AGGREGATE_EXPR);
result.addChild(new CommonTree(new CommonToken(JPALexer.COUNT, "COUNT")));
result.addChild(new CommonTree(new CommonToken(JPALexer.LPAREN, "(")));
result.addChild(new CommonTree(new CommonToken(JPA2Lexer.COUNT, "COUNT")));
result.addChild(new CommonTree(new CommonToken(JPA2Lexer.LPAREN, "(")));
if (distinct) {
result.addChild(new CommonTree(new CommonToken(JPALexer.DISTINCT, "DISTINCT")));
result.addChild(new CommonTree(new CommonToken(JPA2Lexer.DISTINCT, "DISTINCT")));
}
result.addChild(ref.createNode());
result.addChild(new CommonTree(new CommonToken(JPALexer.RPAREN, ")")));
result.addChild(new CommonTree(new CommonToken(JPA2Lexer.RPAREN, ")")));
return result;
}

View File

@ -5,7 +5,7 @@
package com.haulmont.cuba.core.sys.jpql.transform;
import com.haulmont.cuba.core.sys.jpql.antlr.JPALexer;
import com.haulmont.cuba.core.sys.jpql.antlr2.JPA2Lexer;
import com.haulmont.cuba.core.sys.jpql.tree.IdentificationVariableNode;
import com.haulmont.cuba.core.sys.jpql.tree.PathNode;
import org.antlr.runtime.CommonToken;
@ -35,7 +35,7 @@ public class VariableEntityReference implements EntityReference {
}
public Tree createNode() {
return new CommonTree(new CommonToken(JPALexer.WORD, entityVariableName));
return new CommonTree(new CommonToken(JPA2Lexer.WORD, entityVariableName));
}
public boolean isJoinableTo(IdentificationVariableNode node) {
@ -44,7 +44,7 @@ public class VariableEntityReference implements EntityReference {
public PathEntityReference addFieldPath(String fieldPath) {
PathNode pathNode = new PathNode(JPALexer.T_SELECTED_FIELD, entityVariableName);
PathNode pathNode = new PathNode(JPA2Lexer.T_SELECTED_FIELD, entityVariableName);
pathNode.addDefaultChildren(fieldPath);
return new PathEntityReference(pathNode, entityName);
}

View File

@ -5,14 +5,10 @@
package com.haulmont.cuba.core.sys.jpql.tree;
import com.haulmont.cuba.core.sys.jpql.ErrorRec;
import org.antlr.runtime.CommonToken;
import org.antlr.runtime.Token;
import org.antlr.runtime.tree.CommonTree;
import org.antlr.runtime.tree.Tree;
import java.util.List;
/**
* Author: Alexander Chevelev
* Date: 30.10.2010

View File

@ -6,7 +6,7 @@
package com.haulmont.cuba.core.sys.jpql.tree;
import com.haulmont.cuba.core.sys.jpql.*;
import com.haulmont.cuba.core.sys.jpql.antlr.JPALexer;
import com.haulmont.cuba.core.sys.jpql.antlr2.JPA2Lexer;
import com.haulmont.cuba.core.sys.jpql.pointer.Pointer;
import org.antlr.runtime.CommonToken;
import org.antlr.runtime.Token;
@ -93,11 +93,11 @@ public class PathNode extends BaseCustomNode {
public void addDefaultChildren(String fieldPath) {
String[] strings = fieldPath.split("\\.");
for (String string : strings) {
addChild(new CommonTree(new CommonToken(JPALexer.WORD, string)));
addChild(new CommonTree(new CommonToken(JPA2Lexer.WORD, string)));
}
}
public void addDefaultChild(String field) {
addChild(new CommonTree(new CommonToken(JPALexer.WORD, field)));
addChild(new CommonTree(new CommonToken(JPA2Lexer.WORD, field)));
}
}

View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2008-2015 Haulmont. All rights reserved.
* Use is subject to license terms, see http://www.cuba-platform.com/license for details.
*/
package com.haulmont.cuba.core.sys.jpql;
import com.haulmont.cuba.core.sys.jpql.antlr2.*;
import org.antlr.runtime.CharStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.TokenStream;
import org.junit.Test;
/**
* @author degtyarjov
* @version $Id$
*/
public class Jpa2GrammarTest {
@Test
public void testParser() throws Exception {
CharStream cs = new AntlrNoCaseStringStream(
"select u.login " +
"from sec$User u " +
"where u.login = 'admin' " +
"group by u.login having u.version > 0" +
"order by u.login");
JPA2Lexer lexer = new JPA2Lexer(cs);
TokenStream tstream = new CommonTokenStream(lexer);
JPA2Parser jpa2Parser = new JPA2Parser(tstream);
JPA2Parser.ql_statement_return aReturn = jpa2Parser.ql_statement();
System.out.println();
}
}

View File

@ -7,7 +7,7 @@ package com.haulmont.cuba.gui.autocomplete.impl;
import com.haulmont.cuba.core.sys.jpql.DomainModel;
import com.haulmont.cuba.core.sys.jpql.Parser;
import com.haulmont.cuba.core.sys.jpql.antlr.JPALexer;
import com.haulmont.cuba.core.sys.jpql.antlr2.JPA2Lexer;
import com.haulmont.cuba.core.sys.jpql.model.Entity;
import com.haulmont.cuba.core.sys.jpql.model.EntityBuilder;
import com.haulmont.cuba.core.sys.jpql.transform.PathEntityReference;
@ -32,12 +32,12 @@ public class QueryAnalyzerTest {
DomainModel model = prepareDomainModel();
QueryTreeTransformer qa = new QueryTreeTransformer();
qa.prepare(model, "select f from sec$SearchFolder f " +
String query = "select f from sec$SearchFolder f " +
"left join f.user u " +
"left join f.presentation p " +
"where (f.user.id = ?1 or f.user is null) " +
"order by f.sortOrder, f.name");
System.out.println("");
"order by f.sortOrder, f.name";
qa.prepare(model, query);
}
@Test
@ -48,17 +48,17 @@ public class QueryAnalyzerTest {
qa.prepare(model, "select c from Car c");
CommonTree tree = qa.getTree();
CommonTree sources = (CommonTree) tree.getFirstChildWithType(JPALexer.T_SOURCES);
CommonTree sources = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_SOURCES);
assertEquals(1, sources.getChildCount());
assertTrue(sources.getChild(0) instanceof SelectionSourceNode);
CommonTree source = (CommonTree) sources.getFirstChildWithType(JPALexer.T_SOURCE);
CommonTree source = (CommonTree) sources.getFirstChildWithType(JPA2Lexer.T_SOURCE);
assertTrue(source.getChild(0) instanceof IdentificationVariableNode);
JoinVariableNode join = (JoinVariableNode) Parser.parseJoinClause("join a.drivers d");
qa.mixinJoinIntoTree(join, new VariableEntityReference("Car", "c"), true);
tree = qa.getTree();
sources = (CommonTree) tree.getFirstChildWithType(JPALexer.T_SOURCES);
sources = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_SOURCES);
assertEquals(1, sources.getChildCount());
SelectionSourceNode sourceNode = (SelectionSourceNode) sources.getChild(0);
assertEquals(2, sourceNode.getChildCount());
@ -95,7 +95,7 @@ public class QueryAnalyzerTest {
qa.prepare(model, "select d.name from Car c, in(c.drivers) d");
CommonTree tree = qa.getTree();
CommonTree sources = (CommonTree) tree.getFirstChildWithType(JPALexer.T_SOURCES);
CommonTree sources = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_SOURCES);
assertEquals(2, sources.getChildCount());
assertTrue(sources.getChild(0) instanceof SelectionSourceNode);
@ -110,7 +110,7 @@ public class QueryAnalyzerTest {
qa.mixinJoinIntoTree(join, new VariableEntityReference("Car", "c"), true);
tree = qa.getTree();
sources = (CommonTree) tree.getFirstChildWithType(JPALexer.T_SOURCES);
sources = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_SOURCES);
assertEquals(2, sources.getChildCount());
assertTrue(sources.getChild(0) instanceof SelectionSourceNode);
source0 = (CommonTree) sources.getChild(0);
@ -134,12 +134,12 @@ public class QueryAnalyzerTest {
WhereNode where = (WhereNode) Parser.parseWhereClause("where c.model = ?1");
CommonTree tree = qa.getTree();
assertNull(tree.getFirstChildWithType(JPALexer.T_CONDITION));
assertNull(tree.getFirstChildWithType(JPA2Lexer.T_CONDITION));
qa.mixinWhereConditionsIntoTree(where);
tree = qa.getTree();
assertNotNull(tree.getFirstChildWithType(JPALexer.T_CONDITION));
assertNotNull(tree.getFirstChildWithType(JPA2Lexer.T_CONDITION));
}
@Test
@ -150,14 +150,14 @@ public class QueryAnalyzerTest {
qa.prepare(model, "select c from Car c order by c.model");
CommonTree tree = qa.getTree();
CommonTree orderByNode = (CommonTree) tree.getFirstChildWithType(JPALexer.T_ORDER_BY);
Tree orderByField = orderByNode.getFirstChildWithType(JPALexer.T_ORDER_BY_FIELD);
CommonTree orderByNode = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_ORDER_BY);
Tree orderByField = orderByNode.getFirstChildWithType(JPA2Lexer.T_ORDER_BY_FIELD);
assertEquals(1, orderByField.getChildCount());
PathNode pathNode = (PathNode) orderByField.getChild(0);
assertEquals("c", pathNode.getEntityVariableName());
assertEquals("model", pathNode.getChild(0).getText());
pathNode = new PathNode(JPALexer.T_SELECTED_FIELD, "c");
pathNode = new PathNode(JPA2Lexer.T_SELECTED_FIELD, "c");
pathNode.addDefaultChild("regNumber");
qa.replaceOrderBy(new PathEntityReference(pathNode, "Car"), true);
@ -176,14 +176,14 @@ public class QueryAnalyzerTest {
qa.prepare(model, "select c from Car c order by c.model");
CommonTree tree = qa.getTree();
CommonTree selectedItems = (CommonTree) tree.getFirstChildWithType(JPALexer.T_SELECTED_ITEMS);
Tree selectedItem = selectedItems.getFirstChildWithType(JPALexer.T_SELECTED_ITEM);
CommonTree selectedItems = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_SELECTED_ITEMS);
Tree selectedItem = selectedItems.getFirstChildWithType(JPA2Lexer.T_SELECTED_ITEM);
PathNode pathNode = (PathNode) selectedItem.getChild(0);
assertEquals("c", pathNode.getEntityVariableName());
assertEquals(0, pathNode.getChildCount());
CommonTree orderByNode = (CommonTree) tree.getFirstChildWithType(JPALexer.T_ORDER_BY);
CommonTree orderByNode = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_ORDER_BY);
assertNotNull(orderByNode.getFirstChildWithType(JPALexer.T_ORDER_BY_FIELD));
assertNotNull(orderByNode.getFirstChildWithType(JPA2Lexer.T_ORDER_BY_FIELD));
qa.replaceWithCount(new VariableEntityReference("Car", "c"));
@ -193,7 +193,7 @@ public class QueryAnalyzerTest {
assertEquals("COUNT", countExpr.getChild(0).getText());
assertEquals("c", countExpr.getChild(2).getText());
assertEquals(4, countExpr.getChildCount());
assertNull(orderByNode.getFirstChildWithType(JPALexer.T_ORDER_BY));
assertNull(orderByNode.getFirstChildWithType(JPA2Lexer.T_ORDER_BY));
}
@Test
@ -204,20 +204,20 @@ public class QueryAnalyzerTest {
qa.prepare(model, "select distinct d from Car c, in(c.drivers) d order by d.name");
CommonTree tree = qa.getTree();
CommonTree selectedItems = (CommonTree) tree.getFirstChildWithType(JPALexer.T_SELECTED_ITEMS);
Tree selectedItem = selectedItems.getFirstChildWithType(JPALexer.T_SELECTED_ITEM);
CommonTree selectedItems = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_SELECTED_ITEMS);
Tree selectedItem = selectedItems.getFirstChildWithType(JPA2Lexer.T_SELECTED_ITEM);
PathNode pathNode = (PathNode) selectedItem.getChild(0);
assertEquals("d", pathNode.getEntityVariableName());
assertEquals(0, pathNode.getChildCount());
CommonTree orderByNode = (CommonTree) tree.getFirstChildWithType(JPALexer.T_ORDER_BY);
CommonTree orderByNode = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_ORDER_BY);
assertNotNull(orderByNode.getFirstChildWithType(JPALexer.T_ORDER_BY_FIELD));
assertNotNull(orderByNode.getFirstChildWithType(JPA2Lexer.T_ORDER_BY_FIELD));
qa.replaceWithCount(new VariableEntityReference("Driver", "d"));
selectedItems = (CommonTree) tree.getFirstChildWithType(JPALexer.T_SELECTED_ITEMS);
selectedItems = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_SELECTED_ITEMS);
assertEquals(1, selectedItems.getChildCount());
selectedItem = selectedItems.getFirstChildWithType(JPALexer.T_SELECTED_ITEM);
selectedItem = selectedItems.getFirstChildWithType(JPA2Lexer.T_SELECTED_ITEM);
assertTrue(selectedItem.getChild(0) instanceof AggregateExpressionNode);
AggregateExpressionNode countExpr = (AggregateExpressionNode) selectedItem.getChild(0);
@ -225,7 +225,7 @@ public class QueryAnalyzerTest {
assertEquals("DISTINCT", countExpr.getChild(2).getText());
assertEquals("d", countExpr.getChild(3).getText());
assertEquals(5, countExpr.getChildCount());
assertNull(orderByNode.getFirstChildWithType(JPALexer.T_ORDER_BY));
assertNull(orderByNode.getFirstChildWithType(JPA2Lexer.T_ORDER_BY));
}
private DomainModel prepareDomainModel() {

View File

@ -133,7 +133,6 @@ public class QueryTransformerAstBasedTest {
QueryTransformerAstBased transformerAstBased = new QueryTransformerAstBased(model, "SELECT p FROM Player p left join p.team as t WHERE t.name = 'KS FC'", "Player");
String result = transformerAstBased.getResult();
System.out.println(result);
assertEquals("SELECT p FROM Player p left join p.team t WHERE t.name = 'KS FC'", result);
}
@ -238,8 +237,48 @@ public class QueryTransformerAstBasedTest {
assertTransformsToSame(model, "select distinct m from Player p left join p.team.manager m");
}
// The following functions are not supported by JPA2 JPQL (see jpql21.bnf)
// @Test
// public void getResult_noChangesMade_withSubqueries() throws RecognitionException {
// EntityBuilder builder = new EntityBuilder();
// Entity teamEntity = builder.produceImmediately("Team", "name", "owner");
//
// builder.startNewEntity("Player");
// builder.addStringAttribute("name");
// builder.addStringAttribute("nickname");
// builder.addReferenceAttribute("team", "Team");
// Entity playerEntity = builder.produce();
//
// DomainModel model = new DomainModel(playerEntity, teamEntity);
//
// assertTransformsToSame(model, "select p.name from (select t.name from Team t) p");
// assertTransformsToSame(model, "select p.owner from (select t.name, t.owner from Team t) p");
// assertTransformsToSame(model, "select g.owner from (select t.name, t.owner from Team t) p, (select t.name from Team t) g");
// }
// The following functions are not supported by JPA2 JPQL (see jpql21.bnf)
// @Test
// public void getResult_noChangesMade_severalLevelsOfSubquery() throws RecognitionException {
// EntityBuilder builder = new EntityBuilder();
// Entity teamEntity = builder.produceImmediately("Team", "name", "owner");
//
// builder.startNewEntity("Player");
// builder.addStringAttribute("name");
// builder.addStringAttribute("nickname");
// builder.addReferenceAttribute("team", "Team");
// Entity playerEntity = builder.produce();
//
// DomainModel model = new DomainModel(playerEntity, teamEntity);
//
// assertTransformsToSame(model, "select p.owner from (select t from Team t where t.name in (select a.name from Player a)) p");
// // 'as' опускается
// QueryTransformerAstBased transformerAstBased = new QueryTransformerAstBased(model, "select p.owner from (select t.owner from Team as t where t.name = '1') p", "AsdfAsdfAsdf");
// String result = transformerAstBased.getResult();
// assertEquals("select p.owner from (select t.owner from Team t where t.name = '1') p", result);
// }
@Test
public void getResult_noChangesMade_withSubqueries() throws RecognitionException {
public void getResult_noChangesMade_subqueries() throws RecognitionException {
EntityBuilder builder = new EntityBuilder();
Entity teamEntity = builder.produceImmediately("Team", "name", "owner");
@ -251,29 +290,9 @@ public class QueryTransformerAstBasedTest {
DomainModel model = new DomainModel(playerEntity, teamEntity);
assertTransformsToSame(model, "select p.name from (select t.name from Team t) p");
assertTransformsToSame(model, "select p.owner from (select t.name, t.owner from Team t) p");
assertTransformsToSame(model, "select g.owner from (select t.name, t.owner from Team t) p, (select t.name from Team t) g");
}
@Test
public void getResult_noChangesMade_severalLevelsOfSubquery() throws RecognitionException {
EntityBuilder builder = new EntityBuilder();
Entity teamEntity = builder.produceImmediately("Team", "name", "owner");
builder.startNewEntity("Player");
builder.addStringAttribute("name");
builder.addStringAttribute("nickname");
builder.addReferenceAttribute("team", "Team");
Entity playerEntity = builder.produce();
DomainModel model = new DomainModel(playerEntity, teamEntity);
assertTransformsToSame(model, "select p.owner from (select t from Team t where t.name in (select a.name from Player a)) p");
// 'as' опускается
QueryTransformerAstBased transformerAstBased = new QueryTransformerAstBased(model, "select p.owner from (select t.owner from Team as t where t.name = '1') p", "AsdfAsdfAsdf");
String result = transformerAstBased.getResult();
assertEquals("select p.owner from (select t.owner from Team t where t.name = '1') p", result);
assertTransformsToSame(model, "select p.owner from Player pl where exists (select t from Team t where t.name = 'Team1' and pl.team.id = t.id)");
assertTransformsToSame(model, "select p.owner from Player pl where pl.team.id in (select t.id from Team t where t.name = 'Team1')");
assertTransformsToSame(model, "select t.name from Team t where (select count(p) from Player p where p.team.id = t.id) > 10");
}
@Test