mirror of
https://github.com/Canner/WrenAI.git
synced 2026-09-21 13:20:21 +08:00
Bump trino-parser to Trino 358 (#1)
This commit is contained in:
@@ -44,7 +44,6 @@
|
||||
<artifactId>antlr4-runtime</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- for testing -->
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
@@ -63,16 +62,7 @@
|
||||
<plugin>
|
||||
<groupId>org.antlr</groupId>
|
||||
<artifactId>antlr4-maven-plugin</artifactId>
|
||||
<version>${dep.antlr.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>antlr4</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
||||
@@ -34,6 +34,10 @@ standaloneType
|
||||
: type EOF
|
||||
;
|
||||
|
||||
standaloneRowPattern
|
||||
: rowPattern EOF
|
||||
;
|
||||
|
||||
statement
|
||||
: query #statementDefault
|
||||
| USE schema=identifier #use
|
||||
@@ -121,7 +125,7 @@ statement
|
||||
| SHOW COLUMNS (FROM | IN) qualifiedName?
|
||||
(LIKE pattern=string (ESCAPE escape=string)?)? #showColumns
|
||||
| SHOW STATS FOR qualifiedName #showStats
|
||||
| SHOW STATS FOR '(' querySpecification ')' #showStatsForQuery
|
||||
| SHOW STATS FOR '(' query ')' #showStatsForQuery
|
||||
| SHOW CURRENT? ROLES ((FROM | IN) identifier)? #showRoles
|
||||
| SHOW ROLE GRANTS ((FROM | IN) identifier)? #showRoleGrants
|
||||
| DESCRIBE qualifiedName #showColumns
|
||||
@@ -191,7 +195,7 @@ limitRowCount
|
||||
|
||||
rowCount
|
||||
: INTEGER_VALUE
|
||||
| PARAMETER
|
||||
| QUESTION_MARK
|
||||
;
|
||||
|
||||
queryTerm
|
||||
@@ -284,7 +288,7 @@ joinCriteria
|
||||
;
|
||||
|
||||
sampledRelation
|
||||
: aliasedRelation (
|
||||
: patternRecognition (
|
||||
TABLESAMPLE sampleType '(' percentage=expression ')'
|
||||
)?
|
||||
;
|
||||
@@ -294,6 +298,53 @@ sampleType
|
||||
| SYSTEM
|
||||
;
|
||||
|
||||
patternRecognition
|
||||
: aliasedRelation (
|
||||
MATCH_RECOGNIZE '('
|
||||
(PARTITION BY partition+=expression (',' partition+=expression)*)?
|
||||
(ORDER BY sortItem (',' sortItem)*)?
|
||||
(MEASURES measureDefinition (',' measureDefinition)*)?
|
||||
rowsPerMatch?
|
||||
(AFTER MATCH skipTo)?
|
||||
(INITIAL | SEEK)?
|
||||
PATTERN '(' rowPattern ')'
|
||||
(SUBSET subsetDefinition (',' subsetDefinition)*)?
|
||||
DEFINE variableDefinition (',' variableDefinition)*
|
||||
')'
|
||||
(AS? identifier columnAliases?)?)?
|
||||
;
|
||||
|
||||
measureDefinition
|
||||
: expression AS identifier
|
||||
;
|
||||
|
||||
rowsPerMatch
|
||||
: ONE ROW PER MATCH
|
||||
| ALL ROWS PER MATCH emptyMatchHandling?
|
||||
;
|
||||
|
||||
emptyMatchHandling
|
||||
: SHOW EMPTY MATCHES
|
||||
| OMIT EMPTY MATCHES
|
||||
| WITH UNMATCHED ROWS
|
||||
;
|
||||
|
||||
skipTo
|
||||
: 'SKIP' TO NEXT ROW
|
||||
| 'SKIP' PAST LAST ROW
|
||||
| 'SKIP' TO FIRST identifier
|
||||
| 'SKIP' TO LAST identifier
|
||||
| 'SKIP' TO identifier
|
||||
;
|
||||
|
||||
subsetDefinition
|
||||
: name=identifier EQ '(' union+=identifier (',' union+=identifier)* ')'
|
||||
;
|
||||
|
||||
variableDefinition
|
||||
: identifier AS expression
|
||||
;
|
||||
|
||||
aliasedRelation
|
||||
: relationPrimary (AS? identifier columnAliases?)?
|
||||
;
|
||||
@@ -356,16 +407,18 @@ primaryExpression
|
||||
| interval #intervalLiteral
|
||||
| identifier string #typeConstructor
|
||||
| DOUBLE PRECISION string #typeConstructor
|
||||
// for wireprotocol pg style type consturctor
|
||||
| string PG_CAST identifier #typeConstructor
|
||||
| number #numericLiteral
|
||||
| booleanValue #booleanLiteral
|
||||
| string #stringLiteral
|
||||
| BINARY_LITERAL #binaryLiteral
|
||||
| PARAMETER #parameter
|
||||
| QUESTION_MARK #parameter
|
||||
| POSITION '(' valueExpression IN valueExpression ')' #position
|
||||
| '(' expression (',' expression)+ ')' #rowConstructor
|
||||
| ROW '(' expression (',' expression)* ')' #rowConstructor
|
||||
| qualifiedName '(' ASTERISK ')' filter? over? #functionCall
|
||||
| qualifiedName '(' (setQuantifier? expression (',' expression)*)?
|
||||
| processingMode? qualifiedName '(' (setQuantifier? expression (',' expression)*)?
|
||||
(ORDER BY sortItem (',' sortItem)*)? ')' filter? (nullTreatment? over)? #functionCall
|
||||
| identifier '->' expression #lambda
|
||||
| '(' (identifier (',' identifier)*)? ')' '->' expression #lambda
|
||||
@@ -388,6 +441,9 @@ primaryExpression
|
||||
| name=LOCALTIME ('(' precision=INTEGER_VALUE ')')? #specialDateTimeFunction
|
||||
| name=LOCALTIMESTAMP ('(' precision=INTEGER_VALUE ')')? #specialDateTimeFunction
|
||||
| name=CURRENT_USER #currentUser
|
||||
| name=CURRENT_CATALOG #currentCatalog
|
||||
// To support pg-style current_schema()
|
||||
| name=CURRENT_SCHEMA ('(' ')')? #currentSchema
|
||||
| name=CURRENT_PATH #currentPath
|
||||
| SUBSTRING '(' valueExpression FROM valueExpression (FOR valueExpression)? ')' #substring
|
||||
| NORMALIZE '(' valueExpression (',' normalForm)? ')' #normalize
|
||||
@@ -396,6 +452,11 @@ primaryExpression
|
||||
| GROUPING '(' (qualifiedName (',' qualifiedName)*)? ')' #groupingOperation
|
||||
;
|
||||
|
||||
processingMode
|
||||
: RUNNING
|
||||
| FINAL
|
||||
;
|
||||
|
||||
nullTreatment
|
||||
: IGNORE NULLS
|
||||
| RESPECT NULLS
|
||||
@@ -496,6 +557,30 @@ frameBound
|
||||
| expression boundType=(PRECEDING | FOLLOWING) #boundedFrame
|
||||
;
|
||||
|
||||
rowPattern
|
||||
: patternPrimary patternQuantifier? #quantifiedPrimary
|
||||
| rowPattern rowPattern #patternConcatenation
|
||||
| rowPattern '|' rowPattern #patternAlternation
|
||||
;
|
||||
|
||||
patternPrimary
|
||||
: identifier #patternVariable
|
||||
| '(' ')' #emptyPattern
|
||||
| PERMUTE '(' rowPattern (',' rowPattern)* ')' #patternPermutation
|
||||
| '(' rowPattern ')' #groupedPattern
|
||||
| '^' #partitionStartAnchor
|
||||
| '$' #partitionEndAnchor
|
||||
| '{-' rowPattern '-}' #excludedPattern
|
||||
;
|
||||
|
||||
patternQuantifier
|
||||
: ASTERISK (reluctant=QUESTION_MARK)? #zeroOrMoreQuantifier
|
||||
| PLUS (reluctant=QUESTION_MARK)? #oneOrMoreQuantifier
|
||||
| QUESTION_MARK (reluctant=QUESTION_MARK)? #zeroOrOneQuantifier
|
||||
| '{' exactly=INTEGER_VALUE '}' (reluctant=QUESTION_MARK)? #rangeQuantifier
|
||||
| '{' (atLeast=INTEGER_VALUE)? ',' (atMost=INTEGER_VALUE)? '}' (reluctant=QUESTION_MARK)? #rangeQuantifier
|
||||
;
|
||||
|
||||
updateAssignment
|
||||
: identifier EQ expression
|
||||
;
|
||||
@@ -571,26 +656,26 @@ number
|
||||
|
||||
nonReserved
|
||||
// IMPORTANT: this rule must only contain tokens. Nested rules are not supported. See SqlParser.exitNonReserved
|
||||
: ADD | ADMIN | ALL | ANALYZE | ANY | ARRAY | ASC | AT | AUTHORIZATION
|
||||
: ADD | ADMIN | AFTER | ALL | ANALYZE | ANY | ARRAY | ASC | AT | AUTHORIZATION
|
||||
| BERNOULLI
|
||||
| CALL | CASCADE | CATALOGS | COLUMN | COLUMNS | COMMENT | COMMIT | COMMITTED | CURRENT
|
||||
| DATA | DATE | DAY | DEFINER | DESC | DISTRIBUTED | DOUBLE
|
||||
| EXCLUDING | EXPLAIN
|
||||
| FETCH | FILTER | FIRST | FOLLOWING | FORMAT | FUNCTIONS
|
||||
| DATA | DATE | DAY | DEFINE | DEFINER | DESC | DISTRIBUTED | DOUBLE
|
||||
| EMPTY | EXCLUDING | EXPLAIN
|
||||
| FETCH | FILTER | FINAL | FIRST | FOLLOWING | FORMAT | FUNCTIONS
|
||||
| GRANT | GRANTED | GRANTS | GRAPHVIZ | GROUPS
|
||||
| HOUR
|
||||
| IF | IGNORE | INCLUDING | INPUT | INTERVAL | INVOKER | IO | ISOLATION
|
||||
| IF | IGNORE | INCLUDING | INITIAL | INPUT | INTERVAL | INVOKER | IO | ISOLATION
|
||||
| JSON
|
||||
| LAST | LATERAL | LEVEL | LIMIT | LOGICAL
|
||||
| MAP | MATCHED | MATERIALIZED | MERGE | MINUTE | MONTH
|
||||
| MAP | MATCH | MATCHED | MATCHES | MATCH_RECOGNIZE | MATERIALIZED | MEASURES | MERGE | MINUTE | MONTH
|
||||
| NEXT | NFC | NFD | NFKC | NFKD | NO | NONE | NULLIF | NULLS
|
||||
| OFFSET | ONLY | OPTION | ORDINALITY | OUTPUT | OVER
|
||||
| PARTITION | PARTITIONS | PATH | POSITION | PRECEDING | PRECISION | PRIVILEGES | PROPERTIES
|
||||
| RANGE | READ | REFRESH | RENAME | REPEATABLE | REPLACE | RESET | RESPECT | RESTRICT | REVOKE | ROLE | ROLES | ROLLBACK | ROW | ROWS
|
||||
| SCHEMA | SCHEMAS | SECOND | SECURITY | SERIALIZABLE | SESSION | SET | SETS
|
||||
| SHOW | SOME | START | STATS | SUBSTRING | SYSTEM
|
||||
| OFFSET | OMIT | ONE | ONLY | OPTION | ORDINALITY | OUTPUT | OVER
|
||||
| PARTITION | PARTITIONS | PAST | PATH | PATTERN | PER | PERMUTE | POSITION | PRECEDING | PRECISION | PRIVILEGES | PROPERTIES
|
||||
| RANGE | READ | REFRESH | RENAME | REPEATABLE | REPLACE | RESET | RESPECT | RESTRICT | REVOKE | ROLE | ROLES | ROLLBACK | ROW | ROWS | RUNNING
|
||||
| SCHEMA | SCHEMAS | SECOND | SECURITY | SEEK | SERIALIZABLE | SESSION | SET | SETS
|
||||
| SHOW | SOME | START | STATS | SUBSET | SUBSTRING | SYSTEM
|
||||
| TABLES | TABLESAMPLE | TEXT | TIES | TIME | TIMESTAMP | TO | TRANSACTION | TRY_CAST | TYPE
|
||||
| UNBOUNDED | UNCOMMITTED | UPDATE | USE | USER | SESSION_USER
|
||||
| UNBOUNDED | UNCOMMITTED | UNMATCHED| UPDATE | USE | USER | SESSION_USER
|
||||
| VALIDATE | VERBOSE | VIEW
|
||||
| WINDOW | WITHOUT | WORK | WRITE
|
||||
| YEAR
|
||||
@@ -599,6 +684,7 @@ nonReserved
|
||||
|
||||
ADD: 'ADD';
|
||||
ADMIN: 'ADMIN';
|
||||
AFTER: 'AFTER';
|
||||
ALL: 'ALL';
|
||||
ALTER: 'ALTER';
|
||||
ANALYZE: 'ANALYZE';
|
||||
@@ -627,9 +713,11 @@ CREATE: 'CREATE';
|
||||
CROSS: 'CROSS';
|
||||
CUBE: 'CUBE';
|
||||
CURRENT: 'CURRENT';
|
||||
CURRENT_CATALOG: 'CURRENT_CATALOG';
|
||||
CURRENT_DATE: 'CURRENT_DATE';
|
||||
CURRENT_PATH: 'CURRENT_PATH';
|
||||
CURRENT_ROLE: 'CURRENT_ROLE';
|
||||
CURRENT_SCHEMA: 'CURRENT_SCHEMA';
|
||||
CURRENT_TIME: 'CURRENT_TIME';
|
||||
CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP';
|
||||
CURRENT_USER: 'CURRENT_USER';
|
||||
@@ -641,11 +729,13 @@ DEFINER: 'DEFINER';
|
||||
DELETE: 'DELETE';
|
||||
DESC: 'DESC';
|
||||
DESCRIBE: 'DESCRIBE';
|
||||
DEFINE: 'DEFINE';
|
||||
DISTINCT: 'DISTINCT';
|
||||
DISTRIBUTED: 'DISTRIBUTED';
|
||||
DOUBLE: 'DOUBLE';
|
||||
DROP: 'DROP';
|
||||
ELSE: 'ELSE';
|
||||
EMPTY: 'EMPTY';
|
||||
END: 'END';
|
||||
ESCAPE: 'ESCAPE';
|
||||
EXCEPT: 'EXCEPT';
|
||||
@@ -657,6 +747,7 @@ EXTRACT: 'EXTRACT';
|
||||
FALSE: 'FALSE';
|
||||
FETCH: 'FETCH';
|
||||
FILTER: 'FILTER';
|
||||
FINAL: 'FINAL';
|
||||
FIRST: 'FIRST';
|
||||
FOLLOWING: 'FOLLOWING';
|
||||
FOR: 'FOR';
|
||||
@@ -677,6 +768,7 @@ IF: 'IF';
|
||||
IGNORE: 'IGNORE';
|
||||
IN: 'IN';
|
||||
INCLUDING: 'INCLUDING';
|
||||
INITIAL: 'INITIAL';
|
||||
INNER: 'INNER';
|
||||
INPUT: 'INPUT';
|
||||
INSERT: 'INSERT';
|
||||
@@ -699,8 +791,12 @@ LOCALTIME: 'LOCALTIME';
|
||||
LOCALTIMESTAMP: 'LOCALTIMESTAMP';
|
||||
LOGICAL: 'LOGICAL';
|
||||
MAP: 'MAP';
|
||||
MATCH: 'MATCH';
|
||||
MATCHED: 'MATCHED';
|
||||
MATCHES: 'MATCHES';
|
||||
MATCH_RECOGNIZE: 'MATCH_RECOGNIZE';
|
||||
MATERIALIZED: 'MATERIALIZED';
|
||||
MEASURES: 'MEASURES';
|
||||
MERGE: 'MERGE';
|
||||
MINUTE: 'MINUTE';
|
||||
MONTH: 'MONTH';
|
||||
@@ -718,7 +814,9 @@ NULL: 'NULL';
|
||||
NULLIF: 'NULLIF';
|
||||
NULLS: 'NULLS';
|
||||
OFFSET: 'OFFSET';
|
||||
OMIT: 'OMIT';
|
||||
ON: 'ON';
|
||||
ONE: 'ONE';
|
||||
ONLY: 'ONLY';
|
||||
OPTION: 'OPTION';
|
||||
OR: 'OR';
|
||||
@@ -729,7 +827,11 @@ OUTPUT: 'OUTPUT';
|
||||
OVER: 'OVER';
|
||||
PARTITION: 'PARTITION';
|
||||
PARTITIONS: 'PARTITIONS';
|
||||
PAST: 'PAST';
|
||||
PATH: 'PATH';
|
||||
PATTERN: 'PATTERN';
|
||||
PER: 'PER';
|
||||
PERMUTE: 'PERMUTE';
|
||||
POSITION: 'POSITION';
|
||||
PRECEDING: 'PRECEDING';
|
||||
PRECISION: 'PRECISION';
|
||||
@@ -754,10 +856,12 @@ ROLLBACK: 'ROLLBACK';
|
||||
ROLLUP: 'ROLLUP';
|
||||
ROW: 'ROW';
|
||||
ROWS: 'ROWS';
|
||||
RUNNING: 'RUNNING';
|
||||
SCHEMA: 'SCHEMA';
|
||||
SCHEMAS: 'SCHEMAS';
|
||||
SECOND: 'SECOND';
|
||||
SECURITY: 'SECURITY';
|
||||
SEEK: 'SEEK';
|
||||
SELECT: 'SELECT';
|
||||
SERIALIZABLE: 'SERIALIZABLE';
|
||||
SESSION: 'SESSION';
|
||||
@@ -768,6 +872,7 @@ SHOW: 'SHOW';
|
||||
SOME: 'SOME';
|
||||
START: 'START';
|
||||
STATS: 'STATS';
|
||||
SUBSET: 'SUBSET';
|
||||
SUBSTRING: 'SUBSTRING';
|
||||
SYSTEM: 'SYSTEM';
|
||||
TABLE: 'TABLE';
|
||||
@@ -787,6 +892,7 @@ UESCAPE: 'UESCAPE';
|
||||
UNBOUNDED: 'UNBOUNDED';
|
||||
UNCOMMITTED: 'UNCOMMITTED';
|
||||
UNION: 'UNION';
|
||||
UNMATCHED: 'UNMATCHED';
|
||||
UNNEST: 'UNNEST';
|
||||
UPDATE: 'UPDATE';
|
||||
USE: 'USE';
|
||||
@@ -819,6 +925,7 @@ ASTERISK: '*';
|
||||
SLASH: '/';
|
||||
PERCENT: '%';
|
||||
CONCAT: '||';
|
||||
QUESTION_MARK : '?';
|
||||
// for wireprotocol to use POSIX regular expressions
|
||||
REGEX_MATCH: '~';
|
||||
|
||||
@@ -891,10 +998,6 @@ WS
|
||||
: [ \r\n\t]+ -> channel(HIDDEN)
|
||||
;
|
||||
|
||||
PARAMETER
|
||||
: '?'
|
||||
;
|
||||
|
||||
// Catch-all for anything we can't recognize.
|
||||
// We use this to be able to ignore and recover all the text
|
||||
// when splitting statements with DelimiterLexer
|
||||
|
||||
@@ -32,7 +32,9 @@ import io.trino.sql.tree.CharLiteral;
|
||||
import io.trino.sql.tree.CoalesceExpression;
|
||||
import io.trino.sql.tree.ComparisonExpression;
|
||||
import io.trino.sql.tree.Cube;
|
||||
import io.trino.sql.tree.CurrentCatalog;
|
||||
import io.trino.sql.tree.CurrentPath;
|
||||
import io.trino.sql.tree.CurrentSchema;
|
||||
import io.trino.sql.tree.CurrentTime;
|
||||
import io.trino.sql.tree.CurrentUser;
|
||||
import io.trino.sql.tree.DateTimeDataType;
|
||||
@@ -59,6 +61,7 @@ import io.trino.sql.tree.IntervalDayTimeDataType;
|
||||
import io.trino.sql.tree.IntervalLiteral;
|
||||
import io.trino.sql.tree.IsNotNullPredicate;
|
||||
import io.trino.sql.tree.IsNullPredicate;
|
||||
import io.trino.sql.tree.LabelDereference;
|
||||
import io.trino.sql.tree.LambdaArgumentDeclaration;
|
||||
import io.trino.sql.tree.LambdaExpression;
|
||||
import io.trino.sql.tree.LikePredicate;
|
||||
@@ -158,6 +161,18 @@ public final class ExpressionFormatter
|
||||
.append(process(node.getTimeZone(), context)).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String visitCurrentCatalog(CurrentCatalog node, Void context)
|
||||
{
|
||||
return "CURRENT_CATALOG";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String visitCurrentSchema(CurrentSchema node, Void context)
|
||||
{
|
||||
return "CURRENT_SCHEMA";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String visitCurrentUser(CurrentUser node, Void context)
|
||||
{
|
||||
@@ -363,6 +378,11 @@ public final class ExpressionFormatter
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
if (node.getProcessingMode().isPresent()) {
|
||||
builder.append(node.getProcessingMode().get().getMode())
|
||||
.append(" ");
|
||||
}
|
||||
|
||||
String arguments = joinExpressions(node.getArguments());
|
||||
if (node.getArguments().isEmpty() && "count".equalsIgnoreCase(node.getName().getSuffix())) {
|
||||
arguments = "*";
|
||||
@@ -736,6 +756,16 @@ public final class ExpressionFormatter
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String visitLabelDereference(LabelDereference node, Void context)
|
||||
{
|
||||
// format LabelDereference L.x as "LABEL_DEREFERENCE("L", "x")"
|
||||
// LabelDereference, like SymbolReference, is an IR-type expression. It is never a result of the parser.
|
||||
// After being formatted this way for serialization, it will be parsed as functionCall
|
||||
// and swapped back for LabelDereference.
|
||||
return "LABEL_DEREFERENCE(" + formatIdentifier(node.getLabel()) + ", " + process(node.getReference()) + ")";
|
||||
}
|
||||
|
||||
private String formatBinaryExpression(String operator, Expression left, Expression right)
|
||||
{
|
||||
return '(' + process(left, null) + ' ' + operator + ' ' + process(right, null) + ')';
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.trino.sql;
|
||||
|
||||
import io.trino.sql.tree.AnchorPattern;
|
||||
import io.trino.sql.tree.AstVisitor;
|
||||
import io.trino.sql.tree.EmptyPattern;
|
||||
import io.trino.sql.tree.ExcludedPattern;
|
||||
import io.trino.sql.tree.Node;
|
||||
import io.trino.sql.tree.OneOrMoreQuantifier;
|
||||
import io.trino.sql.tree.PatternAlternation;
|
||||
import io.trino.sql.tree.PatternConcatenation;
|
||||
import io.trino.sql.tree.PatternPermutation;
|
||||
import io.trino.sql.tree.PatternVariable;
|
||||
import io.trino.sql.tree.QuantifiedPattern;
|
||||
import io.trino.sql.tree.RangeQuantifier;
|
||||
import io.trino.sql.tree.RowPattern;
|
||||
import io.trino.sql.tree.ZeroOrMoreQuantifier;
|
||||
import io.trino.sql.tree.ZeroOrOneQuantifier;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
|
||||
public final class RowPatternFormatter
|
||||
{
|
||||
private RowPatternFormatter() {}
|
||||
|
||||
public static String formatPattern(RowPattern pattern)
|
||||
{
|
||||
return new Formatter().process(pattern, null);
|
||||
}
|
||||
|
||||
public static class Formatter
|
||||
extends AstVisitor<String, Void>
|
||||
{
|
||||
@Override
|
||||
protected String visitNode(Node node, Void context)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String visitRowPattern(RowPattern node, Void context)
|
||||
{
|
||||
throw new UnsupportedOperationException(format("not yet implemented: %s.visit%s", getClass().getName(), node.getClass().getSimpleName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String visitPatternAlternation(PatternAlternation node, Void context)
|
||||
{
|
||||
return node.getPatterns().stream()
|
||||
.map(child -> process(child, context))
|
||||
.collect(joining(" | ", "(", ")"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String visitPatternConcatenation(PatternConcatenation node, Void context)
|
||||
{
|
||||
return node.getPatterns().stream()
|
||||
.map(child -> process(child, context))
|
||||
.collect(joining(" ", "(", ")"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String visitQuantifiedPattern(QuantifiedPattern node, Void context)
|
||||
{
|
||||
return "(" + process(node.getPattern(), context) + process(node.getPatternQuantifier(), context) + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String visitPatternVariable(PatternVariable node, Void context)
|
||||
{
|
||||
return ExpressionFormatter.formatExpression(node.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String visitEmptyPattern(EmptyPattern node, Void context)
|
||||
{
|
||||
return "()";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String visitPatternPermutation(PatternPermutation node, Void context)
|
||||
{
|
||||
return node.getPatterns().stream()
|
||||
.map(child -> process(child, context))
|
||||
.collect(joining(", ", "PERMUTE(", ")"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String visitAnchorPattern(AnchorPattern node, Void context)
|
||||
{
|
||||
switch (node.getType()) {
|
||||
case PARTITION_START:
|
||||
return "^";
|
||||
case PARTITION_END:
|
||||
return "$";
|
||||
default:
|
||||
throw new IllegalStateException("unexpected anchor pattern type: " + node.getType());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String visitExcludedPattern(ExcludedPattern node, Void context)
|
||||
{
|
||||
return "{-" + process(node.getPattern(), context) + "-}";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String visitZeroOrMoreQuantifier(ZeroOrMoreQuantifier node, Void context)
|
||||
{
|
||||
String greedy = node.isGreedy() ? "" : "?";
|
||||
return "*" + greedy;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String visitOneOrMoreQuantifier(OneOrMoreQuantifier node, Void context)
|
||||
{
|
||||
String greedy = node.isGreedy() ? "" : "?";
|
||||
return "+" + greedy;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String visitZeroOrOneQuantifier(ZeroOrOneQuantifier node, Void context)
|
||||
{
|
||||
String greedy = node.isGreedy() ? "" : "?";
|
||||
return "?" + greedy;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String visitRangeQuantifier(RangeQuantifier node, Void context)
|
||||
{
|
||||
String greedy = node.isGreedy() ? "" : "?";
|
||||
String atLeast = node.getAtLeast().map(ExpressionFormatter::formatExpression).orElse("");
|
||||
String atMost = node.getAtMost().map(ExpressionFormatter::formatExpression).orElse("");
|
||||
return "{" + atLeast + "," + atMost + "}" + greedy;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,6 +72,7 @@ import io.trino.sql.tree.NaturalJoin;
|
||||
import io.trino.sql.tree.Node;
|
||||
import io.trino.sql.tree.Offset;
|
||||
import io.trino.sql.tree.OrderBy;
|
||||
import io.trino.sql.tree.PatternRecognitionRelation;
|
||||
import io.trino.sql.tree.Prepare;
|
||||
import io.trino.sql.tree.PrincipalSpecification;
|
||||
import io.trino.sql.tree.Property;
|
||||
@@ -89,6 +90,7 @@ import io.trino.sql.tree.Revoke;
|
||||
import io.trino.sql.tree.RevokeRoles;
|
||||
import io.trino.sql.tree.Rollback;
|
||||
import io.trino.sql.tree.Row;
|
||||
import io.trino.sql.tree.RowPattern;
|
||||
import io.trino.sql.tree.SampledRelation;
|
||||
import io.trino.sql.tree.Select;
|
||||
import io.trino.sql.tree.SelectItem;
|
||||
@@ -120,7 +122,6 @@ import io.trino.sql.tree.Unnest;
|
||||
import io.trino.sql.tree.Update;
|
||||
import io.trino.sql.tree.UpdateAssignment;
|
||||
import io.trino.sql.tree.Values;
|
||||
import io.trino.sql.tree.WindowDefinition;
|
||||
import io.trino.sql.tree.With;
|
||||
import io.trino.sql.tree.WithQuery;
|
||||
|
||||
@@ -131,6 +132,7 @@ import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static com.google.common.collect.Iterables.getOnlyElement;
|
||||
import static com.google.common.collect.Iterables.transform;
|
||||
@@ -139,6 +141,7 @@ import static io.trino.sql.ExpressionFormatter.formatGroupBy;
|
||||
import static io.trino.sql.ExpressionFormatter.formatOrderBy;
|
||||
import static io.trino.sql.ExpressionFormatter.formatStringLiteral;
|
||||
import static io.trino.sql.ExpressionFormatter.formatWindowSpecification;
|
||||
import static io.trino.sql.RowPatternFormatter.formatPattern;
|
||||
import static java.lang.String.format;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
|
||||
@@ -186,6 +189,14 @@ public final class SqlFormatter
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void visitRowPattern(RowPattern node, Integer indent)
|
||||
{
|
||||
checkArgument(indent == 0, "visitRowPattern should only be called at root");
|
||||
builder.append(formatPattern(node));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void visitUnnest(Unnest node, Integer indent)
|
||||
{
|
||||
@@ -327,21 +338,9 @@ public final class SqlFormatter
|
||||
|
||||
if (!node.getWindows().isEmpty()) {
|
||||
append(indent, "WINDOW");
|
||||
if (node.getWindows().size() == 1) {
|
||||
builder.append(" ")
|
||||
.append(formatWindowDefinition(node.getWindows().get(0)))
|
||||
.append("\n");
|
||||
}
|
||||
else {
|
||||
int size = node.getWindows().size();
|
||||
builder.append("\n");
|
||||
for (int i = 0; i < size - 1; i++) {
|
||||
append(indent + 1, formatWindowDefinition(node.getWindows().get(i)))
|
||||
.append(",\n");
|
||||
}
|
||||
append(indent + 1, formatWindowDefinition(node.getWindows().get(size - 1)))
|
||||
.append("\n");
|
||||
}
|
||||
formatDefinitionList(node.getWindows().stream()
|
||||
.map(definition -> formatExpression(definition.getName()) + " AS " + formatWindowSpecification(definition.getWindow()))
|
||||
.collect(toImmutableList()), indent + 1);
|
||||
}
|
||||
|
||||
if (node.getOrderBy().isPresent()) {
|
||||
@@ -358,11 +357,6 @@ public final class SqlFormatter
|
||||
return null;
|
||||
}
|
||||
|
||||
private String formatWindowDefinition(WindowDefinition definition)
|
||||
{
|
||||
return formatExpression(definition.getName()) + " AS " + formatWindowSpecification(definition.getWindow());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void visitOrderBy(OrderBy node, Integer indent)
|
||||
{
|
||||
@@ -526,6 +520,97 @@ public final class SqlFormatter
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void visitPatternRecognitionRelation(PatternRecognitionRelation node, Integer indent)
|
||||
{
|
||||
processRelationSuffix(node.getInput(), indent);
|
||||
|
||||
builder.append(" MATCH_RECOGNIZE (\n");
|
||||
if (!node.getPartitionBy().isEmpty()) {
|
||||
append(indent + 1, "PARTITION BY ")
|
||||
.append(node.getPartitionBy().stream()
|
||||
.map(ExpressionFormatter::formatExpression)
|
||||
.collect(joining(", ")))
|
||||
.append("\n");
|
||||
}
|
||||
if (node.getOrderBy().isPresent()) {
|
||||
process(node.getOrderBy().get(), indent + 1);
|
||||
}
|
||||
if (!node.getMeasures().isEmpty()) {
|
||||
append(indent + 1, "MEASURES");
|
||||
formatDefinitionList(node.getMeasures().stream()
|
||||
.map(measure -> formatExpression(measure.getExpression()) + " AS " + formatExpression(measure.getName()))
|
||||
.collect(toImmutableList()), indent + 2);
|
||||
}
|
||||
if (node.getRowsPerMatch().isPresent()) {
|
||||
String rowsPerMatch;
|
||||
switch (node.getRowsPerMatch().get()) {
|
||||
case ONE:
|
||||
rowsPerMatch = "ONE ROW PER MATCH";
|
||||
break;
|
||||
case ALL_SHOW_EMPTY:
|
||||
rowsPerMatch = "ALL ROWS PER MATCH SHOW EMPTY MATCHES";
|
||||
break;
|
||||
case ALL_OMIT_EMPTY:
|
||||
rowsPerMatch = "ALL ROWS PER MATCH OMIT EMPTY MATCHES";
|
||||
break;
|
||||
case ALL_WITH_UNMATCHED:
|
||||
rowsPerMatch = "ALL ROWS PER MATCH WITH UNMATCHED ROWS";
|
||||
break;
|
||||
default:
|
||||
// RowsPerMatch of type WINDOW cannot occur in MATCH_RECOGNIZE clause
|
||||
throw new IllegalStateException("unexpected rowsPerMatch: " + node.getRowsPerMatch().get());
|
||||
}
|
||||
append(indent + 1, rowsPerMatch)
|
||||
.append("\n");
|
||||
}
|
||||
if (node.getAfterMatchSkipTo().isPresent()) {
|
||||
String skipTo;
|
||||
switch (node.getAfterMatchSkipTo().get().getPosition()) {
|
||||
case PAST_LAST:
|
||||
skipTo = "AFTER MATCH SKIP PAST LAST ROW";
|
||||
break;
|
||||
case NEXT:
|
||||
skipTo = "AFTER MATCH SKIP TO NEXT ROW";
|
||||
break;
|
||||
case LAST:
|
||||
checkState(node.getAfterMatchSkipTo().get().getIdentifier().isPresent(), "missing identifier in AFTER MATCH SKIP TO LAST");
|
||||
skipTo = "AFTER MATCH SKIP TO LAST " + formatExpression(node.getAfterMatchSkipTo().get().getIdentifier().get());
|
||||
break;
|
||||
case FIRST:
|
||||
checkState(node.getAfterMatchSkipTo().get().getIdentifier().isPresent(), "missing identifier in AFTER MATCH SKIP TO FIRST");
|
||||
skipTo = "AFTER MATCH SKIP TO FIRST " + formatExpression(node.getAfterMatchSkipTo().get().getIdentifier().get());
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("unexpected skipTo: " + node.getAfterMatchSkipTo().get());
|
||||
}
|
||||
append(indent + 1, skipTo)
|
||||
.append("\n");
|
||||
}
|
||||
if (node.getPatternSearchMode().isPresent()) {
|
||||
append(indent + 1, node.getPatternSearchMode().get().getMode().name())
|
||||
.append("\n");
|
||||
}
|
||||
append(indent + 1, "PATTERN (")
|
||||
.append(formatPattern(node.getPattern()))
|
||||
.append(")\n");
|
||||
if (!node.getSubsets().isEmpty()) {
|
||||
append(indent + 1, "SUBSET");
|
||||
formatDefinitionList(node.getSubsets().stream()
|
||||
.map(subset -> formatExpression(subset.getName()) + " = " + subset.getIdentifiers().stream()
|
||||
.map(ExpressionFormatter::formatExpression).collect(joining(", ", "(", ")")))
|
||||
.collect(toImmutableList()), indent + 2);
|
||||
}
|
||||
append(indent + 1, "DEFINE");
|
||||
formatDefinitionList(node.getVariableDefinitions().stream()
|
||||
.map(variable -> formatExpression(variable.getName()) + " AS " + formatExpression(variable.getExpression()))
|
||||
.collect(toImmutableList()), indent + 2);
|
||||
|
||||
builder.append(")");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void visitSampledRelation(SampledRelation node, Integer indent)
|
||||
{
|
||||
@@ -542,7 +627,7 @@ public final class SqlFormatter
|
||||
|
||||
private void processRelationSuffix(Relation relation, Integer indent)
|
||||
{
|
||||
if ((relation instanceof AliasedRelation) || (relation instanceof SampledRelation)) {
|
||||
if ((relation instanceof AliasedRelation) || (relation instanceof SampledRelation) || (relation instanceof PatternRecognitionRelation)) {
|
||||
builder.append("( ");
|
||||
process(relation, indent + 1);
|
||||
append(indent, ")");
|
||||
@@ -1572,7 +1657,7 @@ public final class SqlFormatter
|
||||
builder.append(node.getType().get());
|
||||
builder.append(" ");
|
||||
}
|
||||
builder.append(node.getName())
|
||||
builder.append(formatName(node.getName()))
|
||||
.append(" TO ")
|
||||
.append(formatPrincipal(node.getGrantee()));
|
||||
if (node.isWithGrantOption()) {
|
||||
@@ -1689,6 +1774,24 @@ public final class SqlFormatter
|
||||
{
|
||||
return Strings.repeat(INDENT, indent);
|
||||
}
|
||||
|
||||
private void formatDefinitionList(List<String> elements, int indent)
|
||||
{
|
||||
if (elements.size() == 1) {
|
||||
builder.append(" ")
|
||||
.append(getOnlyElement(elements))
|
||||
.append("\n");
|
||||
}
|
||||
else {
|
||||
builder.append("\n");
|
||||
for (int i = 0; i < elements.size() - 1; i++) {
|
||||
append(indent, elements.get(i))
|
||||
.append(",\n");
|
||||
}
|
||||
append(indent, elements.get(elements.size() - 1))
|
||||
.append("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void appendAliasColumns(StringBuilder builder, List<Identifier> columns)
|
||||
|
||||
@@ -22,6 +22,7 @@ import io.trino.sql.tree.AliasedRelation;
|
||||
import io.trino.sql.tree.AllColumns;
|
||||
import io.trino.sql.tree.AllRows;
|
||||
import io.trino.sql.tree.Analyze;
|
||||
import io.trino.sql.tree.AnchorPattern;
|
||||
import io.trino.sql.tree.ArithmeticBinaryExpression;
|
||||
import io.trino.sql.tree.ArithmeticUnaryExpression;
|
||||
import io.trino.sql.tree.ArrayConstructor;
|
||||
@@ -46,7 +47,9 @@ import io.trino.sql.tree.CreateTable;
|
||||
import io.trino.sql.tree.CreateTableAsSelect;
|
||||
import io.trino.sql.tree.CreateView;
|
||||
import io.trino.sql.tree.Cube;
|
||||
import io.trino.sql.tree.CurrentCatalog;
|
||||
import io.trino.sql.tree.CurrentPath;
|
||||
import io.trino.sql.tree.CurrentSchema;
|
||||
import io.trino.sql.tree.CurrentTime;
|
||||
import io.trino.sql.tree.CurrentUser;
|
||||
import io.trino.sql.tree.DataType;
|
||||
@@ -65,7 +68,9 @@ import io.trino.sql.tree.DropRole;
|
||||
import io.trino.sql.tree.DropSchema;
|
||||
import io.trino.sql.tree.DropTable;
|
||||
import io.trino.sql.tree.DropView;
|
||||
import io.trino.sql.tree.EmptyPattern;
|
||||
import io.trino.sql.tree.Except;
|
||||
import io.trino.sql.tree.ExcludedPattern;
|
||||
import io.trino.sql.tree.Execute;
|
||||
import io.trino.sql.tree.ExistsPredicate;
|
||||
import io.trino.sql.tree.Explain;
|
||||
@@ -112,6 +117,7 @@ import io.trino.sql.tree.LikePredicate;
|
||||
import io.trino.sql.tree.Limit;
|
||||
import io.trino.sql.tree.LogicalBinaryExpression;
|
||||
import io.trino.sql.tree.LongLiteral;
|
||||
import io.trino.sql.tree.MeasureDefinition;
|
||||
import io.trino.sql.tree.Merge;
|
||||
import io.trino.sql.tree.MergeCase;
|
||||
import io.trino.sql.tree.MergeDelete;
|
||||
@@ -125,18 +131,30 @@ import io.trino.sql.tree.NullIfExpression;
|
||||
import io.trino.sql.tree.NullLiteral;
|
||||
import io.trino.sql.tree.NumericParameter;
|
||||
import io.trino.sql.tree.Offset;
|
||||
import io.trino.sql.tree.OneOrMoreQuantifier;
|
||||
import io.trino.sql.tree.OrderBy;
|
||||
import io.trino.sql.tree.Parameter;
|
||||
import io.trino.sql.tree.PathElement;
|
||||
import io.trino.sql.tree.PathSpecification;
|
||||
import io.trino.sql.tree.PatternAlternation;
|
||||
import io.trino.sql.tree.PatternConcatenation;
|
||||
import io.trino.sql.tree.PatternPermutation;
|
||||
import io.trino.sql.tree.PatternQuantifier;
|
||||
import io.trino.sql.tree.PatternRecognitionRelation;
|
||||
import io.trino.sql.tree.PatternRecognitionRelation.RowsPerMatch;
|
||||
import io.trino.sql.tree.PatternSearchMode;
|
||||
import io.trino.sql.tree.PatternVariable;
|
||||
import io.trino.sql.tree.Prepare;
|
||||
import io.trino.sql.tree.PrincipalSpecification;
|
||||
import io.trino.sql.tree.ProcessingMode;
|
||||
import io.trino.sql.tree.Property;
|
||||
import io.trino.sql.tree.QualifiedName;
|
||||
import io.trino.sql.tree.QuantifiedComparisonExpression;
|
||||
import io.trino.sql.tree.QuantifiedPattern;
|
||||
import io.trino.sql.tree.Query;
|
||||
import io.trino.sql.tree.QueryBody;
|
||||
import io.trino.sql.tree.QuerySpecification;
|
||||
import io.trino.sql.tree.RangeQuantifier;
|
||||
import io.trino.sql.tree.RefreshMaterializedView;
|
||||
import io.trino.sql.tree.Relation;
|
||||
import io.trino.sql.tree.RenameColumn;
|
||||
@@ -150,6 +168,7 @@ import io.trino.sql.tree.Rollback;
|
||||
import io.trino.sql.tree.Rollup;
|
||||
import io.trino.sql.tree.Row;
|
||||
import io.trino.sql.tree.RowDataType;
|
||||
import io.trino.sql.tree.RowPattern;
|
||||
import io.trino.sql.tree.SampledRelation;
|
||||
import io.trino.sql.tree.SearchedCaseExpression;
|
||||
import io.trino.sql.tree.Select;
|
||||
@@ -174,12 +193,14 @@ import io.trino.sql.tree.ShowTables;
|
||||
import io.trino.sql.tree.SimpleCaseExpression;
|
||||
import io.trino.sql.tree.SimpleGroupBy;
|
||||
import io.trino.sql.tree.SingleColumn;
|
||||
import io.trino.sql.tree.SkipTo;
|
||||
import io.trino.sql.tree.SortItem;
|
||||
import io.trino.sql.tree.StartTransaction;
|
||||
import io.trino.sql.tree.Statement;
|
||||
import io.trino.sql.tree.StringLiteral;
|
||||
import io.trino.sql.tree.SubqueryExpression;
|
||||
import io.trino.sql.tree.SubscriptExpression;
|
||||
import io.trino.sql.tree.SubsetDefinition;
|
||||
import io.trino.sql.tree.Table;
|
||||
import io.trino.sql.tree.TableElement;
|
||||
import io.trino.sql.tree.TableSubquery;
|
||||
@@ -195,6 +216,7 @@ import io.trino.sql.tree.Update;
|
||||
import io.trino.sql.tree.UpdateAssignment;
|
||||
import io.trino.sql.tree.Use;
|
||||
import io.trino.sql.tree.Values;
|
||||
import io.trino.sql.tree.VariableDefinition;
|
||||
import io.trino.sql.tree.WhenClause;
|
||||
import io.trino.sql.tree.Window;
|
||||
import io.trino.sql.tree.WindowDefinition;
|
||||
@@ -203,6 +225,8 @@ import io.trino.sql.tree.WindowReference;
|
||||
import io.trino.sql.tree.WindowSpecification;
|
||||
import io.trino.sql.tree.With;
|
||||
import io.trino.sql.tree.WithQuery;
|
||||
import io.trino.sql.tree.ZeroOrMoreQuantifier;
|
||||
import io.trino.sql.tree.ZeroOrOneQuantifier;
|
||||
import io.trino.sql.util.IntervalLiteralUtil;
|
||||
import org.antlr.v4.runtime.ParserRuleContext;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
@@ -217,12 +241,25 @@ import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static com.google.common.collect.Iterables.getOnlyElement;
|
||||
import static io.trino.sql.QueryUtil.functionCall;
|
||||
import static io.trino.sql.QueryUtil.identifier;
|
||||
import static io.trino.sql.QueryUtil.query;
|
||||
import static io.trino.sql.QueryUtil.selectAll;
|
||||
import static io.trino.sql.QueryUtil.selectList;
|
||||
import static io.trino.sql.QueryUtil.simpleQuery;
|
||||
import static io.trino.sql.parser.SqlBaseParser.TIME;
|
||||
import static io.trino.sql.parser.SqlBaseParser.TIMESTAMP;
|
||||
import static io.trino.sql.tree.AnchorPattern.Type.PARTITION_END;
|
||||
import static io.trino.sql.tree.AnchorPattern.Type.PARTITION_START;
|
||||
import static io.trino.sql.tree.PatternRecognitionRelation.RowsPerMatch.ALL_OMIT_EMPTY;
|
||||
import static io.trino.sql.tree.PatternRecognitionRelation.RowsPerMatch.ALL_SHOW_EMPTY;
|
||||
import static io.trino.sql.tree.PatternRecognitionRelation.RowsPerMatch.ALL_WITH_UNMATCHED;
|
||||
import static io.trino.sql.tree.PatternRecognitionRelation.RowsPerMatch.ONE;
|
||||
import static io.trino.sql.tree.PatternSearchMode.Mode.INITIAL;
|
||||
import static io.trino.sql.tree.PatternSearchMode.Mode.SEEK;
|
||||
import static io.trino.sql.tree.ProcessingMode.Mode.FINAL;
|
||||
import static io.trino.sql.tree.ProcessingMode.Mode.RUNNING;
|
||||
import static io.trino.sql.tree.SkipTo.skipPastLastRow;
|
||||
import static io.trino.sql.tree.SkipTo.skipToFirst;
|
||||
import static io.trino.sql.tree.SkipTo.skipToLast;
|
||||
import static io.trino.sql.tree.SkipTo.skipToNextRow;
|
||||
import static io.trino.sql.util.EscapedCharsUtil.replaceEscapedChars;
|
||||
import static java.lang.String.format;
|
||||
import static java.util.Locale.ENGLISH;
|
||||
@@ -265,6 +302,12 @@ class AstBuilder
|
||||
return visit(context.pathSpecification());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitStandaloneRowPattern(SqlBaseParser.StandaloneRowPatternContext context)
|
||||
{
|
||||
return visit(context.rowPattern());
|
||||
}
|
||||
|
||||
// ******************* statements **********************
|
||||
|
||||
@Override
|
||||
@@ -805,7 +848,7 @@ class AstBuilder
|
||||
rowCount = new LongLiteral(getLocation(context.offset.INTEGER_VALUE()), context.offset.getText());
|
||||
}
|
||||
else {
|
||||
rowCount = new Parameter(getLocation(context.offset.PARAMETER()), parameterPosition);
|
||||
rowCount = new Parameter(getLocation(context.offset.QUESTION_MARK()), parameterPosition);
|
||||
parameterPosition++;
|
||||
}
|
||||
offset = Optional.of(new Offset(Optional.of(getLocation(context.OFFSET())), rowCount));
|
||||
@@ -819,7 +862,7 @@ class AstBuilder
|
||||
rowCount = Optional.of(new LongLiteral(getLocation(context.fetchFirst.INTEGER_VALUE()), context.fetchFirst.getText()));
|
||||
}
|
||||
else {
|
||||
rowCount = Optional.of(new Parameter(getLocation(context.fetchFirst.PARAMETER()), parameterPosition));
|
||||
rowCount = Optional.of(new Parameter(getLocation(context.fetchFirst.QUESTION_MARK()), parameterPosition));
|
||||
parameterPosition++;
|
||||
}
|
||||
}
|
||||
@@ -837,7 +880,7 @@ class AstBuilder
|
||||
rowCount = new LongLiteral(getLocation(context.limit.rowCount().INTEGER_VALUE()), context.limit.getText());
|
||||
}
|
||||
else {
|
||||
rowCount = new Parameter(getLocation(context.limit.rowCount().PARAMETER()), parameterPosition);
|
||||
rowCount = new Parameter(getLocation(context.limit.rowCount().QUESTION_MARK()), parameterPosition);
|
||||
parameterPosition++;
|
||||
}
|
||||
|
||||
@@ -1125,8 +1168,8 @@ class AstBuilder
|
||||
@Override
|
||||
public Node visitShowStatsForQuery(SqlBaseParser.ShowStatsForQueryContext context)
|
||||
{
|
||||
QuerySpecification specification = (QuerySpecification) visitQuerySpecification(context.querySpecification());
|
||||
return new ShowStats(Optional.of(getLocation(context)), new TableSubquery(query(specification)));
|
||||
Query query = (Query) visit(context.query());
|
||||
return new ShowStats(Optional.of(getLocation(context)), new TableSubquery(query));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1404,7 +1447,7 @@ class AstBuilder
|
||||
@Override
|
||||
public Node visitSampledRelation(SqlBaseParser.SampledRelationContext context)
|
||||
{
|
||||
Relation child = (Relation) visit(context.aliasedRelation());
|
||||
Relation child = (Relation) visit(context.patternRecognition());
|
||||
|
||||
if (context.TABLESAMPLE() == null) {
|
||||
return child;
|
||||
@@ -1417,6 +1460,114 @@ class AstBuilder
|
||||
(Expression) visit(context.percentage));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitPatternRecognition(SqlBaseParser.PatternRecognitionContext context)
|
||||
{
|
||||
Relation child = (Relation) visit(context.aliasedRelation());
|
||||
|
||||
if (context.MATCH_RECOGNIZE() == null) {
|
||||
return child;
|
||||
}
|
||||
|
||||
Optional<OrderBy> orderBy = Optional.empty();
|
||||
if (context.ORDER() != null) {
|
||||
orderBy = Optional.of(new OrderBy(getLocation(context.ORDER()), visit(context.sortItem(), SortItem.class)));
|
||||
}
|
||||
|
||||
Optional<PatternSearchMode> searchMode = Optional.empty();
|
||||
if (context.INITIAL() != null) {
|
||||
searchMode = Optional.of(new PatternSearchMode(getLocation(context.INITIAL()), INITIAL));
|
||||
}
|
||||
else if (context.SEEK() != null) {
|
||||
searchMode = Optional.of(new PatternSearchMode(getLocation(context.SEEK()), SEEK));
|
||||
}
|
||||
|
||||
PatternRecognitionRelation relation = new PatternRecognitionRelation(
|
||||
getLocation(context),
|
||||
child,
|
||||
visit(context.partition, Expression.class),
|
||||
orderBy,
|
||||
visit(context.measureDefinition(), MeasureDefinition.class),
|
||||
getRowsPerMatch(context.rowsPerMatch()),
|
||||
visitIfPresent(context.skipTo(), SkipTo.class),
|
||||
searchMode,
|
||||
(RowPattern) visit(context.rowPattern()),
|
||||
visit(context.subsetDefinition(), SubsetDefinition.class),
|
||||
visit(context.variableDefinition(), VariableDefinition.class));
|
||||
|
||||
if (context.identifier() == null) {
|
||||
return relation;
|
||||
}
|
||||
|
||||
List<Identifier> aliases = null;
|
||||
if (context.columnAliases() != null) {
|
||||
aliases = visit(context.columnAliases().identifier(), Identifier.class);
|
||||
}
|
||||
|
||||
return new AliasedRelation(getLocation(context), relation, (Identifier) visit(context.identifier()), aliases);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitMeasureDefinition(SqlBaseParser.MeasureDefinitionContext context)
|
||||
{
|
||||
return new MeasureDefinition(getLocation(context), (Expression) visit(context.expression()), (Identifier) visit(context.identifier()));
|
||||
}
|
||||
|
||||
private Optional<RowsPerMatch> getRowsPerMatch(SqlBaseParser.RowsPerMatchContext context)
|
||||
{
|
||||
if (context == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
if (context.ONE() != null) {
|
||||
return Optional.of(ONE);
|
||||
}
|
||||
|
||||
if (context.emptyMatchHandling() == null) {
|
||||
return Optional.of(ALL_SHOW_EMPTY);
|
||||
}
|
||||
|
||||
if (context.emptyMatchHandling().SHOW() != null) {
|
||||
return Optional.of(ALL_SHOW_EMPTY);
|
||||
}
|
||||
|
||||
if (context.emptyMatchHandling().OMIT() != null) {
|
||||
return Optional.of(ALL_OMIT_EMPTY);
|
||||
}
|
||||
|
||||
return Optional.of(ALL_WITH_UNMATCHED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitSkipTo(SqlBaseParser.SkipToContext context)
|
||||
{
|
||||
if (context.PAST() != null) {
|
||||
return skipPastLastRow(getLocation(context));
|
||||
}
|
||||
|
||||
if (context.NEXT() != null) {
|
||||
return skipToNextRow(getLocation(context));
|
||||
}
|
||||
|
||||
if (context.FIRST() != null) {
|
||||
return skipToFirst(getLocation(context), (Identifier) visit(context.identifier()));
|
||||
}
|
||||
|
||||
return skipToLast(getLocation(context), (Identifier) visit(context.identifier()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitSubsetDefinition(SqlBaseParser.SubsetDefinitionContext context)
|
||||
{
|
||||
return new SubsetDefinition(getLocation(context), (Identifier) visit(context.name), visit(context.union, Identifier.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitVariableDefinition(SqlBaseParser.VariableDefinitionContext context)
|
||||
{
|
||||
return new VariableDefinition(getLocation(context), (Identifier) visit(context.identifier()), (Expression) visit(context.expression()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitAliasedRelation(SqlBaseParser.AliasedRelationContext context)
|
||||
{
|
||||
@@ -1752,6 +1903,18 @@ class AstBuilder
|
||||
return new CurrentTime(getLocation(context), function);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitCurrentCatalog(SqlBaseParser.CurrentCatalogContext context)
|
||||
{
|
||||
return new CurrentCatalog(getLocation(context.CURRENT_CATALOG()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitCurrentSchema(SqlBaseParser.CurrentSchemaContext context)
|
||||
{
|
||||
return new CurrentSchema(getLocation(context.CURRENT_SCHEMA()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitCurrentUser(SqlBaseParser.CurrentUserContext context)
|
||||
{
|
||||
@@ -1871,11 +2034,14 @@ class AstBuilder
|
||||
|
||||
SqlBaseParser.NullTreatmentContext nullTreatment = context.nullTreatment();
|
||||
|
||||
SqlBaseParser.ProcessingModeContext processingMode = context.processingMode();
|
||||
|
||||
if (name.toString().equalsIgnoreCase("if")) {
|
||||
check(context.expression().size() == 2 || context.expression().size() == 3, "Invalid number of arguments for 'if' function", context);
|
||||
check(!window.isPresent(), "OVER clause not valid for 'if' function", context);
|
||||
check(!distinct, "DISTINCT not valid for 'if' function", context);
|
||||
check(nullTreatment == null, "Null treatment clause not valid for 'if' function", context);
|
||||
check(processingMode == null, "Running or final semantics not valid for 'if' function", context);
|
||||
check(!filter.isPresent(), "FILTER not valid for 'if' function", context);
|
||||
|
||||
Expression elseExpression = null;
|
||||
@@ -1895,6 +2061,7 @@ class AstBuilder
|
||||
check(!window.isPresent(), "OVER clause not valid for 'nullif' function", context);
|
||||
check(!distinct, "DISTINCT not valid for 'nullif' function", context);
|
||||
check(nullTreatment == null, "Null treatment clause not valid for 'nullif' function", context);
|
||||
check(processingMode == null, "Running or final semantics not valid for 'nullif' function", context);
|
||||
check(!filter.isPresent(), "FILTER not valid for 'nullif' function", context);
|
||||
|
||||
return new NullIfExpression(
|
||||
@@ -1908,6 +2075,7 @@ class AstBuilder
|
||||
check(!window.isPresent(), "OVER clause not valid for 'coalesce' function", context);
|
||||
check(!distinct, "DISTINCT not valid for 'coalesce' function", context);
|
||||
check(nullTreatment == null, "Null treatment clause not valid for 'coalesce' function", context);
|
||||
check(processingMode == null, "Running or final semantics not valid for 'coalesce' function", context);
|
||||
check(!filter.isPresent(), "FILTER not valid for 'coalesce' function", context);
|
||||
|
||||
return new CoalesceExpression(getLocation(context), visit(context.expression(), Expression.class));
|
||||
@@ -1918,6 +2086,7 @@ class AstBuilder
|
||||
check(!window.isPresent(), "OVER clause not valid for 'try' function", context);
|
||||
check(!distinct, "DISTINCT not valid for 'try' function", context);
|
||||
check(nullTreatment == null, "Null treatment clause not valid for 'try' function", context);
|
||||
check(processingMode == null, "Running or final semantics not valid for 'try' function", context);
|
||||
check(!filter.isPresent(), "FILTER not valid for 'try' function", context);
|
||||
|
||||
return new TryExpression(getLocation(context), (Expression) visit(getOnlyElement(context.expression())));
|
||||
@@ -1928,6 +2097,7 @@ class AstBuilder
|
||||
check(!window.isPresent(), "OVER clause not valid for 'format' function", context);
|
||||
check(!distinct, "DISTINCT not valid for 'format' function", context);
|
||||
check(nullTreatment == null, "Null treatment clause not valid for 'format' function", context);
|
||||
check(processingMode == null, "Running or final semantics not valid for 'format' function", context);
|
||||
check(!filter.isPresent(), "FILTER not valid for 'format' function", context);
|
||||
|
||||
return new Format(getLocation(context), visit(context.expression(), Expression.class));
|
||||
@@ -1938,6 +2108,7 @@ class AstBuilder
|
||||
check(!window.isPresent(), "OVER clause not valid for '$internal$bind' function", context);
|
||||
check(!distinct, "DISTINCT not valid for '$internal$bind' function", context);
|
||||
check(nullTreatment == null, "Null treatment clause not valid for '$internal$bind' function", context);
|
||||
check(processingMode == null, "Running or final semantics not valid for '$internal$bind' function", context);
|
||||
check(!filter.isPresent(), "FILTER not valid for '$internal$bind' function", context);
|
||||
|
||||
int numValues = context.expression().size() - 1;
|
||||
@@ -1962,6 +2133,16 @@ class AstBuilder
|
||||
}
|
||||
}
|
||||
|
||||
Optional<ProcessingMode> mode = Optional.empty();
|
||||
if (processingMode != null) {
|
||||
if (processingMode.RUNNING() != null) {
|
||||
mode = Optional.of(new ProcessingMode(getLocation(processingMode), RUNNING));
|
||||
}
|
||||
else if (processingMode.FINAL() != null) {
|
||||
mode = Optional.of(new ProcessingMode(getLocation(processingMode), FINAL));
|
||||
}
|
||||
}
|
||||
|
||||
return new FunctionCall(
|
||||
Optional.of(getLocation(context)),
|
||||
name,
|
||||
@@ -1970,6 +2151,7 @@ class AstBuilder
|
||||
orderBy,
|
||||
distinct,
|
||||
nulls,
|
||||
mode,
|
||||
visit(context.expression(), Expression.class));
|
||||
}
|
||||
|
||||
@@ -2103,6 +2285,114 @@ class AstBuilder
|
||||
return new Identifier(getLocation(context), identifier, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitPatternAlternation(SqlBaseParser.PatternAlternationContext context)
|
||||
{
|
||||
List<RowPattern> parts = visit(context.rowPattern(), RowPattern.class);
|
||||
return new PatternAlternation(getLocation(context), parts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitPatternConcatenation(SqlBaseParser.PatternConcatenationContext context)
|
||||
{
|
||||
List<RowPattern> parts = visit(context.rowPattern(), RowPattern.class);
|
||||
return new PatternConcatenation(getLocation(context), parts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitQuantifiedPrimary(SqlBaseParser.QuantifiedPrimaryContext context)
|
||||
{
|
||||
RowPattern primary = (RowPattern) visit(context.patternPrimary());
|
||||
if (context.patternQuantifier() != null) {
|
||||
return new QuantifiedPattern(getLocation(context), primary, (PatternQuantifier) visit(context.patternQuantifier()));
|
||||
}
|
||||
return primary;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitPatternVariable(SqlBaseParser.PatternVariableContext context)
|
||||
{
|
||||
return new PatternVariable(getLocation(context), (Identifier) visit(context.identifier()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitEmptyPattern(SqlBaseParser.EmptyPatternContext context)
|
||||
{
|
||||
return new EmptyPattern(getLocation(context));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitPatternPermutation(SqlBaseParser.PatternPermutationContext context)
|
||||
{
|
||||
return new PatternPermutation(getLocation(context), visit(context.rowPattern(), RowPattern.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitGroupedPattern(SqlBaseParser.GroupedPatternContext context)
|
||||
{
|
||||
// skip parentheses
|
||||
return visit(context.rowPattern());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitPartitionStartAnchor(SqlBaseParser.PartitionStartAnchorContext context)
|
||||
{
|
||||
return new AnchorPattern(getLocation(context), PARTITION_START);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitPartitionEndAnchor(SqlBaseParser.PartitionEndAnchorContext context)
|
||||
{
|
||||
return new AnchorPattern(getLocation(context), PARTITION_END);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitExcludedPattern(SqlBaseParser.ExcludedPatternContext context)
|
||||
{
|
||||
return new ExcludedPattern(getLocation(context), (RowPattern) visit(context.rowPattern()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitZeroOrMoreQuantifier(SqlBaseParser.ZeroOrMoreQuantifierContext context)
|
||||
{
|
||||
boolean greedy = context.reluctant == null;
|
||||
return new ZeroOrMoreQuantifier(getLocation(context), greedy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitOneOrMoreQuantifier(SqlBaseParser.OneOrMoreQuantifierContext context)
|
||||
{
|
||||
boolean greedy = context.reluctant == null;
|
||||
return new OneOrMoreQuantifier(getLocation(context), greedy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitZeroOrOneQuantifier(SqlBaseParser.ZeroOrOneQuantifierContext context)
|
||||
{
|
||||
boolean greedy = context.reluctant == null;
|
||||
return new ZeroOrOneQuantifier(getLocation(context), greedy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitRangeQuantifier(SqlBaseParser.RangeQuantifierContext context)
|
||||
{
|
||||
boolean greedy = context.reluctant == null;
|
||||
|
||||
Optional<LongLiteral> atLeast = Optional.empty();
|
||||
Optional<LongLiteral> atMost = Optional.empty();
|
||||
if (context.exactly != null) {
|
||||
atLeast = Optional.of(new LongLiteral(getLocation(context.exactly), context.exactly.getText()));
|
||||
atMost = Optional.of(new LongLiteral(getLocation(context.exactly), context.exactly.getText()));
|
||||
}
|
||||
if (context.atLeast != null) {
|
||||
atLeast = Optional.of(new LongLiteral(getLocation(context.atLeast), context.atLeast.getText()));
|
||||
}
|
||||
if (context.atMost != null) {
|
||||
atMost = Optional.of(new LongLiteral(getLocation(context.atMost), context.atMost.getText()));
|
||||
}
|
||||
return new RangeQuantifier(getLocation(context), greedy, atLeast, atMost);
|
||||
}
|
||||
|
||||
// ************** literals **************
|
||||
|
||||
@Override
|
||||
@@ -2157,7 +2447,8 @@ class AstBuilder
|
||||
if (type.equalsIgnoreCase("decimal")) {
|
||||
return new DecimalLiteral(getLocation(context), value);
|
||||
}
|
||||
if (type.equalsIgnoreCase("char")) {
|
||||
// bpchar for PostgreSQL wire protocol, handle blank-padding char
|
||||
if (type.equalsIgnoreCase("char") || type.equalsIgnoreCase("bpchar")) {
|
||||
return new CharLiteral(getLocation(context), value);
|
||||
}
|
||||
// for PostgreSQL wire protocol, handle interval pattern
|
||||
@@ -2219,7 +2510,7 @@ class AstBuilder
|
||||
@Override
|
||||
public Node visitParameter(SqlBaseParser.ParameterContext context)
|
||||
{
|
||||
io.trino.sql.tree.Parameter parameter = new io.trino.sql.tree.Parameter(getLocation(context), parameterPosition);
|
||||
Parameter parameter = new Parameter(getLocation(context), parameterPosition);
|
||||
parameterPosition++;
|
||||
return parameter;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import io.trino.sql.tree.DataType;
|
||||
import io.trino.sql.tree.Expression;
|
||||
import io.trino.sql.tree.Node;
|
||||
import io.trino.sql.tree.PathSpecification;
|
||||
import io.trino.sql.tree.RowPattern;
|
||||
import io.trino.sql.tree.Statement;
|
||||
import org.antlr.v4.runtime.BaseErrorListener;
|
||||
import org.antlr.v4.runtime.CharStreams;
|
||||
@@ -99,6 +100,11 @@ public class SqlParser
|
||||
return (PathSpecification) invokeParser("path specification", expression, SqlBaseParser::standalonePathSpecification, new ParsingOptions());
|
||||
}
|
||||
|
||||
public RowPattern createRowPattern(String pattern)
|
||||
{
|
||||
return (RowPattern) invokeParser("row pattern", pattern, SqlBaseParser::standaloneRowPattern, new ParsingOptions());
|
||||
}
|
||||
|
||||
private Node invokeParser(String name, String sql, Function<SqlBaseParser, ParserRuleContext> parseFunction, ParsingOptions parsingOptions)
|
||||
{
|
||||
try {
|
||||
|
||||
@@ -43,7 +43,7 @@ public class AddColumn
|
||||
private AddColumn(Optional<NodeLocation> location, QualifiedName name, ColumnDefinition column, boolean tableExists, boolean columnNotExists)
|
||||
{
|
||||
super(location);
|
||||
this.name = requireNonNull(name, "table is null");
|
||||
this.name = requireNonNull(name, "name is null");
|
||||
this.column = requireNonNull(column, "column is null");
|
||||
this.tableExists = tableExists;
|
||||
this.columnNotExists = columnNotExists;
|
||||
|
||||
@@ -41,7 +41,7 @@ public class Analyze
|
||||
private Analyze(Optional<NodeLocation> location, QualifiedName tableName, List<Property> properties)
|
||||
{
|
||||
super(location);
|
||||
this.tableName = requireNonNull(tableName, "table is null");
|
||||
this.tableName = requireNonNull(tableName, "tableName is null");
|
||||
this.properties = ImmutableList.copyOf(requireNonNull(properties, "properties is null"));
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.trino.sql.tree;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public class AnchorPattern
|
||||
extends RowPattern
|
||||
{
|
||||
public enum Type
|
||||
{
|
||||
PARTITION_START,
|
||||
PARTITION_END
|
||||
}
|
||||
|
||||
private final Type type;
|
||||
|
||||
public AnchorPattern(NodeLocation location, Type type)
|
||||
{
|
||||
this(Optional.of(location), type);
|
||||
}
|
||||
|
||||
private AnchorPattern(Optional<NodeLocation> location, Type type)
|
||||
{
|
||||
super(location);
|
||||
this.type = requireNonNull(type, "type is null");
|
||||
}
|
||||
|
||||
public Type getType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, C> R accept(AstVisitor<R, C> visitor, C context)
|
||||
{
|
||||
return visitor.visitAnchorPattern(this, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Node> getChildren()
|
||||
{
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if ((obj == null) || (getClass() != obj.getClass())) {
|
||||
return false;
|
||||
}
|
||||
AnchorPattern o = (AnchorPattern) obj;
|
||||
return Objects.equals(type, o.type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return getClass().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return toStringHelper(this)
|
||||
.add("type", type)
|
||||
.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shallowEquals(Node other)
|
||||
{
|
||||
return sameClass(this, other);
|
||||
}
|
||||
}
|
||||
@@ -292,6 +292,11 @@ public abstract class AstVisitor<R, C>
|
||||
return visitExpression(node, context);
|
||||
}
|
||||
|
||||
protected R visitProcessingMode(ProcessingMode node, C context)
|
||||
{
|
||||
return visitNode(node, context);
|
||||
}
|
||||
|
||||
protected R visitLambdaExpression(LambdaExpression node, C context)
|
||||
{
|
||||
return visitExpression(node, context);
|
||||
@@ -842,6 +847,16 @@ public abstract class AstVisitor<R, C>
|
||||
return visitExpression(node, context);
|
||||
}
|
||||
|
||||
protected R visitCurrentCatalog(CurrentCatalog node, C context)
|
||||
{
|
||||
return visitExpression(node, context);
|
||||
}
|
||||
|
||||
protected R visitCurrentSchema(CurrentSchema node, C context)
|
||||
{
|
||||
return visitExpression(node, context);
|
||||
}
|
||||
|
||||
protected R visitCurrentUser(CurrentUser node, C context)
|
||||
{
|
||||
return visitExpression(node, context);
|
||||
@@ -916,4 +931,109 @@ public abstract class AstVisitor<R, C>
|
||||
{
|
||||
return visitStatement(node, context);
|
||||
}
|
||||
|
||||
protected R visitMeasureDefinition(MeasureDefinition node, C context)
|
||||
{
|
||||
return visitNode(node, context);
|
||||
}
|
||||
|
||||
protected R visitSkipTo(SkipTo node, C context)
|
||||
{
|
||||
return visitNode(node, context);
|
||||
}
|
||||
|
||||
protected R visitPatternSearchMode(PatternSearchMode node, C context)
|
||||
{
|
||||
return visitNode(node, context);
|
||||
}
|
||||
|
||||
protected R visitSubsetDefinition(SubsetDefinition node, C context)
|
||||
{
|
||||
return visitNode(node, context);
|
||||
}
|
||||
|
||||
protected R visitVariableDefinition(VariableDefinition node, C context)
|
||||
{
|
||||
return visitNode(node, context);
|
||||
}
|
||||
|
||||
protected R visitPatternRecognitionRelation(PatternRecognitionRelation node, C context)
|
||||
{
|
||||
return visitRelation(node, context);
|
||||
}
|
||||
|
||||
protected R visitLabelDereference(LabelDereference node, C context)
|
||||
{
|
||||
return visitExpression(node, context);
|
||||
}
|
||||
|
||||
protected R visitRowPattern(RowPattern node, C context)
|
||||
{
|
||||
return visitNode(node, context);
|
||||
}
|
||||
|
||||
protected R visitPatternAlternation(PatternAlternation node, C context)
|
||||
{
|
||||
return visitRowPattern(node, context);
|
||||
}
|
||||
|
||||
protected R visitPatternConcatenation(PatternConcatenation node, C context)
|
||||
{
|
||||
return visitRowPattern(node, context);
|
||||
}
|
||||
|
||||
protected R visitQuantifiedPattern(QuantifiedPattern node, C context)
|
||||
{
|
||||
return visitRowPattern(node, context);
|
||||
}
|
||||
|
||||
protected R visitAnchorPattern(AnchorPattern node, C context)
|
||||
{
|
||||
return visitRowPattern(node, context);
|
||||
}
|
||||
|
||||
protected R visitEmptyPattern(EmptyPattern node, C context)
|
||||
{
|
||||
return visitRowPattern(node, context);
|
||||
}
|
||||
|
||||
protected R visitExcludedPattern(ExcludedPattern node, C context)
|
||||
{
|
||||
return visitRowPattern(node, context);
|
||||
}
|
||||
|
||||
protected R visitPatternPermutation(PatternPermutation node, C context)
|
||||
{
|
||||
return visitRowPattern(node, context);
|
||||
}
|
||||
|
||||
protected R visitPatternVariable(PatternVariable node, C context)
|
||||
{
|
||||
return visitRowPattern(node, context);
|
||||
}
|
||||
|
||||
protected R visitPatternQuantifier(PatternQuantifier node, C context)
|
||||
{
|
||||
return visitNode(node, context);
|
||||
}
|
||||
|
||||
protected R visitZeroOrMoreQuantifier(ZeroOrMoreQuantifier node, C context)
|
||||
{
|
||||
return visitPatternQuantifier(node, context);
|
||||
}
|
||||
|
||||
protected R visitOneOrMoreQuantifier(OneOrMoreQuantifier node, C context)
|
||||
{
|
||||
return visitPatternQuantifier(node, context);
|
||||
}
|
||||
|
||||
protected R visitZeroOrOneQuantifier(ZeroOrOneQuantifier node, C context)
|
||||
{
|
||||
return visitPatternQuantifier(node, context);
|
||||
}
|
||||
|
||||
protected R visitRangeQuantifier(RangeQuantifier node, C context)
|
||||
{
|
||||
return visitPatternQuantifier(node, context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ public class BindExpression
|
||||
private BindExpression(Optional<NodeLocation> location, List<Expression> values, Expression function)
|
||||
{
|
||||
super(location);
|
||||
this.values = requireNonNull(values, "value is null");
|
||||
this.values = requireNonNull(values, "values is null");
|
||||
this.function = requireNonNull(function, "function is null");
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ public final class Comment
|
||||
{
|
||||
super(location);
|
||||
this.type = requireNonNull(type, "type is null");
|
||||
this.name = requireNonNull(name, "table is null");
|
||||
this.name = requireNonNull(name, "name is null");
|
||||
this.comment = requireNonNull(comment, "comment is null");
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ public class ComparisonExpression
|
||||
private ComparisonExpression(Optional<NodeLocation> location, Operator operator, Expression left, Expression right)
|
||||
{
|
||||
super(location);
|
||||
requireNonNull(operator, "type is null");
|
||||
requireNonNull(operator, "operator is null");
|
||||
requireNonNull(left, "left is null");
|
||||
requireNonNull(right, "right is null");
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ public class CreateTable
|
||||
private CreateTable(Optional<NodeLocation> location, QualifiedName name, List<TableElement> elements, boolean notExists, List<Property> properties, Optional<String> comment)
|
||||
{
|
||||
super(location);
|
||||
this.name = requireNonNull(name, "table is null");
|
||||
this.name = requireNonNull(name, "name is null");
|
||||
this.elements = ImmutableList.copyOf(requireNonNull(elements, "elements is null"));
|
||||
this.notExists = notExists;
|
||||
this.properties = requireNonNull(properties, "properties is null");
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.trino.sql.tree;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
public class CurrentCatalog
|
||||
extends Expression
|
||||
{
|
||||
public CurrentCatalog(NodeLocation location)
|
||||
{
|
||||
this(Optional.of(location));
|
||||
}
|
||||
|
||||
private CurrentCatalog(Optional<NodeLocation> location)
|
||||
{
|
||||
super(location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Node> getChildren()
|
||||
{
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, C> R accept(AstVisitor<R, C> visitor, C context)
|
||||
{
|
||||
return visitor.visitCurrentCatalog(this, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if ((obj == null) || (getClass() != obj.getClass())) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shallowEquals(Node other)
|
||||
{
|
||||
return sameClass(this, other);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.trino.sql.tree;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
public class CurrentSchema
|
||||
extends Expression
|
||||
{
|
||||
public CurrentSchema(NodeLocation location)
|
||||
{
|
||||
this(Optional.of(location));
|
||||
}
|
||||
|
||||
private CurrentSchema(Optional<NodeLocation> location)
|
||||
{
|
||||
super(location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Node> getChildren()
|
||||
{
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, C> R accept(AstVisitor<R, C> visitor, C context)
|
||||
{
|
||||
return visitor.visitCurrentSchema(this, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if ((obj == null) || (getClass() != obj.getClass())) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shallowEquals(Node other)
|
||||
{
|
||||
return sameClass(this, other);
|
||||
}
|
||||
}
|
||||
@@ -71,7 +71,7 @@ public class CurrentTime
|
||||
private CurrentTime(Optional<NodeLocation> location, Function function, Integer precision)
|
||||
{
|
||||
super(location);
|
||||
requireNonNull(function, "type is null");
|
||||
requireNonNull(function, "function is null");
|
||||
this.function = function;
|
||||
this.precision = precision;
|
||||
}
|
||||
|
||||
@@ -801,4 +801,66 @@ public abstract class DefaultTraversalVisitor<C>
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void visitExcludedPattern(ExcludedPattern node, C context)
|
||||
{
|
||||
process(node.getPattern(), context);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void visitPatternAlternation(PatternAlternation node, C context)
|
||||
{
|
||||
for (RowPattern rowPattern : node.getPatterns()) {
|
||||
process(rowPattern, context);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void visitPatternConcatenation(PatternConcatenation node, C context)
|
||||
{
|
||||
for (RowPattern rowPattern : node.getPatterns()) {
|
||||
process(rowPattern, context);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void visitPatternPermutation(PatternPermutation node, C context)
|
||||
{
|
||||
for (RowPattern rowPattern : node.getPatterns()) {
|
||||
process(rowPattern, context);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void visitPatternVariable(PatternVariable node, C context)
|
||||
{
|
||||
process(node.getName(), context);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void visitQuantifiedPattern(QuantifiedPattern node, C context)
|
||||
{
|
||||
process(node.getPattern(), context);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void visitLabelDereference(LabelDereference node, C context)
|
||||
{
|
||||
process(node.getReference(), context);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.trino.sql.tree;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
|
||||
public class EmptyPattern
|
||||
extends RowPattern
|
||||
{
|
||||
public EmptyPattern(NodeLocation location)
|
||||
{
|
||||
this(Optional.of(location));
|
||||
}
|
||||
|
||||
private EmptyPattern(Optional<NodeLocation> location)
|
||||
{
|
||||
super(location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, C> R accept(AstVisitor<R, C> visitor, C context)
|
||||
{
|
||||
return visitor.visitEmptyPattern(this, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Node> getChildren()
|
||||
{
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if ((obj == null) || (getClass() != obj.getClass())) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return getClass().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return toStringHelper(this)
|
||||
.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shallowEquals(Node other)
|
||||
{
|
||||
return sameClass(this, other);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.trino.sql.tree;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public class ExcludedPattern
|
||||
extends RowPattern
|
||||
{
|
||||
private final RowPattern pattern;
|
||||
|
||||
public ExcludedPattern(NodeLocation location, RowPattern pattern)
|
||||
{
|
||||
this(Optional.of(location), pattern);
|
||||
}
|
||||
|
||||
private ExcludedPattern(Optional<NodeLocation> location, RowPattern pattern)
|
||||
{
|
||||
super(location);
|
||||
this.pattern = requireNonNull(pattern, "pattern is null");
|
||||
}
|
||||
|
||||
public RowPattern getPattern()
|
||||
{
|
||||
return pattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, C> R accept(AstVisitor<R, C> visitor, C context)
|
||||
{
|
||||
return visitor.visitExcludedPattern(this, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Node> getChildren()
|
||||
{
|
||||
return ImmutableList.of(pattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if ((obj == null) || (getClass() != obj.getClass())) {
|
||||
return false;
|
||||
}
|
||||
ExcludedPattern o = (ExcludedPattern) obj;
|
||||
return Objects.equals(pattern, o.pattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(pattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return toStringHelper(this)
|
||||
.add("pattern", pattern)
|
||||
.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shallowEquals(Node other)
|
||||
{
|
||||
return sameClass(this, other);
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,7 @@ public class Execute
|
||||
{
|
||||
super(location);
|
||||
this.name = requireNonNull(name, "name is null");
|
||||
this.parameters = requireNonNull(ImmutableList.copyOf(parameters), "parameters is null");
|
||||
this.parameters = ImmutableList.copyOf(requireNonNull(parameters, "parameters is null"));
|
||||
}
|
||||
|
||||
public Identifier getName()
|
||||
|
||||
@@ -185,6 +185,16 @@ public class ExpressionRewriter<C>
|
||||
return rewriteExpression(node, context, treeRewriter);
|
||||
}
|
||||
|
||||
public Expression rewriteCurrentCatalog(CurrentCatalog node, C context, ExpressionTreeRewriter<C> treeRewriter)
|
||||
{
|
||||
return rewriteExpression(node, context, treeRewriter);
|
||||
}
|
||||
|
||||
public Expression rewriteCurrentSchema(CurrentSchema node, C context, ExpressionTreeRewriter<C> treeRewriter)
|
||||
{
|
||||
return rewriteExpression(node, context, treeRewriter);
|
||||
}
|
||||
|
||||
public Expression rewriteCurrentUser(CurrentUser node, C context, ExpressionTreeRewriter<C> treeRewriter)
|
||||
{
|
||||
return rewriteExpression(node, context, treeRewriter);
|
||||
@@ -244,4 +254,9 @@ public class ExpressionRewriter<C>
|
||||
{
|
||||
return rewriteExpression(node, context, treeRewriter);
|
||||
}
|
||||
|
||||
public Expression rewriteLabelDereference(LabelDereference node, C context, ExpressionTreeRewriter<C> treeRewriter)
|
||||
{
|
||||
return rewriteExpression(node, context, treeRewriter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
public final class ExpressionTreeRewriter<C>
|
||||
{
|
||||
private final ExpressionRewriter<C> rewriter;
|
||||
private final AstVisitor<Expression, ExpressionTreeRewriter.Context<C>> visitor;
|
||||
private final AstVisitor<Expression, Context<C>> visitor;
|
||||
|
||||
public static <T extends Expression> T rewriteWith(ExpressionRewriter<Void> rewriter, T node)
|
||||
{
|
||||
@@ -68,7 +68,7 @@ public final class ExpressionTreeRewriter<C>
|
||||
}
|
||||
|
||||
private class RewritingVisitor
|
||||
extends AstVisitor<Expression, ExpressionTreeRewriter.Context<C>>
|
||||
extends AstVisitor<Expression, Context<C>>
|
||||
{
|
||||
@Override
|
||||
protected Expression visitExpression(Expression node, Context<C> context)
|
||||
@@ -547,7 +547,16 @@ public final class ExpressionTreeRewriter<C>
|
||||
|
||||
if (!sameElements(node.getArguments(), arguments) || !sameElements(rewrittenWindow, node.getWindow())
|
||||
|| !sameElements(filter, node.getFilter())) {
|
||||
return new FunctionCall(node.getLocation(), node.getName(), rewrittenWindow, filter, node.getOrderBy().map(orderBy -> rewriteOrderBy(orderBy, context)), node.isDistinct(), node.getNullTreatment(), arguments);
|
||||
return new FunctionCall(
|
||||
node.getLocation(),
|
||||
node.getName(),
|
||||
rewrittenWindow,
|
||||
filter,
|
||||
node.getOrderBy().map(orderBy -> rewriteOrderBy(orderBy, context)),
|
||||
node.isDistinct(),
|
||||
node.getNullTreatment(),
|
||||
node.getProcessingMode(),
|
||||
arguments);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
@@ -989,6 +998,32 @@ public final class ExpressionTreeRewriter<C>
|
||||
return node;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Expression visitCurrentCatalog(CurrentCatalog node, Context<C> context)
|
||||
{
|
||||
if (!context.isDefaultRewrite()) {
|
||||
Expression result = rewriter.rewriteCurrentCatalog(node, context.get(), ExpressionTreeRewriter.this);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Expression visitCurrentSchema(CurrentSchema node, Context<C> context)
|
||||
{
|
||||
if (!context.isDefaultRewrite()) {
|
||||
Expression result = rewriter.rewriteCurrentSchema(node, context.get(), ExpressionTreeRewriter.this);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Expression visitCurrentUser(CurrentUser node, Context<C> context)
|
||||
{
|
||||
@@ -1032,6 +1067,24 @@ public final class ExpressionTreeRewriter<C>
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Expression visitLabelDereference(LabelDereference node, Context<C> context)
|
||||
{
|
||||
if (!context.isDefaultRewrite()) {
|
||||
Expression result = rewriter.rewriteLabelDereference(node, context.get(), ExpressionTreeRewriter.this);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
SymbolReference reference = rewrite(node.getReference(), context.get());
|
||||
if (node.getReference() != reference) {
|
||||
return new LabelDereference(node.getLabel(), reference);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Context<C>
|
||||
|
||||
@@ -31,16 +31,17 @@ public class FunctionCall
|
||||
private final Optional<OrderBy> orderBy;
|
||||
private final boolean distinct;
|
||||
private final Optional<NullTreatment> nullTreatment;
|
||||
private final Optional<ProcessingMode> processingMode;
|
||||
private final List<Expression> arguments;
|
||||
|
||||
public FunctionCall(QualifiedName name, List<Expression> arguments)
|
||||
{
|
||||
this(Optional.empty(), name, Optional.empty(), Optional.empty(), Optional.empty(), false, Optional.empty(), arguments);
|
||||
this(Optional.empty(), name, Optional.empty(), Optional.empty(), Optional.empty(), false, Optional.empty(), Optional.empty(), arguments);
|
||||
}
|
||||
|
||||
public FunctionCall(NodeLocation location, QualifiedName name, List<Expression> arguments)
|
||||
{
|
||||
this(Optional.of(location), name, Optional.empty(), Optional.empty(), Optional.empty(), false, Optional.empty(), arguments);
|
||||
this(Optional.of(location), name, Optional.empty(), Optional.empty(), Optional.empty(), false, Optional.empty(), Optional.empty(), arguments);
|
||||
}
|
||||
|
||||
public FunctionCall(
|
||||
@@ -51,6 +52,7 @@ public class FunctionCall
|
||||
Optional<OrderBy> orderBy,
|
||||
boolean distinct,
|
||||
Optional<NullTreatment> nullTreatment,
|
||||
Optional<ProcessingMode> processingMode,
|
||||
List<Expression> arguments)
|
||||
{
|
||||
super(location);
|
||||
@@ -60,6 +62,7 @@ public class FunctionCall
|
||||
requireNonNull(filter, "filter is null");
|
||||
requireNonNull(orderBy, "orderBy is null");
|
||||
requireNonNull(nullTreatment, "nullTreatment is null");
|
||||
requireNonNull(processingMode, "processingMode is null");
|
||||
requireNonNull(arguments, "arguments is null");
|
||||
|
||||
this.name = name;
|
||||
@@ -68,6 +71,7 @@ public class FunctionCall
|
||||
this.orderBy = orderBy;
|
||||
this.distinct = distinct;
|
||||
this.nullTreatment = nullTreatment;
|
||||
this.processingMode = processingMode;
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
@@ -96,6 +100,11 @@ public class FunctionCall
|
||||
return nullTreatment;
|
||||
}
|
||||
|
||||
public Optional<ProcessingMode> getProcessingMode()
|
||||
{
|
||||
return processingMode;
|
||||
}
|
||||
|
||||
public List<Expression> getArguments()
|
||||
{
|
||||
return arguments;
|
||||
@@ -139,13 +148,14 @@ public class FunctionCall
|
||||
Objects.equals(orderBy, o.orderBy) &&
|
||||
Objects.equals(distinct, o.distinct) &&
|
||||
Objects.equals(nullTreatment, o.nullTreatment) &&
|
||||
Objects.equals(processingMode, o.processingMode) &&
|
||||
Objects.equals(arguments, o.arguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(name, distinct, nullTreatment, window, filter, orderBy, arguments);
|
||||
return Objects.hash(name, distinct, nullTreatment, processingMode, window, filter, orderBy, arguments);
|
||||
}
|
||||
|
||||
// TODO: make this a proper Tree node so that we can report error
|
||||
@@ -166,6 +176,7 @@ public class FunctionCall
|
||||
|
||||
return name.equals(otherFunction.name) &&
|
||||
distinct == otherFunction.distinct &&
|
||||
nullTreatment.equals(otherFunction.nullTreatment);
|
||||
nullTreatment.equals(otherFunction.nullTreatment) &&
|
||||
processingMode.equals(otherFunction.processingMode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.util.Optional;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static java.util.Locale.ENGLISH;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public class Identifier
|
||||
@@ -66,6 +67,15 @@ public class Identifier
|
||||
return delimited;
|
||||
}
|
||||
|
||||
public String getCanonicalValue()
|
||||
{
|
||||
if (isDelimited()) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return value.toUpperCase(ENGLISH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, C> R accept(AstVisitor<R, C> visitor, C context)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.trino.sql.tree;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
* A temporary IR representation of a label-prefixed column reference
|
||||
* in the context of row pattern recognition.
|
||||
* <p>
|
||||
* It is created from a DereferenceExpression when the MEASURES or DEFINE
|
||||
* expressions are rewritten using the TranslationMap:
|
||||
* A.price -> DereferenceExpression("A", "price") -> LabelDereference("A", price_symbol).
|
||||
* Next, the LabelDereference is processed by the LogicalIndexExtractor,
|
||||
* and it is removed from the expression.
|
||||
* <p>
|
||||
* LabelDereference is a synthetic AST node. It had to be introduced in order to carry
|
||||
* the rewritten symbol (`price_symbol` in the example). The DereferenceExpression
|
||||
* cannot be used for that purpose, because it only contains identifiers, and a Symbol
|
||||
* cannot be safely converted to an Identifier.
|
||||
*/
|
||||
public class LabelDereference
|
||||
extends Expression
|
||||
{
|
||||
private final String label;
|
||||
private final SymbolReference reference;
|
||||
|
||||
public LabelDereference(String label, SymbolReference reference)
|
||||
{
|
||||
super(Optional.empty());
|
||||
this.label = requireNonNull(label, "label is null");
|
||||
this.reference = requireNonNull(reference, "reference is null");
|
||||
}
|
||||
|
||||
public String getLabel()
|
||||
{
|
||||
return label;
|
||||
}
|
||||
|
||||
public SymbolReference getReference()
|
||||
{
|
||||
return reference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, C> R accept(AstVisitor<R, C> visitor, C context)
|
||||
{
|
||||
return visitor.visitLabelDereference(this, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Node> getChildren()
|
||||
{
|
||||
return ImmutableList.of(reference);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
LabelDereference that = (LabelDereference) o;
|
||||
return Objects.equals(label, that.label) &&
|
||||
Objects.equals(reference, that.reference);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(label, reference);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.trino.sql.tree;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public class MeasureDefinition
|
||||
extends Node
|
||||
{
|
||||
private final Expression expression;
|
||||
private final Identifier name;
|
||||
|
||||
public MeasureDefinition(Expression expression, Identifier name)
|
||||
{
|
||||
this(Optional.empty(), expression, name);
|
||||
}
|
||||
|
||||
public MeasureDefinition(NodeLocation location, Expression expression, Identifier name)
|
||||
{
|
||||
this(Optional.of(location), expression, name);
|
||||
}
|
||||
|
||||
private MeasureDefinition(Optional<NodeLocation> location, Expression expression, Identifier name)
|
||||
{
|
||||
super(location);
|
||||
this.expression = requireNonNull(expression, "expression is null");
|
||||
this.name = requireNonNull(name, "name is null");
|
||||
}
|
||||
|
||||
public Expression getExpression()
|
||||
{
|
||||
return expression;
|
||||
}
|
||||
|
||||
public Identifier getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, C> R accept(AstVisitor<R, C> visitor, C context)
|
||||
{
|
||||
return visitor.visitMeasureDefinition(this, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends Node> getChildren()
|
||||
{
|
||||
return ImmutableList.of(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return toStringHelper(this)
|
||||
.add("expression", expression)
|
||||
.add("name", name)
|
||||
.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MeasureDefinition that = (MeasureDefinition) o;
|
||||
return Objects.equals(expression, that.expression) &&
|
||||
Objects.equals(name, that.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(expression, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shallowEquals(Node other)
|
||||
{
|
||||
if (!sameClass(this, other)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Objects.equals(name, ((MeasureDefinition) other).name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.trino.sql.tree;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class OneOrMoreQuantifier
|
||||
extends PatternQuantifier
|
||||
{
|
||||
public OneOrMoreQuantifier(boolean greedy)
|
||||
{
|
||||
this(Optional.empty(), greedy);
|
||||
}
|
||||
|
||||
public OneOrMoreQuantifier(NodeLocation location, boolean greedy)
|
||||
{
|
||||
this(Optional.of(location), greedy);
|
||||
}
|
||||
|
||||
public OneOrMoreQuantifier(Optional<NodeLocation> location, boolean greedy)
|
||||
{
|
||||
super(location, greedy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, C> R accept(AstVisitor<R, C> visitor, C context)
|
||||
{
|
||||
return visitor.visitOneOrMoreQuantifier(this, context);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.trino.sql.tree;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public class PatternAlternation
|
||||
extends RowPattern
|
||||
{
|
||||
private final List<RowPattern> patterns;
|
||||
|
||||
public PatternAlternation(NodeLocation location, List<RowPattern> patterns)
|
||||
{
|
||||
this(Optional.of(location), patterns);
|
||||
}
|
||||
|
||||
private PatternAlternation(Optional<NodeLocation> location, List<RowPattern> patterns)
|
||||
{
|
||||
super(location);
|
||||
this.patterns = requireNonNull(patterns, "patterns is null");
|
||||
checkArgument(!patterns.isEmpty(), "patterns list is empty");
|
||||
}
|
||||
|
||||
public List<RowPattern> getPatterns()
|
||||
{
|
||||
return patterns;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, C> R accept(AstVisitor<R, C> visitor, C context)
|
||||
{
|
||||
return visitor.visitPatternAlternation(this, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Node> getChildren()
|
||||
{
|
||||
return ImmutableList.copyOf(patterns);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if ((obj == null) || (getClass() != obj.getClass())) {
|
||||
return false;
|
||||
}
|
||||
PatternAlternation o = (PatternAlternation) obj;
|
||||
return Objects.equals(patterns, o.patterns);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(patterns);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return toStringHelper(this)
|
||||
.add("patterns", patterns)
|
||||
.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shallowEquals(Node other)
|
||||
{
|
||||
return sameClass(this, other);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.trino.sql.tree;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public class PatternConcatenation
|
||||
extends RowPattern
|
||||
{
|
||||
private final List<RowPattern> patterns;
|
||||
|
||||
public PatternConcatenation(NodeLocation location, List<RowPattern> patterns)
|
||||
{
|
||||
this(Optional.of(location), patterns);
|
||||
}
|
||||
|
||||
private PatternConcatenation(Optional<NodeLocation> location, List<RowPattern> patterns)
|
||||
{
|
||||
super(location);
|
||||
this.patterns = requireNonNull(patterns, "patterns is null");
|
||||
checkArgument(!patterns.isEmpty(), "patterns list is empty");
|
||||
}
|
||||
|
||||
public List<RowPattern> getPatterns()
|
||||
{
|
||||
return patterns;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, C> R accept(AstVisitor<R, C> visitor, C context)
|
||||
{
|
||||
return visitor.visitPatternConcatenation(this, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Node> getChildren()
|
||||
{
|
||||
return ImmutableList.copyOf(patterns);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if ((obj == null) || (getClass() != obj.getClass())) {
|
||||
return false;
|
||||
}
|
||||
PatternConcatenation o = (PatternConcatenation) obj;
|
||||
return Objects.equals(patterns, o.patterns);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(patterns);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return toStringHelper(this)
|
||||
.add("patterns", patterns)
|
||||
.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shallowEquals(Node other)
|
||||
{
|
||||
return sameClass(this, other);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.trino.sql.tree;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public class PatternPermutation
|
||||
extends RowPattern
|
||||
{
|
||||
private final List<RowPattern> patterns;
|
||||
|
||||
public PatternPermutation(NodeLocation location, List<RowPattern> patterns)
|
||||
{
|
||||
this(Optional.of(location), patterns);
|
||||
}
|
||||
|
||||
private PatternPermutation(Optional<NodeLocation> location, List<RowPattern> patterns)
|
||||
{
|
||||
super(location);
|
||||
this.patterns = requireNonNull(patterns, "patterns is null");
|
||||
checkArgument(!patterns.isEmpty(), "patterns list is empty");
|
||||
}
|
||||
|
||||
public List<RowPattern> getPatterns()
|
||||
{
|
||||
return patterns;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, C> R accept(AstVisitor<R, C> visitor, C context)
|
||||
{
|
||||
return visitor.visitPatternPermutation(this, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Node> getChildren()
|
||||
{
|
||||
return ImmutableList.copyOf(patterns);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if ((obj == null) || (getClass() != obj.getClass())) {
|
||||
return false;
|
||||
}
|
||||
PatternPermutation o = (PatternPermutation) obj;
|
||||
return Objects.equals(patterns, o.patterns);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(patterns);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return toStringHelper(this)
|
||||
.add("patterns", patterns)
|
||||
.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shallowEquals(Node other)
|
||||
{
|
||||
return sameClass(this, other);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.trino.sql.tree;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
|
||||
public abstract class PatternQuantifier
|
||||
extends Node
|
||||
{
|
||||
private final boolean greedy;
|
||||
|
||||
protected PatternQuantifier(Optional<NodeLocation> location, boolean greedy)
|
||||
{
|
||||
super(location);
|
||||
this.greedy = greedy;
|
||||
}
|
||||
|
||||
public boolean isGreedy()
|
||||
{
|
||||
return greedy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, C> R accept(AstVisitor<R, C> visitor, C context)
|
||||
{
|
||||
return visitor.visitPatternQuantifier(this, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Node> getChildren()
|
||||
{
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if ((obj == null) || (getClass() != obj.getClass())) {
|
||||
return false;
|
||||
}
|
||||
PatternQuantifier o = (PatternQuantifier) obj;
|
||||
return greedy == o.greedy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(greedy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shallowEquals(Node other)
|
||||
{
|
||||
if (!sameClass(this, other)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PatternQuantifier otherNode = (PatternQuantifier) other;
|
||||
return greedy == otherNode.greedy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return toStringHelper(this)
|
||||
.add("greedy", greedy)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,356 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.trino.sql.tree;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public class PatternRecognitionRelation
|
||||
extends Relation
|
||||
{
|
||||
private final Relation input;
|
||||
private final List<Expression> partitionBy;
|
||||
private final Optional<OrderBy> orderBy;
|
||||
private final List<MeasureDefinition> measures;
|
||||
private final Optional<RowsPerMatch> rowsPerMatch;
|
||||
private final Optional<SkipTo> afterMatchSkipTo;
|
||||
private final Optional<PatternSearchMode> patternSearchMode;
|
||||
private final RowPattern pattern;
|
||||
private final List<SubsetDefinition> subsets;
|
||||
private final List<VariableDefinition> variableDefinitions;
|
||||
|
||||
public PatternRecognitionRelation(
|
||||
Relation input,
|
||||
List<Expression> partitionBy,
|
||||
Optional<OrderBy> orderBy,
|
||||
List<MeasureDefinition> measures,
|
||||
Optional<RowsPerMatch> rowsPerMatch,
|
||||
Optional<SkipTo> afterMatchSkipTo,
|
||||
Optional<PatternSearchMode> patternSearchMode,
|
||||
RowPattern pattern,
|
||||
List<SubsetDefinition> subsets,
|
||||
List<VariableDefinition> variableDefinitions)
|
||||
{
|
||||
this(Optional.empty(), input, partitionBy, orderBy, measures, rowsPerMatch, afterMatchSkipTo, patternSearchMode, pattern, subsets, variableDefinitions);
|
||||
}
|
||||
|
||||
public PatternRecognitionRelation(
|
||||
NodeLocation location,
|
||||
Relation input,
|
||||
List<Expression> partitionBy,
|
||||
Optional<OrderBy> orderBy,
|
||||
List<MeasureDefinition> measures,
|
||||
Optional<RowsPerMatch> rowsPerMatch,
|
||||
Optional<SkipTo> afterMatchSkipTo,
|
||||
Optional<PatternSearchMode> patternSearchMode,
|
||||
RowPattern pattern,
|
||||
List<SubsetDefinition> subsets,
|
||||
List<VariableDefinition> variableDefinitions)
|
||||
{
|
||||
this(Optional.of(location), input, partitionBy, orderBy, measures, rowsPerMatch, afterMatchSkipTo, patternSearchMode, pattern, subsets, variableDefinitions);
|
||||
}
|
||||
|
||||
private PatternRecognitionRelation(
|
||||
Optional<NodeLocation> location,
|
||||
Relation input,
|
||||
List<Expression> partitionBy,
|
||||
Optional<OrderBy> orderBy,
|
||||
List<MeasureDefinition> measures,
|
||||
Optional<RowsPerMatch> rowsPerMatch,
|
||||
Optional<SkipTo> afterMatchSkipTo,
|
||||
Optional<PatternSearchMode> patternSearchMode,
|
||||
RowPattern pattern,
|
||||
List<SubsetDefinition> subsets,
|
||||
List<VariableDefinition> variableDefinitions)
|
||||
{
|
||||
super(location);
|
||||
this.input = requireNonNull(input, "input is null");
|
||||
this.partitionBy = requireNonNull(partitionBy, "partitionBy is null");
|
||||
this.orderBy = requireNonNull(orderBy, "orderBy is null");
|
||||
this.measures = requireNonNull(measures, "measures is null");
|
||||
this.rowsPerMatch = requireNonNull(rowsPerMatch, "rowsPerMatch is null");
|
||||
this.afterMatchSkipTo = requireNonNull(afterMatchSkipTo, "afterMatchSkipTo is null");
|
||||
this.patternSearchMode = requireNonNull(patternSearchMode, "patternSearchMode is null");
|
||||
this.pattern = requireNonNull(pattern, "pattern is null");
|
||||
this.subsets = requireNonNull(subsets, "subsets is null");
|
||||
requireNonNull(variableDefinitions, "variableDefinitions is null");
|
||||
checkArgument(!variableDefinitions.isEmpty(), "variableDefinitions is empty");
|
||||
this.variableDefinitions = variableDefinitions;
|
||||
}
|
||||
|
||||
public Relation getInput()
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
public List<Expression> getPartitionBy()
|
||||
{
|
||||
return partitionBy;
|
||||
}
|
||||
|
||||
public Optional<OrderBy> getOrderBy()
|
||||
{
|
||||
return orderBy;
|
||||
}
|
||||
|
||||
public List<MeasureDefinition> getMeasures()
|
||||
{
|
||||
return measures;
|
||||
}
|
||||
|
||||
public Optional<RowsPerMatch> getRowsPerMatch()
|
||||
{
|
||||
return rowsPerMatch;
|
||||
}
|
||||
|
||||
public Optional<SkipTo> getAfterMatchSkipTo()
|
||||
{
|
||||
return afterMatchSkipTo;
|
||||
}
|
||||
|
||||
public Optional<PatternSearchMode> getPatternSearchMode()
|
||||
{
|
||||
return patternSearchMode;
|
||||
}
|
||||
|
||||
public RowPattern getPattern()
|
||||
{
|
||||
return pattern;
|
||||
}
|
||||
|
||||
public List<SubsetDefinition> getSubsets()
|
||||
{
|
||||
return subsets;
|
||||
}
|
||||
|
||||
public List<VariableDefinition> getVariableDefinitions()
|
||||
{
|
||||
return variableDefinitions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, C> R accept(AstVisitor<R, C> visitor, C context)
|
||||
{
|
||||
return visitor.visitPatternRecognitionRelation(this, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Node> getChildren()
|
||||
{
|
||||
ImmutableList.Builder<Node> builder = ImmutableList.builder();
|
||||
builder.add(input);
|
||||
builder.addAll(partitionBy);
|
||||
orderBy.ifPresent(builder::add);
|
||||
builder.addAll(measures);
|
||||
afterMatchSkipTo.ifPresent(builder::add);
|
||||
builder.add(pattern)
|
||||
.addAll(subsets)
|
||||
.addAll(variableDefinitions);
|
||||
patternSearchMode.ifPresent(builder::add);
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return toStringHelper(this)
|
||||
.add("input", input)
|
||||
.add("partitionBy", partitionBy)
|
||||
.add("orderBy", orderBy.orElse(null))
|
||||
.add("measures", measures)
|
||||
.add("rowsPerMatch", rowsPerMatch.orElse(null))
|
||||
.add("afterMatchSkipTo", afterMatchSkipTo)
|
||||
.add("patternSearchMode", patternSearchMode.orElse(null))
|
||||
.add("pattern", pattern)
|
||||
.add("subsets", subsets)
|
||||
.add("variableDefinitions", variableDefinitions)
|
||||
.omitNullValues()
|
||||
.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PatternRecognitionRelation that = (PatternRecognitionRelation) o;
|
||||
return Objects.equals(input, that.input) &&
|
||||
Objects.equals(partitionBy, that.partitionBy) &&
|
||||
Objects.equals(orderBy, that.orderBy) &&
|
||||
Objects.equals(measures, that.measures) &&
|
||||
Objects.equals(rowsPerMatch, that.rowsPerMatch) &&
|
||||
Objects.equals(afterMatchSkipTo, that.afterMatchSkipTo) &&
|
||||
Objects.equals(patternSearchMode, that.patternSearchMode) &&
|
||||
Objects.equals(pattern, that.pattern) &&
|
||||
Objects.equals(subsets, that.subsets) &&
|
||||
Objects.equals(variableDefinitions, that.variableDefinitions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(input, partitionBy, orderBy, measures, rowsPerMatch, afterMatchSkipTo, patternSearchMode, pattern, subsets, variableDefinitions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shallowEquals(Node other)
|
||||
{
|
||||
if (!sameClass(this, other)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return rowsPerMatch.equals(((PatternRecognitionRelation) other).rowsPerMatch);
|
||||
}
|
||||
|
||||
public enum RowsPerMatch
|
||||
{
|
||||
// ONE option applies to the MATCH_RECOGNIZE clause. This is the default option.
|
||||
// Output a single summary row for every match, including empty matches.
|
||||
// In the case of an empty match, output the starting row of the match attempt.
|
||||
ONE {
|
||||
@Override
|
||||
public boolean isOneRow()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmptyMatches()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnmatchedRows()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
// ALL_SHOW_EMPTY option applies to the MATCH_RECOGNIZE clause.
|
||||
// Output all rows of every match, including empty matches.
|
||||
// In the case of an empty match, output the starting row of the match attempt.
|
||||
// Do not produce output for the rows matched within exclusion `{- ... -}`.
|
||||
ALL_SHOW_EMPTY {
|
||||
@Override
|
||||
public boolean isOneRow()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmptyMatches()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnmatchedRows()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
// ALL_OMIT_EMPTY option applies to the MATCH_RECOGNIZE clause.
|
||||
// Output all rows of every non-empty match.
|
||||
// Do not produce output for the rows matched within exclusion `{- ... -}`
|
||||
ALL_OMIT_EMPTY {
|
||||
@Override
|
||||
public boolean isOneRow()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmptyMatches()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnmatchedRows()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
// ALL_WITH_UNMATCHED option applies to the MATCH_RECOGNIZE clause.
|
||||
// Output all rows of every match, including empty matches.
|
||||
// Produce an additional output row for every unmatched row.
|
||||
// Pattern exclusions are not allowed with this option.
|
||||
ALL_WITH_UNMATCHED {
|
||||
@Override
|
||||
public boolean isOneRow()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmptyMatches()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnmatchedRows()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
// WINDOW option applies to pattern recognition within window specification.
|
||||
// Output one row for every input row:
|
||||
// - if the row is skipped by some previous match, produce output as for unmatched row
|
||||
// - if match is found (either empty or non-empty), output a single-row summary
|
||||
// - if no match is found, produce output as for unmatched row
|
||||
WINDOW {
|
||||
@Override
|
||||
public boolean isOneRow()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmptyMatches()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnmatchedRows()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
public abstract boolean isOneRow();
|
||||
|
||||
public abstract boolean isEmptyMatches();
|
||||
|
||||
public abstract boolean isUnmatchedRows();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.trino.sql.tree;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public final class PatternSearchMode
|
||||
extends Node
|
||||
{
|
||||
private final Mode mode;
|
||||
|
||||
public PatternSearchMode(Mode mode)
|
||||
{
|
||||
this(Optional.empty(), mode);
|
||||
}
|
||||
|
||||
public PatternSearchMode(NodeLocation location, Mode mode)
|
||||
{
|
||||
this(Optional.of(location), mode);
|
||||
}
|
||||
|
||||
public PatternSearchMode(Optional<NodeLocation> location, Mode mode)
|
||||
{
|
||||
super(location);
|
||||
this.mode = requireNonNull(mode, "mode is null");
|
||||
}
|
||||
|
||||
public Mode getMode()
|
||||
{
|
||||
return mode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, C> R accept(AstVisitor<R, C> visitor, C context)
|
||||
{
|
||||
return visitor.visitPatternSearchMode(this, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Node> getChildren()
|
||||
{
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if ((obj == null) || (getClass() != obj.getClass())) {
|
||||
return false;
|
||||
}
|
||||
return mode == ((PatternSearchMode) obj).mode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(mode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return toStringHelper(this)
|
||||
.add("mode", mode)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public enum Mode
|
||||
{
|
||||
INITIAL, SEEK
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.trino.sql.tree;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public class PatternVariable
|
||||
extends RowPattern
|
||||
{
|
||||
private final Identifier name;
|
||||
|
||||
public PatternVariable(NodeLocation location, Identifier name)
|
||||
{
|
||||
this(Optional.of(location), name);
|
||||
}
|
||||
|
||||
private PatternVariable(Optional<NodeLocation> location, Identifier name)
|
||||
{
|
||||
super(location);
|
||||
this.name = requireNonNull(name, "name is null");
|
||||
}
|
||||
|
||||
public Identifier getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, C> R accept(AstVisitor<R, C> visitor, C context)
|
||||
{
|
||||
return visitor.visitPatternVariable(this, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Node> getChildren()
|
||||
{
|
||||
return ImmutableList.of(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if ((obj == null) || (getClass() != obj.getClass())) {
|
||||
return false;
|
||||
}
|
||||
PatternVariable o = (PatternVariable) obj;
|
||||
return Objects.equals(name, o.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return toStringHelper(this)
|
||||
.add("name", name)
|
||||
.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shallowEquals(Node other)
|
||||
{
|
||||
return sameClass(this, other);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.trino.sql.tree;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public final class ProcessingMode
|
||||
extends Node
|
||||
{
|
||||
private final Mode mode;
|
||||
|
||||
public ProcessingMode(NodeLocation location, Mode mode)
|
||||
{
|
||||
this(Optional.of(location), mode);
|
||||
}
|
||||
|
||||
public ProcessingMode(Optional<NodeLocation> location, Mode mode)
|
||||
{
|
||||
super(location);
|
||||
this.mode = requireNonNull(mode, "mode is null");
|
||||
}
|
||||
|
||||
public Mode getMode()
|
||||
{
|
||||
return mode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, C> R accept(AstVisitor<R, C> visitor, C context)
|
||||
{
|
||||
return visitor.visitProcessingMode(this, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Node> getChildren()
|
||||
{
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if ((obj == null) || (getClass() != obj.getClass())) {
|
||||
return false;
|
||||
}
|
||||
return mode == ((ProcessingMode) obj).mode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(mode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return toStringHelper(this)
|
||||
.add("mode", mode)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public enum Mode
|
||||
{
|
||||
RUNNING, FINAL
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -49,7 +49,7 @@ public class QuantifiedComparisonExpression
|
||||
private QuantifiedComparisonExpression(Optional<NodeLocation> location, ComparisonExpression.Operator operator, Quantifier quantifier, Expression value, Expression subquery)
|
||||
{
|
||||
super(location);
|
||||
this.operator = requireNonNull(operator, "comparisonType is null");
|
||||
this.operator = requireNonNull(operator, "operator is null");
|
||||
this.quantifier = requireNonNull(quantifier, "quantifier is null");
|
||||
this.value = requireNonNull(value, "value is null");
|
||||
this.subquery = requireNonNull(subquery, "subquery is null");
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.trino.sql.tree;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public class QuantifiedPattern
|
||||
extends RowPattern
|
||||
{
|
||||
private final RowPattern pattern;
|
||||
private final PatternQuantifier patternQuantifier;
|
||||
|
||||
public QuantifiedPattern(NodeLocation location, RowPattern pattern, PatternQuantifier patternQuantifier)
|
||||
{
|
||||
this(Optional.of(location), pattern, patternQuantifier);
|
||||
}
|
||||
|
||||
private QuantifiedPattern(Optional<NodeLocation> location, RowPattern pattern, PatternQuantifier patternQuantifier)
|
||||
{
|
||||
super(location);
|
||||
this.pattern = requireNonNull(pattern, "pattern is null");
|
||||
this.patternQuantifier = requireNonNull(patternQuantifier, "patternQuantifier is null");
|
||||
}
|
||||
|
||||
public RowPattern getPattern()
|
||||
{
|
||||
return pattern;
|
||||
}
|
||||
|
||||
public PatternQuantifier getPatternQuantifier()
|
||||
{
|
||||
return patternQuantifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, C> R accept(AstVisitor<R, C> visitor, C context)
|
||||
{
|
||||
return visitor.visitQuantifiedPattern(this, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Node> getChildren()
|
||||
{
|
||||
return ImmutableList.of(pattern, patternQuantifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if ((obj == null) || (getClass() != obj.getClass())) {
|
||||
return false;
|
||||
}
|
||||
QuantifiedPattern o = (QuantifiedPattern) obj;
|
||||
return Objects.equals(pattern, o.pattern) &&
|
||||
Objects.equals(patternQuantifier, o.patternQuantifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(pattern, patternQuantifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return toStringHelper(this)
|
||||
.add("pattern", pattern)
|
||||
.add("patternQuantifier", patternQuantifier)
|
||||
.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shallowEquals(Node other)
|
||||
{
|
||||
return sameClass(this, other);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.trino.sql.tree;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public class RangeQuantifier
|
||||
extends PatternQuantifier
|
||||
{
|
||||
private final Optional<LongLiteral> atLeast;
|
||||
private final Optional<LongLiteral> atMost;
|
||||
|
||||
public RangeQuantifier(boolean greedy, Optional<LongLiteral> atLeast, Optional<LongLiteral> atMost)
|
||||
{
|
||||
this(Optional.empty(), greedy, atLeast, atMost);
|
||||
}
|
||||
|
||||
public RangeQuantifier(NodeLocation location, boolean greedy, Optional<LongLiteral> atLeast, Optional<LongLiteral> atMost)
|
||||
{
|
||||
this(Optional.of(location), greedy, atLeast, atMost);
|
||||
}
|
||||
|
||||
private RangeQuantifier(Optional<NodeLocation> location, boolean greedy, Optional<LongLiteral> atLeast, Optional<LongLiteral> atMost)
|
||||
{
|
||||
super(location, greedy);
|
||||
this.atLeast = requireNonNull(atLeast, "atLeast is null");
|
||||
this.atMost = requireNonNull(atMost, "atMost is null");
|
||||
}
|
||||
|
||||
public Optional<LongLiteral> getAtLeast()
|
||||
{
|
||||
return atLeast;
|
||||
}
|
||||
|
||||
public Optional<LongLiteral> getAtMost()
|
||||
{
|
||||
return atMost;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, C> R accept(AstVisitor<R, C> visitor, C context)
|
||||
{
|
||||
return visitor.visitRangeQuantifier(this, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Node> getChildren()
|
||||
{
|
||||
ImmutableList.Builder<Node> children = ImmutableList.builder();
|
||||
atLeast.ifPresent(children::add);
|
||||
atMost.ifPresent(children::add);
|
||||
return children.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if ((obj == null) || (getClass() != obj.getClass())) {
|
||||
return false;
|
||||
}
|
||||
RangeQuantifier o = (RangeQuantifier) obj;
|
||||
return isGreedy() == o.isGreedy() &&
|
||||
Objects.equals(atLeast, o.atLeast) &&
|
||||
Objects.equals(atMost, o.atMost);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(isGreedy(), atLeast, atMost);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return toStringHelper(this)
|
||||
.add("atLeast", atLeast)
|
||||
.add("atMost", atMost)
|
||||
.add("greedy", isGreedy())
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.trino.sql.tree;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public abstract class RowPattern
|
||||
extends Node
|
||||
{
|
||||
protected RowPattern(Optional<NodeLocation> location)
|
||||
{
|
||||
super(location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, C> R accept(AstVisitor<R, C> visitor, C context)
|
||||
{
|
||||
return visitor.visitRowPattern(this, context);
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,7 @@ public class SetPath
|
||||
private SetPath(Optional<NodeLocation> location, PathSpecification pathSpecification)
|
||||
{
|
||||
super(location);
|
||||
this.pathSpecification = requireNonNull(pathSpecification, "path is null");
|
||||
this.pathSpecification = requireNonNull(pathSpecification, "pathSpecification is null");
|
||||
}
|
||||
|
||||
public PathSpecification getPathSpecification()
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.trino.sql.tree;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static io.trino.sql.tree.SkipTo.Position.FIRST;
|
||||
import static io.trino.sql.tree.SkipTo.Position.LAST;
|
||||
import static io.trino.sql.tree.SkipTo.Position.NEXT;
|
||||
import static io.trino.sql.tree.SkipTo.Position.PAST_LAST;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public class SkipTo
|
||||
extends Node
|
||||
{
|
||||
private final Position position;
|
||||
private final Optional<Identifier> identifier;
|
||||
|
||||
public enum Position
|
||||
{
|
||||
PAST_LAST,
|
||||
NEXT,
|
||||
FIRST,
|
||||
LAST
|
||||
}
|
||||
|
||||
// default
|
||||
public static SkipTo skipPastLastRow()
|
||||
{
|
||||
return skipPastLastRow(Optional.empty());
|
||||
}
|
||||
|
||||
public static SkipTo skipPastLastRow(NodeLocation location)
|
||||
{
|
||||
return skipPastLastRow(Optional.of(location));
|
||||
}
|
||||
|
||||
private static SkipTo skipPastLastRow(Optional<NodeLocation> location)
|
||||
{
|
||||
return new SkipTo(location, PAST_LAST, Optional.empty());
|
||||
}
|
||||
|
||||
public static SkipTo skipToNextRow()
|
||||
{
|
||||
return skipToNextRow(Optional.empty());
|
||||
}
|
||||
|
||||
public static SkipTo skipToNextRow(NodeLocation location)
|
||||
{
|
||||
return skipToNextRow(Optional.of(location));
|
||||
}
|
||||
|
||||
private static SkipTo skipToNextRow(Optional<NodeLocation> location)
|
||||
{
|
||||
return new SkipTo(location, NEXT, Optional.empty());
|
||||
}
|
||||
|
||||
public static SkipTo skipToFirst(Identifier identifier)
|
||||
{
|
||||
return skipToFirst(Optional.empty(), identifier);
|
||||
}
|
||||
|
||||
public static SkipTo skipToFirst(NodeLocation location, Identifier identifier)
|
||||
{
|
||||
return skipToFirst(Optional.of(location), identifier);
|
||||
}
|
||||
|
||||
private static SkipTo skipToFirst(Optional<NodeLocation> location, Identifier identifier)
|
||||
{
|
||||
return new SkipTo(location, FIRST, Optional.of(identifier));
|
||||
}
|
||||
|
||||
public static SkipTo skipToLast(Identifier identifier)
|
||||
{
|
||||
return skipToLast(Optional.empty(), identifier);
|
||||
}
|
||||
|
||||
public static SkipTo skipToLast(NodeLocation location, Identifier identifier)
|
||||
{
|
||||
return skipToLast(Optional.of(location), identifier);
|
||||
}
|
||||
|
||||
private static SkipTo skipToLast(Optional<NodeLocation> location, Identifier identifier)
|
||||
{
|
||||
return new SkipTo(location, LAST, Optional.of(identifier));
|
||||
}
|
||||
|
||||
private SkipTo(Optional<NodeLocation> location, Position position, Optional<Identifier> identifier)
|
||||
{
|
||||
super(location);
|
||||
requireNonNull(position, "position is null");
|
||||
requireNonNull(identifier, "identifier is null");
|
||||
checkArgument(identifier.isPresent() || (position == PAST_LAST || position == NEXT), "missing identifier in SKIP TO " + position.name());
|
||||
checkArgument(!identifier.isPresent() || (position == FIRST || position == LAST), "unexpected identifier in SKIP TO " + position.name());
|
||||
this.position = position;
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public Position getPosition()
|
||||
{
|
||||
return position;
|
||||
}
|
||||
|
||||
public Optional<Identifier> getIdentifier()
|
||||
{
|
||||
return identifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, C> R accept(AstVisitor<R, C> visitor, C context)
|
||||
{
|
||||
return visitor.visitSkipTo(this, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends Node> getChildren()
|
||||
{
|
||||
return identifier.map(ImmutableList::of).orElse(ImmutableList.of());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return toStringHelper(this)
|
||||
.add("position", position)
|
||||
.add("identifier", identifier.orElse(null))
|
||||
.omitNullValues()
|
||||
.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SkipTo that = (SkipTo) o;
|
||||
return Objects.equals(position, that.position) &&
|
||||
Objects.equals(identifier, that.identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(position, identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shallowEquals(Node other)
|
||||
{
|
||||
if (!sameClass(this, other)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return position == ((SkipTo) other).position;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.trino.sql.tree;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public class SubsetDefinition
|
||||
extends Node
|
||||
{
|
||||
private final Identifier name;
|
||||
private final List<Identifier> identifiers;
|
||||
|
||||
public SubsetDefinition(Identifier name, List<Identifier> identifiers)
|
||||
{
|
||||
this(Optional.empty(), name, identifiers);
|
||||
}
|
||||
|
||||
public SubsetDefinition(NodeLocation location, Identifier name, List<Identifier> identifiers)
|
||||
{
|
||||
this(Optional.of(location), name, identifiers);
|
||||
}
|
||||
|
||||
private SubsetDefinition(Optional<NodeLocation> location, Identifier name, List<Identifier> identifiers)
|
||||
{
|
||||
super(location);
|
||||
this.name = requireNonNull(name, "name is null");
|
||||
requireNonNull(identifiers, "identifiers is null");
|
||||
checkArgument(!identifiers.isEmpty(), "identifiers is empty");
|
||||
this.identifiers = identifiers;
|
||||
}
|
||||
|
||||
public Identifier getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public List<Identifier> getIdentifiers()
|
||||
{
|
||||
return identifiers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, C> R accept(AstVisitor<R, C> visitor, C context)
|
||||
{
|
||||
return visitor.visitSubsetDefinition(this, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends Node> getChildren()
|
||||
{
|
||||
return identifiers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return toStringHelper(this)
|
||||
.add("name", name)
|
||||
.add("identifiers", identifiers)
|
||||
.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SubsetDefinition that = (SubsetDefinition) o;
|
||||
return Objects.equals(name, that.name) &&
|
||||
Objects.equals(identifiers, that.identifiers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(name, identifiers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shallowEquals(Node other)
|
||||
{
|
||||
if (!sameClass(this, other)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Objects.equals(name, ((SubsetDefinition) other).name);
|
||||
}
|
||||
}
|
||||
@@ -25,33 +25,21 @@ public class Table
|
||||
extends QueryBody
|
||||
{
|
||||
private final QualifiedName name;
|
||||
private final Optional<QualifiedName> cannerflowName;
|
||||
|
||||
public Table(QualifiedName name)
|
||||
{
|
||||
this(Optional.empty(), name, Optional.empty());
|
||||
}
|
||||
|
||||
public Table(QualifiedName name, QualifiedName cannerflowName)
|
||||
{
|
||||
this(Optional.empty(), name, Optional.of(cannerflowName));
|
||||
this(Optional.empty(), name);
|
||||
}
|
||||
|
||||
public Table(NodeLocation location, QualifiedName name)
|
||||
{
|
||||
this(Optional.of(location), name, Optional.empty());
|
||||
this(Optional.of(location), name);
|
||||
}
|
||||
|
||||
public Table(NodeLocation location, QualifiedName name, QualifiedName cannerflowName)
|
||||
{
|
||||
this(Optional.of(location), name, Optional.of(cannerflowName));
|
||||
}
|
||||
|
||||
private Table(Optional<NodeLocation> location, QualifiedName name, Optional<QualifiedName> cannerflowName)
|
||||
private Table(Optional<NodeLocation> location, QualifiedName name)
|
||||
{
|
||||
super(location);
|
||||
this.name = name;
|
||||
this.cannerflowName = cannerflowName;
|
||||
}
|
||||
|
||||
public QualifiedName getName()
|
||||
@@ -59,11 +47,6 @@ public class Table
|
||||
return name;
|
||||
}
|
||||
|
||||
public Optional<QualifiedName> getCannerflowName()
|
||||
{
|
||||
return cannerflowName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, C> R accept(AstVisitor<R, C> visitor, C context)
|
||||
{
|
||||
|
||||
@@ -29,7 +29,7 @@ public class TypeParameter
|
||||
public TypeParameter(DataType type)
|
||||
{
|
||||
super(Optional.empty());
|
||||
this.type = requireNonNull(type, "value is null");
|
||||
this.type = requireNonNull(type, "type is null");
|
||||
}
|
||||
|
||||
public DataType getValue()
|
||||
|
||||
@@ -43,7 +43,7 @@ public class Update
|
||||
{
|
||||
super(location);
|
||||
this.table = requireNonNull(table, "table is null");
|
||||
this.assignments = requireNonNull(assignments, "targets is null");
|
||||
this.assignments = requireNonNull(assignments, "assignments is null");
|
||||
this.where = requireNonNull(where, "where is null");
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.trino.sql.tree;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public class VariableDefinition
|
||||
extends Node
|
||||
{
|
||||
private final Identifier name;
|
||||
private final Expression expression;
|
||||
|
||||
public VariableDefinition(Identifier name, Expression expression)
|
||||
{
|
||||
this(Optional.empty(), name, expression);
|
||||
}
|
||||
|
||||
public VariableDefinition(NodeLocation location, Identifier name, Expression expression)
|
||||
{
|
||||
this(Optional.of(location), name, expression);
|
||||
}
|
||||
|
||||
private VariableDefinition(Optional<NodeLocation> location, Identifier name, Expression expression)
|
||||
{
|
||||
super(location);
|
||||
this.name = requireNonNull(name, "name is null");
|
||||
this.expression = requireNonNull(expression, "expression is null");
|
||||
}
|
||||
|
||||
public Identifier getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public Expression getExpression()
|
||||
{
|
||||
return expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, C> R accept(AstVisitor<R, C> visitor, C context)
|
||||
{
|
||||
return visitor.visitVariableDefinition(this, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends Node> getChildren()
|
||||
{
|
||||
return ImmutableList.of(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return toStringHelper(this)
|
||||
.add("name", name)
|
||||
.add("expression", expression)
|
||||
.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
VariableDefinition that = (VariableDefinition) o;
|
||||
return Objects.equals(name, that.name) &&
|
||||
Objects.equals(expression, that.expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(name, expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shallowEquals(Node other)
|
||||
{
|
||||
if (!sameClass(this, other)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Objects.equals(name, ((VariableDefinition) other).name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.trino.sql.tree;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class ZeroOrMoreQuantifier
|
||||
extends PatternQuantifier
|
||||
{
|
||||
public ZeroOrMoreQuantifier(boolean greedy)
|
||||
{
|
||||
this(Optional.empty(), greedy);
|
||||
}
|
||||
|
||||
public ZeroOrMoreQuantifier(NodeLocation location, boolean greedy)
|
||||
{
|
||||
this(Optional.of(location), greedy);
|
||||
}
|
||||
|
||||
public ZeroOrMoreQuantifier(Optional<NodeLocation> location, boolean greedy)
|
||||
{
|
||||
super(location, greedy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, C> R accept(AstVisitor<R, C> visitor, C context)
|
||||
{
|
||||
return visitor.visitZeroOrMoreQuantifier(this, context);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.trino.sql.tree;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class ZeroOrOneQuantifier
|
||||
extends PatternQuantifier
|
||||
{
|
||||
public ZeroOrOneQuantifier(boolean greedy)
|
||||
{
|
||||
this(Optional.empty(), greedy);
|
||||
}
|
||||
|
||||
public ZeroOrOneQuantifier(NodeLocation location, boolean greedy)
|
||||
{
|
||||
this(Optional.of(location), greedy);
|
||||
}
|
||||
|
||||
public ZeroOrOneQuantifier(Optional<NodeLocation> location, boolean greedy)
|
||||
{
|
||||
super(location, greedy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, C> R accept(AstVisitor<R, C> visitor, C context)
|
||||
{
|
||||
return visitor.visitZeroOrOneQuantifier(this, context);
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,8 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Copyright (C) Canner, Inc - All Rights Reserved
|
||||
* Unauthorized copying of this file, via any medium is strictly prohibited
|
||||
* Proprietary and confidential
|
||||
* Written by Canner dev team contact@canner.io, Nov 2021
|
||||
*/
|
||||
|
||||
package io.trino.sql.util;
|
||||
|
||||
@@ -1,15 +1,8 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Copyright (C) Canner, Inc - All Rights Reserved
|
||||
* Unauthorized copying of this file, via any medium is strictly prohibited
|
||||
* Proprietary and confidential
|
||||
* Written by Canner dev team contact@canner.io, Nov 2021
|
||||
*/
|
||||
|
||||
package io.trino.sql.util;
|
||||
|
||||
@@ -1,15 +1,8 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Copyright (C) Canner, Inc - All Rights Reserved
|
||||
* Unauthorized copying of this file, via any medium is strictly prohibited
|
||||
* Proprietary and confidential
|
||||
* Written by Canner dev team contact@canner.io, Feb 2022
|
||||
*/
|
||||
|
||||
package io.trino.sql.util;
|
||||
@@ -32,9 +25,9 @@ public final class IntervalLiteralUtil
|
||||
* <p>
|
||||
* e.g.
|
||||
* when client sends a query like
|
||||
* select CAST((CAST(now() AS timestamp) + (INTERVAL '-30 day')) AS date);
|
||||
* select CAST((CAST(now() AS timestamp) + (INTERVAL '-30 day')) AS date);
|
||||
* will get the same result as
|
||||
* select CAST((CAST(now() AS timestamp) + (INTERVAL - '30' day)) AS date);
|
||||
* select CAST((CAST(now() AS timestamp) + (INTERVAL - '30' day)) AS date);
|
||||
*/
|
||||
public static IntervalLiteral parse(NodeLocation location, String text)
|
||||
{
|
||||
|
||||
@@ -16,6 +16,7 @@ package io.trino.sql.parser;
|
||||
import io.trino.sql.SqlFormatter;
|
||||
import io.trino.sql.tree.Expression;
|
||||
import io.trino.sql.tree.Node;
|
||||
import io.trino.sql.tree.RowPattern;
|
||||
import io.trino.sql.tree.Statement;
|
||||
import org.assertj.core.api.AssertProvider;
|
||||
import org.assertj.core.api.RecursiveComparisonAssert;
|
||||
@@ -35,7 +36,7 @@ public class ParserAssert
|
||||
@Override
|
||||
public String toStringOf(Object object)
|
||||
{
|
||||
if (object instanceof Statement || object instanceof Expression) {
|
||||
if (object instanceof Statement || object instanceof Expression || object instanceof RowPattern) {
|
||||
return SqlFormatter.formatSql((Node) object);
|
||||
}
|
||||
return super.toStringOf(object);
|
||||
@@ -57,6 +58,11 @@ public class ParserAssert
|
||||
return createAssertion(statement -> new SqlParser().createStatement(statement, new ParsingOptions(AS_DECIMAL)), sql);
|
||||
}
|
||||
|
||||
public static AssertProvider<ParserAssert> rowPattern(String sql)
|
||||
{
|
||||
return createAssertion(new SqlParser()::createRowPattern, sql);
|
||||
}
|
||||
|
||||
private ParserAssert(Node actual, RecursiveComparisonConfiguration recursiveComparisonConfiguration)
|
||||
{
|
||||
super(actual, recursiveComparisonConfiguration);
|
||||
|
||||
@@ -22,6 +22,7 @@ import io.trino.sql.tree.AliasedRelation;
|
||||
import io.trino.sql.tree.AllColumns;
|
||||
import io.trino.sql.tree.AllRows;
|
||||
import io.trino.sql.tree.Analyze;
|
||||
import io.trino.sql.tree.AnchorPattern;
|
||||
import io.trino.sql.tree.ArithmeticBinaryExpression;
|
||||
import io.trino.sql.tree.ArrayConstructor;
|
||||
import io.trino.sql.tree.AtTimeZone;
|
||||
@@ -58,6 +59,7 @@ import io.trino.sql.tree.DropRole;
|
||||
import io.trino.sql.tree.DropSchema;
|
||||
import io.trino.sql.tree.DropTable;
|
||||
import io.trino.sql.tree.DropView;
|
||||
import io.trino.sql.tree.EmptyPattern;
|
||||
import io.trino.sql.tree.Execute;
|
||||
import io.trino.sql.tree.ExistsPredicate;
|
||||
import io.trino.sql.tree.Explain;
|
||||
@@ -106,17 +108,24 @@ import io.trino.sql.tree.NotExpression;
|
||||
import io.trino.sql.tree.NullIfExpression;
|
||||
import io.trino.sql.tree.NullLiteral;
|
||||
import io.trino.sql.tree.Offset;
|
||||
import io.trino.sql.tree.OneOrMoreQuantifier;
|
||||
import io.trino.sql.tree.OrderBy;
|
||||
import io.trino.sql.tree.Parameter;
|
||||
import io.trino.sql.tree.PathElement;
|
||||
import io.trino.sql.tree.PathSpecification;
|
||||
import io.trino.sql.tree.PatternAlternation;
|
||||
import io.trino.sql.tree.PatternConcatenation;
|
||||
import io.trino.sql.tree.PatternVariable;
|
||||
import io.trino.sql.tree.Prepare;
|
||||
import io.trino.sql.tree.PrincipalSpecification;
|
||||
import io.trino.sql.tree.ProcessingMode;
|
||||
import io.trino.sql.tree.Property;
|
||||
import io.trino.sql.tree.QualifiedName;
|
||||
import io.trino.sql.tree.QuantifiedComparisonExpression;
|
||||
import io.trino.sql.tree.QuantifiedPattern;
|
||||
import io.trino.sql.tree.Query;
|
||||
import io.trino.sql.tree.QuerySpecification;
|
||||
import io.trino.sql.tree.RangeQuantifier;
|
||||
import io.trino.sql.tree.RefreshMaterializedView;
|
||||
import io.trino.sql.tree.RenameColumn;
|
||||
import io.trino.sql.tree.RenameSchema;
|
||||
@@ -172,6 +181,8 @@ import io.trino.sql.tree.WindowReference;
|
||||
import io.trino.sql.tree.WindowSpecification;
|
||||
import io.trino.sql.tree.With;
|
||||
import io.trino.sql.tree.WithQuery;
|
||||
import io.trino.sql.tree.ZeroOrMoreQuantifier;
|
||||
import io.trino.sql.tree.ZeroOrOneQuantifier;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -195,6 +206,7 @@ import static io.trino.sql.QueryUtil.table;
|
||||
import static io.trino.sql.QueryUtil.values;
|
||||
import static io.trino.sql.SqlFormatter.formatSql;
|
||||
import static io.trino.sql.parser.ParserAssert.expression;
|
||||
import static io.trino.sql.parser.ParserAssert.rowPattern;
|
||||
import static io.trino.sql.parser.ParserAssert.statement;
|
||||
import static io.trino.sql.parser.ParsingOptions.DecimalLiteralTreatment.AS_DECIMAL;
|
||||
import static io.trino.sql.parser.TreeNodes.columnDefinition;
|
||||
@@ -210,6 +222,8 @@ import static io.trino.sql.tree.ArithmeticUnaryExpression.negative;
|
||||
import static io.trino.sql.tree.ArithmeticUnaryExpression.positive;
|
||||
import static io.trino.sql.tree.DateTimeDataType.Type.TIMESTAMP;
|
||||
import static io.trino.sql.tree.FrameBound.Type.CURRENT_ROW;
|
||||
import static io.trino.sql.tree.ProcessingMode.Mode.FINAL;
|
||||
import static io.trino.sql.tree.ProcessingMode.Mode.RUNNING;
|
||||
import static io.trino.sql.tree.SortItem.NullOrdering.UNDEFINED;
|
||||
import static io.trino.sql.tree.SortItem.Ordering.ASCENDING;
|
||||
import static io.trino.sql.tree.SortItem.Ordering.DESCENDING;
|
||||
@@ -647,6 +661,113 @@ public class TestSqlParser
|
||||
subquery(valuesQuery)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRowPattern()
|
||||
{
|
||||
assertThat(rowPattern("(A B)* | CC+? DD?? E | (F | G)"))
|
||||
.isEqualTo(
|
||||
new PatternAlternation(
|
||||
location(1, 1),
|
||||
ImmutableList.of(
|
||||
new PatternAlternation(
|
||||
location(1, 1),
|
||||
ImmutableList.of(
|
||||
new QuantifiedPattern(
|
||||
location(1, 1),
|
||||
new PatternConcatenation(
|
||||
location(1, 2),
|
||||
ImmutableList.of(
|
||||
new PatternVariable(location(1, 2), new Identifier(location(1, 2), "A", false)),
|
||||
new PatternVariable(location(1, 4), new Identifier(location(1, 4), "B", false)))),
|
||||
new ZeroOrMoreQuantifier(location(1, 6), true)),
|
||||
new PatternConcatenation(
|
||||
location(1, 10),
|
||||
ImmutableList.of(
|
||||
new PatternConcatenation(
|
||||
location(1, 10),
|
||||
ImmutableList.of(
|
||||
new QuantifiedPattern(location(1, 10), new PatternVariable(location(1, 10), new Identifier(location(1, 10), "CC", false)), new OneOrMoreQuantifier(location(1, 12), false)),
|
||||
new QuantifiedPattern(location(1, 15), new PatternVariable(location(1, 15), new Identifier(location(1, 15), "DD", false)), new ZeroOrOneQuantifier(location(1, 17), false)))),
|
||||
new PatternVariable(location(1, 20), new Identifier(location(1, 20), "E", false)))))),
|
||||
new PatternAlternation(
|
||||
location(1, 25),
|
||||
ImmutableList.of(
|
||||
new PatternVariable(location(1, 25), new Identifier(location(1, 25), "F", false)),
|
||||
new PatternVariable(location(1, 29), new Identifier(location(1, 29), "G", false)))))));
|
||||
|
||||
assertThat(rowPattern("A | B | C D E F"))
|
||||
.isEqualTo(
|
||||
new PatternAlternation(
|
||||
location(1, 1),
|
||||
ImmutableList.of(
|
||||
new PatternAlternation(
|
||||
location(1, 1),
|
||||
ImmutableList.of(
|
||||
new PatternVariable(location(1, 1), new Identifier(location(1, 1), "A", false)),
|
||||
new PatternVariable(location(1, 5), new Identifier(location(1, 5), "B", false)))),
|
||||
new PatternConcatenation(
|
||||
location(1, 9),
|
||||
ImmutableList.of(
|
||||
new PatternConcatenation(
|
||||
location(1, 9),
|
||||
ImmutableList.of(
|
||||
new PatternConcatenation(
|
||||
location(1, 9),
|
||||
ImmutableList.of(
|
||||
new PatternVariable(location(1, 9), new Identifier(location(1, 9), "C", false)),
|
||||
new PatternVariable(location(1, 11), new Identifier(location(1, 11), "D", false)))),
|
||||
new PatternVariable(location(1, 13), new Identifier(location(1, 13), "E", false)))),
|
||||
new PatternVariable(location(1, 15), new Identifier(location(1, 15), "F", false)))))));
|
||||
|
||||
assertThatThrownBy(() -> SQL_PARSER.createRowPattern("A!"))
|
||||
.isInstanceOf(ParsingException.class)
|
||||
.hasMessageMatching("line 1:2: mismatched input '!'.*");
|
||||
|
||||
assertThatThrownBy(() -> SQL_PARSER.createRowPattern("A**"))
|
||||
.isInstanceOf(ParsingException.class)
|
||||
.hasMessageMatching("line 1:3: mismatched input '*'.*");
|
||||
|
||||
assertThat(rowPattern("A??"))
|
||||
.isEqualTo(new QuantifiedPattern(
|
||||
location(1, 1),
|
||||
new PatternVariable(location(1, 1), new Identifier(location(1, 1), "A", false)),
|
||||
new ZeroOrOneQuantifier(location(1, 2), false)));
|
||||
|
||||
assertThat(rowPattern("^$"))
|
||||
.isEqualTo(new PatternConcatenation(
|
||||
location(1, 1),
|
||||
ImmutableList.of(
|
||||
new AnchorPattern(location(1, 1), AnchorPattern.Type.PARTITION_START),
|
||||
new AnchorPattern(location(1, 2), AnchorPattern.Type.PARTITION_END))));
|
||||
|
||||
assertThat(rowPattern("()"))
|
||||
.isEqualTo(new EmptyPattern(location(1, 1)));
|
||||
|
||||
assertThat(rowPattern("A{3}"))
|
||||
.isEqualTo(new QuantifiedPattern(
|
||||
location(1, 1),
|
||||
new PatternVariable(location(1, 1), new Identifier(location(1, 1), "A", false)),
|
||||
new RangeQuantifier(location(1, 2), true, Optional.of(new LongLiteral(location(1, 3), "3")), Optional.of(new LongLiteral(location(1, 3), "3")))));
|
||||
|
||||
assertThat(rowPattern("A{3,}"))
|
||||
.isEqualTo(new QuantifiedPattern(
|
||||
location(1, 1),
|
||||
new PatternVariable(location(1, 1), new Identifier(location(1, 1), "A", false)),
|
||||
new RangeQuantifier(location(1, 2), true, Optional.of(new LongLiteral(location(1, 3), "3")), Optional.empty())));
|
||||
|
||||
assertThat(rowPattern("A{,3}"))
|
||||
.isEqualTo(new QuantifiedPattern(
|
||||
location(1, 1),
|
||||
new PatternVariable(location(1, 1), new Identifier(location(1, 1), "A", false)),
|
||||
new RangeQuantifier(location(1, 2), true, Optional.empty(), Optional.of(new LongLiteral(location(1, 4), "3")))));
|
||||
|
||||
assertThat(rowPattern("A{3,4}"))
|
||||
.isEqualTo(new QuantifiedPattern(
|
||||
location(1, 1),
|
||||
new PatternVariable(location(1, 1), new Identifier(location(1, 1), "A", false)),
|
||||
new RangeQuantifier(location(1, 2), true, Optional.of(new LongLiteral(location(1, 3), "3")), Optional.of(new LongLiteral(location(1, 5), "4")))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrecedenceAndAssociativity()
|
||||
{
|
||||
@@ -2402,8 +2523,12 @@ public class TestSqlParser
|
||||
|
||||
for (String fullName : tableNames) {
|
||||
QualifiedName qualifiedName = makeQualifiedName(fullName);
|
||||
|
||||
// Simple SELECT
|
||||
assertStatement(format("SHOW STATS FOR (SELECT * FROM %s)", qualifiedName),
|
||||
createShowStats(qualifiedName, ImmutableList.of(new AllColumns()), Optional.empty()));
|
||||
|
||||
// SELECT with predicate
|
||||
assertStatement(format("SHOW STATS FOR (SELECT * FROM %s WHERE field > 0)", qualifiedName),
|
||||
createShowStats(qualifiedName,
|
||||
ImmutableList.of(new AllColumns()),
|
||||
@@ -2411,6 +2536,8 @@ public class TestSqlParser
|
||||
new ComparisonExpression(ComparisonExpression.Operator.GREATER_THAN,
|
||||
new Identifier("field"),
|
||||
new LongLiteral("0")))));
|
||||
|
||||
// SELECT with more complex predicate
|
||||
assertStatement(format("SHOW STATS FOR (SELECT * FROM %s WHERE field > 0 or field < 0)", qualifiedName),
|
||||
createShowStats(qualifiedName,
|
||||
ImmutableList.of(new AllColumns()),
|
||||
@@ -2423,6 +2550,128 @@ public class TestSqlParser
|
||||
new Identifier("field"),
|
||||
new LongLiteral("0"))))));
|
||||
}
|
||||
|
||||
// SELECT with LIMIT
|
||||
assertThat(statement("SHOW STATS FOR (SELECT * FROM t LIMIT 10)"))
|
||||
.isEqualTo(
|
||||
new ShowStats(
|
||||
Optional.of(location(1, 1)),
|
||||
new TableSubquery(
|
||||
new Query(
|
||||
location(1, 17),
|
||||
Optional.empty(),
|
||||
new QuerySpecification(
|
||||
location(1, 17),
|
||||
new Select(
|
||||
location(1, 17),
|
||||
false,
|
||||
ImmutableList.of(new AllColumns(location(1, 24), Optional.empty(), ImmutableList.of()))),
|
||||
Optional.of(new Table(
|
||||
location(1, 31),
|
||||
QualifiedName.of(ImmutableList.of(new Identifier(location(1, 31), "t", false))))),
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
ImmutableList.of(),
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
Optional.of(new Limit(location(1, 33), new LongLiteral(location(1, 39), "10")))),
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
Optional.empty()))));
|
||||
|
||||
// SELECT with ORDER BY ... LIMIT
|
||||
assertThat(statement("SHOW STATS FOR (SELECT * FROM t ORDER BY field LIMIT 10)"))
|
||||
.isEqualTo(
|
||||
new ShowStats(
|
||||
Optional.of(location(1, 1)),
|
||||
new TableSubquery(
|
||||
new Query(
|
||||
location(1, 17),
|
||||
Optional.empty(),
|
||||
new QuerySpecification(
|
||||
location(1, 17),
|
||||
new Select(
|
||||
location(1, 17),
|
||||
false,
|
||||
ImmutableList.of(new AllColumns(location(1, 24), Optional.empty(), ImmutableList.of()))),
|
||||
Optional.of(new Table(
|
||||
location(1, 31),
|
||||
QualifiedName.of(ImmutableList.of(new Identifier(location(1, 31), "t", false))))),
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
ImmutableList.of(),
|
||||
Optional.of(new OrderBy(location(1, 33), ImmutableList.of(
|
||||
new SortItem(location(1, 42), new Identifier(location(1, 42), "field", false), ASCENDING, UNDEFINED)))),
|
||||
Optional.empty(),
|
||||
Optional.of(new Limit(location(1, 48), new LongLiteral(location(1, 54), "10")))),
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
Optional.empty()))));
|
||||
|
||||
// SELECT with WITH
|
||||
assertThat(statement("SHOW STATS FOR (\n" +
|
||||
" WITH t AS (SELECT 1 )\n" +
|
||||
" SELECT * FROM t)"))
|
||||
.isEqualTo(
|
||||
new ShowStats(
|
||||
Optional.of(location(1, 1)),
|
||||
new TableSubquery(
|
||||
new Query(
|
||||
location(2, 4),
|
||||
Optional.of(
|
||||
new With(
|
||||
location(2, 4),
|
||||
false,
|
||||
ImmutableList.of(
|
||||
new WithQuery(
|
||||
location(2, 9),
|
||||
new Identifier(location(2, 9), "t", false),
|
||||
new Query(
|
||||
location(2, 15),
|
||||
Optional.empty(),
|
||||
new QuerySpecification(
|
||||
location(2, 15),
|
||||
new Select(
|
||||
location(2, 15),
|
||||
false,
|
||||
ImmutableList.of(
|
||||
new SingleColumn(
|
||||
location(2, 22),
|
||||
new LongLiteral(location(2, 22), "1"),
|
||||
Optional.empty()))),
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
ImmutableList.of(),
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
Optional.empty()),
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
Optional.empty()),
|
||||
Optional.empty())))),
|
||||
new QuerySpecification(
|
||||
location(3, 4),
|
||||
new Select(
|
||||
location(3, 4),
|
||||
false,
|
||||
ImmutableList.of(new AllColumns(location(3, 11), Optional.empty(), ImmutableList.of()))),
|
||||
Optional.of(new Table(
|
||||
location(3, 18),
|
||||
QualifiedName.of(ImmutableList.of(new Identifier(location(3, 18), "t", false))))),
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
ImmutableList.of(),
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
Optional.empty()),
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
Optional.empty()))));
|
||||
}
|
||||
|
||||
private static ShowStats createShowStats(QualifiedName name, List<SelectItem> selects, Optional<Expression> where)
|
||||
@@ -2462,6 +2711,7 @@ public class TestSqlParser
|
||||
Optional.empty(),
|
||||
false,
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
ImmutableList.of(new Identifier("x"))))));
|
||||
}
|
||||
|
||||
@@ -2500,6 +2750,7 @@ public class TestSqlParser
|
||||
Optional.of(new OrderBy(ImmutableList.of(new SortItem(identifier("x"), DESCENDING, UNDEFINED)))),
|
||||
false,
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
ImmutableList.of(identifier("x"))));
|
||||
assertStatement("SELECT array_agg(x ORDER BY t.y) FROM t",
|
||||
simpleQuery(
|
||||
@@ -2511,6 +2762,7 @@ public class TestSqlParser
|
||||
Optional.of(new OrderBy(ImmutableList.of(new SortItem(new DereferenceExpression(new Identifier("t"), identifier("y")), ASCENDING, UNDEFINED)))),
|
||||
false,
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
ImmutableList.of(new Identifier("x")))),
|
||||
table(QualifiedName.of("t"))));
|
||||
}
|
||||
@@ -2778,6 +3030,7 @@ public class TestSqlParser
|
||||
Optional.empty(),
|
||||
false,
|
||||
Optional.of(NullTreatment.IGNORE),
|
||||
Optional.empty(),
|
||||
ImmutableList.of(new Identifier("x"), new LongLiteral("1"))));
|
||||
assertExpression("lead(x, 1) respect nulls over()",
|
||||
new FunctionCall(
|
||||
@@ -2788,6 +3041,34 @@ public class TestSqlParser
|
||||
Optional.empty(),
|
||||
false,
|
||||
Optional.of(NullTreatment.RESPECT),
|
||||
Optional.empty(),
|
||||
ImmutableList.of(new Identifier("x"), new LongLiteral("1"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessingMode()
|
||||
{
|
||||
assertExpression("RUNNING LAST(x, 1)",
|
||||
new FunctionCall(
|
||||
Optional.empty(),
|
||||
QualifiedName.of("LAST"),
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
false,
|
||||
Optional.empty(),
|
||||
Optional.of(new ProcessingMode(Optional.empty(), RUNNING)),
|
||||
ImmutableList.of(new Identifier("x"), new LongLiteral("1"))));
|
||||
assertExpression("FINAL FIRST(x, 1)",
|
||||
new FunctionCall(
|
||||
Optional.empty(),
|
||||
QualifiedName.of("FIRST"),
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
false,
|
||||
Optional.empty(),
|
||||
Optional.of(new ProcessingMode(Optional.empty(), FINAL)),
|
||||
ImmutableList.of(new Identifier("x"), new LongLiteral("1"))));
|
||||
}
|
||||
|
||||
@@ -2803,6 +3084,7 @@ public class TestSqlParser
|
||||
Optional.empty(),
|
||||
false,
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
ImmutableList.of()));
|
||||
|
||||
assertExpression("rank() OVER (someWindow PARTITION BY x ORDER BY y ROWS CURRENT ROW)",
|
||||
@@ -2818,6 +3100,7 @@ public class TestSqlParser
|
||||
Optional.empty(),
|
||||
false,
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
ImmutableList.of()));
|
||||
|
||||
assertExpression("rank() OVER (PARTITION BY x ORDER BY y ROWS CURRENT ROW)",
|
||||
@@ -2833,6 +3116,7 @@ public class TestSqlParser
|
||||
Optional.empty(),
|
||||
false,
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
ImmutableList.of()));
|
||||
}
|
||||
|
||||
@@ -2866,6 +3150,7 @@ public class TestSqlParser
|
||||
Optional.empty()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdate()
|
||||
{
|
||||
assertStatement("" +
|
||||
@@ -2904,18 +3189,30 @@ public class TestSqlParser
|
||||
return QualifiedName.of(parts);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link ParserAssert#statement(String)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
private static void assertStatement(String query, Statement expected)
|
||||
{
|
||||
assertParsed(query, expected, SQL_PARSER.createStatement(query, new ParsingOptions()));
|
||||
assertFormattedSql(SQL_PARSER, expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link ParserAssert#statement(String)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
private static void assertInvalidStatement(String statement, String expectedErrorMessageRegex)
|
||||
{
|
||||
assertThatThrownBy(() -> SQL_PARSER.createStatement(statement, new ParsingOptions()))
|
||||
.isInstanceOfSatisfying(ParsingException.class, e -> assertTrue(e.getErrorMessage().matches(expectedErrorMessageRegex)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link ParserAssert#expression(String)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
private static void assertExpression(String expression, Expression expected)
|
||||
{
|
||||
requireNonNull(expression, "expression is null");
|
||||
|
||||
@@ -50,8 +50,8 @@ public class TestSqlParserErrorHandling
|
||||
{"select * from 'oops",
|
||||
"line 1:15: mismatched input '''. Expecting: '(', 'LATERAL', 'UNNEST', <identifier>"},
|
||||
{"select *\nfrom x\nfrom",
|
||||
"line 3:1: mismatched input 'from'. Expecting: ',', '.', 'AS', 'CROSS', 'EXCEPT', 'FETCH', 'FULL', 'GROUP', 'HAVING', 'INNER', 'INTERSECT', 'JOIN', 'LEFT', 'LIMIT', 'NATURAL', 'OFFSET', " +
|
||||
"'ORDER', 'RIGHT', 'TABLESAMPLE', 'UNION', 'WHERE', 'WINDOW', <EOF>, <identifier>"},
|
||||
"line 3:1: mismatched input 'from'. Expecting: ',', '.', 'AS', 'CROSS', 'EXCEPT', 'FETCH', 'FULL', 'GROUP', 'HAVING', 'INNER', 'INTERSECT', 'JOIN', 'LEFT', " +
|
||||
"'LIMIT', 'MATCH_RECOGNIZE', 'NATURAL', 'OFFSET', 'ORDER', 'RIGHT', 'TABLESAMPLE', 'UNION', 'WHERE', 'WINDOW', <EOF>, <identifier>"},
|
||||
{"select *\nfrom x\nwhere from",
|
||||
"line 3:7: mismatched input 'from'. Expecting: <expression>"},
|
||||
{"select ",
|
||||
@@ -121,8 +121,8 @@ public class TestSqlParserErrorHandling
|
||||
{"SELECT foo(*) filter (",
|
||||
"line 1:23: mismatched input '<EOF>'. Expecting: 'WHERE'"},
|
||||
{"SELECT * FROM t t x",
|
||||
"line 1:19: mismatched input 'x'. Expecting: '(', ',', 'CROSS', 'EXCEPT', 'FETCH', 'FULL', 'GROUP', 'HAVING', 'INNER', 'INTERSECT', 'JOIN', 'LEFT', 'LIMIT', 'NATURAL', 'OFFSET', 'ORDER', " +
|
||||
"'RIGHT', 'TABLESAMPLE', 'UNION', 'WHERE', 'WINDOW', <EOF>"},
|
||||
"line 1:19: mismatched input 'x'. Expecting: '(', ',', 'CROSS', 'EXCEPT', 'FETCH', 'FULL', 'GROUP', 'HAVING', 'INNER', 'INTERSECT', 'JOIN', 'LEFT', 'LIMIT', " +
|
||||
"'MATCH_RECOGNIZE', 'NATURAL', 'OFFSET', 'ORDER', 'RIGHT', 'TABLESAMPLE', 'UNION', 'WHERE', 'WINDOW', <EOF>"},
|
||||
{"SELECT * FROM t WHERE EXISTS (",
|
||||
"line 1:31: mismatched input '<EOF>'. Expecting: <query>"},
|
||||
{"SELECT \"\" FROM t",
|
||||
|
||||
@@ -34,6 +34,14 @@ public class TestStatementBuilder
|
||||
{
|
||||
private static final SqlParser SQL_PARSER = new SqlParser();
|
||||
|
||||
@Test
|
||||
public void testPreparedGrantWithQuotes()
|
||||
{
|
||||
printStatement("prepare p from grant select on table hive.test.\"case\" to role test");
|
||||
printStatement("prepare p from grant select on hive.test.\"case\" to role test");
|
||||
printStatement("prepare p from grant select on table hive.test.\"case\" to role \"case\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatementBuilder()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user