summaryrefslogtreecommitdiffstats
path: root/container-search/src/main
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@oath.com>2021-04-14 21:27:50 +0200
committerGitHub <noreply@github.com>2021-04-14 21:27:50 +0200
commit3dcdb83b46e70866d11b55a10c4cae797f105b24 (patch)
treea3e2f139d4ebdea0f0f9de2598337b3eda06d6d6 /container-search/src/main
parent73b45b0b5223cc1b6b2ae2dbdf6a587ef59ab192 (diff)
parentd3ec97a8c9b95117d4c37aeb823b6258668eb5f7 (diff)
Merge pull request #17220 from vespa-engine/bratseth/yql-cleanup
Bratseth/yql cleanup
Diffstat (limited to 'container-search/src/main')
-rw-r--r--container-search/src/main/antlr4/com/yahoo/search/yql/yqlplus.g4248
-rw-r--r--container-search/src/main/java/com/yahoo/search/yql/ProgramParser.java1239
2 files changed, 407 insertions, 1080 deletions
diff --git a/container-search/src/main/antlr4/com/yahoo/search/yql/yqlplus.g4 b/container-search/src/main/antlr4/com/yahoo/search/yql/yqlplus.g4
index b7d443ea56c..c0cf293f2ea 100644
--- a/container-search/src/main/antlr4/com/yahoo/search/yql/yqlplus.g4
+++ b/container-search/src/main/antlr4/com/yahoo/search/yql/yqlplus.g4
@@ -18,22 +18,9 @@ options {
protected Stack<expression_scope> expression_stack = new Stack();
}
-// tokens for command syntax
- CREATE : 'create';
+// tokens
+
SELECT : 'select';
- INSERT : 'insert';
- UPDATE : 'update';
- SET : 'set';
- VIEW : 'view';
- TABLE : 'table';
- DELETE : 'delete';
- INTO : 'into';
- VALUES : 'values';
- IMPORT : 'import';
- NEXT : 'next';
- PAGED : 'paged';
- FALLBACK : 'fallback';
- IMPORT_FROM :;
LIMIT : 'limit';
OFFSET : 'offset';
@@ -44,36 +31,11 @@ options {
FROM : 'from';
SOURCES : 'sources';
AS : 'as';
- MERGE : 'merge';
- LEFT : 'left';
- JOIN : 'join';
-
- ON : 'on';
+
COMMA : ',';
OUTPUT : 'output';
COUNT : 'count';
- RETURNING : 'returning';
- APPLY : 'apply';
- CAST : 'cast';
-
- BEGIN : 'begin';
- END : 'end';
-
- // type-related
- TYPE_BYTE : 'byte';
- TYPE_INT16 : 'int16';
- TYPE_INT32 : 'int32';
- TYPE_INT64 : 'int64';
- TYPE_STRING : 'string';
- TYPE_DOUBLE : 'double';
- TYPE_TIMESTAMP : 'timestamp';
- TYPE_BOOLEAN : 'boolean';
- TYPE_ARRAY : 'array';
- TYPE_MAP : 'map';
-
- // READ_FIELD;
-
- // token literals
+
TRUE : 'true';
FALSE : 'false';
@@ -123,7 +85,6 @@ options {
// statement delimiter
SEMI : ';';
- PROGRAM : 'program';
TIMEOUT : 'timeout';
@@ -149,7 +110,6 @@ FLOAT
fragment
EXPONENT : ('e'|'E') ('+'|'-')? ('0'..'9')+ ;
-
fragment
DIGIT : '0'..'9'
;
@@ -163,7 +123,6 @@ STRING : '"' ( ESC_SEQ | ~('\\'| '"') )* '"'
| '\'' ( ESC_SEQ | ~('\\' | '\'') )* '\''
;
-/////////////////////////////
fragment
HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;
@@ -183,13 +142,11 @@ WS : ( ' '
| '\t'
| '\r'
| '\n'
- // ) {$channel=HIDDEN;}
) -> channel(HIDDEN)
;
COMMENT
: ( ('//') ~('\n'|'\r')* '\r'? '\n'?
- // | '/*' ( options {greedy=false;} : . )* '*/'
| '/*' .*? '*/'
)
-> channel(HIDDEN)
@@ -208,39 +165,20 @@ VESPA_GROUPING_ARG
(')' | ']' | '>')
;
-/*------------------------------------------------------------------
- * PARSER RULES
- *------------------------------------------------------------------*/
+// --------- parser rules ------------
ident
: keyword_as_ident //{addChild(new TerminalNodeImpl(keyword_as_ident.getText()));}
- //{return ID<IDNode>[$keyword_as_ident.text];}
| ID
;
keyword_as_ident
- : SELECT | TABLE | DELETE | INTO | VALUES | LIMIT | OFFSET | WHERE | 'order' | 'by' | DESC | MERGE | LEFT | JOIN
- | ON | OUTPUT | COUNT | BEGIN | END | APPLY | TYPE_BYTE | TYPE_INT16 | TYPE_INT32 | TYPE_INT64 | TYPE_BOOLEAN | TYPE_TIMESTAMP | TYPE_DOUBLE | TYPE_STRING | TYPE_ARRAY | TYPE_MAP
- | VIEW | CREATE | IMPORT | PROGRAM | NEXT | PAGED | SOURCES | SET | MATCHES | LIKE | CAST
+ : SELECT | LIMIT | OFFSET | WHERE | 'order' | 'by' | DESC | OUTPUT | COUNT | SOURCES | MATCHES | LIKE
;
-program : params? (import_statement SEMI)* (ddl SEMI)* (statement SEMI)* EOF
+program : (statement SEMI)* EOF
;
-params
- : PROGRAM LPAREN program_arglist? RPAREN SEMI
- ;
-
-import_statement
- : IMPORT moduleName AS moduleId
- | IMPORT moduleId
- | FROM moduleName IMPORT import_list
- ;
-
-import_list
- : moduleId (',' moduleId)*
- ;
-
moduleId
: ID
;
@@ -250,46 +188,18 @@ moduleName
| namespaced_name
;
-ddl
- : view
- ;
-
-view : CREATE VIEW ID AS source_statement
- ;
-
-program_arglist
- : procedure_argument (',' procedure_argument)*
- ;
-
-procedure_argument
- :
- AT (ident TYPE_ARRAY LT typename GTEQ (expression[false])? ) {registerParameter($ident.start.getText(), $typename.start.getText());}
- | AT (ident typename ('=' expression[false])? ) {registerParameter($ident.start.getText(), $typename.start.getText());}
- ;
-
statement
: output_statement
- | selectvar_statement
- | next_statement
;
output_statement
- : source_statement paged_clause? output_spec?
- ;
-
-paged_clause
- : PAGED fixed_or_parameter
+ : source_statement output_spec?
;
-next_statement
- : NEXT literalString OUTPUT AS ident
- ;
-
source_statement
: query_statement (PIPE pipeline_step)*
;
-
pipeline_step
: namespaced_name arguments[false]?
| vespa_grouping
@@ -300,50 +210,17 @@ vespa_grouping
| annotation VESPA_GROUPING
;
-selectvar_statement
- : CREATE ('temp' | 'temporary') TABLE ident AS LPAREN source_statement RPAREN
- ;
-
-typename
- : TYPE_BYTE | TYPE_INT16 | TYPE_INT32 | TYPE_INT64 | TYPE_STRING | TYPE_BOOLEAN | TYPE_TIMESTAMP
- | arrayType | mapType | TYPE_DOUBLE
- ;
-
-arrayType
- : TYPE_ARRAY LT typename GT
- ;
-
-mapType
- : TYPE_MAP LT typename GT
- ;
-
output_spec
: (OUTPUT AS ident)
| (OUTPUT COUNT AS ident)
;
query_statement
- : merge_statement
- | select_statement
- | insert_statement
- | delete_statement
- | update_statement
+ : select_statement
;
-// This does not use the UNION / UNION ALL from SQL because the semantics are different than SQL UNION
-// - no set operation is implied (no DISTINCT)
-// - CQL resultsets may be heterogeneous (rows may have heterogenous types)
-merge_statement
- : merge_component (MERGE merge_component)+
- ;
-
-merge_component
- : select_statement
- | LPAREN source_statement RPAREN
- ;
-
select_statement
- : SELECT select_field_spec select_source? where? orderby? limit? offset? timeout? fallback?
+ : SELECT select_field_spec select_source? where? orderby? limit? offset? timeout?
;
select_field_spec
@@ -355,10 +232,6 @@ project_spec
: field_def (COMMA field_def)*
;
-fallback
- : FALLBACK select_statement
- ;
-
timeout
: TIMEOUT fixed_or_parameter
;
@@ -366,7 +239,7 @@ timeout
select_source
: select_source_all
| select_source_multi
- | select_source_join
+ | select_source_from
;
select_source_all
@@ -377,23 +250,14 @@ select_source_multi
: FROM SOURCES source_list
;
-select_source_join
- : FROM source_spec join_expr*
+select_source_from
+ : FROM source_spec
;
source_list
: namespaced_name (COMMA namespaced_name )*
;
-join_expr
- : (join_spec source_spec ON joinExpression)
- ;
-
-join_spec
- : LEFT JOIN
- | 'inner'? JOIN
- ;
-
source_spec
: ( data_source (alias_def { ($data_source.ctx).addChild($alias_def.ctx); })? )
;
@@ -466,21 +330,6 @@ argument[boolean in_select]
: expression[$in_select]
;
-// -------- join expressions ------------
-
-// Limit expression syntax for joins: A single equality test and one field from each source.
-// This means it can always turn the join into a query to one source, collecting all of the
-// keys from the results, and then a query to the other source (or querying the other source inline).
-// Does not support map or index references.
-
-joinExpression
- : joinDereferencedExpression EQ joinDereferencedExpression
- ;
-
-joinDereferencedExpression
- : namespaced_name
- ;
-
// --------- expressions ------------
expression [boolean select]
@@ -587,15 +436,6 @@ indexref[boolean in_select]
propertyref
: DOT nm=ID
;
-operatorCall
-@init{
- boolean in_select = expression_stack.peek().in_select;
-}
- : multOp arguments[in_select]
- | additiveOp arguments[in_select]
- | AND arguments[in_select]
- | OR arguments[in_select]
- ;
primaryExpression
@init {
@@ -671,7 +511,7 @@ array_parameter
;
literal_list
- : LPAREN literal_element (COMMA literal_element)* RPAREN //{return ^(ARRAY_LITERAL literal_element+);}
+ : LPAREN literal_element (COMMA literal_element)* RPAREN
;
literal_element
@@ -683,63 +523,3 @@ fixed_or_parameter
: INT
| parameter
;
-
-// INSERT
-
-insert_statement
- : INSERT insert_source insert_values returning_spec?
- ;
-
-insert_source
- : INTO write_data_source
- ;
-
-write_data_source
- : namespaced_name
- ;
-
-insert_values
- : field_names_spec VALUES field_values_group_spec (COMMA field_values_group_spec)*
- | query_statement
- ;
-
-field_names_spec
- : LPAREN field_def (COMMA field_def)* RPAREN
- ;
-
-field_values_spec
- : LPAREN expression[true] (COMMA expression[true])* RPAREN
- ;
-
-field_values_group_spec
- : LPAREN expression[true] (COMMA expression[true])* RPAREN
- ;
-
-returning_spec
- : RETURNING select_field_spec
- ;
-
-// DELETE
-
-delete_statement
- : DELETE delete_source where? returning_spec?
- ;
-
-delete_source
- : FROM write_data_source
- ;
-
-// UPDATE
-
-update_statement
- : UPDATE update_source SET update_values where? returning_spec?
- ;
-
-update_source
- : write_data_source
- ;
-
-update_values
- : field_names_spec EQ field_values_spec
- | field_def (COMMA field_def)*
- ;
diff --git a/container-search/src/main/java/com/yahoo/search/yql/ProgramParser.java b/container-search/src/main/java/com/yahoo/search/yql/ProgramParser.java
index bcd5822a6f6..d3f07bae428 100644
--- a/container-search/src/main/java/com/yahoo/search/yql/ProgramParser.java
+++ b/container-search/src/main/java/com/yahoo/search/yql/ProgramParser.java
@@ -14,76 +14,46 @@ import com.yahoo.search.yql.yqlplusParser.AnnotateExpressionContext;
import com.yahoo.search.yql.yqlplusParser.ArgumentContext;
import com.yahoo.search.yql.yqlplusParser.ArgumentsContext;
import com.yahoo.search.yql.yqlplusParser.ArrayLiteralContext;
-import com.yahoo.search.yql.yqlplusParser.ArrayTypeContext;
import com.yahoo.search.yql.yqlplusParser.Call_sourceContext;
import com.yahoo.search.yql.yqlplusParser.ConstantArrayContext;
import com.yahoo.search.yql.yqlplusParser.ConstantExpressionContext;
import com.yahoo.search.yql.yqlplusParser.ConstantMapExpressionContext;
import com.yahoo.search.yql.yqlplusParser.ConstantPropertyNameAndValueContext;
-import com.yahoo.search.yql.yqlplusParser.Delete_statementContext;
import com.yahoo.search.yql.yqlplusParser.DereferencedExpressionContext;
import com.yahoo.search.yql.yqlplusParser.EqualityExpressionContext;
import com.yahoo.search.yql.yqlplusParser.ExpressionContext;
-import com.yahoo.search.yql.yqlplusParser.FallbackContext;
import com.yahoo.search.yql.yqlplusParser.Field_defContext;
-import com.yahoo.search.yql.yqlplusParser.Field_names_specContext;
-import com.yahoo.search.yql.yqlplusParser.Field_values_group_specContext;
-import com.yahoo.search.yql.yqlplusParser.Field_values_specContext;
import com.yahoo.search.yql.yqlplusParser.IdentContext;
-import com.yahoo.search.yql.yqlplusParser.Import_listContext;
-import com.yahoo.search.yql.yqlplusParser.Import_statementContext;
import com.yahoo.search.yql.yqlplusParser.InNotInTargetContext;
-import com.yahoo.search.yql.yqlplusParser.Insert_sourceContext;
-import com.yahoo.search.yql.yqlplusParser.Insert_statementContext;
-import com.yahoo.search.yql.yqlplusParser.Insert_valuesContext;
-import com.yahoo.search.yql.yqlplusParser.JoinExpressionContext;
-import com.yahoo.search.yql.yqlplusParser.Join_exprContext;
import com.yahoo.search.yql.yqlplusParser.LimitContext;
import com.yahoo.search.yql.yqlplusParser.Literal_elementContext;
import com.yahoo.search.yql.yqlplusParser.Literal_listContext;
import com.yahoo.search.yql.yqlplusParser.LogicalANDExpressionContext;
import com.yahoo.search.yql.yqlplusParser.LogicalORExpressionContext;
import com.yahoo.search.yql.yqlplusParser.MapExpressionContext;
-import com.yahoo.search.yql.yqlplusParser.MapTypeContext;
-import com.yahoo.search.yql.yqlplusParser.Merge_componentContext;
-import com.yahoo.search.yql.yqlplusParser.Merge_statementContext;
-import com.yahoo.search.yql.yqlplusParser.ModuleIdContext;
-import com.yahoo.search.yql.yqlplusParser.ModuleNameContext;
import com.yahoo.search.yql.yqlplusParser.MultiplicativeExpressionContext;
import com.yahoo.search.yql.yqlplusParser.Namespaced_nameContext;
-import com.yahoo.search.yql.yqlplusParser.Next_statementContext;
import com.yahoo.search.yql.yqlplusParser.OffsetContext;
import com.yahoo.search.yql.yqlplusParser.OrderbyContext;
import com.yahoo.search.yql.yqlplusParser.Orderby_fieldContext;
import com.yahoo.search.yql.yqlplusParser.Output_specContext;
-import com.yahoo.search.yql.yqlplusParser.Paged_clauseContext;
-import com.yahoo.search.yql.yqlplusParser.ParamsContext;
import com.yahoo.search.yql.yqlplusParser.Pipeline_stepContext;
-import com.yahoo.search.yql.yqlplusParser.Procedure_argumentContext;
-import com.yahoo.search.yql.yqlplusParser.Program_arglistContext;
import com.yahoo.search.yql.yqlplusParser.Project_specContext;
import com.yahoo.search.yql.yqlplusParser.ProgramContext;
import com.yahoo.search.yql.yqlplusParser.PropertyNameAndValueContext;
import com.yahoo.search.yql.yqlplusParser.Query_statementContext;
import com.yahoo.search.yql.yqlplusParser.RelationalExpressionContext;
import com.yahoo.search.yql.yqlplusParser.RelationalOpContext;
-import com.yahoo.search.yql.yqlplusParser.Returning_specContext;
import com.yahoo.search.yql.yqlplusParser.Scalar_literalContext;
-import com.yahoo.search.yql.yqlplusParser.Select_source_joinContext;
import com.yahoo.search.yql.yqlplusParser.Select_source_multiContext;
import com.yahoo.search.yql.yqlplusParser.Select_statementContext;
-import com.yahoo.search.yql.yqlplusParser.Selectvar_statementContext;
import com.yahoo.search.yql.yqlplusParser.Sequence_sourceContext;
import com.yahoo.search.yql.yqlplusParser.Source_listContext;
import com.yahoo.search.yql.yqlplusParser.Source_specContext;
import com.yahoo.search.yql.yqlplusParser.Source_statementContext;
import com.yahoo.search.yql.yqlplusParser.StatementContext;
import com.yahoo.search.yql.yqlplusParser.TimeoutContext;
-import com.yahoo.search.yql.yqlplusParser.TypenameContext;
import com.yahoo.search.yql.yqlplusParser.UnaryExpressionContext;
-import com.yahoo.search.yql.yqlplusParser.Update_statementContext;
-import com.yahoo.search.yql.yqlplusParser.Update_valuesContext;
-import com.yahoo.search.yql.yqlplusParser.ViewContext;
import com.yahoo.search.yql.yqlplusParser.WhereContext;
import org.antlr.v4.runtime.BaseErrorListener;
@@ -126,7 +96,6 @@ final class ProgramParser {
return prepareParser(file.getAbsoluteFile().toString(), new CaseInsensitiveFileStream(file.getAbsolutePath()));
}
-
private yqlplusParser prepareParser(String programName, CharStream input) {
yqlplusLexer lexer = new yqlplusLexer(input);
lexer.removeErrorListeners();
@@ -168,41 +137,18 @@ final class ProgramParser {
try {
return parser.program();
} catch (RecognitionException e) {
- //Retry parsing using full LL mode
+ // Retry parsing using full LL mode
parser.reset();
parser.getInterpreter().setPredictionMode(PredictionMode.LL);
return parser.program();
}
}
- public OperatorNode<StatementOperator> parse(String programName, InputStream program) throws IOException, RecognitionException {
- yqlplusParser parser = prepareParser(programName, program);
- return convertProgram(parseProgram(parser), parser, programName);
- }
-
public OperatorNode<StatementOperator> parse(String programName, String program) throws IOException, RecognitionException {
yqlplusParser parser = prepareParser(programName, program);
return convertProgram(parseProgram(parser), parser, programName);
}
- public OperatorNode<StatementOperator> parse(File input) throws IOException, RecognitionException {
- yqlplusParser parser = prepareParser(input);
- return convertProgram(parseProgram(parser), parser, input.getAbsoluteFile().toString());
- }
-
- public OperatorNode<ExpressionOperator> parseExpression(String input) throws IOException, RecognitionException {
- return convertExpr(prepareParser("<expression>", input).expression(false).getRuleContext(), new Scope());
- }
-
- public OperatorNode<ExpressionOperator> parseExpression(String input, Set<String> visibleAliases) throws IOException, RecognitionException {
- Scope scope = new Scope();
- final Location loc = new Location("<expression>", -1, -1);
- for (String alias : visibleAliases) {
- scope.defineDataSource(loc, alias);
- }
- return convertExpr(prepareParser("<expression>", input).expression(false).getRuleContext(), scope);
- }
-
private Location toLocation(Scope scope, ParseTree node) {
Token start;
if (node instanceof ParserRuleContext) {
@@ -212,8 +158,7 @@ final class ProgramParser {
} else {
throw new ProgramCompileException("Location is not available for type " + node.getClass());
}
- Location location = new Location(scope != null? scope.programName: "<string>", start.getLine(), start.getCharPositionInLine());
- return location;
+ return new Location(scope != null? scope.programName: "<string>", start.getLine(), start.getCharPositionInLine());
}
private List<String> readName(Namespaced_nameContext node) {
@@ -230,14 +175,6 @@ final class ProgramParser {
private final List<String> binding;
- Binding(String moduleName, String exportName) {
- this.binding = ImmutableList.of(moduleName, exportName);
- }
-
- Binding(String moduleName) {
- this.binding = ImmutableList.of(moduleName);
- }
-
Binding(List<String> binding) {
this.binding = binding;
}
@@ -263,13 +200,6 @@ final class ProgramParser {
final yqlplusParser parser;
final String programName;
- Scope() {
- this.parser = null;
- this.programName = null;
- this.root = this;
- this.parent = null;
- }
-
Scope(yqlplusParser parser, String programName) {
this.parser = parser;
this.programName = programName;
@@ -288,15 +218,10 @@ final class ProgramParser {
return parser;
}
- public String getProgramName() {
- return programName;
- }
-
public Set<String> getCursors() {
return cursors;
}
-
boolean isBound(String name) {
// bindings live only in the 'root' node
return root.bindings.containsKey(name);
@@ -329,13 +254,6 @@ final class ProgramParser {
root.bindings.put(symbolName, new Binding(binding));
}
- public void bindModuleSymbol(Location loc, List<String> moduleName, String exportName, String symbolName) {
- ImmutableList.Builder<String> builder = ImmutableList.builder();
- builder.addAll(moduleName);
- builder.add(exportName);
- bindModule(loc, builder.build(), symbolName);
- }
-
public void defineDataSource(Location loc, String name) {
if (isCursor(name)) {
throw new ProgramCompileException(loc, "Alias '%s' is already used.", name);
@@ -376,13 +294,12 @@ final class ProgramParser {
}
}
- private OperatorNode<SequenceOperator> convertSelectOrInsertOrUpdateOrDelete(ParseTree node, Scope scopeParent) {
+ private OperatorNode<SequenceOperator> convertSelect(ParseTree node, Scope scopeParent) {
- Preconditions.checkArgument(node instanceof Select_statementContext || node instanceof Insert_statementContext ||
- node instanceof Update_statementContext || node instanceof Delete_statementContext);
+ Preconditions.checkArgument(node instanceof Select_statementContext);
- // SELECT^ select_field_spec select_source where? orderby? limit? offset? timeout? fallback?
- // select is the only place to define where/orderby/limit/offset and joins
+ // SELECT^ select_field_spec select_source where? orderby? limit? offset? timeout?
+ // select is the only place to define where/orderby/limit/offset
Scope scope = scopeParent.child();
ProjectionBuilder proj = null;
OperatorNode<SequenceOperator> source = null;
@@ -391,29 +308,18 @@ final class ProgramParser {
OperatorNode<ExpressionOperator> offset = null;
OperatorNode<ExpressionOperator> limit = null;
OperatorNode<ExpressionOperator> timeout = null;
- OperatorNode<SequenceOperator> fallback = null;
- OperatorNode<SequenceOperator> insertValues = null;
- OperatorNode<ExpressionOperator> updateValues = null;
- ParseTree sourceNode;
-
- if (node instanceof Select_statementContext ) {
- sourceNode = node.getChild(2) != null ? node.getChild(2).getChild(0):null;
- } else {
- sourceNode = node.getChild(1);
- }
+ ParseTree sourceNode = node.getChild(2) != null ? node.getChild(2).getChild(0):null;
if (sourceNode != null) {
switch (getParseTreeIndex(sourceNode)) {
// ALL_SOURCE and MULTI_SOURCE are how FROM SOURCES
// *|source_name,... are parsed
- // They can't be used directly with the JOIN syntax at this time
- case yqlplusParser.RULE_select_source_all: {
+ case yqlplusParser.RULE_select_source_all:
Location location = toLocation(scope, sourceNode.getChild(2));
source = OperatorNode.create(location, SequenceOperator.ALL);
source.putAnnotation("alias", "row");
scope.defineDataSource(location, "row");
- }
break;
case yqlplusParser.RULE_select_source_multi:
Source_listContext multiSourceContext = ((Select_source_multiContext) sourceNode).source_list();
@@ -421,22 +327,8 @@ final class ProgramParser {
source.putAnnotation("alias", "row");
scope.defineDataSource(toLocation(scope, multiSourceContext), "row");
break;
- case yqlplusParser.RULE_select_source_join:
+ case yqlplusParser.RULE_select_source_from:
source = convertSource((ParserRuleContext) sourceNode.getChild(1), scope);
- List<Join_exprContext> joinContexts = ((Select_source_joinContext)sourceNode).join_expr();
- for (Join_exprContext joinContext:joinContexts) {
- source = convertJoin(joinContext, source, scope);
- }
- break;
- case yqlplusParser.RULE_insert_source:
- Insert_sourceContext insertSourceContext = (Insert_sourceContext) sourceNode;
- source = convertSource((ParserRuleContext)insertSourceContext.getChild(1), scope);
- break;
- case yqlplusParser.RULE_delete_source:
- source = convertSource((ParserRuleContext)sourceNode.getChild(1), scope);
- break;
- case yqlplusParser.RULE_update_source:
- source = convertSource((ParserRuleContext)sourceNode.getChild(0), scope);
break;
}
} else {
@@ -451,9 +343,6 @@ final class ProgramParser {
proj = readProjection(((Project_specContext) child.getChild(0)).field_def(), scope);
}
break;
- case yqlplusParser.RULE_returning_spec:
- proj = readProjection(((Returning_specContext) child).select_field_spec().project_spec().field_def(), scope);
- break;
case yqlplusParser.RULE_where:
filter = convertExpr(((WhereContext) child).expression(), scope);
break;
@@ -475,23 +364,6 @@ final class ProgramParser {
case yqlplusParser.RULE_timeout:
timeout = convertExpr(((TimeoutContext) child).fixed_or_parameter(), scope);
break;
- case yqlplusParser.RULE_fallback:
- fallback = convertQuery(((FallbackContext) child).select_statement(), scope);
- break;
- case yqlplusParser.RULE_insert_values:
- if (child.getChild(0) instanceof yqlplusParser.Query_statementContext) {
- insertValues = convertQuery(child.getChild(0).getChild(0), scope);
- } else {
- insertValues = readBatchValues(((Insert_valuesContext) child).field_names_spec(), ((Insert_valuesContext)child).field_values_group_spec(), scope);
- }
- break;
- case yqlplusParser.RULE_update_values:
- if (getParseTreeIndex(child.getChild(0)) == yqlplusParser.RULE_field_def) {
- updateValues = readValues(((Update_valuesContext)child).field_def(), scope);
- } else {
- updateValues = readValues((Field_names_specContext)child.getChild(0), (Field_values_specContext)child.getChild(2), scope);
- }
- break;
}
}
// now assemble the logical plan
@@ -500,26 +372,6 @@ final class ProgramParser {
if (filter != null) {
result = OperatorNode.create(SequenceOperator.FILTER, result, filter);
}
- // insert values
- if (insertValues != null) {
- result = OperatorNode.create(SequenceOperator.INSERT, result, insertValues);
- }
- // update
- if (updateValues != null) {
- if (filter != null) {
- result = OperatorNode.create(SequenceOperator.UPDATE, source, updateValues, filter);
- } else {
- result = OperatorNode.create(SequenceOperator.UPDATE_ALL, source, updateValues);
- }
- }
- // delete
- if (getParseTreeIndex(node) == yqlplusParser.RULE_delete_statement) {
- if (filter != null) {
- result = OperatorNode.create(SequenceOperator.DELETE, source, filter);
- } else {
- result = OperatorNode.create(SequenceOperator.DELETE_ALL, source);
- }
- }
// then sort (or project and sort)
boolean projectBeforeSort = false;
if (orderby != null) {
@@ -558,30 +410,9 @@ final class ProgramParser {
if (timeout != null) {
result = OperatorNode.create(SequenceOperator.TIMEOUT, result, timeout);
}
- // if there's a fallback, emit a fallback node
- if (fallback != null) {
- result = OperatorNode.create(SequenceOperator.FALLBACK, result, fallback);
- }
return result;
}
- private OperatorNode<ExpressionOperator> readValues(List<Field_defContext> fieldDefs, Scope scope) {
- List<String> fieldNames;
- List<OperatorNode<ExpressionOperator>> fieldValues;
- int numPairs = fieldDefs.size();
- fieldNames = Lists.newArrayListWithExpectedSize(numPairs);
- fieldValues = Lists.newArrayListWithExpectedSize(numPairs);
- for (int j = 0; j < numPairs; j++) {
- ParseTree startNode = fieldDefs.get(j);
- while(startNode.getChildCount() < 3) {
- startNode = startNode.getChild(0);
- }
- fieldNames.add((String) convertExpr(startNode.getChild(0), scope).getArgument(1));
- fieldValues.add(convertExpr(startNode.getChild(2), scope));
- }
- return OperatorNode.create(ExpressionOperator.MAP, fieldNames, fieldValues);
- }
-
private OperatorNode<SequenceOperator> readMultiSource(Scope scope, Source_listContext multiSource) {
List<List<String>> sourceNameList = Lists.newArrayList();
List<Namespaced_nameContext> nameSpaces = multiSource.namespaced_name();
@@ -591,9 +422,7 @@ final class ProgramParser {
}
return OperatorNode.create(toLocation(scope, multiSource), SequenceOperator.MULTISOURCE, sourceNameList);
}
-// pipeline_step
-// : namespaced_name arguments[false]?
-// ;
+
private OperatorNode<SequenceOperator> convertPipe(Query_statementContext queryStatementContext, List<Pipeline_stepContext> nodes, Scope scope) {
OperatorNode<SequenceOperator> result = convertQuery(queryStatementContext.getChild(0), scope.getRoot());
for (Pipeline_stepContext step:nodes) {
@@ -603,7 +432,7 @@ final class ProgramParser {
} else {
List<String> name = readName(step.namespaced_name());
List<OperatorNode<ExpressionOperator>> args = ImmutableList.of();
- //LPAREN (argument[$in_select] (COMMA argument[$in_select])*) RPAREN
+ // LPAREN (argument[$in_select] (COMMA argument[$in_select])*) RPAREN
if (step.getChildCount() > 1) {
ArgumentsContext arguments = step.arguments();
if (arguments.getChildCount() > 2) {
@@ -621,56 +450,25 @@ final class ProgramParser {
return result;
}
- private OperatorNode<SequenceOperator> convertMerge(List<Merge_componentContext> mergeComponentList, Scope scope) {
- Preconditions.checkArgument(mergeComponentList != null);
- List<OperatorNode<SequenceOperator>> sources = Lists.newArrayListWithExpectedSize(mergeComponentList.size());
- for (Merge_componentContext mergeComponent:mergeComponentList) {
- Select_statementContext selectContext = mergeComponent.select_statement();
- Source_statementContext sourceContext = mergeComponent.source_statement();
- if (selectContext != null) {
- sources.add(convertQuery(selectContext, scope.getRoot()));
- } else {
- sources.add(convertQuery(sourceContext, scope.getRoot()));
- }
- }
- return OperatorNode.create(SequenceOperator.MERGE, sources);
- }
-
private OperatorNode<SequenceOperator> convertQuery(ParseTree node, Scope scope) {
- if (node instanceof Select_statementContext
- || node instanceof Insert_statementContext
- || node instanceof Update_statementContext
- || node instanceof Delete_statementContext) {
- return convertSelectOrInsertOrUpdateOrDelete(node, scope.getRoot());
+ if (node instanceof Select_statementContext) {
+ return convertSelect(node, scope.getRoot());
} else if (node instanceof Source_statementContext) { // for pipe
Source_statementContext sourceStatementContext = (Source_statementContext)node;
return convertPipe(sourceStatementContext.query_statement(), sourceStatementContext.pipeline_step(), scope);
- } else if (node instanceof Merge_statementContext) {
- return convertMerge(((Merge_statementContext)node).merge_component(), scope);
} else {
throw new IllegalArgumentException("Unexpected argument type to convertQueryStatement: " + node.toStringTree());
}
}
- private OperatorNode<SequenceOperator> convertJoin(Join_exprContext node, OperatorNode<SequenceOperator> left, Scope scope) {
- Source_specContext sourceSpec = node.source_spec();
- OperatorNode<SequenceOperator> right = convertSource(sourceSpec, scope);
- JoinExpressionContext joinContext = node.joinExpression();
- OperatorNode<ExpressionOperator> joinExpression = readBinOp(ExpressionOperator.valueOf("EQ"), joinContext.getChild(0), joinContext.getChild(2), scope);
- if (joinExpression.getOperator() != ExpressionOperator.EQ) {
- throw new ProgramCompileException(joinExpression.getLocation(), "Unexpected join expression type: %s (expected EQ)", joinExpression.getOperator());
- }
- return OperatorNode.create(toLocation(scope, sourceSpec), node.join_spec().LEFT() != null ? SequenceOperator.LEFT_JOIN : SequenceOperator.JOIN, left, right, joinExpression);
- }
-
private String assignAlias(String alias, ParserRuleContext node, Scope scope) {
if (alias == null) {
alias = "source";
}
- if (node != null && node instanceof yqlplusParser.Alias_defContext) {
- //alias_def : (AS? ID);
+ if (node instanceof yqlplusParser.Alias_defContext) {
+ // alias_def : (AS? ID);
ParseTree idChild = node;
if (node.getChildCount() > 1) {
idChild = node.getChild(1);
@@ -690,20 +488,14 @@ final class ProgramParser {
scope.defineDataSource(null, candidate);
return alias;
}
- }
-
- private OperatorNode<SequenceOperator> convertSource(ParserRuleContext sourceSpecNode, Scope scope) {
+ }
+ private OperatorNode<SequenceOperator> convertSource(ParserRuleContext sourceSpecNode, Scope scope) {
// DataSources
String alias;
OperatorNode<SequenceOperator> result;
ParserRuleContext dataSourceNode = sourceSpecNode;
ParserRuleContext aliasContext = null;
- //data_source
- //: call_source
- //| LPAREN source_statement RPAREN
- //| sequence_source
- //;
if (sourceSpecNode instanceof Source_specContext) {
dataSourceNode = (ParserRuleContext)sourceSpecNode.getChild(0);
if (sourceSpecNode.getChildCount() == 2) {
@@ -717,7 +509,6 @@ final class ProgramParser {
}
}
switch (getParseTreeIndex(dataSourceNode)) {
- case yqlplusParser.RULE_write_data_source:
case yqlplusParser.RULE_call_source: {
List<String> names = readName(dataSourceNode.getChild(Namespaced_nameContext.class, 0));
alias = assignAlias(names.get(names.size() - 1), aliasContext, scope);
@@ -763,60 +554,9 @@ final class ProgramParser {
return result;
}
- private OperatorNode<TypeOperator> decodeType(Scope scope, TypenameContext type) {
-
- TypeOperator op;
- ParseTree typeNode = type.getChild(0);
- switch (getParseTreeIndex(typeNode)) {
- case yqlplusParser.TYPE_BOOLEAN:
- op = TypeOperator.BOOLEAN;
- break;
- case yqlplusParser.TYPE_BYTE:
- op = TypeOperator.BYTE;
- break;
- case yqlplusParser.TYPE_DOUBLE:
- op = TypeOperator.DOUBLE;
- break;
- case yqlplusParser.TYPE_INT16:
- op = TypeOperator.INT16;
- break;
- case yqlplusParser.TYPE_INT32:
- op = TypeOperator.INT32;
- break;
- case yqlplusParser.TYPE_INT64:
- op = TypeOperator.INT64;
- break;
- case yqlplusParser.TYPE_STRING:
- op = TypeOperator.STRING;
- break;
- case yqlplusParser.TYPE_TIMESTAMP:
- op = TypeOperator.TIMESTAMP;
- break;
- case yqlplusParser.RULE_arrayType:
- return OperatorNode.create(toLocation(scope, typeNode), TypeOperator.ARRAY, decodeType(scope, ((ArrayTypeContext)typeNode).getChild(TypenameContext.class, 0)));
- case yqlplusParser.RULE_mapType:
- return OperatorNode.create(toLocation(scope, typeNode), TypeOperator.MAP, decodeType(scope, ((MapTypeContext)typeNode).getChild(TypenameContext.class, 0)));
- default:
- throw new ProgramCompileException("Unknown type " + typeNode.getText());
- }
- return OperatorNode.create(toLocation(scope, typeNode), op);
- }
-
- private List<String> createBindingName(ParseTree node) {
- if (node instanceof ModuleNameContext) {
- if (((ModuleNameContext)node).namespaced_name() != null) {
- return readName(((ModuleNameContext)node).namespaced_name());
- } else if (((ModuleNameContext)node).literalString() != null) {
- return ImmutableList.of(((ModuleNameContext)node).literalString().STRING().getText());
- }
- } else if (node instanceof ModuleIdContext) {
- return ImmutableList.of(node.getText());
- }
- throw new ProgramCompileException("Wrong context");
- }
-
- private OperatorNode<StatementOperator> convertProgram(
- ParserRuleContext program, yqlplusParser parser, String programName) {
+ private OperatorNode<StatementOperator> convertProgram(ParserRuleContext program,
+ yqlplusParser parser,
+ String programName) {
Scope scope = new Scope(parser, programName);
List<OperatorNode<StatementOperator>> stmts = Lists.newArrayList();
int output = 0;
@@ -825,148 +565,37 @@ final class ProgramParser {
continue;
}
ParserRuleContext ruleContext = (ParserRuleContext) node;
- switch (ruleContext.getRuleIndex()) {
- case yqlplusParser.RULE_params: {
- // ^(ARGUMENT ident typeref expression?)
- ParamsContext paramsContext = (ParamsContext) ruleContext;
- Program_arglistContext program_arglistContext = paramsContext.program_arglist();
- if (program_arglistContext != null) {
- List<Procedure_argumentContext> argList = program_arglistContext.procedure_argument();
- for (Procedure_argumentContext procedureArgumentContext : argList) {
- String name = procedureArgumentContext.ident().getText();
- OperatorNode<TypeOperator> type = decodeType(scope, procedureArgumentContext.getChild(TypenameContext.class, 0));
- OperatorNode<ExpressionOperator> defaultValue = OperatorNode.create(ExpressionOperator.NULL);
- if (procedureArgumentContext.expression() != null) {
- defaultValue = convertExpr(procedureArgumentContext.expression(), scope);
- }
- scope.defineVariable(toLocation(scope, procedureArgumentContext), name);
- stmts.add(OperatorNode.create(StatementOperator.ARGUMENT, name, type, defaultValue));
- }
- }
- break;
- }
- case yqlplusParser.RULE_import_statement: {
- Import_statementContext importContext = (Import_statementContext) ruleContext;
- if (null == importContext.import_list()) {
- List<String> name = createBindingName(node.getChild(1));
- String target;
- Location location = toLocation(scope, node.getChild(1));
- if (node.getChildCount() == 2) {
- target = name.get(0);
- } else if (node.getChildCount() == 4) {
- target = node.getChild(3).getText();
- } else {
- throw new ProgramCompileException("Unknown node count for IMPORT: " + node.toStringTree());
- }
- scope.bindModule(location, name, target);
- } else {
- // | FROM moduleName IMPORT import_list -> ^(IMPORT_FROM
- // moduleName import_list+)
- Import_listContext importListContext = importContext.import_list();
- List<String> name = createBindingName(importContext.moduleName());
- Location location = toLocation(scope, importContext.moduleName());
- List<ModuleIdContext> moduleIds = importListContext.moduleId();
- List<String> symbols = Lists.newArrayListWithExpectedSize(moduleIds.size());
- for (ModuleIdContext cnode : moduleIds) {
- symbols.add(cnode.ID().getText());
- }
- for (String sym : symbols) {
- scope.bindModuleSymbol(location, name, sym, sym);
- }
- }
- break;
- }
+ if (ruleContext.getRuleIndex() != yqlplusParser.RULE_statement)
+ throw new ProgramCompileException("Unknown program element: " + node.getText());
- // DDL
- case yqlplusParser.RULE_ddl:
- ruleContext = (ParserRuleContext)ruleContext.getChild(0);
- break;
- case yqlplusParser.RULE_view: {
- // view and projection expansion now has to be done by the
- // execution engine
- // since views/projections, in order to be useful, have to
- // support being used from outside the same program
- ViewContext viewContext = (ViewContext) ruleContext;
- Location loc = toLocation(scope, viewContext);
- scope.getRoot().defineView(loc, viewContext.ID().getText());
- stmts.add(OperatorNode.create(loc, StatementOperator.DEFINE_VIEW, viewContext.ID().getText(), convertQuery(viewContext.source_statement(), scope.getRoot())));
- break;
+ // ^(STATEMENT_QUERY source_statement paged_clause? output_spec?)
+ StatementContext statementContext = (StatementContext) ruleContext;
+ Source_statementContext source_statement = statementContext.output_statement().source_statement();
+ OperatorNode<SequenceOperator> query;
+ if (source_statement.getChildCount() == 1) {
+ query = convertQuery( source_statement.query_statement().getChild(0), scope);
+ } else {
+ query = convertQuery(source_statement, scope);
}
- case yqlplusParser.RULE_statement: {
- // ^(STATEMENT_QUERY source_statement paged_clause?
- // output_spec?)
- StatementContext statementContext = (StatementContext) ruleContext;
- switch (getParseTreeIndex(ruleContext.getChild(0))) {
- case yqlplusParser.RULE_selectvar_statement: {
- // ^(STATEMENT_SELECTVAR ident source_statement)
- Selectvar_statementContext selectVarContext = (Selectvar_statementContext) ruleContext.getChild(0);
- String variable = selectVarContext.ident().getText();
- OperatorNode<SequenceOperator> query = convertQuery(selectVarContext.source_statement(), scope);
- Location location = toLocation(scope, selectVarContext.ident());
- scope.defineVariable(location, variable);
- stmts.add(OperatorNode.create(location, StatementOperator.EXECUTE, query, variable));
- break;
- }
- case yqlplusParser.RULE_next_statement: {
- // NEXT^ literalString OUTPUT! AS! ident
- Next_statementContext nextStateContext = (Next_statementContext) ruleContext.getChild(0);
- String continuationValue = StringUnescaper.unquote(nextStateContext.literalString().getText());
- String variable = nextStateContext.ident().getText();
- Location location = toLocation(scope, node);
- OperatorNode<SequenceOperator> next = OperatorNode.create(location, SequenceOperator.NEXT, continuationValue);
- stmts.add(OperatorNode.create(location, StatementOperator.EXECUTE, next, variable));
- stmts.add(OperatorNode.create(location, StatementOperator.OUTPUT, variable));
- scope.defineVariable(location, variable);
- break;
+ String variable = "result" + (++output);
+ boolean isCountVariable = false;
+ ParseTree outputStatement = node.getChild(0);
+ Location location = toLocation(scope, outputStatement);
+ for (int i = 1; i < outputStatement.getChildCount(); ++i) {
+ ParseTree child = outputStatement.getChild(i);
+ if ( getParseTreeIndex(child) != yqlplusParser.RULE_output_spec)
+ throw new ProgramCompileException( "Unknown statement attribute: " + child.toStringTree());
+
+ Output_specContext outputSpecContext = (Output_specContext) child;
+ variable = outputSpecContext.ident().getText();
+ if (outputSpecContext.COUNT() != null) {
+ isCountVariable = true;
}
- case yqlplusParser.RULE_output_statement:
- Source_statementContext source_statement = statementContext.output_statement().source_statement();
- OperatorNode<SequenceOperator> query;
- if (source_statement.getChildCount() == 1) {
- query = convertQuery( source_statement.query_statement().getChild(0), scope);
- } else {
- query = convertQuery(source_statement, scope);
- }
- String variable = "result" + (++output);
- boolean isCountVariable = false;
- OperatorNode<ExpressionOperator> pageSize = null;
- ParseTree outputStatement = node.getChild(0);
- Location location = toLocation(scope, outputStatement);
- for (int i = 1; i < outputStatement.getChildCount(); ++i) {
- ParseTree child = outputStatement.getChild(i);
- switch (getParseTreeIndex(child)) {
- case yqlplusParser.RULE_paged_clause:
- Paged_clauseContext pagedContext = (Paged_clauseContext) child;
- pageSize = convertExpr(pagedContext.fixed_or_parameter(), scope);
- break;
- case yqlplusParser.RULE_output_spec:
- Output_specContext outputSpecContext = (Output_specContext) child;
- variable = outputSpecContext.ident().getText();
- if (outputSpecContext.COUNT() != null) {
- isCountVariable = true;
- }
- break;
- default:
- throw new ProgramCompileException( "Unknown statement attribute: " + child.toStringTree());
- }
- }
- scope.defineVariable(location, variable);
- if (pageSize != null) {
- query = OperatorNode.create(SequenceOperator.PAGE, query, pageSize);
- }
- stmts.add(OperatorNode.create(location, StatementOperator.EXECUTE, query, variable));
- stmts.add(OperatorNode.create(location, isCountVariable ? StatementOperator.COUNT:StatementOperator.OUTPUT, variable));
- }
- break;
- }
- default:
- throw new ProgramCompileException("Unknown program element: " + node.getText());
}
+ scope.defineVariable(location, variable);
+ stmts.add(OperatorNode.create(location, StatementOperator.EXECUTE, query, variable));
+ stmts.add(OperatorNode.create(location, isCountVariable ? StatementOperator.COUNT:StatementOperator.OUTPUT, variable));
}
- // traverse the tree, find all of the namespaced calls not covered by
- // imports so we can
- // define "implicit" import statements for them (to make engine
- // implementation easier)
return OperatorNode.create(StatementOperator.PROGRAM, stmts);
}
@@ -982,19 +611,19 @@ final class ProgramParser {
private ProjectionBuilder readProjection(List<Field_defContext> fieldDefs, Scope scope) {
if (null == fieldDefs)
- throw new ProgramCompileException("Null fieldDefs");
+ throw new ProgramCompileException("Null fieldDefs");
ProjectionBuilder proj = new ProjectionBuilder();
for (Field_defContext rulenode : fieldDefs) {
// FIELD
- // expression alias_def?
- OperatorNode<ExpressionOperator> expr = convertExpr(rulenode.getChild(0), scope);
+ // expression alias_def?
+ OperatorNode<ExpressionOperator> expr = convertExpr(rulenode.getChild(0), scope);
- String aliasName = null;
- if (rulenode.getChildCount() > 1) {
- // ^(ALIAS ID)
- aliasName = rulenode.alias_def().ID().getText();
- }
- proj.addField(aliasName, expr);
+ String aliasName = null;
+ if (rulenode.getChildCount() > 1) {
+ // ^(ALIAS ID)
+ aliasName = rulenode.alias_def().ID().getText();
+ }
+ proj.addField(aliasName, expr);
// no grammar for the other rule types at this time
}
return proj;
@@ -1009,358 +638,345 @@ final class ProgramParser {
}
public OperatorNode<ExpressionOperator> convertExpr(ParseTree parseTree, Scope scope) {
- switch (getParseTreeIndex(parseTree)) {
- case yqlplusParser.RULE_vespa_grouping: {
- ParseTree firstChild = parseTree.getChild(0);
- if (getParseTreeIndex(firstChild) == yqlplusParser.RULE_annotation) {
- ParseTree secondChild = parseTree.getChild(1);
- OperatorNode<ExpressionOperator> annotation = convertExpr(((AnnotationContext) firstChild)
- .constantMapExpression(), scope);
- OperatorNode<ExpressionOperator> expr = OperatorNode.create(toLocation(scope, secondChild),
- ExpressionOperator.VESPA_GROUPING, secondChild.getText());
- List<String> names = annotation.getArgument(0);
- List<OperatorNode<ExpressionOperator>> annotates = annotation.getArgument(1);
- for (int i = 0; i < names.size(); ++i) {
- expr.putAnnotation(names.get(i), readConstantExpression(annotates.get(i)));
- }
- return expr;
- } else {
- return OperatorNode.create(toLocation(scope, firstChild), ExpressionOperator.VESPA_GROUPING,
- firstChild.getText());
- }
- }
- case yqlplusParser.RULE_nullOperator:
- return OperatorNode.create(ExpressionOperator.NULL);
- case yqlplusParser.RULE_argument:
- return convertExpr(parseTree.getChild(0), scope);
- case yqlplusParser.RULE_fixed_or_parameter: {
- ParseTree firstChild = parseTree.getChild(0);
- if (getParseTreeIndex(firstChild) == yqlplusParser.INT) {
- return OperatorNode.create(toLocation(scope, firstChild), ExpressionOperator.LITERAL, Integer.valueOf(firstChild.getText()));
- } else {
- return convertExpr(firstChild, scope);
- }
- }
- case yqlplusParser.RULE_constantMapExpression: {
- List<ConstantPropertyNameAndValueContext> propertyList = ((ConstantMapExpressionContext) parseTree).constantPropertyNameAndValue();
- List<String> names = Lists.newArrayListWithExpectedSize(propertyList.size());
- List<OperatorNode<ExpressionOperator>> exprs = Lists.newArrayListWithExpectedSize(propertyList.size());
- for (ConstantPropertyNameAndValueContext child : propertyList) {
- // : propertyName ':' expression[$expression::namespace] ->
- // ^(PROPERTY propertyName expression)
- names.add(StringUnescaper.unquote(child.getChild(0).getText()));
- exprs.add(convertExpr(child.getChild(2), scope));
+ switch (getParseTreeIndex(parseTree)) {
+ case yqlplusParser.RULE_vespa_grouping: {
+ ParseTree firstChild = parseTree.getChild(0);
+ if (getParseTreeIndex(firstChild) == yqlplusParser.RULE_annotation) {
+ ParseTree secondChild = parseTree.getChild(1);
+ OperatorNode<ExpressionOperator> annotation = convertExpr(((AnnotationContext) firstChild)
+ .constantMapExpression(), scope);
+ OperatorNode<ExpressionOperator> expr = OperatorNode.create(toLocation(scope, secondChild),
+ ExpressionOperator.VESPA_GROUPING, secondChild.getText());
+ List<String> names = annotation.getArgument(0);
+ List<OperatorNode<ExpressionOperator>> annotates = annotation.getArgument(1);
+ for (int i = 0; i < names.size(); ++i) {
+ expr.putAnnotation(names.get(i), readConstantExpression(annotates.get(i)));
+ }
+ return expr;
+ } else {
+ return OperatorNode.create(toLocation(scope, firstChild), ExpressionOperator.VESPA_GROUPING,
+ firstChild.getText());
+ }
}
- return OperatorNode.create(toLocation(scope, parseTree),ExpressionOperator.MAP, names, exprs);
- }
- case yqlplusParser.RULE_mapExpression: {
- List<PropertyNameAndValueContext> propertyList = ((MapExpressionContext)parseTree).propertyNameAndValue();
- List<String> names = Lists.newArrayListWithExpectedSize(propertyList.size());
- List<OperatorNode<ExpressionOperator>> exprs = Lists.newArrayListWithCapacity(propertyList.size());
- for (PropertyNameAndValueContext child : propertyList) {
- // : propertyName ':' expression[$expression::namespace] ->
- // ^(PROPERTY propertyName expression)
- names.add(StringUnescaper.unquote(child.getChild(0).getText()));
- exprs.add(convertExpr(child.getChild(2), scope));
- }
- return OperatorNode.create(toLocation(scope, parseTree),ExpressionOperator.MAP, names, exprs);
- }
- case yqlplusParser.RULE_constantArray: {
- List<ConstantExpressionContext> expressionList = ((ConstantArrayContext)parseTree).constantExpression();
- List<OperatorNode<ExpressionOperator>> values = Lists.newArrayListWithExpectedSize(expressionList.size());
- for (ConstantExpressionContext expr : expressionList) {
- values.add(convertExpr(expr, scope));
+ case yqlplusParser.RULE_nullOperator:
+ return OperatorNode.create(ExpressionOperator.NULL);
+ case yqlplusParser.RULE_argument:
+ return convertExpr(parseTree.getChild(0), scope);
+ case yqlplusParser.RULE_fixed_or_parameter: {
+ ParseTree firstChild = parseTree.getChild(0);
+ if (getParseTreeIndex(firstChild) == yqlplusParser.INT) {
+ return OperatorNode.create(toLocation(scope, firstChild), ExpressionOperator.LITERAL, Integer.valueOf(firstChild.getText()));
+ } else {
+ return convertExpr(firstChild, scope);
+ }
+ }
+ case yqlplusParser.RULE_constantMapExpression: {
+ List<ConstantPropertyNameAndValueContext> propertyList = ((ConstantMapExpressionContext) parseTree).constantPropertyNameAndValue();
+ List<String> names = Lists.newArrayListWithExpectedSize(propertyList.size());
+ List<OperatorNode<ExpressionOperator>> exprs = Lists.newArrayListWithExpectedSize(propertyList.size());
+ for (ConstantPropertyNameAndValueContext child : propertyList) {
+ // : propertyName ':' expression[$expression::namespace] ->
+ // ^(PROPERTY propertyName expression)
+ names.add(StringUnescaper.unquote(child.getChild(0).getText()));
+ exprs.add(convertExpr(child.getChild(2), scope));
+ }
+ return OperatorNode.create(toLocation(scope, parseTree),ExpressionOperator.MAP, names, exprs);
+ }
+ case yqlplusParser.RULE_mapExpression: {
+ List<PropertyNameAndValueContext> propertyList = ((MapExpressionContext)parseTree).propertyNameAndValue();
+ List<String> names = Lists.newArrayListWithExpectedSize(propertyList.size());
+ List<OperatorNode<ExpressionOperator>> exprs = Lists.newArrayListWithCapacity(propertyList.size());
+ for (PropertyNameAndValueContext child : propertyList) {
+ // : propertyName ':' expression[$expression::namespace] ->
+ // ^(PROPERTY propertyName expression)
+ names.add(StringUnescaper.unquote(child.getChild(0).getText()));
+ exprs.add(convertExpr(child.getChild(2), scope));
+ }
+ return OperatorNode.create(toLocation(scope, parseTree),ExpressionOperator.MAP, names, exprs);
+ }
+ case yqlplusParser.RULE_constantArray: {
+ List<ConstantExpressionContext> expressionList = ((ConstantArrayContext)parseTree).constantExpression();
+ List<OperatorNode<ExpressionOperator>> values = Lists.newArrayListWithExpectedSize(expressionList.size());
+ for (ConstantExpressionContext expr : expressionList) {
+ values.add(convertExpr(expr, scope));
+ }
+ return OperatorNode.create(toLocation(scope, expressionList.isEmpty()? parseTree:expressionList.get(0)), ExpressionOperator.ARRAY, values);
+ }
+ case yqlplusParser.RULE_arrayLiteral: {
+ List<ExpressionContext> expressionList = ((ArrayLiteralContext) parseTree).expression();
+ List<OperatorNode<ExpressionOperator>> values = Lists.newArrayListWithExpectedSize(expressionList.size());
+ for (ExpressionContext expr : expressionList) {
+ values.add(convertExpr(expr, scope));
+ }
+ return OperatorNode.create(toLocation(scope, expressionList.isEmpty()? parseTree:expressionList.get(0)), ExpressionOperator.ARRAY, values);
+ }
+ // dereferencedExpression: primaryExpression(indexref[in_select]| propertyref)*
+ case yqlplusParser.RULE_dereferencedExpression: {
+ DereferencedExpressionContext dereferencedExpression = (DereferencedExpressionContext) parseTree;
+ Iterator<ParseTree> it = dereferencedExpression.children.iterator();
+ OperatorNode<ExpressionOperator> result = convertExpr(it.next(), scope);
+ while (it.hasNext()) {
+ ParseTree defTree = it.next();
+ if (getParseTreeIndex(defTree) == yqlplusParser.RULE_propertyref) {
+ // DOT nm=ID
+ result = OperatorNode.create(toLocation(scope, parseTree), ExpressionOperator.PROPREF, result, defTree.getChild(1).getText());
+ } else {
+ // indexref
+ result = OperatorNode.create(toLocation(scope, parseTree), ExpressionOperator.INDEX, result, convertExpr(defTree.getChild(1), scope));
+ }
+ }
+ return result;
+ }
+ case yqlplusParser.RULE_primaryExpression: {
+ // ^(CALL namespaced_name arguments)
+ ParseTree firstChild = parseTree.getChild(0);
+ switch (getParseTreeIndex(firstChild)) {
+ case yqlplusParser.RULE_fieldref: {
+ return convertExpr(firstChild, scope);
+ }
+ case yqlplusParser.RULE_callExpresion: {
+ List<ArgumentContext> args = ((ArgumentsContext) firstChild.getChild(1)).argument();
+ List<OperatorNode<ExpressionOperator>> arguments = Lists.newArrayListWithExpectedSize(args.size());
+ for (ArgumentContext argContext : args) {
+ arguments.add(convertExpr(argContext.expression(),scope));
+ }
+ return OperatorNode.create(toLocation(scope, parseTree), ExpressionOperator.CALL, scope.resolvePath(readName((Namespaced_nameContext) firstChild.getChild(0))), arguments);
+ }
+ case yqlplusParser.RULE_parameter:
+ // external variable reference
+ return OperatorNode.create(toLocation(scope, firstChild), ExpressionOperator.VARREF, firstChild.getChild(1).getText());
+ case yqlplusParser.RULE_scalar_literal:
+ case yqlplusParser.RULE_arrayLiteral:
+ case yqlplusParser.RULE_mapExpression:
+ return convertExpr(firstChild, scope);
+ case yqlplusParser.LPAREN:
+ return convertExpr(parseTree.getChild(1), scope);
+ }
+ break;
+ }
+ case yqlplusParser.RULE_parameter: {
+ // external variable reference
+ ParserRuleContext parameterContext = (ParserRuleContext) parseTree;
+ IdentContext identContext = parameterContext.getRuleContext(IdentContext.class, 0);
+ return OperatorNode.create(toLocation(scope, identContext), ExpressionOperator.VARREF, identContext.getText());
+ }
+ case yqlplusParser.RULE_annotateExpression: {
+ //annotation logicalORExpression
+ AnnotationContext annotateExpressionContext = ((AnnotateExpressionContext)parseTree).annotation();
+ OperatorNode<ExpressionOperator> annotation = convertExpr(annotateExpressionContext.constantMapExpression(), scope);
+ OperatorNode<ExpressionOperator> expr = convertExpr(parseTree.getChild(1), scope);
+ List<String> names = annotation.getArgument(0);
+ List<OperatorNode<ExpressionOperator>> annotates = annotation.getArgument(1);
+ for (int i = 0; i < names.size(); ++i) {
+ expr.putAnnotation(names.get(i), readConstantExpression(annotates.get(i)));
+ }
+ return expr;
+ }
+ case yqlplusParser.RULE_expression: {
+ return convertExpr(parseTree.getChild(0), scope);
+ }
+ case yqlplusParser.RULE_logicalANDExpression:
+ LogicalANDExpressionContext andExpressionContext = (LogicalANDExpressionContext) parseTree;
+ return readConjOp(ExpressionOperator.AND, andExpressionContext.equalityExpression(), scope);
+ case yqlplusParser.RULE_logicalORExpression: {
+ int childCount = parseTree.getChildCount();
+ LogicalORExpressionContext logicalORExpressionContext = (LogicalORExpressionContext) parseTree;
+ if (childCount > 1) {
+ return readConjOrOp(ExpressionOperator.OR, logicalORExpressionContext, scope);
+ } else {
+ List<EqualityExpressionContext> equalityExpressionList = ((LogicalANDExpressionContext) parseTree.getChild(0)).equalityExpression();
+ if (equalityExpressionList.size() > 1) {
+ return readConjOp(ExpressionOperator.AND, equalityExpressionList, scope);
+ } else {
+ return convertExpr(equalityExpressionList.get(0), scope);
+ }
+ }
+ }
+ case yqlplusParser.RULE_equalityExpression: {
+ EqualityExpressionContext equalityExpression = (EqualityExpressionContext) parseTree;
+ RelationalExpressionContext relationalExpressionContext = equalityExpression.relationalExpression(0);
+ OperatorNode<ExpressionOperator> expr = convertExpr(relationalExpressionContext, scope);
+ InNotInTargetContext inNotInTarget = equalityExpression.inNotInTarget();
+ int childCount = equalityExpression.getChildCount();
+ if (childCount == 1) {
+ return expr;
+ }
+ if (inNotInTarget != null) {
+ Literal_listContext literalListContext = inNotInTarget.literal_list();
+ boolean isIN = equalityExpression.IN() != null;
+ if (literalListContext == null) {
+ Select_statementContext selectStatementContext = inNotInTarget.select_statement();
+ OperatorNode<SequenceOperator> query = convertQuery(selectStatementContext, scope);
+ return OperatorNode.create(expr.getLocation(),isIN ? ExpressionOperator.IN_QUERY: ExpressionOperator.NOT_IN_QUERY, expr, query);
+ } else {
+ // we need to identify the type of the target; if it's a
+ // scalar we need to wrap it in a CREATE_ARRAY
+ // if it's already a CREATE ARRAY then it's fine, otherwise
+ // we need to know the variable type
+ // return readBinOp(node.getType() == yqlplusParser.IN ?
+ // ExpressionOperator.IN : ExpressionOperator.NOT_IN, node,
+ // scope);
+ return readBinOp(isIN ? ExpressionOperator.IN: ExpressionOperator.NOT_IN, equalityExpression.getChild(0), literalListContext, scope);
+ }
+
+ } else {
+ ParseTree firstChild = equalityExpression.getChild(1);
+ if (equalityExpression.getChildCount() == 2) {
+ switch (getParseTreeIndex(firstChild)) {
+ case yqlplusParser.IS_NULL:
+ return readUnOp(ExpressionOperator.IS_NULL, relationalExpressionContext, scope);
+ case yqlplusParser.IS_NOT_NULL:
+ return readUnOp(ExpressionOperator.IS_NOT_NULL, relationalExpressionContext, scope);
+ }
+ } else {
+ switch (getParseTreeIndex(firstChild.getChild(0))) {
+ case yqlplusParser.EQ:
+ return readBinOp(ExpressionOperator.EQ, equalityExpression.getChild(0), equalityExpression.getChild(2), scope);
+ case yqlplusParser.NEQ:
+ return readBinOp(ExpressionOperator.NEQ, equalityExpression.getChild(0), equalityExpression.getChild(2), scope);
+ case yqlplusParser.LIKE:
+ return readBinOp(ExpressionOperator.LIKE, equalityExpression.getChild(0), equalityExpression.getChild(2), scope);
+ case yqlplusParser.NOTLIKE:
+ return readBinOp(ExpressionOperator.NOT_LIKE, equalityExpression.getChild(0), equalityExpression.getChild(2), scope);
+ case yqlplusParser.MATCHES:
+ return readBinOp(ExpressionOperator.MATCHES, equalityExpression.getChild(0), equalityExpression.getChild(2), scope);
+ case yqlplusParser.NOTMATCHES:
+ return readBinOp(ExpressionOperator.NOT_MATCHES, equalityExpression.getChild(0), equalityExpression.getChild(2), scope);
+ case yqlplusParser.CONTAINS:
+ return readBinOp(ExpressionOperator.CONTAINS, equalityExpression.getChild(0), equalityExpression.getChild(2), scope);
+ }
+ }
+
+ }
+ break;
+ }
+ case yqlplusParser.RULE_relationalExpression: {
+ RelationalExpressionContext relationalExpressionContext = (RelationalExpressionContext) parseTree;
+ RelationalOpContext opContext = relationalExpressionContext.relationalOp();
+ if (opContext != null) {
+ switch (getParseTreeIndex(relationalExpressionContext.relationalOp().getChild(0))) {
+ case yqlplusParser.LT:
+ return readBinOp(ExpressionOperator.LT, parseTree, scope);
+ case yqlplusParser.LTEQ:
+ return readBinOp(ExpressionOperator.LTEQ, parseTree, scope);
+ case yqlplusParser.GT:
+ return readBinOp(ExpressionOperator.GT, parseTree, scope);
+ case yqlplusParser.GTEQ:
+ return readBinOp(ExpressionOperator.GTEQ, parseTree, scope);
+ }
+ } else {
+ return convertExpr(relationalExpressionContext.additiveExpression(0), scope);
+ }
+ }
+ break;
+ case yqlplusParser.RULE_additiveExpression:
+ case yqlplusParser.RULE_multiplicativeExpression: {
+ if (parseTree.getChildCount() > 1) {
+ String opStr = parseTree.getChild(1).getText();
+ switch (opStr) {
+ case "+":
+ return readBinOp(ExpressionOperator.ADD, parseTree, scope);
+ case "-":
+ return readBinOp(ExpressionOperator.SUB, parseTree, scope);
+ case "/":
+ return readBinOp(ExpressionOperator.DIV, parseTree, scope);
+ case "*":
+ return readBinOp(ExpressionOperator.MULT, parseTree, scope);
+ case "%":
+ return readBinOp(ExpressionOperator.MOD, parseTree, scope);
+ default:
+ if (parseTree.getChild(0) instanceof UnaryExpressionContext) {
+ return convertExpr(parseTree.getChild(0), scope);
+ } else {
+ throw new ProgramCompileException(toLocation(scope, parseTree), "Unknown expression type: " + parseTree.toStringTree());
+ }
+ }
+ } else {
+ if (parseTree.getChild(0) instanceof UnaryExpressionContext) {
+ return convertExpr(parseTree.getChild(0), scope);
+ } else if (parseTree.getChild(0) instanceof MultiplicativeExpressionContext) {
+ return convertExpr(parseTree.getChild(0), scope);
+ } else {
+ throw new ProgramCompileException(toLocation(scope, parseTree), "Unknown expression type: " + parseTree.getText());
+ }
+ }
+ }
+ case yqlplusParser.RULE_unaryExpression: {
+ if (1 == parseTree.getChildCount()) {
+ return convertExpr(parseTree.getChild(0), scope);
+ } else if (2 == parseTree.getChildCount()) {
+ if ("-".equals(parseTree.getChild(0).getText())) {
+ return readUnOp(ExpressionOperator.NEGATE, parseTree, scope);
+ } else if ("!".equals(parseTree.getChild(0).getText())) {
+ return readUnOp(ExpressionOperator.NOT, parseTree, scope);
+ }
+ throw new ProgramCompileException(toLocation(scope, parseTree),"Unknown unary operator " + parseTree.getText());
+ } else {
+ throw new ProgramCompileException(toLocation(scope, parseTree),"Unknown child count " + parseTree.getChildCount() + " of " + parseTree.getText());
+ }
+ }
+ case yqlplusParser.RULE_fieldref: {
+ // all in-scope data sources should be defined in scope
+ // the 'first' field in a namespaced reference must be:
+ // - a field name if (and only if) there is exactly one data source
+ // in scope OR
+ // - an alias name, which will be followed by a field name
+ // ^(FIELDREF<FieldReference>[$expression::namespace]
+ // namespaced_name)
+ List<String> path = readName((Namespaced_nameContext) parseTree.getChild(0));
+ Location loc = toLocation(scope, parseTree.getChild(0));
+ String alias = path.get(0);
+ OperatorNode<ExpressionOperator> result = null;
+ int start = 0;
+ if (scope.isCursor(alias)) {
+ if (path.size() > 1) {
+ result = OperatorNode.create(loc, ExpressionOperator.READ_FIELD, alias, path.get(1));
+ start = 2;
+ } else {
+ result = OperatorNode.create(loc, ExpressionOperator.READ_RECORD, alias);
+ start = 1;
+ }
+ } else if (scope.isBound(alias)) {
+ return OperatorNode.create(loc, ExpressionOperator.READ_MODULE, scope.getBinding(alias).toPathWith(path.subList(1, path.size())));
+ } else if (scope.getCursors().size() == 1) {
+ alias = scope.getCursors().iterator().next();
+ result = OperatorNode.create(loc, ExpressionOperator.READ_FIELD, alias, path.get(0));
+ start = 1;
+ } else {
+ // ah ha, we can't end up with a 'loose' UDF call because it
+ // won't be a module or known alias
+ // so we need not support implicit imports for constants used in
+ // UDFs
+ throw new ProgramCompileException(loc, "Unknown field or alias '%s'", alias);
+ }
+ for (int idx = start; idx < path.size(); ++idx) {
+ result = OperatorNode.create(loc, ExpressionOperator.PROPREF, result, path.get(idx));
+ }
+ return result;
}
- return OperatorNode.create(toLocation(scope, expressionList.isEmpty()? parseTree:expressionList.get(0)), ExpressionOperator.ARRAY, values);
+ case yqlplusParser.RULE_scalar_literal:
+ return OperatorNode.create(toLocation(scope, parseTree), ExpressionOperator.LITERAL, convertLiteral((Scalar_literalContext) parseTree));
+ case yqlplusParser.RULE_constantExpression:
+ return convertExpr(parseTree.getChild(0), scope);
+ case yqlplusParser.RULE_literal_list:
+ if (getParseTreeIndex(parseTree.getChild(1)) == yqlplusParser.RULE_array_parameter) {
+ return convertExpr(parseTree.getChild(1), scope);
+ } else {
+ List<Literal_elementContext> elements = ((Literal_listContext) parseTree).literal_element();
+ ParseTree firldElement = elements.get(0).getChild(0);
+ if (elements.size() == 1 && scope.getParser().isArrayParameter(firldElement)) {
+ return convertExpr(firldElement, scope);
+ } else {
+ List<OperatorNode<ExpressionOperator>> values = Lists.newArrayListWithExpectedSize(elements.size());
+ for (Literal_elementContext child : elements) {
+ values.add(convertExpr(child.getChild(0), scope));
+ }
+ return OperatorNode.create(toLocation(scope, elements.get(0)),ExpressionOperator.ARRAY, values);
+ }
+ }
}
- case yqlplusParser.RULE_arrayLiteral: {
- List<ExpressionContext> expressionList = ((ArrayLiteralContext) parseTree).expression();
- List<OperatorNode<ExpressionOperator>> values = Lists.newArrayListWithExpectedSize(expressionList.size());
- for (ExpressionContext expr : expressionList) {
- values.add(convertExpr(expr, scope));
- }
- return OperatorNode.create(toLocation(scope, expressionList.isEmpty()? parseTree:expressionList.get(0)), ExpressionOperator.ARRAY, values);
- }
- //dereferencedExpression: primaryExpression(indexref[in_select]| propertyref)*
- case yqlplusParser.RULE_dereferencedExpression: {
- DereferencedExpressionContext dereferencedExpression = (DereferencedExpressionContext) parseTree;
- Iterator<ParseTree> it = dereferencedExpression.children.iterator();
- OperatorNode<ExpressionOperator> result = convertExpr(it.next(), scope);
- while (it.hasNext()) {
- ParseTree defTree = it.next();
- if (getParseTreeIndex(defTree) == yqlplusParser.RULE_propertyref) {
- //DOT nm=ID
- result = OperatorNode.create(toLocation(scope, parseTree), ExpressionOperator.PROPREF, result, defTree.getChild(1).getText());
- } else {
- //indexref
- result = OperatorNode.create(toLocation(scope, parseTree), ExpressionOperator.INDEX, result, convertExpr(defTree.getChild(1), scope));
- }
- }
- return result;
- }
- case yqlplusParser.RULE_primaryExpression: {
- // ^(CALL namespaced_name arguments)
- ParseTree firstChild = parseTree.getChild(0);
- switch (getParseTreeIndex(firstChild)) {
- case yqlplusParser.RULE_fieldref: {
- return convertExpr(firstChild, scope);
- }
- case yqlplusParser.RULE_callExpresion: {
- List<ArgumentContext> args = ((ArgumentsContext) firstChild.getChild(1)).argument();
- List<OperatorNode<ExpressionOperator>> arguments = Lists.newArrayListWithExpectedSize(args.size());
- for (ArgumentContext argContext : args) {
- arguments.add(convertExpr(argContext.expression(),scope));
- }
- return OperatorNode.create(toLocation(scope, parseTree), ExpressionOperator.CALL, scope.resolvePath(readName((Namespaced_nameContext) firstChild.getChild(0))), arguments);
- }
- // TODO add processing this is not implemented in V3
- // case yqlplusParser.APPLY:
-
- case yqlplusParser.RULE_parameter:
- // external variable reference
- return OperatorNode.create(toLocation(scope, firstChild), ExpressionOperator.VARREF, firstChild.getChild(1).getText());
- case yqlplusParser.RULE_scalar_literal:
- case yqlplusParser.RULE_arrayLiteral:
- case yqlplusParser.RULE_mapExpression:
- return convertExpr(firstChild, scope);
- case yqlplusParser.LPAREN:
- return convertExpr(parseTree.getChild(1), scope);
- }
- break;
- }
-
- // TODO: Temporarily disable CAST - think through how types are named
- // case yqlplusParser.CAST: {
- //
- // return new Cast()
- // }
- // return new CastExpression(payload);
- case yqlplusParser.RULE_parameter: {
- // external variable reference
- ParserRuleContext parameterContext = (ParserRuleContext) parseTree;
- IdentContext identContext = parameterContext.getRuleContext(IdentContext.class, 0);
- return OperatorNode.create(toLocation(scope, identContext), ExpressionOperator.VARREF, identContext.getText());
- }
- case yqlplusParser.RULE_annotateExpression: {
- //annotation logicalORExpression
- AnnotationContext annotateExpressionContext = ((AnnotateExpressionContext)parseTree).annotation();
- OperatorNode<ExpressionOperator> annotation = convertExpr(annotateExpressionContext.constantMapExpression(), scope);
- OperatorNode<ExpressionOperator> expr = convertExpr(parseTree.getChild(1), scope);
- List<String> names = annotation.getArgument(0);
- List<OperatorNode<ExpressionOperator>> annotates = annotation.getArgument(1);
- for (int i = 0; i < names.size(); ++i) {
- expr.putAnnotation(names.get(i), readConstantExpression(annotates.get(i)));
- }
- return expr;
- }
- case yqlplusParser.RULE_expression: {
- return convertExpr(parseTree.getChild(0), scope);
- }
- case yqlplusParser.RULE_logicalANDExpression:
- LogicalANDExpressionContext andExpressionContext = (LogicalANDExpressionContext) parseTree;
- return readConjOp(ExpressionOperator.AND, andExpressionContext.equalityExpression(), scope);
- case yqlplusParser.RULE_logicalORExpression: {
- int childCount = parseTree.getChildCount();
- LogicalORExpressionContext logicalORExpressionContext = (LogicalORExpressionContext) parseTree;
- if (childCount > 1) {
- return readConjOrOp(ExpressionOperator.OR, logicalORExpressionContext, scope);
- } else {
- List<EqualityExpressionContext> equalityExpressionList = ((LogicalANDExpressionContext) parseTree.getChild(0)).equalityExpression();
- if (equalityExpressionList.size() > 1) {
- return readConjOp(ExpressionOperator.AND, equalityExpressionList, scope);
- } else {
- return convertExpr(equalityExpressionList.get(0), scope);
- }
- }
- }
- case yqlplusParser.RULE_equalityExpression: {
- EqualityExpressionContext equalityExpression = (EqualityExpressionContext) parseTree;
- RelationalExpressionContext relationalExpressionContext = equalityExpression.relationalExpression(0);
- OperatorNode<ExpressionOperator> expr = convertExpr(relationalExpressionContext, scope);
- InNotInTargetContext inNotInTarget = equalityExpression.inNotInTarget();
- int childCount = equalityExpression.getChildCount();
- if (childCount == 1) {
- return expr;
- }
- if (inNotInTarget != null) {
- Literal_listContext literalListContext = inNotInTarget.literal_list();
- boolean isIN = equalityExpression.IN() != null;
- if (literalListContext == null) {
- Select_statementContext selectStatementContext = inNotInTarget.select_statement();
- OperatorNode<SequenceOperator> query = convertQuery(selectStatementContext, scope);
- return OperatorNode.create(expr.getLocation(),isIN ? ExpressionOperator.IN_QUERY: ExpressionOperator.NOT_IN_QUERY, expr, query);
- } else {
- // we need to identify the type of the target; if it's a
- // scalar we need to wrap it in a CREATE_ARRAY
- // if it's already a CREATE ARRAY then it's fine, otherwise
- // we need to know the variable type
- // return readBinOp(node.getType() == yqlplusParser.IN ?
- // ExpressionOperator.IN : ExpressionOperator.NOT_IN, node,
- // scope);
- return readBinOp(isIN ? ExpressionOperator.IN: ExpressionOperator.NOT_IN, equalityExpression.getChild(0), literalListContext, scope);
- }
-
- } else {
- ParseTree firstChild = equalityExpression.getChild(1);
- if (equalityExpression.getChildCount() == 2) {
- switch (getParseTreeIndex(firstChild)) {
- case yqlplusParser.IS_NULL:
- return readUnOp(ExpressionOperator.IS_NULL, relationalExpressionContext, scope);
- case yqlplusParser.IS_NOT_NULL:
- return readUnOp(ExpressionOperator.IS_NOT_NULL, relationalExpressionContext, scope);
- }
- } else {
- switch (getParseTreeIndex(firstChild.getChild(0))) {
- case yqlplusParser.EQ:
- return readBinOp(ExpressionOperator.EQ, equalityExpression.getChild(0), equalityExpression.getChild(2), scope);
- case yqlplusParser.NEQ:
- return readBinOp(ExpressionOperator.NEQ, equalityExpression.getChild(0), equalityExpression.getChild(2), scope);
- case yqlplusParser.LIKE:
- return readBinOp(ExpressionOperator.LIKE, equalityExpression.getChild(0), equalityExpression.getChild(2), scope);
- case yqlplusParser.NOTLIKE:
- return readBinOp(ExpressionOperator.NOT_LIKE, equalityExpression.getChild(0), equalityExpression.getChild(2), scope);
- case yqlplusParser.MATCHES:
- return readBinOp(ExpressionOperator.MATCHES, equalityExpression.getChild(0), equalityExpression.getChild(2), scope);
- case yqlplusParser.NOTMATCHES:
- return readBinOp(ExpressionOperator.NOT_MATCHES, equalityExpression.getChild(0), equalityExpression.getChild(2), scope);
- case yqlplusParser.CONTAINS:
- return readBinOp(ExpressionOperator.CONTAINS, equalityExpression.getChild(0), equalityExpression.getChild(2), scope);
- }
- }
-
- }
- break;
- }
- case yqlplusParser.RULE_relationalExpression: {
- RelationalExpressionContext relationalExpressionContext = (RelationalExpressionContext) parseTree;
- RelationalOpContext opContext = relationalExpressionContext.relationalOp();
- if (opContext != null) {
- switch (getParseTreeIndex(relationalExpressionContext.relationalOp().getChild(0))) {
- case yqlplusParser.LT:
- return readBinOp(ExpressionOperator.LT, parseTree, scope);
- case yqlplusParser.LTEQ:
- return readBinOp(ExpressionOperator.LTEQ, parseTree, scope);
- case yqlplusParser.GT:
- return readBinOp(ExpressionOperator.GT, parseTree, scope);
- case yqlplusParser.GTEQ:
- return readBinOp(ExpressionOperator.GTEQ, parseTree, scope);
- }
- } else {
- return convertExpr(relationalExpressionContext.additiveExpression(0), scope);
- }
- }
- break;
- case yqlplusParser.RULE_additiveExpression:
- case yqlplusParser.RULE_multiplicativeExpression: {
- if (parseTree.getChildCount() > 1) {
- String opStr = parseTree.getChild(1).getText();
- switch (opStr) {
- case "+":
- return readBinOp(ExpressionOperator.ADD, parseTree, scope);
- case "-":
- return readBinOp(ExpressionOperator.SUB, parseTree, scope);
- case "/":
- return readBinOp(ExpressionOperator.DIV, parseTree, scope);
- case "*":
- return readBinOp(ExpressionOperator.MULT, parseTree, scope);
- case "%":
- return readBinOp(ExpressionOperator.MOD, parseTree, scope);
- default:
- if (parseTree.getChild(0) instanceof UnaryExpressionContext) {
- return convertExpr(parseTree.getChild(0), scope);
- } else {
- throw new ProgramCompileException(toLocation(scope, parseTree), "Unknown expression type: " + parseTree.toStringTree());
- }
- }
- } else {
- if (parseTree.getChild(0) instanceof UnaryExpressionContext) {
- return convertExpr(parseTree.getChild(0), scope);
- } else if (parseTree.getChild(0) instanceof MultiplicativeExpressionContext) {
- return convertExpr(parseTree.getChild(0), scope);
- } else {
- throw new ProgramCompileException(toLocation(scope, parseTree), "Unknown expression type: " + parseTree.getText());
- }
- }
- }
- case yqlplusParser.RULE_unaryExpression: {
- if (1 == parseTree.getChildCount()) {
- return convertExpr(parseTree.getChild(0), scope);
- } else if (2 == parseTree.getChildCount()) {
- if ("-".equals(parseTree.getChild(0).getText())) {
- return readUnOp(ExpressionOperator.NEGATE, parseTree, scope);
- } else if ("!".equals(parseTree.getChild(0).getText())) {
- return readUnOp(ExpressionOperator.NOT, parseTree, scope);
- }
- throw new ProgramCompileException(toLocation(scope, parseTree),"Unknown unary operator " + parseTree.getText());
- } else {
- throw new ProgramCompileException(toLocation(scope, parseTree),"Unknown child count " + parseTree.getChildCount() + " of " + parseTree.getText());
- }
- }
- case yqlplusParser.RULE_fieldref:
- case yqlplusParser.RULE_joinDereferencedExpression: {
- // all in-scope data sources should be defined in scope
- // the 'first' field in a namespaced reference must be:
- // - a field name if (and only if) there is exactly one data source
- // in scope OR
- // - an alias name, which will be followed by a field name
- // ^(FIELDREF<FieldReference>[$expression::namespace]
- // namespaced_name)
- List<String> path = readName((Namespaced_nameContext) parseTree.getChild(0));
- Location loc = toLocation(scope, parseTree.getChild(0));
- String alias = path.get(0);
- OperatorNode<ExpressionOperator> result = null;
- int start = 0;
- if (scope.isCursor(alias)) {
- if (path.size() > 1) {
- result = OperatorNode.create(loc, ExpressionOperator.READ_FIELD, alias, path.get(1));
- start = 2;
- } else {
- result = OperatorNode.create(loc, ExpressionOperator.READ_RECORD, alias);
- start = 1;
- }
- } else if (scope.isBound(alias)) {
- return OperatorNode.create(loc, ExpressionOperator.READ_MODULE, scope.getBinding(alias).toPathWith(path.subList(1, path.size())));
- } else if (scope.getCursors().size() == 1) {
- alias = scope.getCursors().iterator().next();
- result = OperatorNode.create(loc, ExpressionOperator.READ_FIELD, alias, path.get(0));
- start = 1;
- } else {
- // ah ha, we can't end up with a 'loose' UDF call because it
- // won't be a module or known alias
- // so we need not support implicit imports for constants used in
- // UDFs
- throw new ProgramCompileException(loc, "Unknown field or alias '%s'", alias);
- }
- for (int idx = start; idx < path.size(); ++idx) {
- result = OperatorNode.create(loc, ExpressionOperator.PROPREF, result, path.get(idx));
- }
- return result;
- }
- case yqlplusParser.RULE_scalar_literal:
- return OperatorNode.create(toLocation(scope, parseTree), ExpressionOperator.LITERAL, convertLiteral((Scalar_literalContext) parseTree));
- case yqlplusParser.RULE_insert_values:
- return readValues((Insert_valuesContext) parseTree, scope);
- case yqlplusParser.RULE_constantExpression:
- return convertExpr(parseTree.getChild(0), scope);
- case yqlplusParser.RULE_literal_list:
- if (getParseTreeIndex(parseTree.getChild(1)) == yqlplusParser.RULE_array_parameter) {
- return convertExpr(parseTree.getChild(1), scope);
- } else {
- List<Literal_elementContext> elements = ((Literal_listContext) parseTree).literal_element();
- ParseTree firldElement = elements.get(0).getChild(0);
- if (elements.size() == 1 && scope.getParser().isArrayParameter(firldElement)) {
- return convertExpr(firldElement, scope);
- } else {
- List<OperatorNode<ExpressionOperator>> values = Lists.newArrayListWithExpectedSize(elements.size());
- for (Literal_elementContext child : elements) {
- values.add(convertExpr(child.getChild(0), scope));
- }
- return OperatorNode.create(toLocation(scope, elements.get(0)),ExpressionOperator.ARRAY, values);
- }
- }
- }
- throw new ProgramCompileException(toLocation(scope, parseTree),
- "Unknown expression type: " + parseTree.getText());
+ throw new ProgramCompileException(toLocation(scope, parseTree),
+ "Unknown expression type: " + parseTree.getText());
}
public Object convertLiteral(Scalar_literalContext literal) {
@@ -1462,77 +1078,7 @@ final class ProgramParser {
}
}
- private OperatorNode<ExpressionOperator> readValues(Field_names_specContext nameDefs, Field_values_specContext values, Scope scope) {
- List<Field_defContext> fieldDefs = nameDefs.field_def();
- List<ExpressionContext> valueDefs = values.expression();
- assert fieldDefs.size() == valueDefs.size();
- List<String> fieldNames;
- List<OperatorNode<ExpressionOperator>> fieldValues;
- int numPairs = fieldDefs.size();
- fieldNames = Lists.newArrayListWithExpectedSize(numPairs);
- fieldValues = Lists.newArrayListWithExpectedSize(numPairs);
- for (int i = 0; i < numPairs; i++) {
- fieldNames.add((String) convertExpr(fieldDefs.get(i).expression(), scope).getArgument(1));
- fieldValues.add(convertExpr(valueDefs.get(i), scope));
- }
- return OperatorNode.create(ExpressionOperator.MAP, fieldNames, fieldValues);
- }
-
- private OperatorNode<ExpressionOperator> readValues(ParserRuleContext node, Scope scope) {
- List<String> fieldNames;
- List<OperatorNode<ExpressionOperator>> fieldValues;
- if (node.getRuleIndex() == yqlplusParser.RULE_field_def) {
- Field_defContext fieldDefContext = (Field_defContext)node;
- //TODO double check
- fieldNames = Lists.newArrayListWithExpectedSize(node.getChildCount());
- fieldValues = Lists.newArrayListWithExpectedSize(node.getChildCount());
- for (int i = 0; i < node.getChildCount(); i++) {
- fieldNames.add((String) convertExpr(node.getChild(i).getChild(0).getChild(0), scope).getArgument(1));
- fieldValues.add(convertExpr(node.getChild(i).getChild(0).getChild(1), scope));
- }
- } else {
- assert node.getChildCount() % 2 == 0;
- int numPairs = node.getChildCount() / 2;
- fieldNames = Lists.newArrayListWithExpectedSize(numPairs);
- fieldValues = Lists.newArrayListWithExpectedSize(numPairs);
- for (int i = 0; i < numPairs; i++) {
- fieldNames.add((String) convertExpr(node.getChild(i).getChild(0), scope).getArgument(1));
- fieldValues.add(convertExpr(node.getChild(numPairs + i), scope));
- }
- }
- return OperatorNode.create(ExpressionOperator.MAP, fieldNames, fieldValues);
- }
-
- /*
- * Converts node list
- *
- * a_name, b_name, c_name, a_value_1, b_value_1, c_value_1, a_value_2, b_value_2, c_value2, a_value_3, b_value_3, c_value_3
- *
- * into corresponding constant sequence:
- *
- * [ { a_name : a_value_1, b_name : b_value_1, c_name : c_value_1 }, ... ]
- *
- */
- private OperatorNode<SequenceOperator> readBatchValues(Field_names_specContext nameDefs, List<Field_values_group_specContext> valueGroups, Scope scope) {
- List<Field_defContext> nameContexts = nameDefs.field_def();
- List<String> fieldNames = Lists.newArrayList();
- for (Field_defContext nameContext:nameContexts) {
- fieldNames.add((String) convertExpr(nameContext.getChild(0), scope).getArgument(1));
- }
- List<OperatorNode> records = Lists.newArrayList();
- for (Field_values_group_specContext valueGorup:valueGroups) {
- List<ExpressionContext> expressionList = valueGorup.expression();
- List<OperatorNode<ExpressionOperator>> fieldValues = Lists.newArrayListWithExpectedSize(expressionList.size());
- for (ExpressionContext expressionContext:expressionList) {
- fieldValues.add(convertExpr(expressionContext, scope));
- }
- records.add(OperatorNode.create(ExpressionOperator.MAP, fieldNames, fieldValues));
- }
- // Return constant sequence of records with the given name/values
- return OperatorNode.create(SequenceOperator.EVALUATE, OperatorNode.create(ExpressionOperator.ARRAY, records));
- }
-
- /*
+ /**
* Scans the given node for READ_FIELD expressions.
*
* TODO: Search recursively and consider additional operators
@@ -1557,4 +1103,5 @@ final class ProgramParser {
}
return readFieldList;
}
+
}