expressions)
- {
- return Joiner.on(", ").join(expressions.stream()
- .map((e) -> process(e, null))
- .iterator());
- }
-
- /**
- * Returns the formatted `LISTAGG` function call corresponding to the specified node.
- *
- * During the parsing of the syntax tree, the `LISTAGG` expression is synthetically converted
- * to a function call. This method formats the specified {@link FunctionCall} node to correspond
- * to the standardised syntax of the `LISTAGG` expression.
- *
- * @param node the `LISTAGG` function call
- */
- private String visitListagg(FunctionCall node)
- {
- StringBuilder builder = new StringBuilder();
-
- List arguments = node.getArguments();
- Expression expression = arguments.get(0);
- Expression separator = arguments.get(1);
- BooleanLiteral overflowError = (BooleanLiteral) arguments.get(2);
- Expression overflowFiller = arguments.get(3);
- BooleanLiteral showOverflowEntryCount = (BooleanLiteral) arguments.get(4);
-
- String innerArguments = joinExpressions(ImmutableList.of(expression, separator));
- if (node.isDistinct()) {
- innerArguments = "DISTINCT " + innerArguments;
- }
-
- builder.append("LISTAGG")
- .append('(').append(innerArguments);
-
- builder.append(" ON OVERFLOW ");
- if (overflowError.getValue()) {
- builder.append(" ERROR");
- }
- else {
- builder.append(" TRUNCATE")
- .append(' ')
- .append(process(overflowFiller, null));
- if (showOverflowEntryCount.getValue()) {
- builder.append(" WITH COUNT");
- }
- else {
- builder.append(" WITHOUT COUNT");
- }
- }
-
- builder.append(')');
-
- if (node.getOrderBy().isPresent()) {
- builder.append(" WITHIN GROUP ")
- .append('(')
- .append(formatOrderBy(node.getOrderBy().get(), dialect))
- .append(')');
- }
-
- return builder.toString();
- }
-
- private String processSliceInBigQuery(FunctionCall node)
- {
- List arguments = node.getArguments();
- Expression expression = arguments.get(0);
- LongLiteral start = (LongLiteral) arguments.get(1);
- LongLiteral length = (LongLiteral) arguments.get(2);
- return format("ARRAY(SELECT p FROM UNNEST(%s) p WITH OFFSET index WHERE index BETWEEN %s AND %s ORDER BY index)",
- process(expression),
- // bigquery use zero-based indexes
- start.getValue() - 1,
- start.getValue() - 1 + length.getValue());
- }
-
- private String processGenerateTimestampArrayInDuckDB(FunctionCall node)
- {
- List arguments = node.getArguments();
- Expression start = arguments.get(0);
- Expression end = arguments.get(1);
- return format("GENERATE_SERIES(%s, %s, INTERVAL 1 DAY)",
- start,
- end);
- }
-
- private String processDateDiffInBigQuery(FunctionCall node, Void context)
- {
- checkArgument(node.getArguments().size() == 3, "DATE_DIFF function should have 3 arguments");
- List arguments = node.getArguments();
- StringLiteral datePart = (StringLiteral) arguments.get(0);
- Expression start = arguments.get(1);
- Expression end = arguments.get(2);
- // In BigQuery, the formula is `start - end` but it's `end - start` in trino.
- return format("TIMESTAMP_DIFF(%s, %s, %s)",
- process(end, context),
- process(start, context),
- datePart.getValue());
- }
- }
-
- static String formatStringLiteral(String s)
- {
- return "'" + s.replace("'", "''") + "'";
- }
-
- public static String formatOrderBy(OrderBy orderBy, Dialect dialect)
- {
- return "ORDER BY " + formatSortItems(orderBy.getSortItems(), dialect);
- }
-
- private static String formatSortItems(List sortItems, Dialect dialect)
- {
- return Joiner.on(", ").join(sortItems.stream()
- .map(sortItemFormatterFunction(dialect))
- .iterator());
- }
-
- private static String formatWindow(Window window, Dialect dialect)
- {
- if (window instanceof WindowReference) {
- return formatExpression(((WindowReference) window).getName(), dialect);
- }
-
- return formatWindowSpecification((WindowSpecification) window, dialect);
- }
-
- static String formatWindowSpecification(WindowSpecification windowSpecification, Dialect dialect)
- {
- List parts = new ArrayList<>();
-
- if (windowSpecification.getExistingWindowName().isPresent()) {
- parts.add(formatExpression(windowSpecification.getExistingWindowName().get(), dialect));
- }
- if (!windowSpecification.getPartitionBy().isEmpty()) {
- parts.add("PARTITION BY " + windowSpecification.getPartitionBy().stream()
- .map(expression -> formatExpression(expression, dialect))
- .collect(joining(", ")));
- }
- if (windowSpecification.getOrderBy().isPresent()) {
- parts.add(formatOrderBy(windowSpecification.getOrderBy().get(), dialect));
- }
- if (windowSpecification.getFrame().isPresent()) {
- parts.add(formatFrame(windowSpecification.getFrame().get(), dialect));
- }
-
- return '(' + Joiner.on(' ').join(parts) + ')';
- }
-
- private static String formatFrame(WindowFrame windowFrame, Dialect dialect)
- {
- StringBuilder builder = new StringBuilder();
-
- if (!windowFrame.getMeasures().isEmpty()) {
- builder.append("MEASURES ")
- .append(windowFrame.getMeasures().stream()
- .map(measure -> formatExpression(measure.getExpression(), dialect) + " AS " + formatExpression(measure.getName(), dialect))
- .collect(joining(", ")))
- .append(" ");
- }
-
- builder.append(windowFrame.getType().toString())
- .append(' ');
-
- if (windowFrame.getEnd().isPresent()) {
- builder.append("BETWEEN ")
- .append(formatFrameBound(windowFrame.getStart(), dialect))
- .append(" AND ")
- .append(formatFrameBound(windowFrame.getEnd().get(), dialect));
- }
- else {
- builder.append(formatFrameBound(windowFrame.getStart(), dialect));
- }
-
- windowFrame.getAfterMatchSkipTo().ifPresent(skipTo ->
- builder.append(" ")
- .append(formatSkipTo(skipTo, dialect)));
- windowFrame.getPatternSearchMode().ifPresent(searchMode ->
- builder.append(" ")
- .append(searchMode.getMode().name()));
- windowFrame.getPattern().ifPresent(pattern ->
- builder.append(" PATTERN(")
- .append(formatPattern(pattern, dialect))
- .append(")"));
- if (!windowFrame.getSubsets().isEmpty()) {
- builder.append(" SUBSET ");
- builder.append(windowFrame.getSubsets().stream()
- .map(subset -> formatExpression(subset.getName(), dialect) + " = " + subset.getIdentifiers().stream()
- .map(expression -> formatExpression(expression, dialect)).collect(joining(", ", "(", ")")))
- .collect(joining(", ")));
- }
- if (!windowFrame.getVariableDefinitions().isEmpty()) {
- builder.append(" DEFINE ");
- builder.append(windowFrame.getVariableDefinitions().stream()
- .map(variable -> formatExpression(variable.getName(), dialect) + " AS " + formatExpression(variable.getExpression(), dialect))
- .collect(joining(", ")));
- }
-
- return builder.toString();
- }
-
- private static String formatFrameBound(FrameBound frameBound, Dialect dialect)
- {
- switch (frameBound.getType()) {
- case UNBOUNDED_PRECEDING:
- return "UNBOUNDED PRECEDING";
- case PRECEDING:
- return formatExpression(frameBound.getValue().get(), dialect) + " PRECEDING";
- case CURRENT_ROW:
- return "CURRENT ROW";
- case FOLLOWING:
- return formatExpression(frameBound.getValue().get(), dialect) + " FOLLOWING";
- case UNBOUNDED_FOLLOWING:
- return "UNBOUNDED FOLLOWING";
- }
- throw new IllegalArgumentException("unhandled type: " + frameBound.getType());
- }
-
- public static String formatSkipTo(SkipTo skipTo, Dialect dialect)
- {
- switch (skipTo.getPosition()) {
- case PAST_LAST:
- return "AFTER MATCH SKIP PAST LAST ROW";
- case NEXT:
- return "AFTER MATCH SKIP TO NEXT ROW";
- case LAST:
- checkState(skipTo.getIdentifier().isPresent(), "missing identifier in AFTER MATCH SKIP TO LAST");
- return "AFTER MATCH SKIP TO LAST " + formatExpression(skipTo.getIdentifier().get(), dialect);
- case FIRST:
- checkState(skipTo.getIdentifier().isPresent(), "missing identifier in AFTER MATCH SKIP TO FIRST");
- return "AFTER MATCH SKIP TO FIRST " + formatExpression(skipTo.getIdentifier().get(), dialect);
- default:
- throw new IllegalStateException("unexpected skipTo: " + skipTo);
- }
- }
-
- static String formatGroupBy(List groupingElements, Dialect dialect)
- {
- ImmutableList.Builder resultStrings = ImmutableList.builder();
-
- for (GroupingElement groupingElement : groupingElements) {
- String result = "";
- if (groupingElement instanceof SimpleGroupBy) {
- List columns = groupingElement.getExpressions();
- if (columns.size() == 1) {
- result = formatExpression(getOnlyElement(columns), dialect);
- }
- else {
- result = formatGroupingSet(columns, dialect);
- }
- }
- else if (groupingElement instanceof GroupingSets) {
- result = format("GROUPING SETS (%s)", Joiner.on(", ").join(
- ((GroupingSets) groupingElement).getSets().stream()
- .map(expression -> formatGroupingSet(expression, dialect))
- .iterator()));
- }
- else if (groupingElement instanceof Cube) {
- result = format("CUBE %s", formatGroupingSet(groupingElement.getExpressions(), dialect));
- }
- else if (groupingElement instanceof Rollup) {
- result = format("ROLLUP %s", formatGroupingSet(groupingElement.getExpressions(), dialect));
- }
- resultStrings.add(result);
- }
- return Joiner.on(", ").join(resultStrings.build());
- }
-
- private static boolean isAsciiPrintable(int codePoint)
- {
- return codePoint >= 0x20 && codePoint < 0x7F;
- }
-
- private static String formatGroupingSet(List groupingSet, Dialect dialect)
- {
- return format("(%s)", Joiner.on(", ").join(groupingSet.stream()
- .map(expression -> formatExpression(expression, dialect))
- .iterator()));
- }
-
- private static Function sortItemFormatterFunction(Dialect dialect)
- {
- return input -> {
- StringBuilder builder = new StringBuilder();
-
- builder.append(formatExpression(input.getSortKey(), dialect));
-
- switch (input.getOrdering()) {
- case ASCENDING:
- builder.append(" ASC");
- break;
- case DESCENDING:
- builder.append(" DESC");
- break;
- default:
- throw new UnsupportedOperationException("unknown ordering: " + input.getOrdering());
- }
-
- switch (input.getNullOrdering()) {
- case FIRST:
- builder.append(" NULLS FIRST");
- break;
- case LAST:
- builder.append(" NULLS LAST");
- break;
- case UNDEFINED:
- // no op
- break;
- default:
- throw new UnsupportedOperationException("unknown null ordering: " + input.getNullOrdering());
- }
-
- return builder.toString();
- };
- }
-}
diff --git a/trino-parser/src/main/java/io/trino/sql/QueryUtil.java b/trino-parser/src/main/java/io/trino/sql/QueryUtil.java
deleted file mode 100644
index d5faccee9..000000000
--- a/trino-parser/src/main/java/io/trino/sql/QueryUtil.java
+++ /dev/null
@@ -1,367 +0,0 @@
-package io.trino.sql;
-
-import com.google.common.collect.ImmutableList;
-import io.trino.sql.parser.ParsingOptions;
-import io.trino.sql.parser.SqlParser;
-import io.trino.sql.tree.AliasedRelation;
-import io.trino.sql.tree.AllColumns;
-import io.trino.sql.tree.CoalesceExpression;
-import io.trino.sql.tree.ComparisonExpression;
-import io.trino.sql.tree.DereferenceExpression;
-import io.trino.sql.tree.Expression;
-import io.trino.sql.tree.FunctionCall;
-import io.trino.sql.tree.GroupBy;
-import io.trino.sql.tree.Identifier;
-import io.trino.sql.tree.Join;
-import io.trino.sql.tree.JoinCriteria;
-import io.trino.sql.tree.JoinOn;
-import io.trino.sql.tree.LogicalExpression;
-import io.trino.sql.tree.LongLiteral;
-import io.trino.sql.tree.Node;
-import io.trino.sql.tree.NullLiteral;
-import io.trino.sql.tree.Offset;
-import io.trino.sql.tree.OrderBy;
-import io.trino.sql.tree.QualifiedName;
-import io.trino.sql.tree.Query;
-import io.trino.sql.tree.QueryBody;
-import io.trino.sql.tree.QuerySpecification;
-import io.trino.sql.tree.Relation;
-import io.trino.sql.tree.Row;
-import io.trino.sql.tree.SearchedCaseExpression;
-import io.trino.sql.tree.Select;
-import io.trino.sql.tree.SelectItem;
-import io.trino.sql.tree.SingleColumn;
-import io.trino.sql.tree.SortItem;
-import io.trino.sql.tree.StringLiteral;
-import io.trino.sql.tree.SubscriptExpression;
-import io.trino.sql.tree.Table;
-import io.trino.sql.tree.TableSubquery;
-import io.trino.sql.tree.Unnest;
-import io.trino.sql.tree.Values;
-import io.trino.sql.tree.WhenClause;
-import io.trino.sql.tree.WindowDefinition;
-
-import java.util.List;
-import java.util.Optional;
-import java.util.stream.Collectors;
-
-import static io.trino.sql.parser.ParsingOptions.DecimalLiteralTreatment.AS_DOUBLE;
-import static io.trino.sql.tree.BooleanLiteral.FALSE_LITERAL;
-import static io.trino.sql.tree.BooleanLiteral.TRUE_LITERAL;
-import static java.util.Arrays.asList;
-
-public final class QueryUtil
-{
- private QueryUtil() {}
-
- public static Identifier identifier(String name)
- {
- return new Identifier(name);
- }
-
- public static Identifier quotedIdentifier(String name)
- {
- return new Identifier(name, true);
- }
-
- public static Expression nameReference(String first, String... rest)
- {
- return DereferenceExpression.from(QualifiedName.of(first, rest));
- }
-
- public static SelectItem unaliasedName(String name)
- {
- return new SingleColumn(identifier(name));
- }
-
- public static SelectItem aliasedName(String name, String alias)
- {
- return new SingleColumn(identifier(name), identifier(alias));
- }
-
- public static SubscriptExpression subscriptExpression(Expression name, String index)
- {
- return new SubscriptExpression(name, new LongLiteral(index));
- }
-
- public static Select selectList(Expression... expressions)
- {
- return selectList(asList(expressions));
- }
-
- public static Select selectList(List expressions)
- {
- ImmutableList.Builder items = ImmutableList.builder();
- for (Expression expression : expressions) {
- items.add(new SingleColumn(expression));
- }
- return new Select(false, items.build());
- }
-
- public static Select selectListDistinct(List expressions)
- {
- ImmutableList.Builder items = ImmutableList.builder();
- for (Expression expression : expressions) {
- items.add(new SingleColumn(expression));
- }
- return new Select(true, items.build());
- }
-
- public static Select selectList(List expressions, List aliases)
- {
- ImmutableList.Builder items = ImmutableList.builder();
- for (int i = 0; i < expressions.size(); i++) {
- items.add(new SingleColumn(expressions.get(i), identifier(aliases.get(i))));
- }
- return new Select(false, items.build());
- }
-
- public static Select selectList(SelectItem... items)
- {
- return new Select(false, ImmutableList.copyOf(items));
- }
-
- public static Select selectAll(List items)
- {
- return new Select(false, items);
- }
-
- public static Table table(QualifiedName name)
- {
- return new Table(name);
- }
-
- public static Unnest unnest(Expression... expressions)
- {
- return new Unnest(asList(expressions), false);
- }
-
- public static Join leftJoin(Relation left, Relation right, JoinCriteria joinCriteria)
- {
- return new Join(Join.Type.LEFT, left, right, Optional.ofNullable(joinCriteria));
- }
-
- public static Join crossJoin(Relation left, Relation right)
- {
- return new Join(Join.Type.CROSS, left, right, Optional.empty());
- }
-
- public static Join implicitJoin(Relation left, Relation right)
- {
- return new Join(Join.Type.IMPLICIT, left, right, Optional.empty());
- }
-
- public static JoinOn joinOn(Expression conditionSql)
- {
- return new JoinOn(conditionSql);
- }
-
- public static ComparisonExpression getConditionNode(String condition)
- {
- SqlParser sqlParser = new SqlParser();
- Query statement = (Query) sqlParser.createStatement("SELECT " + condition, new ParsingOptions(AS_DOUBLE));
- return (ComparisonExpression)
- ((SingleColumn) ((QuerySpecification) statement.getQueryBody()).getSelect().getSelectItems().get(0)).getExpression();
- }
-
- public static Relation subquery(Query query)
- {
- return new TableSubquery(query);
- }
-
- public static SortItem ascending(String name)
- {
- return new SortItem(identifier(name), SortItem.Ordering.ASCENDING, SortItem.NullOrdering.UNDEFINED);
- }
-
- public static Expression logicalAnd(Expression left, Expression right)
- {
- return LogicalExpression.and(left, right);
- }
-
- public static Expression equal(Expression left, Expression right)
- {
- return new ComparisonExpression(ComparisonExpression.Operator.EQUAL, left, right);
- }
-
- public static Expression caseWhen(Expression operand, Expression result)
- {
- return new SearchedCaseExpression(ImmutableList.of(new WhenClause(operand, result)), Optional.empty());
- }
-
- public static Expression functionCall(String name, List arguments)
- {
- return new FunctionCall(QualifiedName.of(name), ImmutableList.copyOf(arguments));
- }
-
- public static Expression functionCall(String name, Expression... arguments)
- {
- return new FunctionCall(QualifiedName.of(name), ImmutableList.copyOf(arguments));
- }
-
- public static Values values(Row... row)
- {
- return new Values(ImmutableList.copyOf(row));
- }
-
- public static Row row(Expression... values)
- {
- return new Row(ImmutableList.copyOf(values));
- }
-
- public static Relation aliased(Relation relation, String alias)
- {
- return new AliasedRelation(relation, identifier(alias), null);
- }
-
- public static Relation aliased(Relation relation, String alias, List columnAliases)
- {
- return new AliasedRelation(
- relation,
- identifier(alias),
- columnAliases.stream()
- .map(QueryUtil::identifier)
- .collect(Collectors.toList()));
- }
-
- public static SelectItem aliasedNullToEmpty(String column, String alias)
- {
- return new SingleColumn(new CoalesceExpression(identifier(column), new StringLiteral("")), identifier(alias));
- }
-
- public static OrderBy ordering(SortItem... items)
- {
- return new OrderBy(ImmutableList.copyOf(items));
- }
-
- public static Query simpleQuery(Select select)
- {
- return query(new QuerySpecification(
- select,
- Optional.empty(),
- Optional.empty(),
- Optional.empty(),
- Optional.empty(),
- ImmutableList.of(),
- Optional.empty(),
- Optional.empty(),
- Optional.empty()));
- }
-
- public static Query simpleQuery(Select select, Relation from)
- {
- return simpleQuery(select, from, Optional.empty(), Optional.empty());
- }
-
- public static Query simpleQuery(Select select, Relation from, OrderBy orderBy)
- {
- return simpleQuery(select, from, Optional.empty(), Optional.of(orderBy));
- }
-
- public static Query simpleQuery(Select select, Relation from, Expression where)
- {
- return simpleQuery(select, from, Optional.of(where), Optional.empty());
- }
-
- public static Query simpleQuery(Select select, Relation from, Expression where, OrderBy orderBy)
- {
- return simpleQuery(select, from, Optional.of(where), Optional.of(orderBy));
- }
-
- public static Query simpleQuery(Select select, Relation from, Optional where, Optional orderBy)
- {
- return simpleQuery(select, from, where, Optional.empty(), Optional.empty(), orderBy, Optional.empty(), Optional.empty());
- }
-
- public static Query simpleQuery(
- Select select,
- Relation from,
- Optional where,
- Optional groupBy,
- Optional having,
- Optional orderBy,
- Optional offset,
- Optional limit)
- {
- return simpleQuery(select, from, where, groupBy, having, ImmutableList.of(), orderBy, offset, limit);
- }
-
- public static Query simpleQuery(
- Select select,
- Relation from,
- Optional where,
- Optional groupBy,
- Optional having,
- List windows,
- Optional orderBy,
- Optional offset,
- Optional limit)
- {
- return query(new QuerySpecification(
- select,
- Optional.of(from),
- where,
- groupBy,
- having,
- windows,
- orderBy,
- offset,
- limit));
- }
-
- public static Query singleValueQuery(String columnName, String value)
- {
- Relation values = values(row(new StringLiteral((value))));
- return simpleQuery(
- selectList(new AllColumns()),
- aliased(values, "t", ImmutableList.of(columnName)));
- }
-
- public static Query singleValueQuery(String columnName, boolean value)
- {
- Relation values = values(row(value ? TRUE_LITERAL : FALSE_LITERAL));
- return simpleQuery(
- selectList(new AllColumns()),
- aliased(values, "t", ImmutableList.of(columnName)));
- }
-
- // TODO pass column types
- public static Query emptyQuery(List columns)
- {
- Select select = selectList(columns.stream()
- .map(column -> new SingleColumn(new NullLiteral(), QueryUtil.identifier(column)))
- .toArray(SelectItem[]::new));
- Optional where = Optional.of(FALSE_LITERAL);
- return query(new QuerySpecification(
- select,
- Optional.empty(),
- where,
- Optional.empty(),
- Optional.empty(),
- ImmutableList.of(),
- Optional.empty(),
- Optional.empty(),
- Optional.empty()));
- }
-
- public static Query query(QueryBody body)
- {
- return new Query(
- Optional.empty(),
- body,
- Optional.empty(),
- Optional.empty(),
- Optional.empty());
- }
-
- public static QualifiedName getQualifiedName(Expression expression)
- {
- if (expression instanceof DereferenceExpression) {
- return DereferenceExpression.getQualifiedName((DereferenceExpression) expression);
- }
- if (expression instanceof Identifier) {
- return QualifiedName.of(ImmutableList.of((Identifier) expression));
- }
- return null;
- }
-}
diff --git a/trino-parser/src/main/java/io/trino/sql/ReservedIdentifiers.java b/trino-parser/src/main/java/io/trino/sql/ReservedIdentifiers.java
deleted file mode 100644
index 6b9145d23..000000000
--- a/trino-parser/src/main/java/io/trino/sql/ReservedIdentifiers.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * 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 com.google.common.collect.ImmutableSet;
-import io.trino.sql.parser.ParsingException;
-import io.trino.sql.parser.ParsingOptions;
-import io.trino.sql.parser.SqlBaseLexer;
-import io.trino.sql.parser.SqlParser;
-import io.trino.sql.tree.Identifier;
-import org.antlr.v4.runtime.Vocabulary;
-
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import static com.google.common.base.Strings.nullToEmpty;
-import static com.google.common.collect.ImmutableSet.toImmutableSet;
-import static java.lang.String.format;
-
-public final class ReservedIdentifiers
-{
- private static final Pattern IDENTIFIER = Pattern.compile("'([A-Z_]+)'");
- private static final Pattern TABLE_ROW = Pattern.compile("``([A-Z_]+)``.*");
- private static final String TABLE_PREFIX = "============================== ";
-
- private static final SqlParser PARSER = new SqlParser();
-
- private ReservedIdentifiers() {}
-
- @SuppressWarnings("CallToPrintStackTrace")
- public static void main(String[] args)
- {
- if ((args.length == 2) && args[0].equals("validateDocs")) {
- try {
- validateDocs(Paths.get(args[1]));
- }
- catch (Throwable t) {
- t.printStackTrace();
- System.exit(100);
- }
- }
- else {
- for (String name : reservedIdentifiers()) {
- System.out.println(name);
- }
- }
- }
-
- private static void validateDocs(Path path)
- throws IOException
- {
- System.out.println("Validating " + path);
- List lines = Files.readAllLines(path);
-
- if (lines.stream().filter(s -> s.startsWith(TABLE_PREFIX)).count() != 3) {
- throw new RuntimeException("Failed to find exactly one table");
- }
-
- Iterator iterator = lines.iterator();
-
- // find table and skip header
- while (!iterator.next().startsWith(TABLE_PREFIX)) {
- // skip
- }
- if (iterator.next().startsWith(TABLE_PREFIX)) {
- throw new RuntimeException("Expected to find a header line");
- }
- if (!iterator.next().startsWith(TABLE_PREFIX)) {
- throw new RuntimeException("Found multiple header lines");
- }
-
- Set reserved = reservedIdentifiers();
- Set found = new HashSet<>();
- while (true) {
- String line = iterator.next();
- if (line.startsWith(TABLE_PREFIX)) {
- break;
- }
-
- Matcher matcher = TABLE_ROW.matcher(line);
- if (!matcher.matches()) {
- throw new RuntimeException("Invalid table line: " + line);
- }
- String name = matcher.group(1);
-
- if (!reserved.contains(name)) {
- throw new RuntimeException("Documented identifier is not reserved: " + name);
- }
- if (!found.add(name)) {
- throw new RuntimeException("Duplicate documented identifier: " + name);
- }
- }
-
- for (String name : reserved) {
- if (!found.contains(name)) {
- throw new RuntimeException("Reserved identifier is not documented: " + name);
- }
- }
-
- System.out.println(format("Validated %s reserved identifiers", reserved.size()));
- }
-
- public static Set reservedIdentifiers()
- {
- return sqlKeywords().stream()
- .filter(ReservedIdentifiers::reserved)
- .sorted()
- .collect(toImmutableSet());
- }
-
- public static Set sqlKeywords()
- {
- ImmutableSet.Builder names = ImmutableSet.builder();
- Vocabulary vocabulary = SqlBaseLexer.VOCABULARY;
- for (int i = 0; i <= vocabulary.getMaxTokenType(); i++) {
- String name = nullToEmpty(vocabulary.getLiteralName(i));
- Matcher matcher = IDENTIFIER.matcher(name);
- if (matcher.matches()) {
- names.add(matcher.group(1));
- }
- }
- return names.build();
- }
-
- public static boolean reserved(String name)
- {
- try {
- return !(PARSER.createExpression(name, new ParsingOptions()) instanceof Identifier);
- }
- catch (ParsingException ignored) {
- return true;
- }
- }
-}
diff --git a/trino-parser/src/main/java/io/trino/sql/RowPatternFormatter.java b/trino-parser/src/main/java/io/trino/sql/RowPatternFormatter.java
deleted file mode 100644
index db27e4ff9..000000000
--- a/trino-parser/src/main/java/io/trino/sql/RowPatternFormatter.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * 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.SqlFormatter.Dialect;
-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 io.trino.sql.ExpressionFormatter.formatExpression;
-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, Dialect dialect)
- {
- return new Formatter(dialect).process(pattern, null);
- }
-
- public static class Formatter
- extends AstVisitor
- {
- private final Dialect dialect;
-
- public Formatter(Dialect dialect)
- {
- this.dialect = dialect;
- }
-
- @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 formatExpression(node.getName(), dialect);
- }
-
- @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(expression -> formatExpression(expression, dialect)).orElse("");
- String atMost = node.getAtMost().map(expression -> formatExpression(expression, dialect)).orElse("");
- return "{" + atLeast + "," + atMost + "}" + greedy;
- }
- }
-}
diff --git a/trino-parser/src/main/java/io/trino/sql/SqlFormatter.java b/trino-parser/src/main/java/io/trino/sql/SqlFormatter.java
deleted file mode 100644
index eb0845113..000000000
--- a/trino-parser/src/main/java/io/trino/sql/SqlFormatter.java
+++ /dev/null
@@ -1,1999 +0,0 @@
-/*
- * 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 com.google.common.base.Joiner;
-import com.google.common.base.Strings;
-import io.trino.sql.tree.AddColumn;
-import io.trino.sql.tree.AliasedRelation;
-import io.trino.sql.tree.AllColumns;
-import io.trino.sql.tree.Analyze;
-import io.trino.sql.tree.AstVisitor;
-import io.trino.sql.tree.Call;
-import io.trino.sql.tree.CallArgument;
-import io.trino.sql.tree.ColumnDefinition;
-import io.trino.sql.tree.Comment;
-import io.trino.sql.tree.Commit;
-import io.trino.sql.tree.CreateMaterializedView;
-import io.trino.sql.tree.CreateRole;
-import io.trino.sql.tree.CreateSchema;
-import io.trino.sql.tree.CreateTable;
-import io.trino.sql.tree.CreateTableAsSelect;
-import io.trino.sql.tree.CreateView;
-import io.trino.sql.tree.Deallocate;
-import io.trino.sql.tree.Declare;
-import io.trino.sql.tree.Delete;
-import io.trino.sql.tree.Deny;
-import io.trino.sql.tree.DescribeInput;
-import io.trino.sql.tree.DescribeOutput;
-import io.trino.sql.tree.DropColumn;
-import io.trino.sql.tree.DropMaterializedView;
-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.Except;
-import io.trino.sql.tree.Execute;
-import io.trino.sql.tree.Explain;
-import io.trino.sql.tree.ExplainAnalyze;
-import io.trino.sql.tree.ExplainFormat;
-import io.trino.sql.tree.ExplainOption;
-import io.trino.sql.tree.ExplainType;
-import io.trino.sql.tree.Expression;
-import io.trino.sql.tree.FetchCursor;
-import io.trino.sql.tree.FetchFirst;
-import io.trino.sql.tree.FunctionCall;
-import io.trino.sql.tree.FunctionRelation;
-import io.trino.sql.tree.Grant;
-import io.trino.sql.tree.GrantRoles;
-import io.trino.sql.tree.GrantorSpecification;
-import io.trino.sql.tree.Identifier;
-import io.trino.sql.tree.ImpersonateUser;
-import io.trino.sql.tree.Insert;
-import io.trino.sql.tree.Intersect;
-import io.trino.sql.tree.Isolation;
-import io.trino.sql.tree.Join;
-import io.trino.sql.tree.JoinCriteria;
-import io.trino.sql.tree.JoinOn;
-import io.trino.sql.tree.JoinUsing;
-import io.trino.sql.tree.Lateral;
-import io.trino.sql.tree.LikeClause;
-import io.trino.sql.tree.Limit;
-import io.trino.sql.tree.Merge;
-import io.trino.sql.tree.MergeCase;
-import io.trino.sql.tree.MergeDelete;
-import io.trino.sql.tree.MergeInsert;
-import io.trino.sql.tree.MergeUpdate;
-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.PathRelation;
-import io.trino.sql.tree.PatternRecognitionRelation;
-import io.trino.sql.tree.Prepare;
-import io.trino.sql.tree.PrincipalSpecification;
-import io.trino.sql.tree.Property;
-import io.trino.sql.tree.QualifiedName;
-import io.trino.sql.tree.Query;
-import io.trino.sql.tree.QueryPeriod;
-import io.trino.sql.tree.QuerySpecification;
-import io.trino.sql.tree.RefreshMaterializedView;
-import io.trino.sql.tree.Relation;
-import io.trino.sql.tree.RenameColumn;
-import io.trino.sql.tree.RenameMaterializedView;
-import io.trino.sql.tree.RenameSchema;
-import io.trino.sql.tree.RenameTable;
-import io.trino.sql.tree.RenameView;
-import io.trino.sql.tree.ResetSession;
-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;
-import io.trino.sql.tree.SetPath;
-import io.trino.sql.tree.SetProperties;
-import io.trino.sql.tree.SetRole;
-import io.trino.sql.tree.SetSchemaAuthorization;
-import io.trino.sql.tree.SetSession;
-import io.trino.sql.tree.SetTableAuthorization;
-import io.trino.sql.tree.SetTimeZone;
-import io.trino.sql.tree.SetViewAuthorization;
-import io.trino.sql.tree.ShowCatalogs;
-import io.trino.sql.tree.ShowColumns;
-import io.trino.sql.tree.ShowCreate;
-import io.trino.sql.tree.ShowFunctions;
-import io.trino.sql.tree.ShowGrants;
-import io.trino.sql.tree.ShowRoleGrants;
-import io.trino.sql.tree.ShowRoles;
-import io.trino.sql.tree.ShowSchemas;
-import io.trino.sql.tree.ShowSession;
-import io.trino.sql.tree.ShowStats;
-import io.trino.sql.tree.ShowTables;
-import io.trino.sql.tree.SingleColumn;
-import io.trino.sql.tree.StartTransaction;
-import io.trino.sql.tree.Table;
-import io.trino.sql.tree.TableExecute;
-import io.trino.sql.tree.TableSubquery;
-import io.trino.sql.tree.TransactionAccessMode;
-import io.trino.sql.tree.TransactionMode;
-import io.trino.sql.tree.TruncateTable;
-import io.trino.sql.tree.Union;
-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.WithQuery;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Optional;
-import java.util.stream.Collectors;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.collect.ImmutableList.toImmutableList;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static com.google.common.collect.Iterables.transform;
-import static io.trino.sql.ExpressionFormatter.formatExpression;
-import static io.trino.sql.ExpressionFormatter.formatGroupBy;
-import static io.trino.sql.ExpressionFormatter.formatOrderBy;
-import static io.trino.sql.ExpressionFormatter.formatSkipTo;
-import static io.trino.sql.ExpressionFormatter.formatStringLiteral;
-import static io.trino.sql.ExpressionFormatter.formatWindowSpecification;
-import static io.trino.sql.RowPatternFormatter.formatPattern;
-import static io.trino.sql.SqlFormatter.Dialect.BIGQUERY;
-import static io.trino.sql.SqlFormatter.Dialect.DEFAULT;
-import static io.trino.sql.SqlFormatter.Dialect.POSTGRES;
-import static java.lang.String.format;
-import static java.util.stream.Collectors.joining;
-
-public final class SqlFormatter
-{
- private static final String INDENT = " ";
-
- public enum Dialect
- {
- DEFAULT,
- BIGQUERY,
- DUCKDB,
- POSTGRES
- }
-
- private SqlFormatter() {}
-
- public static String formatSql(Node root)
- {
- return formatSql(root, DEFAULT);
- }
-
- public static String formatSql(Node root, Dialect dialect)
- {
- StringBuilder builder = new StringBuilder();
- new Formatter(builder, dialect).process(root, 0);
- return builder.toString();
- }
-
- static String formatName(QualifiedName name, Dialect dialect)
- {
- return name.getOriginalParts().stream()
- .map(expression -> formatExpression(expression, dialect))
- .collect(joining("."));
- }
-
- private static class Formatter
- extends AstVisitor
- {
- private final StringBuilder builder;
- private final Dialect dialect;
-
- public Formatter(StringBuilder builder, Dialect dialect)
- {
- this.builder = builder;
- this.dialect = dialect;
- }
-
- @Override
- protected Void visitNode(Node node, Integer indent)
- {
- throw new UnsupportedOperationException("not yet implemented: " + node);
- }
-
- @Override
- protected Void visitExpression(Expression node, Integer indent)
- {
- checkArgument(indent == 0, "visitExpression should only be called at root");
- builder.append(formatExpression(node, dialect));
- return null;
- }
-
- @Override
- protected Void visitRowPattern(RowPattern node, Integer indent)
- {
- checkArgument(indent == 0, "visitRowPattern should only be called at root");
- builder.append(formatPattern(node, dialect));
- return null;
- }
-
- @Override
- protected Void visitFunctionRelation(FunctionRelation node, Integer indent)
- {
- builder.append(formatName(node.getName(), dialect))
- .append("(")
- .append(node.getArguments().stream()
- .map(expression -> formatExpression(expression, dialect))
- .collect(joining(", ")))
- .append(")");
- return null;
- }
-
- @Override
- protected Void visitPathRelation(PathRelation node, Integer context)
- {
- builder.append(node.getPath());
- return null;
- }
-
- @Override
- protected Void visitUnnest(Unnest node, Integer indent)
- {
- // Postgres doesn't have `generate_array` function and `generate_series` is a table function.
- // Use `generate_series` to instead `UNNEST(generate_array(...))` for Postgres.
- if (dialect == POSTGRES &&
- node.getExpressions().size() == 1 &&
- node.getExpressions().get(0) instanceof FunctionCall &&
- ((FunctionCall) node.getExpressions().get(0)).getName().equals(QualifiedName.of("generate_array"))) {
- builder.append("generate_series(")
- .append(((FunctionCall) node.getExpressions().get(0)).getArguments().stream()
- .map(expression -> formatExpression(expression, dialect))
- .collect(joining(", ")))
- .append(")");
- return null;
- }
-
- builder.append("UNNEST(")
- .append(node.getExpressions().stream()
- .map(expression -> formatExpression(expression, dialect))
- .collect(joining(", ")))
- .append(")");
- if (node.isWithOrdinality()) {
- builder.append(" WITH ORDINALITY");
- }
- return null;
- }
-
- @Override
- protected Void visitLateral(Lateral node, Integer indent)
- {
- append(indent, "LATERAL (");
- process(node.getQuery(), indent + 1);
- append(indent, ")");
- return null;
- }
-
- @Override
- protected Void visitPrepare(Prepare node, Integer indent)
- {
- append(indent, "PREPARE ");
- builder.append(node.getName());
- builder.append(" FROM");
- builder.append("\n");
- process(node.getStatement(), indent + 1);
- return null;
- }
-
- @Override
- protected Void visitDeallocate(Deallocate node, Integer indent)
- {
- append(indent, "DEALLOCATE PREPARE ");
- builder.append(node.getName());
- return null;
- }
-
- // pg syntax
- @Override
- protected Void visitDeclareCursor(Declare node, Integer ident)
- {
- append(ident, "DECLARE ");
- builder.append(node.getName());
- builder.append(" CURSOR FOR ");
- process(node.getBody(), ident + 1);
- return null;
- }
-
- // pg syntax
- @Override
- protected Void visitFetchCursor(FetchCursor node, Integer ident)
- {
- append(ident, "FETCH ")
- .append(node.getRowCount())
- .append(" FROM ")
- .append(node.getCursor());
- return null;
- }
-
- @Override
- protected Void visitImpersonateUser(ImpersonateUser node, Integer ident)
- {
- append(ident, "IMPERSONATE ")
- .append(node.getExpression());
- return null;
- }
-
- @Override
- protected Void visitExecute(Execute node, Integer indent)
- {
- append(indent, "EXECUTE ");
- builder.append(node.getName());
- List parameters = node.getParameters();
- if (!parameters.isEmpty()) {
- builder.append(" USING ");
- Joiner.on(", ").appendTo(builder, parameters);
- }
- return null;
- }
-
- @Override
- protected Void visitDescribeOutput(DescribeOutput node, Integer indent)
- {
- append(indent, "DESCRIBE OUTPUT ");
- builder.append(node.getName());
- return null;
- }
-
- @Override
- protected Void visitDescribeInput(DescribeInput node, Integer indent)
- {
- append(indent, "DESCRIBE INPUT ");
- builder.append(node.getName());
- return null;
- }
-
- @Override
- protected Void visitQuery(Query node, Integer indent)
- {
- node.getWith().ifPresent(with -> {
- append(indent, "WITH");
- if (with.isRecursive()) {
- builder.append(" RECURSIVE");
- }
- builder.append("\n ");
- Iterator queries = with.getQueries().iterator();
- while (queries.hasNext()) {
- WithQuery query = queries.next();
- append(indent, formatExpression(query.getName(), dialect));
- query.getColumnNames().ifPresent(columnNames -> appendAliasColumns(builder, columnNames, dialect));
- builder.append(" AS ");
- process(new TableSubquery(query.getQuery()), indent);
- builder.append('\n');
- if (queries.hasNext()) {
- builder.append(", ");
- }
- }
- });
-
- processRelation(node.getQueryBody(), indent);
- node.getOrderBy().ifPresent(orderBy -> process(orderBy, indent));
- if (dialect.equals(BIGQUERY)) {
- node.getLimit().ifPresent(limit -> process(limit, indent));
- node.getOffset().ifPresent(offset -> process(offset, indent));
- }
- else {
- node.getOffset().ifPresent(offset -> process(offset, indent));
- node.getLimit().ifPresent(limit -> process(limit, indent));
- }
- return null;
- }
-
- @Override
- protected Void visitQuerySpecification(QuerySpecification node, Integer indent)
- {
- process(node.getSelect(), indent);
-
- node.getFrom().ifPresent(from -> {
- append(indent, "FROM");
- builder.append('\n');
- append(indent, " ");
- process(from, indent);
- });
-
- builder.append('\n');
-
- node.getWhere().ifPresent(where ->
- append(indent, "WHERE " + formatExpression(where, dialect)).append('\n'));
-
- node.getGroupBy().ifPresent(groupBy ->
- append(indent, "GROUP BY " + (groupBy.isDistinct() ? " DISTINCT " : "") + formatGroupBy(groupBy.getGroupingElements(), dialect)).append('\n'));
-
- node.getHaving().ifPresent(having -> append(indent, "HAVING " + formatExpression(having, dialect))
- .append('\n'));
-
- if (!node.getWindows().isEmpty()) {
- append(indent, "WINDOW");
- formatDefinitionList(node.getWindows().stream()
- .map(definition -> formatExpression(definition.getName(), dialect) + " AS " + formatWindowSpecification(definition.getWindow(), dialect))
- .collect(toImmutableList()), indent + 1);
- }
-
- node.getOrderBy().ifPresent(orderBy -> process(orderBy, indent));
- if (dialect.equals(BIGQUERY)) {
- node.getLimit().ifPresent(limit -> process(limit, indent));
- node.getOffset().ifPresent(offset -> process(offset, indent));
- }
- else {
- node.getOffset().ifPresent(offset -> process(offset, indent));
- node.getLimit().ifPresent(limit -> process(limit, indent));
- }
- return null;
- }
-
- @Override
- protected Void visitOrderBy(OrderBy node, Integer indent)
- {
- append(indent, formatOrderBy(node, dialect))
- .append('\n');
- return null;
- }
-
- @Override
- protected Void visitOffset(Offset node, Integer indent)
- {
- append(indent, "OFFSET ")
- .append(formatExpression(node.getRowCount(), dialect))
- .append("\n");
- if (!dialect.equals(BIGQUERY)) {
- append(indent, "ROWS\n");
- }
- return null;
- }
-
- @Override
- protected Void visitFetchFirst(FetchFirst node, Integer indent)
- {
- append(indent, "FETCH FIRST " + node.getRowCount().map(count -> formatExpression(count, dialect) + " ROWS ").orElse("ROW "))
- .append(node.isWithTies() ? "WITH TIES" : "ONLY")
- .append('\n');
- return null;
- }
-
- @Override
- protected Void visitLimit(Limit node, Integer indent)
- {
- append(indent, "LIMIT ")
- .append(formatExpression(node.getRowCount(), dialect))
- .append('\n');
- return null;
- }
-
- @Override
- protected Void visitSelect(Select node, Integer indent)
- {
- append(indent, "SELECT");
- if (node.isDistinct()) {
- builder.append(" DISTINCT");
- }
-
- if (node.getSelectItems().size() > 1) {
- boolean first = true;
- for (SelectItem item : node.getSelectItems()) {
- builder.append("\n")
- .append(indentString(indent))
- .append(first ? " " : ", ");
-
- process(item, indent);
- first = false;
- }
- }
- else {
- builder.append(' ');
- process(getOnlyElement(node.getSelectItems()), indent);
- }
-
- builder.append('\n');
-
- return null;
- }
-
- @Override
- protected Void visitSingleColumn(SingleColumn node, Integer indent)
- {
- builder.append(formatExpression(node.getExpression(), dialect));
- node.getAlias().ifPresent(alias -> builder
- .append(' ')
- .append(formatExpression(alias, dialect)));
-
- return null;
- }
-
- @Override
- protected Void visitAllColumns(AllColumns node, Integer indent)
- {
- node.getTarget().ifPresent(value -> builder
- .append(formatExpression(value, dialect))
- .append("."));
- builder.append("*");
-
- if (!node.getAliases().isEmpty()) {
- builder.append(" AS (")
- .append(Joiner.on(", ").join(node.getAliases().stream()
- .map(expression -> formatExpression(expression, dialect))
- .collect(toImmutableList())))
- .append(")");
- }
-
- return null;
- }
-
- @Override
- protected Void visitTable(Table node, Integer indent)
- {
- builder.append(formatName(node.getName(), dialect));
- node.getQueryPeriod().ifPresent(queryPeriod -> builder
- .append(" " + queryPeriod));
- return null;
- }
-
- @Override
- protected Void visitQueryPeriod(QueryPeriod node, Integer indent)
- {
- builder.append("FOR " + node.getRangeType().name() + " AS OF " + formatExpression(node.getEnd().get(), dialect));
- return null;
- }
-
- @Override
- protected Void visitJoin(Join node, Integer indent)
- {
- JoinCriteria criteria = node.getCriteria().orElse(null);
- String type = node.getType().toString();
- if (criteria instanceof NaturalJoin) {
- type = "NATURAL " + type;
- }
-
- process(node.getLeft(), indent);
-
- builder.append('\n');
- if (node.getType() == Join.Type.IMPLICIT) {
- append(indent, ", ");
- }
- else {
- append(indent, type).append(" JOIN ");
- }
-
- process(node.getRight(), indent);
-
- if (node.getType() != Join.Type.CROSS && node.getType() != Join.Type.IMPLICIT) {
- if (criteria instanceof JoinUsing) {
- JoinUsing using = (JoinUsing) criteria;
- builder.append(" USING (")
- .append(Joiner.on(", ").join(using.getColumns()))
- .append(")");
- }
- else if (criteria instanceof JoinOn) {
- JoinOn on = (JoinOn) criteria;
- builder.append(" ON ")
- .append(formatExpression(on.getExpression(), dialect));
- }
- else if (!(criteria instanceof NaturalJoin)) {
- throw new UnsupportedOperationException("unknown join criteria: " + criteria);
- }
- }
-
- return null;
- }
-
- @Override
- protected Void visitAliasedRelation(AliasedRelation node, Integer indent)
- {
- processRelationSuffix(node.getRelation(), indent);
-
- builder.append(' ')
- .append(formatExpression(node.getAlias(), dialect));
- appendAliasColumns(builder, node.getColumnNames(), dialect);
-
- 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(expression -> formatExpression(expression, dialect))
- .collect(joining(", ")))
- .append("\n");
- }
- node.getOrderBy().ifPresent(orderBy -> process(orderBy, indent + 1));
-
- if (!node.getMeasures().isEmpty()) {
- append(indent + 1, "MEASURES");
- formatDefinitionList(node.getMeasures().stream()
- .map(measure -> formatExpression(measure.getExpression(), dialect) + " AS " + formatExpression(measure.getName(), dialect))
- .collect(toImmutableList()), indent + 2);
- }
-
- node.getRowsPerMatch().ifPresent(rowsPerMatch -> {
- String rowsPerMatchDescription;
- switch (rowsPerMatch) {
- case ONE:
- rowsPerMatchDescription = "ONE ROW PER MATCH";
- break;
- case ALL_SHOW_EMPTY:
- rowsPerMatchDescription = "ALL ROWS PER MATCH SHOW EMPTY MATCHES";
- break;
- case ALL_OMIT_EMPTY:
- rowsPerMatchDescription = "ALL ROWS PER MATCH OMIT EMPTY MATCHES";
- break;
- case ALL_WITH_UNMATCHED:
- rowsPerMatchDescription = "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, rowsPerMatchDescription)
- .append("\n");
- });
-
- node.getAfterMatchSkipTo().ifPresent(afterMatchSkipTo -> {
- String skipTo = formatSkipTo(afterMatchSkipTo, dialect);
- append(indent + 1, skipTo)
- .append("\n");
- });
-
- node.getPatternSearchMode().ifPresent(patternSearchMode ->
- append(indent + 1, patternSearchMode.getMode().name())
- .append("\n"));
-
- append(indent + 1, "PATTERN (")
- .append(formatPattern(node.getPattern(), dialect))
- .append(")\n");
- if (!node.getSubsets().isEmpty()) {
- append(indent + 1, "SUBSET");
- formatDefinitionList(node.getSubsets().stream()
- .map(subset -> formatExpression(subset.getName(), dialect) + " = " + subset.getIdentifiers().stream()
- .map(expression -> formatExpression(expression, dialect)).collect(joining(", ", "(", ")")))
- .collect(toImmutableList()), indent + 2);
- }
- append(indent + 1, "DEFINE");
- formatDefinitionList(node.getVariableDefinitions().stream()
- .map(variable -> formatExpression(variable.getName(), dialect) + " AS " + formatExpression(variable.getExpression(), dialect))
- .collect(toImmutableList()), indent + 2);
-
- builder.append(")");
-
- return null;
- }
-
- @Override
- protected Void visitSampledRelation(SampledRelation node, Integer indent)
- {
- processRelationSuffix(node.getRelation(), indent);
-
- builder.append(" TABLESAMPLE ")
- .append(node.getType())
- .append(" (")
- .append(node.getSamplePercentage())
- .append(')');
-
- return null;
- }
-
- private void processRelationSuffix(Relation relation, Integer indent)
- {
- if ((relation instanceof AliasedRelation) || (relation instanceof SampledRelation) || (relation instanceof PatternRecognitionRelation) || (relation instanceof Join)) {
- builder.append("( ");
- process(relation, indent + 1);
- append(indent, ")");
- }
- else {
- process(relation, indent);
- }
- }
-
- @Override
- protected Void visitValues(Values node, Integer indent)
- {
- builder.append(" VALUES ");
-
- boolean first = true;
- for (Expression row : node.getRows()) {
- builder.append("\n")
- .append(indentString(indent))
- .append(first ? " " : ", ");
- if (row instanceof Row) {
- builder.append(formatExpression(row, dialect));
- }
- else {
- builder.append("(")
- .append(formatExpression(row, dialect))
- .append(")");
- }
- first = false;
- }
- builder.append('\n');
-
- return null;
- }
-
- @Override
- protected Void visitTableSubquery(TableSubquery node, Integer indent)
- {
- builder.append('(')
- .append('\n');
-
- process(node.getQuery(), indent + 1);
-
- append(indent, ") ");
-
- return null;
- }
-
- @Override
- protected Void visitUnion(Union node, Integer indent)
- {
- Iterator relations = node.getRelations().iterator();
-
- while (relations.hasNext()) {
- processRelation(relations.next(), indent);
-
- if (relations.hasNext()) {
- builder.append("UNION ");
- if (!node.isDistinct()) {
- builder.append("ALL ");
- }
- }
- }
-
- return null;
- }
-
- @Override
- protected Void visitExcept(Except node, Integer indent)
- {
- processRelation(node.getLeft(), indent);
-
- builder.append("EXCEPT ");
- if (!node.isDistinct()) {
- builder.append("ALL ");
- }
-
- processRelation(node.getRight(), indent);
-
- return null;
- }
-
- @Override
- protected Void visitIntersect(Intersect node, Integer indent)
- {
- Iterator relations = node.getRelations().iterator();
-
- while (relations.hasNext()) {
- processRelation(relations.next(), indent);
-
- if (relations.hasNext()) {
- builder.append("INTERSECT ");
- if (!node.isDistinct()) {
- builder.append("ALL ");
- }
- }
- }
-
- return null;
- }
-
- @Override
- protected Void visitMerge(Merge node, Integer indent)
- {
- builder.append("MERGE INTO ")
- .append(node.getTable().getName());
-
- node.getTargetAlias().ifPresent(value -> builder
- .append(' ')
- .append(value));
- builder.append("\n");
-
- append(indent + 1, "USING ");
-
- processRelation(node.getRelation(), indent + 2);
-
- builder.append("\n");
- append(indent + 1, "ON ");
- builder.append(formatExpression(node.getExpression(), dialect));
-
- for (MergeCase mergeCase : node.getMergeCases()) {
- builder.append("\n");
- process(mergeCase, indent);
- }
-
- return null;
- }
-
- @Override
- protected Void visitMergeInsert(MergeInsert node, Integer indent)
- {
- appendMergeCaseWhen(false, node.getExpression());
- append(indent + 1, "THEN INSERT ");
-
- if (!node.getColumns().isEmpty()) {
- builder.append("(");
- Joiner.on(", ").appendTo(builder, node.getColumns());
- builder.append(")");
- }
-
- builder.append("VALUES (");
- Joiner.on(", ").appendTo(builder, transform(node.getValues(), expression -> formatExpression(expression, dialect)));
- builder.append(")");
-
- return null;
- }
-
- @Override
- protected Void visitMergeUpdate(MergeUpdate node, Integer indent)
- {
- appendMergeCaseWhen(true, node.getExpression());
- append(indent + 1, "THEN UPDATE SET");
-
- boolean first = true;
- for (MergeUpdate.Assignment assignment : node.getAssignments()) {
- builder.append("\n");
- append(indent + 1, first ? " " : ", ");
- builder.append(assignment.getTarget())
- .append(" = ")
- .append(formatExpression(assignment.getValue(), dialect));
- first = false;
- }
-
- return null;
- }
-
- @Override
- protected Void visitMergeDelete(MergeDelete node, Integer indent)
- {
- appendMergeCaseWhen(true, node.getExpression());
- append(indent + 1, "THEN DELETE");
- return null;
- }
-
- private void appendMergeCaseWhen(boolean matched, Optional expression)
- {
- builder.append(matched ? "WHEN MATCHED" : "WHEN NOT MATCHED");
- expression.ifPresent(value -> builder
- .append(" AND ")
- .append(formatExpression(value, dialect)));
- builder.append("\n");
- }
-
- @Override
- protected Void visitCreateView(CreateView node, Integer indent)
- {
- builder.append("CREATE ");
- if (node.isReplace()) {
- builder.append("OR REPLACE ");
- }
- builder.append("VIEW ")
- .append(formatName(node.getName(), dialect));
-
- node.getComment().ifPresent(comment -> builder
- .append(" COMMENT ")
- .append(formatStringLiteral(comment)));
-
- node.getSecurity().ifPresent(security -> builder
- .append(" SECURITY ")
- .append(security));
-
- builder.append(" AS\n");
-
- process(node.getQuery(), indent);
-
- return null;
- }
-
- @Override
- protected Void visitRenameView(RenameView node, Integer indent)
- {
- builder.append("ALTER VIEW ")
- .append(node.getSource())
- .append(" RENAME TO ")
- .append(node.getTarget());
-
- return null;
- }
-
- @Override
- protected Void visitRenameMaterializedView(RenameMaterializedView node, Integer indent)
- {
- builder.append("ALTER MATERIALIZED VIEW ");
- if (node.isExists()) {
- builder.append("IF EXISTS ");
- }
- builder.append(node.getSource())
- .append(" RENAME TO ")
- .append(node.getTarget());
-
- return null;
- }
-
- @Override
- protected Void visitSetViewAuthorization(SetViewAuthorization node, Integer indent)
- {
- builder.append("ALTER VIEW ")
- .append(formatName(node.getSource(), dialect))
- .append(" SET AUTHORIZATION ")
- .append(formatPrincipal(node.getPrincipal()));
-
- return null;
- }
-
- @Override
- protected Void visitCreateMaterializedView(CreateMaterializedView node, Integer indent)
- {
- builder.append("CREATE ");
- if (node.isReplace()) {
- builder.append("OR REPLACE ");
- }
- builder.append("MATERIALIZED VIEW ");
-
- if (node.isNotExists()) {
- builder.append("IF NOT EXISTS ");
- }
-
- builder.append(formatName(node.getName(), dialect));
- node.getComment().ifPresent(comment -> builder
- .append("\nCOMMENT ")
- .append(formatStringLiteral(comment)));
- builder.append(formatPropertiesMultiLine(node.getProperties()));
- builder.append(" AS\n");
-
- process(node.getQuery(), indent);
-
- return null;
- }
-
- @Override
- protected Void visitRefreshMaterializedView(RefreshMaterializedView node, Integer indent)
- {
- builder.append("REFRESH MATERIALIZED VIEW ");
- builder.append(formatName(node.getName(), dialect));
-
- return null;
- }
-
- @Override
- protected Void visitDropMaterializedView(DropMaterializedView node, Integer indent)
- {
- builder.append("DROP MATERIALIZED VIEW ");
- if (node.isExists()) {
- builder.append("IF EXISTS ");
- }
- builder.append(formatName(node.getName(), dialect));
- return null;
- }
-
- @Override
- protected Void visitDropView(DropView node, Integer indent)
- {
- builder.append("DROP VIEW ");
- if (node.isExists()) {
- builder.append("IF EXISTS ");
- }
- builder.append(node.getName());
-
- return null;
- }
-
- @Override
- protected Void visitExplain(Explain node, Integer indent)
- {
- builder.append("EXPLAIN ");
-
- List options = new ArrayList<>();
-
- for (ExplainOption option : node.getOptions()) {
- if (option instanceof ExplainType) {
- options.add("TYPE " + ((ExplainType) option).getType());
- }
- else if (option instanceof ExplainFormat) {
- options.add("FORMAT " + ((ExplainFormat) option).getType());
- }
- else {
- throw new UnsupportedOperationException("unhandled explain option: " + option);
- }
- }
-
- if (!options.isEmpty()) {
- builder.append("(");
- Joiner.on(", ").appendTo(builder, options);
- builder.append(")");
- }
-
- builder.append("\n");
-
- process(node.getStatement(), indent);
-
- return null;
- }
-
- @Override
- protected Void visitExplainAnalyze(ExplainAnalyze node, Integer indent)
- {
- builder.append("EXPLAIN ANALYZE");
- if (node.isVerbose()) {
- builder.append(" VERBOSE");
- }
- builder.append("\n");
-
- process(node.getStatement(), indent);
-
- return null;
- }
-
- @Override
- protected Void visitShowCatalogs(ShowCatalogs node, Integer indent)
- {
- builder.append("SHOW CATALOGS");
-
- node.getLikePattern().ifPresent(value -> builder
- .append(" LIKE ")
- .append(formatStringLiteral(value)));
-
- node.getEscape().ifPresent(value -> builder
- .append(" ESCAPE ")
- .append(formatStringLiteral(value)));
-
- return null;
- }
-
- @Override
- protected Void visitShowSchemas(ShowSchemas node, Integer indent)
- {
- builder.append("SHOW SCHEMAS");
-
- node.getCatalog().ifPresent(catalog -> builder
- .append(" FROM ")
- .append(node.getCatalog().get()));
-
- node.getLikePattern().ifPresent(value -> builder
- .append(" LIKE ")
- .append(formatStringLiteral(value)));
-
- node.getEscape().ifPresent(value -> builder
- .append(" ESCAPE ")
- .append(formatStringLiteral(value)));
-
- return null;
- }
-
- @Override
- protected Void visitShowTables(ShowTables node, Integer indent)
- {
- builder.append("SHOW TABLES");
-
- node.getSchema().ifPresent(value -> builder
- .append(" FROM ")
- .append(formatName(value, dialect)));
-
- node.getLikePattern().ifPresent(value -> builder
- .append(" LIKE ")
- .append(formatStringLiteral(value)));
-
- node.getEscape().ifPresent(value -> builder
- .append(" ESCAPE ")
- .append(formatStringLiteral(value)));
-
- return null;
- }
-
- @Override
- protected Void visitShowCreate(ShowCreate node, Integer indent)
- {
- if (node.getType() == ShowCreate.Type.TABLE) {
- builder.append("SHOW CREATE TABLE ")
- .append(formatName(node.getName(), dialect));
- }
- else if (node.getType() == ShowCreate.Type.VIEW) {
- builder.append("SHOW CREATE VIEW ")
- .append(formatName(node.getName(), dialect));
- }
- else if (node.getType() == ShowCreate.Type.MATERIALIZED_VIEW) {
- builder.append("SHOW CREATE MATERIALIZED VIEW ")
- .append(formatName(node.getName(), dialect));
- }
- return null;
- }
-
- @Override
- protected Void visitShowColumns(ShowColumns node, Integer indent)
- {
- builder.append("SHOW COLUMNS FROM ")
- .append(formatName(node.getTable(), dialect));
-
- node.getLikePattern().ifPresent(value -> builder
- .append(" LIKE ")
- .append(formatStringLiteral(value)));
-
- node.getEscape().ifPresent(value -> builder
- .append(" ESCAPE ")
- .append(formatStringLiteral(value)));
-
- return null;
- }
-
- @Override
- protected Void visitShowStats(ShowStats node, Integer indent)
- {
- builder.append("SHOW STATS FOR ");
- process(node.getRelation(), 0);
-
- return null;
- }
-
- @Override
- protected Void visitShowFunctions(ShowFunctions node, Integer indent)
- {
- builder.append("SHOW FUNCTIONS");
-
- node.getLikePattern().ifPresent(value -> builder
- .append(" LIKE ")
- .append(formatStringLiteral(value)));
-
- node.getEscape().ifPresent(value -> builder
- .append(" ESCAPE ")
- .append(formatStringLiteral(value)));
-
- return null;
- }
-
- @Override
- protected Void visitShowSession(ShowSession node, Integer indent)
- {
- builder.append("SHOW SESSION");
-
- node.getLikePattern().ifPresent(value -> builder
- .append(" LIKE ")
- .append(formatStringLiteral(value)));
-
- node.getEscape().ifPresent(value -> builder
- .append(" ESCAPE ")
- .append(formatStringLiteral(value)));
-
- return null;
- }
-
- @Override
- protected Void visitDelete(Delete node, Integer indent)
- {
- builder.append("DELETE FROM ")
- .append(formatName(node.getTable().getName(), dialect));
-
- node.getWhere().ifPresent(where -> builder
- .append(" WHERE ")
- .append(formatExpression(where, dialect)));
-
- return null;
- }
-
- @Override
- protected Void visitCreateSchema(CreateSchema node, Integer indent)
- {
- builder.append("CREATE SCHEMA ");
- if (node.isNotExists()) {
- builder.append("IF NOT EXISTS ");
- }
- builder.append(formatName(node.getSchemaName(), dialect));
- node.getPrincipal().ifPresent(principal -> builder
- .append("\nAUTHORIZATION ")
- .append(formatPrincipal(principal)));
- builder.append(formatPropertiesMultiLine(node.getProperties()));
-
- return null;
- }
-
- @Override
- protected Void visitDropSchema(DropSchema node, Integer indent)
- {
- builder.append("DROP SCHEMA ");
- if (node.isExists()) {
- builder.append("IF EXISTS ");
- }
- builder.append(formatName(node.getSchemaName(), dialect))
- .append(" ")
- .append(node.isCascade() ? "CASCADE" : "RESTRICT");
-
- return null;
- }
-
- @Override
- protected Void visitRenameSchema(RenameSchema node, Integer indent)
- {
- builder.append("ALTER SCHEMA ")
- .append(formatName(node.getSource(), dialect))
- .append(" RENAME TO ")
- .append(formatExpression(node.getTarget(), dialect));
-
- return null;
- }
-
- @Override
- protected Void visitSetSchemaAuthorization(SetSchemaAuthorization node, Integer indent)
- {
- builder.append("ALTER SCHEMA ")
- .append(formatName(node.getSource(), dialect))
- .append(" SET AUTHORIZATION ")
- .append(formatPrincipal(node.getPrincipal()));
-
- return null;
- }
-
- @Override
- protected Void visitCreateTableAsSelect(CreateTableAsSelect node, Integer indent)
- {
- builder.append("CREATE TABLE ");
- if (node.isNotExists()) {
- builder.append("IF NOT EXISTS ");
- }
- builder.append(formatName(node.getName(), dialect));
-
- node.getColumnAliases().ifPresent(columnAliases -> {
- String columnList = columnAliases.stream()
- .map(alias -> formatExpression(alias, dialect))
- .collect(joining(", "));
- builder.append(format("( %s )", columnList));
- });
-
- node.getComment().ifPresent(comment -> builder
- .append("\nCOMMENT ")
- .append(formatStringLiteral(comment)));
- builder.append(formatPropertiesMultiLine(node.getProperties()));
-
- builder.append(" AS ");
- process(node.getQuery(), indent);
-
- if (!node.isWithData()) {
- builder.append(" WITH NO DATA");
- }
-
- return null;
- }
-
- @Override
- protected Void visitCreateTable(CreateTable node, Integer indent)
- {
- builder.append("CREATE TABLE ");
- if (node.isNotExists()) {
- builder.append("IF NOT EXISTS ");
- }
- String tableName = formatName(node.getName(), dialect);
- builder.append(tableName).append(" (\n");
-
- String elementIndent = indentString(indent + 1);
- String columnList = node.getElements().stream()
- .map(element -> {
- if (element instanceof ColumnDefinition) {
- ColumnDefinition column = (ColumnDefinition) element;
- return elementIndent + formatColumnDefinition(column);
- }
- if (element instanceof LikeClause) {
- LikeClause likeClause = (LikeClause) element;
- StringBuilder builder = new StringBuilder(elementIndent);
- builder.append("LIKE ")
- .append(formatName(likeClause.getTableName(), dialect));
-
- likeClause.getPropertiesOption().ifPresent(propertiesOption -> builder
- .append(" ")
- .append(propertiesOption.name())
- .append(" PROPERTIES"));
-
- return builder.toString();
- }
- throw new UnsupportedOperationException("unknown table element: " + element);
- })
- .collect(joining(",\n"));
- builder.append(columnList);
- builder.append("\n").append(")");
-
- node.getComment().ifPresent(comment -> builder
- .append("\nCOMMENT ")
- .append(formatStringLiteral(comment)));
-
- builder.append(formatPropertiesMultiLine(node.getProperties()));
-
- return null;
- }
-
- private String formatPropertiesMultiLine(List properties)
- {
- if (properties.isEmpty()) {
- return "";
- }
-
- String propertyList = properties.stream()
- .map(element -> INDENT +
- formatExpression(element.getName(), dialect) + " = " +
- (element.isSetToDefault() ? "DEFAULT" : formatExpression(element.getNonDefaultValue(), dialect)))
- .collect(joining(",\n"));
-
- return "\nWITH (\n" + propertyList + "\n)";
- }
-
- private String formatPropertiesSingleLine(List properties)
- {
- if (properties.isEmpty()) {
- return "";
- }
-
- return " WITH ( " + joinProperties(properties) + " )";
- }
-
- private String formatColumnDefinition(ColumnDefinition column)
- {
- StringBuilder builder = new StringBuilder()
- .append(formatExpression(column.getName(), dialect))
- .append(" ").append(column.getType());
- if (!column.isNullable()) {
- builder.append(" NOT NULL");
- }
- column.getComment().ifPresent(comment -> builder
- .append(" COMMENT ")
- .append(formatStringLiteral(comment)));
- builder.append(formatPropertiesSingleLine(column.getProperties()));
- return builder.toString();
- }
-
- private static String formatGrantor(GrantorSpecification grantor)
- {
- GrantorSpecification.Type type = grantor.getType();
- switch (type) {
- case CURRENT_ROLE:
- case CURRENT_USER:
- return type.name();
- case PRINCIPAL:
- return formatPrincipal(grantor.getPrincipal().get());
- }
- throw new IllegalArgumentException("Unsupported principal type: " + type);
- }
-
- private static String formatPrincipal(PrincipalSpecification principal)
- {
- PrincipalSpecification.Type type = principal.getType();
- switch (type) {
- case UNSPECIFIED:
- return principal.getName().toString();
- case USER:
- case ROLE:
- return format("%s %s", type.name(), principal.getName());
- }
- throw new IllegalArgumentException("Unsupported principal type: " + type);
- }
-
- @Override
- protected Void visitDropTable(DropTable node, Integer indent)
- {
- builder.append("DROP TABLE ");
- if (node.isExists()) {
- builder.append("IF EXISTS ");
- }
- builder.append(formatName(node.getTableName(), dialect));
-
- return null;
- }
-
- @Override
- protected Void visitRenameTable(RenameTable node, Integer indent)
- {
- builder.append("ALTER TABLE ");
- if (node.isExists()) {
- builder.append("IF EXISTS ");
- }
- builder.append(node.getSource())
- .append(" RENAME TO ")
- .append(node.getTarget());
-
- return null;
- }
-
- @Override
- protected Void visitSetProperties(SetProperties node, Integer context)
- {
- SetProperties.Type type = node.getType();
- builder.append("ALTER ");
- switch (type) {
- case TABLE:
- builder.append("TABLE ");
- break;
- case MATERIALIZED_VIEW:
- builder.append("MATERIALIZED VIEW ");
- break;
- default:
- throw new IllegalArgumentException("Unsupported SetProperties.Type: " + type);
- }
- builder.append(formatName(node.getName(), dialect))
- .append(" SET PROPERTIES ")
- .append(joinProperties(node.getProperties()));
-
- return null;
- }
-
- private String joinProperties(List properties)
- {
- return properties.stream()
- .map(element -> formatExpression(element.getName(), dialect) + " = " +
- (element.isSetToDefault() ? "DEFAULT" : formatExpression(element.getNonDefaultValue(), dialect)))
- .collect(joining(", "));
- }
-
- @Override
- protected Void visitComment(Comment node, Integer context)
- {
- String comment = node.getComment()
- .map(ExpressionFormatter::formatStringLiteral)
- .orElse("NULL");
-
- switch (node.getType()) {
- case TABLE:
- builder.append("COMMENT ON TABLE ")
- .append(node.getName())
- .append(" IS ")
- .append(comment);
- break;
- case COLUMN:
- builder.append("COMMENT ON COLUMN ")
- .append(node.getName())
- .append(" IS ")
- .append(comment);
- break;
- }
-
- return null;
- }
-
- @Override
- protected Void visitRenameColumn(RenameColumn node, Integer indent)
- {
- builder.append("ALTER TABLE ");
- if (node.isTableExists()) {
- builder.append("IF EXISTS ");
- }
- builder.append(node.getTable())
- .append(" RENAME COLUMN ");
- if (node.isColumnExists()) {
- builder.append("IF EXISTS ");
- }
- builder.append(node.getSource())
- .append(" TO ")
- .append(node.getTarget());
-
- return null;
- }
-
- @Override
- protected Void visitDropColumn(DropColumn node, Integer indent)
- {
- builder.append("ALTER TABLE ");
- if (node.isTableExists()) {
- builder.append("IF EXISTS ");
- }
- builder.append(formatName(node.getTable(), dialect))
- .append(" DROP COLUMN ");
- if (node.isColumnExists()) {
- builder.append("IF EXISTS ");
- }
- builder.append(formatExpression(node.getColumn(), dialect));
-
- return null;
- }
-
- @Override
- protected Void visitTableExecute(TableExecute node, Integer indent)
- {
- builder.append("ALTER TABLE ");
- builder.append(formatName(node.getTable().getName(), dialect));
- builder.append(" EXECUTE ");
- builder.append(formatExpression(node.getProcedureName(), dialect));
- if (!node.getArguments().isEmpty()) {
- builder.append("(");
- formatCallArguments(indent, node.getArguments());
- builder.append(")");
- }
- node.getWhere().ifPresent(where -> builder
- .append("\n")
- .append(indentString(indent))
- .append("WHERE ")
- .append(formatExpression(where, dialect)));
- return null;
- }
-
- @Override
- protected Void visitAnalyze(Analyze node, Integer indent)
- {
- builder.append("ANALYZE ")
- .append(formatName(node.getTableName(), dialect));
- builder.append(formatPropertiesMultiLine(node.getProperties()));
- return null;
- }
-
- @Override
- protected Void visitAddColumn(AddColumn node, Integer indent)
- {
- builder.append("ALTER TABLE ");
- if (node.isTableExists()) {
- builder.append("IF EXISTS ");
- }
- builder.append(node.getName())
- .append(" ADD COLUMN ");
- if (node.isColumnNotExists()) {
- builder.append("IF NOT EXISTS ");
- }
- builder.append(formatColumnDefinition(node.getColumn()));
-
- return null;
- }
-
- @Override
- protected Void visitSetTableAuthorization(SetTableAuthorization node, Integer indent)
- {
- builder.append("ALTER TABLE ")
- .append(formatName(node.getSource(), dialect))
- .append(" SET AUTHORIZATION ")
- .append(formatPrincipal(node.getPrincipal()));
-
- return null;
- }
-
- @Override
- protected Void visitInsert(Insert node, Integer indent)
- {
- builder.append("INSERT INTO ")
- .append(formatName(node.getTarget(), dialect));
-
- node.getColumns().ifPresent(columns -> builder
- .append(" (")
- .append(Joiner.on(", ").join(columns))
- .append(")"));
-
- builder.append("\n");
-
- process(node.getQuery(), indent);
-
- return null;
- }
-
- @Override
- protected Void visitUpdate(Update node, Integer indent)
- {
- builder.append("UPDATE ")
- .append(node.getTable().getName())
- .append(" SET");
- int setCounter = node.getAssignments().size() - 1;
- for (UpdateAssignment assignment : node.getAssignments()) {
- builder.append("\n")
- .append(indentString(indent + 1))
- .append(assignment.getName().getValue())
- .append(" = ")
- .append(formatExpression(assignment.getValue(), dialect));
- if (setCounter > 0) {
- builder.append(",");
- }
- setCounter--;
- }
- node.getWhere().ifPresent(where -> builder
- .append("\n")
- .append(indentString(indent))
- .append("WHERE ").append(formatExpression(where, dialect)));
- return null;
- }
-
- @Override
- protected Void visitTruncateTable(TruncateTable node, Integer indent)
- {
- builder.append("TRUNCATE TABLE ");
- builder.append(formatName(node.getTableName(), dialect));
-
- return null;
- }
-
- @Override
- public Void visitSetSession(SetSession node, Integer indent)
- {
- builder.append("SET SESSION ")
- .append(formatName(node.getName(), dialect))
- .append(" = ")
- .append(formatExpression(node.getValue(), dialect));
-
- return null;
- }
-
- @Override
- public Void visitResetSession(ResetSession node, Integer indent)
- {
- builder.append("RESET SESSION ")
- .append(formatName(node.getName(), dialect));
-
- return null;
- }
-
- @Override
- protected Void visitCallArgument(CallArgument node, Integer indent)
- {
- node.getName().ifPresent(name -> builder
- .append(name)
- .append(" => "));
- builder.append(formatExpression(node.getValue(), dialect));
-
- return null;
- }
-
- @Override
- protected Void visitCall(Call node, Integer indent)
- {
- builder.append("CALL ")
- .append(node.getName())
- .append("(");
- formatCallArguments(indent, node.getArguments());
- builder.append(")");
-
- return null;
- }
-
- private void formatCallArguments(Integer indent, List arguments)
- {
- Iterator iterator = arguments.iterator();
- while (iterator.hasNext()) {
- process(iterator.next(), indent);
- if (iterator.hasNext()) {
- builder.append(", ");
- }
- }
- }
-
- @Override
- protected Void visitRow(Row node, Integer indent)
- {
- builder.append("ROW(");
- boolean firstItem = true;
- for (Expression item : node.getItems()) {
- if (!firstItem) {
- builder.append(", ");
- }
- process(item, indent);
- firstItem = false;
- }
- builder.append(")");
- return null;
- }
-
- @Override
- protected Void visitStartTransaction(StartTransaction node, Integer indent)
- {
- builder.append("START TRANSACTION");
-
- Iterator iterator = node.getTransactionModes().iterator();
- while (iterator.hasNext()) {
- builder.append(" ");
- process(iterator.next(), indent);
- if (iterator.hasNext()) {
- builder.append(",");
- }
- }
- return null;
- }
-
- @Override
- protected Void visitIsolationLevel(Isolation node, Integer indent)
- {
- builder.append("ISOLATION LEVEL ").append(node.getLevel().getText());
- return null;
- }
-
- @Override
- protected Void visitTransactionAccessMode(TransactionAccessMode node, Integer indent)
- {
- builder.append(node.isReadOnly() ? "READ ONLY" : "READ WRITE");
- return null;
- }
-
- @Override
- protected Void visitCommit(Commit node, Integer indent)
- {
- builder.append("COMMIT");
- return null;
- }
-
- @Override
- protected Void visitRollback(Rollback node, Integer indent)
- {
- builder.append("ROLLBACK");
- return null;
- }
-
- @Override
- protected Void visitCreateRole(CreateRole node, Integer indent)
- {
- builder.append("CREATE ROLE ").append(node.getName());
- node.getGrantor().ifPresent(grantor -> builder
- .append(" WITH ADMIN ")
- .append(formatGrantor(grantor)));
- node.getCatalog().ifPresent(catalog -> builder
- .append(" IN ")
- .append(catalog));
- return null;
- }
-
- @Override
- protected Void visitDropRole(DropRole node, Integer indent)
- {
- builder.append("DROP ROLE ").append(node.getName());
- node.getCatalog().ifPresent(catalog -> builder
- .append(" IN ")
- .append(catalog));
- return null;
- }
-
- @Override
- protected Void visitGrantRoles(GrantRoles node, Integer indent)
- {
- builder.append("GRANT ");
- builder.append(node.getRoles().stream()
- .map(Identifier::toString)
- .collect(joining(", ")));
- builder.append(" TO ");
- builder.append(node.getGrantees().stream()
- .map(Formatter::formatPrincipal)
- .collect(joining(", ")));
- if (node.isAdminOption()) {
- builder.append(" WITH ADMIN OPTION");
- }
- node.getGrantor().ifPresent(grantor -> builder
- .append(" GRANTED BY ")
- .append(formatGrantor(grantor)));
- node.getCatalog().ifPresent(catalog -> builder
- .append(" IN ")
- .append(catalog));
- return null;
- }
-
- @Override
- protected Void visitRevokeRoles(RevokeRoles node, Integer indent)
- {
- builder.append("REVOKE ");
- if (node.isAdminOption()) {
- builder.append("ADMIN OPTION FOR ");
- }
- builder.append(node.getRoles().stream()
- .map(Identifier::toString)
- .collect(joining(", ")));
- builder.append(" FROM ");
- builder.append(node.getGrantees().stream()
- .map(Formatter::formatPrincipal)
- .collect(joining(", ")));
- node.getGrantor().ifPresent(grantor -> builder
- .append(" GRANTED BY ")
- .append(formatGrantor(grantor)));
- node.getCatalog().ifPresent(catalog -> builder
- .append(" IN ")
- .append(catalog));
- return null;
- }
-
- @Override
- protected Void visitSetRole(SetRole node, Integer indent)
- {
- builder.append("SET ROLE ");
- SetRole.Type type = node.getType();
- switch (type) {
- case ALL:
- case NONE:
- builder.append(type);
- break;
- case ROLE:
- builder.append(node.getRole().get());
- break;
- default:
- throw new IllegalArgumentException("Unsupported type: " + type);
- }
- node.getCatalog().ifPresent(catalog -> builder
- .append(" IN ")
- .append(catalog));
- return null;
- }
-
- @Override
- public Void visitGrant(Grant node, Integer indent)
- {
- builder.append("GRANT ");
-
- builder.append(node.getPrivileges()
- .map(privileges -> String.join(", ", privileges))
- .orElse("ALL PRIVILEGES"));
-
- builder.append(" ON ");
- node.getType().ifPresent(type -> builder
- .append(type)
- .append(' '));
- builder.append(formatName(node.getName(), dialect))
- .append(" TO ")
- .append(formatPrincipal(node.getGrantee()));
- if (node.isWithGrantOption()) {
- builder.append(" WITH GRANT OPTION");
- }
-
- return null;
- }
-
- @Override
- public Void visitDeny(Deny node, Integer indent)
- {
- builder.append("DENY ");
-
- if (node.getPrivileges().isPresent()) {
- builder.append(String.join(", ", node.getPrivileges().get()));
- }
- else {
- builder.append("ALL PRIVILEGES");
- }
-
- builder.append(" ON ");
- if (node.getType().isPresent()) {
- builder.append(node.getType().get());
- builder.append(" ");
- }
- builder.append(formatName(node.getName(), dialect))
- .append(" TO ")
- .append(formatPrincipal(node.getGrantee()));
-
- return null;
- }
-
- @Override
- public Void visitRevoke(Revoke node, Integer indent)
- {
- builder.append("REVOKE ");
-
- if (node.isGrantOptionFor()) {
- builder.append("GRANT OPTION FOR ");
- }
-
- builder.append(node.getPrivileges()
- .map(privileges -> String.join(", ", privileges))
- .orElse("ALL PRIVILEGES"));
-
- builder.append(" ON ");
- node.getType().ifPresent(type -> builder
- .append(type)
- .append(' '));
- builder.append(node.getName())
- .append(" FROM ")
- .append(formatPrincipal(node.getGrantee()));
-
- return null;
- }
-
- @Override
- public Void visitShowGrants(ShowGrants node, Integer indent)
- {
- builder.append("SHOW GRANTS ");
-
- node.getTableName().ifPresent(tableName -> {
- builder.append("ON ");
- if (node.getTable()) {
- builder.append("TABLE ");
- }
- builder.append(tableName);
- });
-
- return null;
- }
-
- @Override
- protected Void visitShowRoles(ShowRoles node, Integer indent)
- {
- builder.append("SHOW ");
- if (node.isCurrent()) {
- builder.append("CURRENT ");
- }
- builder.append("ROLES");
- node.getCatalog().ifPresent(catalog -> builder
- .append(" FROM ")
- .append(catalog));
-
- return null;
- }
-
- @Override
- protected Void visitShowRoleGrants(ShowRoleGrants node, Integer indent)
- {
- builder.append("SHOW ROLE GRANTS");
- node.getCatalog().ifPresent(catalog -> builder
- .append(" FROM ")
- .append(catalog));
- return null;
- }
-
- @Override
- public Void visitSetPath(SetPath node, Integer indent)
- {
- builder.append("SET PATH ");
- builder.append(Joiner.on(", ").join(node.getPathSpecification().getPath()));
- return null;
- }
-
- @Override
- public Void visitSetTimeZone(SetTimeZone node, Integer indent)
- {
- builder.append("SET TIME ZONE ");
- builder.append(node.getTimeZone().map(expression -> formatExpression(expression, dialect)).orElse("LOCAL"));
- return null;
- }
-
- private void processRelation(Relation relation, Integer indent)
- {
- // TODO: handle this properly
- if (relation instanceof Table) {
- builder.append("TABLE ")
- .append(((Table) relation).getName())
- .append('\n');
- }
- else {
- process(relation, indent);
- }
- }
-
- private StringBuilder append(int indent, String value)
- {
- return builder.append(indentString(indent))
- .append(value);
- }
-
- private static String indentString(int indent)
- {
- return Strings.repeat(INDENT, indent);
- }
-
- private void formatDefinitionList(List 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 columns, Dialect dialect)
- {
- if ((columns != null) && (!columns.isEmpty())) {
- String formattedColumns = columns.stream()
- .map(expression -> formatExpression(expression, dialect))
- .collect(Collectors.joining(", "));
-
- builder.append(" (")
- .append(formattedColumns)
- .append(')');
- }
- }
-}
diff --git a/trino-parser/src/main/java/io/trino/sql/TreePrinter.java b/trino-parser/src/main/java/io/trino/sql/TreePrinter.java
deleted file mode 100644
index 8e55abc80..000000000
--- a/trino-parser/src/main/java/io/trino/sql/TreePrinter.java
+++ /dev/null
@@ -1,462 +0,0 @@
-package io.trino.sql;
-
-import com.google.common.base.Joiner;
-import com.google.common.base.Strings;
-import io.trino.sql.tree.AliasedRelation;
-import io.trino.sql.tree.AllColumns;
-import io.trino.sql.tree.ArithmeticBinaryExpression;
-import io.trino.sql.tree.AstVisitor;
-import io.trino.sql.tree.BinaryLiteral;
-import io.trino.sql.tree.BooleanLiteral;
-import io.trino.sql.tree.ComparisonExpression;
-import io.trino.sql.tree.Cube;
-import io.trino.sql.tree.DefaultTraversalVisitor;
-import io.trino.sql.tree.DereferenceExpression;
-import io.trino.sql.tree.Expression;
-import io.trino.sql.tree.FunctionCall;
-import io.trino.sql.tree.GroupingElement;
-import io.trino.sql.tree.GroupingSets;
-import io.trino.sql.tree.Identifier;
-import io.trino.sql.tree.InPredicate;
-import io.trino.sql.tree.LikePredicate;
-import io.trino.sql.tree.LogicalExpression;
-import io.trino.sql.tree.LongLiteral;
-import io.trino.sql.tree.Node;
-import io.trino.sql.tree.OrderBy;
-import io.trino.sql.tree.QualifiedName;
-import io.trino.sql.tree.Query;
-import io.trino.sql.tree.QuerySpecification;
-import io.trino.sql.tree.Rollup;
-import io.trino.sql.tree.Row;
-import io.trino.sql.tree.SampledRelation;
-import io.trino.sql.tree.Select;
-import io.trino.sql.tree.SimpleGroupBy;
-import io.trino.sql.tree.SingleColumn;
-import io.trino.sql.tree.SortItem;
-import io.trino.sql.tree.StringLiteral;
-import io.trino.sql.tree.SubqueryExpression;
-import io.trino.sql.tree.Table;
-import io.trino.sql.tree.TableSubquery;
-import io.trino.sql.tree.Values;
-import io.trino.sql.tree.WindowDefinition;
-import io.trino.sql.tree.WindowReference;
-import io.trino.sql.tree.WindowSpecification;
-
-import java.io.PrintStream;
-import java.util.IdentityHashMap;
-import java.util.List;
-
-public class TreePrinter
-{
- private static final String INDENT = " ";
-
- private final IdentityHashMap resolvedNameReferences;
- private final PrintStream out;
-
- public TreePrinter(IdentityHashMap resolvedNameReferences, PrintStream out)
- {
- this.resolvedNameReferences = new IdentityHashMap<>(resolvedNameReferences);
- this.out = out;
- }
-
- public void print(Node root)
- {
- AstVisitor printer = new DefaultTraversalVisitor()
- {
- @Override
- protected Void visitNode(Node node, Integer indentLevel)
- {
- throw new UnsupportedOperationException("not yet implemented: " + node);
- }
-
- @Override
- protected Void visitQuery(Query node, Integer indentLevel)
- {
- print(indentLevel, "Query ");
-
- indentLevel++;
-
- print(indentLevel, "QueryBody");
- process(node.getQueryBody(), indentLevel);
- if (node.getOrderBy().isPresent()) {
- print(indentLevel, "OrderBy");
- process(node.getOrderBy().get(), indentLevel + 1);
- }
-
- if (node.getLimit().isPresent()) {
- print(indentLevel, "Limit: " + node.getLimit().get());
- }
-
- return null;
- }
-
- @Override
- protected Void visitQuerySpecification(QuerySpecification node, Integer indentLevel)
- {
- print(indentLevel, "QuerySpecification ");
-
- indentLevel++;
-
- process(node.getSelect(), indentLevel);
-
- if (node.getFrom().isPresent()) {
- print(indentLevel, "From");
- process(node.getFrom().get(), indentLevel + 1);
- }
-
- if (node.getWhere().isPresent()) {
- print(indentLevel, "Where");
- process(node.getWhere().get(), indentLevel + 1);
- }
-
- if (node.getGroupBy().isPresent()) {
- String distinct = "";
- if (node.getGroupBy().get().isDistinct()) {
- distinct = "[DISTINCT]";
- }
- print(indentLevel, "GroupBy" + distinct);
- for (GroupingElement groupingElement : node.getGroupBy().get().getGroupingElements()) {
- print(indentLevel, "SimpleGroupBy");
- if (groupingElement instanceof SimpleGroupBy) {
- for (Expression column : groupingElement.getExpressions()) {
- process(column, indentLevel + 1);
- }
- }
- else if (groupingElement instanceof GroupingSets) {
- print(indentLevel + 1, "GroupingSets");
- for (List set : ((GroupingSets) groupingElement).getSets()) {
- print(indentLevel + 2, "GroupingSet[");
- for (Expression expression : set) {
- process(expression, indentLevel + 3);
- }
- print(indentLevel + 2, "]");
- }
- }
- else if (groupingElement instanceof Cube) {
- print(indentLevel + 1, "Cube");
- for (Expression column : groupingElement.getExpressions()) {
- process(column, indentLevel + 1);
- }
- }
- else if (groupingElement instanceof Rollup) {
- print(indentLevel + 1, "Rollup");
- for (Expression column : groupingElement.getExpressions()) {
- process(column, indentLevel + 1);
- }
- }
- }
- }
-
- if (node.getHaving().isPresent()) {
- print(indentLevel, "Having");
- process(node.getHaving().get(), indentLevel + 1);
- }
-
- if (!node.getWindows().isEmpty()) {
- print(indentLevel, "Window");
- for (WindowDefinition windowDefinition : node.getWindows()) {
- process(windowDefinition, indentLevel + 1);
- }
- }
-
- if (node.getOrderBy().isPresent()) {
- print(indentLevel, "OrderBy");
- process(node.getOrderBy().get(), indentLevel + 1);
- }
-
- if (node.getLimit().isPresent()) {
- print(indentLevel, "Limit: " + node.getLimit().get());
- }
-
- return null;
- }
-
- @Override
- protected Void visitOrderBy(OrderBy node, Integer indentLevel)
- {
- for (SortItem sortItem : node.getSortItems()) {
- process(sortItem, indentLevel);
- }
-
- return null;
- }
-
- @Override
- protected Void visitWindowDefinition(WindowDefinition node, Integer indentLevel)
- {
- print(indentLevel, "WindowDefinition[" + node.getName() + "]");
- process(node.getWindow(), indentLevel + 1);
-
- return null;
- }
-
- @Override
- protected Void visitWindowReference(WindowReference node, Integer indentLevel)
- {
- print(indentLevel, "WindowReference[" + node.getName() + "]");
-
- return null;
- }
-
- @Override
- public Void visitWindowSpecification(WindowSpecification node, Integer indentLevel)
- {
- if (node.getExistingWindowName().isPresent()) {
- print(indentLevel, "ExistingWindowName " + node.getExistingWindowName().get());
- }
-
- if (!node.getPartitionBy().isEmpty()) {
- print(indentLevel, "PartitionBy");
- for (Expression expression : node.getPartitionBy()) {
- process(expression, indentLevel + 1);
- }
- }
-
- if (node.getOrderBy().isPresent()) {
- print(indentLevel, "OrderBy");
- process(node.getOrderBy().get(), indentLevel + 1);
- }
-
- if (node.getFrame().isPresent()) {
- print(indentLevel, "Frame");
- process(node.getFrame().get(), indentLevel + 1);
- }
-
- return null;
- }
-
- @Override
- protected Void visitSelect(Select node, Integer indentLevel)
- {
- String distinct = "";
- if (node.isDistinct()) {
- distinct = "[DISTINCT]";
- }
- print(indentLevel, "Select" + distinct);
-
- super.visitSelect(node, indentLevel + 1); // visit children
-
- return null;
- }
-
- @Override
- protected Void visitAllColumns(AllColumns node, Integer indent)
- {
- StringBuilder aliases = new StringBuilder();
- if (!node.getAliases().isEmpty()) {
- aliases.append(" [Aliases: ");
- Joiner.on(", ").appendTo(aliases, node.getAliases());
- aliases.append("]");
- }
- print(indent, "All columns" + aliases.toString());
-
- if (node.getTarget().isPresent()) {
- super.visitAllColumns(node, indent + 1); // visit child
- }
-
- return null;
- }
-
- @Override
- protected Void visitSingleColumn(SingleColumn node, Integer indent)
- {
- if (node.getAlias().isPresent()) {
- print(indent, "Alias: " + node.getAlias().get());
- }
-
- super.visitSingleColumn(node, indent + 1); // visit children
-
- return null;
- }
-
- @Override
- protected Void visitComparisonExpression(ComparisonExpression node, Integer indentLevel)
- {
- print(indentLevel, node.getOperator().toString());
-
- super.visitComparisonExpression(node, indentLevel + 1);
-
- return null;
- }
-
- @Override
- protected Void visitArithmeticBinary(ArithmeticBinaryExpression node, Integer indentLevel)
- {
- print(indentLevel, node.getOperator().toString());
-
- super.visitArithmeticBinary(node, indentLevel + 1);
-
- return null;
- }
-
- @Override
- protected Void visitLogicalExpression(LogicalExpression node, Integer indentLevel)
- {
- print(indentLevel, node.getOperator().toString());
-
- super.visitLogicalExpression(node, indentLevel + 1);
-
- return null;
- }
-
- @Override
- protected Void visitStringLiteral(StringLiteral node, Integer indentLevel)
- {
- print(indentLevel, "String[" + node.getValue() + "]");
- return null;
- }
-
- @Override
- protected Void visitBinaryLiteral(BinaryLiteral node, Integer indentLevel)
- {
- print(indentLevel, "Binary[" + node.toHexString() + "]");
- return null;
- }
-
- @Override
- protected Void visitBooleanLiteral(BooleanLiteral node, Integer indentLevel)
- {
- print(indentLevel, "Boolean[" + node.getValue() + "]");
- return null;
- }
-
- @Override
- protected Void visitLongLiteral(LongLiteral node, Integer indentLevel)
- {
- print(indentLevel, "Long[" + node.getValue() + "]");
- return null;
- }
-
- @Override
- protected Void visitLikePredicate(LikePredicate node, Integer indentLevel)
- {
- print(indentLevel, "LIKE");
-
- super.visitLikePredicate(node, indentLevel + 1);
-
- return null;
- }
-
- @Override
- protected Void visitIdentifier(Identifier node, Integer indentLevel)
- {
- QualifiedName resolved = resolvedNameReferences.get(node);
- String resolvedName = "";
- if (resolved != null) {
- resolvedName = "=>" + resolved.toString();
- }
- print(indentLevel, "Identifier[" + node.getValue() + resolvedName + "]");
- return null;
- }
-
- @Override
- protected Void visitDereferenceExpression(DereferenceExpression node, Integer indentLevel)
- {
- QualifiedName resolved = resolvedNameReferences.get(node);
- String resolvedName = "";
- if (resolved != null) {
- resolvedName = "=>" + resolved.toString();
- }
- print(indentLevel, "DereferenceExpression[" + node + resolvedName + "]");
- return null;
- }
-
- @Override
- protected Void visitFunctionCall(FunctionCall node, Integer indentLevel)
- {
- String name = Joiner.on('.').join(node.getName().getParts());
- print(indentLevel, "FunctionCall[" + name + "]");
-
- super.visitFunctionCall(node, indentLevel + 1);
-
- return null;
- }
-
- @Override
- protected Void visitTable(Table node, Integer indentLevel)
- {
- String name = Joiner.on('.').join(node.getName().getParts());
- print(indentLevel, "Table[" + name + "]");
-
- return null;
- }
-
- @Override
- protected Void visitValues(Values node, Integer indentLevel)
- {
- print(indentLevel, "Values");
-
- super.visitValues(node, indentLevel + 1);
-
- return null;
- }
-
- @Override
- protected Void visitRow(Row node, Integer indentLevel)
- {
- print(indentLevel, "Row");
-
- super.visitRow(node, indentLevel + 1);
-
- return null;
- }
-
- @Override
- protected Void visitAliasedRelation(AliasedRelation node, Integer indentLevel)
- {
- print(indentLevel, "Alias[" + node.getAlias() + "]");
-
- super.visitAliasedRelation(node, indentLevel + 1);
-
- return null;
- }
-
- @Override
- protected Void visitSampledRelation(SampledRelation node, Integer indentLevel)
- {
- print(indentLevel, "TABLESAMPLE[" + node.getType() + " (" + node.getSamplePercentage() + ")]");
-
- super.visitSampledRelation(node, indentLevel + 1);
-
- return null;
- }
-
- @Override
- protected Void visitTableSubquery(TableSubquery node, Integer indentLevel)
- {
- print(indentLevel, "SubQuery");
-
- super.visitTableSubquery(node, indentLevel + 1);
-
- return null;
- }
-
- @Override
- protected Void visitInPredicate(InPredicate node, Integer indentLevel)
- {
- print(indentLevel, "IN");
-
- super.visitInPredicate(node, indentLevel + 1);
-
- return null;
- }
-
- @Override
- protected Void visitSubqueryExpression(SubqueryExpression node, Integer indentLevel)
- {
- print(indentLevel, "SubQuery");
-
- super.visitSubqueryExpression(node, indentLevel + 1);
-
- return null;
- }
- };
-
- printer.process(root, 0);
- }
-
- private void print(Integer indentLevel, String value)
- {
- out.println(Strings.repeat(INDENT, indentLevel) + value);
- }
-}
diff --git a/trino-parser/src/main/java/io/trino/sql/parser/AntlrATNCacheFields.java b/trino-parser/src/main/java/io/trino/sql/parser/AntlrATNCacheFields.java
deleted file mode 100644
index 5b9a6b443..000000000
--- a/trino-parser/src/main/java/io/trino/sql/parser/AntlrATNCacheFields.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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.parser;
-
-import org.antlr.v4.runtime.Lexer;
-import org.antlr.v4.runtime.Parser;
-import org.antlr.v4.runtime.atn.ATN;
-import org.antlr.v4.runtime.atn.LexerATNSimulator;
-import org.antlr.v4.runtime.atn.ParserATNSimulator;
-import org.antlr.v4.runtime.atn.PredictionContextCache;
-import org.antlr.v4.runtime.dfa.DFA;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static java.util.Objects.requireNonNull;
-
-public final class AntlrATNCacheFields
-{
- private final ATN atn;
- private final PredictionContextCache predictionContextCache;
- private final DFA[] decisionToDFA;
-
- public AntlrATNCacheFields(ATN atn)
- {
- this.atn = requireNonNull(atn, "atn is null");
- this.predictionContextCache = new PredictionContextCache();
- this.decisionToDFA = createDecisionToDFA(atn);
- }
-
- @SuppressWarnings("ObjectEquality")
- public void configureLexer(Lexer lexer)
- {
- requireNonNull(lexer, "lexer is null");
- // Intentional identity equals comparison
- checkArgument(atn == lexer.getATN(), "Lexer ATN mismatch: expected %s, found %s", atn, lexer.getATN());
- lexer.setInterpreter(new LexerATNSimulator(lexer, atn, decisionToDFA, predictionContextCache));
- }
-
- @SuppressWarnings("ObjectEquality")
- public void configureParser(Parser parser)
- {
- requireNonNull(parser, "parser is null");
- // Intentional identity equals comparison
- checkArgument(atn == parser.getATN(), "Parser ATN mismatch: expected %s, found %s", atn, parser.getATN());
- parser.setInterpreter(new ParserATNSimulator(parser, atn, decisionToDFA, predictionContextCache));
- }
-
- private static DFA[] createDecisionToDFA(ATN atn)
- {
- DFA[] decisionToDFA = new DFA[atn.getNumberOfDecisions()];
- for (int i = 0; i < decisionToDFA.length; i++) {
- decisionToDFA[i] = new DFA(atn.getDecisionState(i), i);
- }
- return decisionToDFA;
- }
-}
diff --git a/trino-parser/src/main/java/io/trino/sql/parser/AstBuilder.java b/trino-parser/src/main/java/io/trino/sql/parser/AstBuilder.java
deleted file mode 100644
index b83443006..000000000
--- a/trino-parser/src/main/java/io/trino/sql/parser/AstBuilder.java
+++ /dev/null
@@ -1,3492 +0,0 @@
-/*
- * 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.parser;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
-import io.trino.sql.tree.AddColumn;
-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;
-import io.trino.sql.tree.AtTimeZone;
-import io.trino.sql.tree.BetweenPredicate;
-import io.trino.sql.tree.BinaryLiteral;
-import io.trino.sql.tree.BindExpression;
-import io.trino.sql.tree.BooleanLiteral;
-import io.trino.sql.tree.Call;
-import io.trino.sql.tree.CallArgument;
-import io.trino.sql.tree.Cast;
-import io.trino.sql.tree.CharLiteral;
-import io.trino.sql.tree.CoalesceExpression;
-import io.trino.sql.tree.ColumnDefinition;
-import io.trino.sql.tree.Comment;
-import io.trino.sql.tree.Commit;
-import io.trino.sql.tree.ComparisonExpression;
-import io.trino.sql.tree.CreateMaterializedView;
-import io.trino.sql.tree.CreateRole;
-import io.trino.sql.tree.CreateSchema;
-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;
-import io.trino.sql.tree.DataTypeParameter;
-import io.trino.sql.tree.DateTimeDataType;
-import io.trino.sql.tree.Deallocate;
-import io.trino.sql.tree.DecimalLiteral;
-import io.trino.sql.tree.Declare;
-import io.trino.sql.tree.Delete;
-import io.trino.sql.tree.Deny;
-import io.trino.sql.tree.DereferenceExpression;
-import io.trino.sql.tree.DescribeInput;
-import io.trino.sql.tree.DescribeOutput;
-import io.trino.sql.tree.DoubleLiteral;
-import io.trino.sql.tree.DropColumn;
-import io.trino.sql.tree.DropMaterializedView;
-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;
-import io.trino.sql.tree.ExplainAnalyze;
-import io.trino.sql.tree.ExplainFormat;
-import io.trino.sql.tree.ExplainOption;
-import io.trino.sql.tree.ExplainType;
-import io.trino.sql.tree.Expression;
-import io.trino.sql.tree.Extract;
-import io.trino.sql.tree.FetchCursor;
-import io.trino.sql.tree.FetchFirst;
-import io.trino.sql.tree.Format;
-import io.trino.sql.tree.FrameBound;
-import io.trino.sql.tree.FunctionCall;
-import io.trino.sql.tree.FunctionCall.NullTreatment;
-import io.trino.sql.tree.FunctionRelation;
-import io.trino.sql.tree.GenericDataType;
-import io.trino.sql.tree.GenericLiteral;
-import io.trino.sql.tree.Grant;
-import io.trino.sql.tree.GrantOnType;
-import io.trino.sql.tree.GrantRoles;
-import io.trino.sql.tree.GrantorSpecification;
-import io.trino.sql.tree.GroupBy;
-import io.trino.sql.tree.GroupingElement;
-import io.trino.sql.tree.GroupingOperation;
-import io.trino.sql.tree.GroupingSets;
-import io.trino.sql.tree.Identifier;
-import io.trino.sql.tree.IfExpression;
-import io.trino.sql.tree.ImpersonateUser;
-import io.trino.sql.tree.InListExpression;
-import io.trino.sql.tree.InPredicate;
-import io.trino.sql.tree.Insert;
-import io.trino.sql.tree.Intersect;
-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.Isolation;
-import io.trino.sql.tree.Join;
-import io.trino.sql.tree.JoinCriteria;
-import io.trino.sql.tree.JoinOn;
-import io.trino.sql.tree.JoinUsing;
-import io.trino.sql.tree.LambdaArgumentDeclaration;
-import io.trino.sql.tree.LambdaExpression;
-import io.trino.sql.tree.Lateral;
-import io.trino.sql.tree.LikeClause;
-import io.trino.sql.tree.LikePredicate;
-import io.trino.sql.tree.Limit;
-import io.trino.sql.tree.LogicalExpression;
-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;
-import io.trino.sql.tree.MergeInsert;
-import io.trino.sql.tree.MergeUpdate;
-import io.trino.sql.tree.NaturalJoin;
-import io.trino.sql.tree.Node;
-import io.trino.sql.tree.NodeLocation;
-import io.trino.sql.tree.NotExpression;
-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.PathRelation;
-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.QueryPeriod;
-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;
-import io.trino.sql.tree.RenameMaterializedView;
-import io.trino.sql.tree.RenameSchema;
-import io.trino.sql.tree.RenameTable;
-import io.trino.sql.tree.RenameView;
-import io.trino.sql.tree.ResetSession;
-import io.trino.sql.tree.Revoke;
-import io.trino.sql.tree.RevokeRoles;
-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;
-import io.trino.sql.tree.SelectItem;
-import io.trino.sql.tree.SetPath;
-import io.trino.sql.tree.SetProperties;
-import io.trino.sql.tree.SetRole;
-import io.trino.sql.tree.SetSchemaAuthorization;
-import io.trino.sql.tree.SetSession;
-import io.trino.sql.tree.SetTableAuthorization;
-import io.trino.sql.tree.SetTimeZone;
-import io.trino.sql.tree.SetViewAuthorization;
-import io.trino.sql.tree.ShowCatalogs;
-import io.trino.sql.tree.ShowColumns;
-import io.trino.sql.tree.ShowCreate;
-import io.trino.sql.tree.ShowFunctions;
-import io.trino.sql.tree.ShowGrants;
-import io.trino.sql.tree.ShowRoleGrants;
-import io.trino.sql.tree.ShowRoles;
-import io.trino.sql.tree.ShowSchemas;
-import io.trino.sql.tree.ShowSession;
-import io.trino.sql.tree.ShowStats;
-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.TableExecute;
-import io.trino.sql.tree.TableSubquery;
-import io.trino.sql.tree.TimeLiteral;
-import io.trino.sql.tree.TimestampLiteral;
-import io.trino.sql.tree.TransactionAccessMode;
-import io.trino.sql.tree.TransactionMode;
-import io.trino.sql.tree.TruncateTable;
-import io.trino.sql.tree.TryExpression;
-import io.trino.sql.tree.TypeParameter;
-import io.trino.sql.tree.Union;
-import io.trino.sql.tree.Unnest;
-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;
-import io.trino.sql.tree.WindowFrame;
-import io.trino.sql.tree.WindowOperation;
-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;
-import org.antlr.v4.runtime.tree.ParseTree;
-import org.antlr.v4.runtime.tree.TerminalNode;
-
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.Deque;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Optional;
-import java.util.function.Function;
-
-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.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;
-import static java.util.Objects.isNull;
-import static java.util.Objects.requireNonNull;
-import static java.util.stream.Collectors.toList;
-
-@VisibleForTesting
-public class AstBuilder
- extends SqlBaseBaseVisitor
-{
- public static final List DUCKDB_TABLE_FUNCTIONS = ImmutableList.of(
- "read_csv",
- "sniff_csv",
- "read_json",
- "glob",
- "read_parquet",
- "parquet_metadata");
-
- private int parameterPosition;
- private final ParsingOptions parsingOptions;
-
- AstBuilder(ParsingOptions parsingOptions)
- {
- this.parsingOptions = requireNonNull(parsingOptions, "parsingOptions is null");
- }
-
- @Override
- public Node visitSingleStatement(SqlBaseParser.SingleStatementContext context)
- {
- return visit(context.statement());
- }
-
- @Override
- public Node visitStandaloneExpression(SqlBaseParser.StandaloneExpressionContext context)
- {
- return visit(context.expression());
- }
-
- @Override
- public Node visitStandaloneType(SqlBaseParser.StandaloneTypeContext context)
- {
- return visit(context.type());
- }
-
- @Override
- public Node visitStandalonePathSpecification(SqlBaseParser.StandalonePathSpecificationContext context)
- {
- return visit(context.pathSpecification());
- }
-
- @Override
- public Node visitStandaloneRowPattern(SqlBaseParser.StandaloneRowPatternContext context)
- {
- return visit(context.rowPattern());
- }
-
- // ******************* statements **********************
-
- @Override
- public Node visitUse(SqlBaseParser.UseContext context)
- {
- return new Use(
- getLocation(context),
- visitIfPresent(context.catalog, Identifier.class),
- (Identifier) visit(context.schema));
- }
-
- @Override
- public Node visitCreateSchema(SqlBaseParser.CreateSchemaContext context)
- {
- Optional principal = Optional.empty();
- if (context.AUTHORIZATION() != null) {
- principal = Optional.of(getPrincipalSpecification(context.principal()));
- }
-
- List properties = ImmutableList.of();
- if (context.properties() != null) {
- properties = visit(context.properties().propertyAssignments().property(), Property.class);
- }
-
- return new CreateSchema(
- getLocation(context),
- getQualifiedName(context.qualifiedName()),
- context.EXISTS() != null,
- properties,
- principal);
- }
-
- @Override
- public Node visitDropSchema(SqlBaseParser.DropSchemaContext context)
- {
- return new DropSchema(
- getLocation(context),
- getQualifiedName(context.qualifiedName()),
- context.EXISTS() != null,
- context.CASCADE() != null);
- }
-
- @Override
- public Node visitRenameSchema(SqlBaseParser.RenameSchemaContext context)
- {
- return new RenameSchema(
- getLocation(context),
- getQualifiedName(context.qualifiedName()),
- (Identifier) visit(context.identifier()));
- }
-
- @Override
- public Node visitSetSchemaAuthorization(SqlBaseParser.SetSchemaAuthorizationContext context)
- {
- return new SetSchemaAuthorization(
- getLocation(context),
- getQualifiedName(context.qualifiedName()),
- getPrincipalSpecification(context.principal()));
- }
-
- @Override
- public Node visitCreateTableAsSelect(SqlBaseParser.CreateTableAsSelectContext context)
- {
- Optional comment = Optional.empty();
- if (context.COMMENT() != null) {
- comment = Optional.of(((StringLiteral) visit(context.string())).getValue());
- }
-
- Optional> columnAliases = Optional.empty();
- if (context.columnAliases() != null) {
- columnAliases = Optional.of(visit(context.columnAliases().identifier(), Identifier.class));
- }
-
- List properties = ImmutableList.of();
- if (context.properties() != null) {
- properties = visit(context.properties().propertyAssignments().property(), Property.class);
- }
-
- return new CreateTableAsSelect(
- getLocation(context),
- getQualifiedName(context.qualifiedName()),
- (Query) visit(context.query()),
- context.EXISTS() != null,
- properties,
- context.NO() == null,
- columnAliases,
- comment);
- }
-
- @Override
- public Node visitCreateTable(SqlBaseParser.CreateTableContext context)
- {
- Optional comment = Optional.empty();
- if (context.COMMENT() != null) {
- comment = Optional.of(((StringLiteral) visit(context.string())).getValue());
- }
- List properties = ImmutableList.of();
- if (context.properties() != null) {
- properties = visit(context.properties().propertyAssignments().property(), Property.class);
- }
- return new CreateTable(
- getLocation(context),
- getQualifiedName(context.qualifiedName()),
- visit(context.tableElement(), TableElement.class),
- context.EXISTS() != null,
- properties,
- comment);
- }
-
- @Override
- public Node visitCreateMaterializedView(SqlBaseParser.CreateMaterializedViewContext context)
- {
- Optional comment = Optional.empty();
- if (context.COMMENT() != null) {
- comment = Optional.of(((StringLiteral) visit(context.string())).getValue());
- }
-
- List properties = ImmutableList.of();
- if (context.properties() != null) {
- properties = visit(context.properties().propertyAssignments().property(), Property.class);
- }
-
- return new CreateMaterializedView(
- Optional.of(getLocation(context)),
- getQualifiedName(context.qualifiedName()),
- (Query) visit(context.query()),
- context.REPLACE() != null,
- context.EXISTS() != null,
- properties,
- comment);
- }
-
- @Override
- public Node visitRefreshMaterializedView(SqlBaseParser.RefreshMaterializedViewContext context)
- {
- return new RefreshMaterializedView(
- Optional.of(getLocation(context)),
- new Table(getQualifiedName(context.qualifiedName())));
- }
-
- @Override
- public Node visitDropMaterializedView(SqlBaseParser.DropMaterializedViewContext context)
- {
- return new DropMaterializedView(
- getLocation(context), getQualifiedName(context.qualifiedName()), context.EXISTS() != null);
- }
-
- @Override
- public Node visitShowCreateTable(SqlBaseParser.ShowCreateTableContext context)
- {
- return new ShowCreate(getLocation(context), ShowCreate.Type.TABLE, getQualifiedName(context.qualifiedName()));
- }
-
- @Override
- public Node visitDropTable(SqlBaseParser.DropTableContext context)
- {
- return new DropTable(getLocation(context), getQualifiedName(context.qualifiedName()), context.EXISTS() != null);
- }
-
- @Override
- public Node visitDropView(SqlBaseParser.DropViewContext context)
- {
- return new DropView(getLocation(context), getQualifiedName(context.qualifiedName()), context.EXISTS() != null);
- }
-
- @Override
- public Node visitInsertInto(SqlBaseParser.InsertIntoContext context)
- {
- Optional> columnAliases = Optional.empty();
- if (context.columnAliases() != null) {
- columnAliases = Optional.of(visit(context.columnAliases().identifier(), Identifier.class));
- }
-
- return new Insert(
- new Table(getQualifiedName(context.qualifiedName())),
- columnAliases,
- (Query) visit(context.query()));
- }
-
- @Override
- public Node visitDelete(SqlBaseParser.DeleteContext context)
- {
- return new Delete(
- getLocation(context),
- new Table(getLocation(context), getQualifiedName(context.qualifiedName())),
- visitIfPresent(context.booleanExpression(), Expression.class));
- }
-
- @Override
- public Node visitUpdate(SqlBaseParser.UpdateContext context)
- {
- return new Update(
- getLocation(context),
- new Table(getLocation(context), getQualifiedName(context.qualifiedName())),
- visit(context.updateAssignment(), UpdateAssignment.class),
- visitIfPresent(context.booleanExpression(), Expression.class));
- }
-
- @Override
- public Node visitUpdateAssignment(SqlBaseParser.UpdateAssignmentContext context)
- {
- return new UpdateAssignment((Identifier) visit(context.identifier()), (Expression) visit(context.expression()));
- }
-
- @Override
- public Node visitTruncateTable(SqlBaseParser.TruncateTableContext context)
- {
- return new TruncateTable(getLocation(context), getQualifiedName(context.qualifiedName()));
- }
-
- @Override
- public Node visitMerge(SqlBaseParser.MergeContext context)
- {
- return new Merge(
- getLocation(context),
- new Table(getLocation(context), getQualifiedName(context.qualifiedName())),
- visitIfPresent(context.identifier(), Identifier.class),
- (Relation) visit(context.relation()),
- (Expression) visit(context.expression()),
- visit(context.mergeCase(), MergeCase.class));
- }
-
- @Override
- public Node visitMergeInsert(SqlBaseParser.MergeInsertContext context)
- {
- return new MergeInsert(
- getLocation(context),
- visitIfPresent(context.condition, Expression.class),
- visitIdentifiers(context.targets),
- visit(context.values, Expression.class));
- }
-
- private List visitIdentifiers(List identifiers)
- {
- return identifiers.stream()
- .map(identifier -> (Identifier) visit(identifier))
- .collect(toImmutableList());
- }
-
- @Override
- public Node visitMergeUpdate(SqlBaseParser.MergeUpdateContext context)
- {
- ImmutableList.Builder assignments = ImmutableList.builder();
- for (int i = 0; i < context.targets.size(); i++) {
- assignments.add(new MergeUpdate.Assignment(
- (Identifier) visit(context.targets.get(i)),
- (Expression) visit(context.values.get(i))));
- }
-
- return new MergeUpdate(getLocation(context), visitIfPresent(context.condition, Expression.class), assignments.build());
- }
-
- @Override
- public Node visitMergeDelete(SqlBaseParser.MergeDeleteContext context)
- {
- return new MergeDelete(getLocation(context), visitIfPresent(context.condition, Expression.class));
- }
-
- @Override
- public Node visitRenameTable(SqlBaseParser.RenameTableContext context)
- {
- return new RenameTable(getLocation(context), getQualifiedName(context.from), getQualifiedName(context.to), context.EXISTS() != null);
- }
-
- @Override
- public Node visitSetTableProperties(SqlBaseParser.SetTablePropertiesContext context)
- {
- List properties = ImmutableList.of();
- if (context.propertyAssignments() != null) {
- properties = visit(context.propertyAssignments().property(), Property.class);
- }
-
- return new SetProperties(getLocation(context), SetProperties.Type.TABLE, getQualifiedName(context.qualifiedName()), properties);
- }
-
- @Override
- public Node visitCommentTable(SqlBaseParser.CommentTableContext context)
- {
- Optional comment = Optional.empty();
-
- if (context.string() != null) {
- comment = Optional.of(((StringLiteral) visit(context.string())).getValue());
- }
-
- return new Comment(getLocation(context), Comment.Type.TABLE, getQualifiedName(context.qualifiedName()), comment);
- }
-
- @Override
- public Node visitCommentColumn(SqlBaseParser.CommentColumnContext context)
- {
- Optional comment = Optional.empty();
-
- if (context.string() != null) {
- comment = Optional.of(((StringLiteral) visit(context.string())).getValue());
- }
-
- return new Comment(getLocation(context), Comment.Type.COLUMN, getQualifiedName(context.qualifiedName()), comment);
- }
-
- @Override
- public Node visitRenameColumn(SqlBaseParser.RenameColumnContext context)
- {
- return new RenameColumn(
- getLocation(context),
- getQualifiedName(context.tableName),
- (Identifier) visit(context.from),
- (Identifier) visit(context.to),
- context.EXISTS().stream().anyMatch(node -> node.getSymbol().getTokenIndex() < context.COLUMN().getSymbol().getTokenIndex()),
- context.EXISTS().stream().anyMatch(node -> node.getSymbol().getTokenIndex() > context.COLUMN().getSymbol().getTokenIndex()));
- }
-
- @Override
- public Node visitAnalyze(SqlBaseParser.AnalyzeContext context)
- {
- List properties = ImmutableList.of();
- if (context.properties() != null) {
- properties = visit(context.properties().propertyAssignments().property(), Property.class);
- }
- return new Analyze(
- getLocation(context),
- getQualifiedName(context.qualifiedName()),
- properties);
- }
-
- @Override
- public Node visitAddColumn(SqlBaseParser.AddColumnContext context)
- {
- return new AddColumn(getLocation(context),
- getQualifiedName(context.qualifiedName()),
- (ColumnDefinition) visit(context.columnDefinition()),
- context.EXISTS().stream().anyMatch(node -> node.getSymbol().getTokenIndex() < context.COLUMN().getSymbol().getTokenIndex()),
- context.EXISTS().stream().anyMatch(node -> node.getSymbol().getTokenIndex() > context.COLUMN().getSymbol().getTokenIndex()));
- }
-
- @Override
- public Node visitSetTableAuthorization(SqlBaseParser.SetTableAuthorizationContext context)
- {
- return new SetTableAuthorization(
- getLocation(context),
- getQualifiedName(context.qualifiedName()),
- getPrincipalSpecification(context.principal()));
- }
-
- @Override
- public Node visitDropColumn(SqlBaseParser.DropColumnContext context)
- {
- return new DropColumn(getLocation(context),
- getQualifiedName(context.tableName),
- (Identifier) visit(context.column),
- context.EXISTS().stream().anyMatch(node -> node.getSymbol().getTokenIndex() < context.COLUMN().getSymbol().getTokenIndex()),
- context.EXISTS().stream().anyMatch(node -> node.getSymbol().getTokenIndex() > context.COLUMN().getSymbol().getTokenIndex()));
- }
-
- @Override
- public Node visitTableExecute(SqlBaseParser.TableExecuteContext context)
- {
- List arguments = ImmutableList.of();
- if (context.callArgument() != null) {
- arguments = this.visit(context.callArgument(), CallArgument.class);
- }
-
- return new TableExecute(
- new Table(getLocation(context), getQualifiedName(context.tableName)),
- (Identifier) visit(context.procedureName),
- arguments,
- visitIfPresent(context.booleanExpression(), Expression.class));
- }
-
- @Override
- public Node visitCreateView(SqlBaseParser.CreateViewContext context)
- {
- Optional comment = Optional.empty();
- if (context.COMMENT() != null) {
- comment = Optional.of(((StringLiteral) visit(context.string())).getValue());
- }
-
- Optional security = Optional.empty();
- if (context.DEFINER() != null) {
- security = Optional.of(CreateView.Security.DEFINER);
- }
- else if (context.INVOKER() != null) {
- security = Optional.of(CreateView.Security.INVOKER);
- }
-
- return new CreateView(
- getLocation(context),
- getQualifiedName(context.qualifiedName()),
- (Query) visit(context.query()),
- context.REPLACE() != null,
- comment,
- security);
- }
-
- @Override
- public Node visitRenameView(SqlBaseParser.RenameViewContext context)
- {
- return new RenameView(getLocation(context), getQualifiedName(context.from), getQualifiedName(context.to));
- }
-
- @Override
- public Node visitRenameMaterializedView(SqlBaseParser.RenameMaterializedViewContext context)
- {
- return new RenameMaterializedView(getLocation(context), getQualifiedName(context.from), getQualifiedName(context.to), context.EXISTS() != null);
- }
-
- @Override
- public Node visitSetViewAuthorization(SqlBaseParser.SetViewAuthorizationContext context)
- {
- return new SetViewAuthorization(
- getLocation(context),
- getQualifiedName(context.qualifiedName()),
- getPrincipalSpecification(context.principal()));
- }
-
- @Override
- public Node visitSetMaterializedViewProperties(SqlBaseParser.SetMaterializedViewPropertiesContext context)
- {
- return new SetProperties(
- getLocation(context),
- SetProperties.Type.MATERIALIZED_VIEW,
- getQualifiedName(context.qualifiedName()),
- visit(context.propertyAssignments().property(), Property.class));
- }
-
- @Override
- public Node visitStartTransaction(SqlBaseParser.StartTransactionContext context)
- {
- return new StartTransaction(visit(context.transactionMode(), TransactionMode.class));
- }
-
- @Override
- public Node visitCommit(SqlBaseParser.CommitContext context)
- {
- return new Commit(getLocation(context));
- }
-
- @Override
- public Node visitRollback(SqlBaseParser.RollbackContext context)
- {
- return new Rollback(getLocation(context));
- }
-
- @Override
- public Node visitTransactionAccessMode(SqlBaseParser.TransactionAccessModeContext context)
- {
- return new TransactionAccessMode(getLocation(context), context.accessMode.getType() == SqlBaseLexer.ONLY);
- }
-
- @Override
- public Node visitIsolationLevel(SqlBaseParser.IsolationLevelContext context)
- {
- return visit(context.levelOfIsolation());
- }
-
- @Override
- public Node visitReadUncommitted(SqlBaseParser.ReadUncommittedContext context)
- {
- return new Isolation(getLocation(context), Isolation.Level.READ_UNCOMMITTED);
- }
-
- @Override
- public Node visitReadCommitted(SqlBaseParser.ReadCommittedContext context)
- {
- return new Isolation(getLocation(context), Isolation.Level.READ_COMMITTED);
- }
-
- @Override
- public Node visitRepeatableRead(SqlBaseParser.RepeatableReadContext context)
- {
- return new Isolation(getLocation(context), Isolation.Level.REPEATABLE_READ);
- }
-
- @Override
- public Node visitSerializable(SqlBaseParser.SerializableContext context)
- {
- return new Isolation(getLocation(context), Isolation.Level.SERIALIZABLE);
- }
-
- @Override
- public Node visitCall(SqlBaseParser.CallContext context)
- {
- return new Call(
- getLocation(context),
- getQualifiedName(context.qualifiedName()),
- visit(context.callArgument(), CallArgument.class));
- }
-
- @Override
- public Node visitPrepare(SqlBaseParser.PrepareContext context)
- {
- return new Prepare(
- getLocation(context),
- (Identifier) visit(context.identifier()),
- (Statement) visit(context.statement()));
- }
-
- @Override
- public Node visitDeallocate(SqlBaseParser.DeallocateContext context)
- {
- return new Deallocate(
- getLocation(context),
- (Identifier) visit(context.identifier()));
- }
-
- @Override
- public Node visitExecute(SqlBaseParser.ExecuteContext context)
- {
- return new Execute(
- getLocation(context),
- (Identifier) visit(context.identifier()),
- visit(context.expression(), Expression.class));
- }
-
- @Override
- public Node visitDescribeOutput(SqlBaseParser.DescribeOutputContext context)
- {
- return new DescribeOutput(
- getLocation(context),
- (Identifier) visit(context.identifier()));
- }
-
- @Override
- public Node visitDescribeInput(SqlBaseParser.DescribeInputContext context)
- {
- return new DescribeInput(
- getLocation(context),
- (Identifier) visit(context.identifier()));
- }
-
- @Override
- public Node visitProperty(SqlBaseParser.PropertyContext context)
- {
- NodeLocation location = getLocation(context);
- Identifier name = (Identifier) visit(context.identifier());
- SqlBaseParser.PropertyValueContext valueContext = context.propertyValue();
- if (valueContext instanceof SqlBaseParser.DefaultPropertyValueContext) {
- return new Property(location, name);
- }
- Expression value = (Expression) visit(((SqlBaseParser.NonDefaultPropertyValueContext) valueContext).expression());
- return new Property(location, name, value);
- }
-
- // pg syntax
- @Override
- public Node visitDeclareCursor(SqlBaseParser.DeclareCursorContext ctx)
- {
- NodeLocation location = getLocation(ctx);
- Identifier name = (Identifier) visit(ctx.name);
- Query body = (Query) visit(ctx.body);
- return new Declare(location, name, body);
- }
-
- // pg syntax
- @Override
- public Node visitFetchCursor(SqlBaseParser.FetchCursorContext ctx)
- {
- NodeLocation location = getLocation(ctx);
- Integer rowCount = Integer.parseInt(ctx.row.getText());
- Identifier cursor = (Identifier) visit(ctx.cursor);
- return new FetchCursor(location, rowCount, cursor);
- }
-
- // added by canner
- @Override
- public Node visitImpersonateUser(SqlBaseParser.ImpersonateUserContext ctx)
- {
- return new ImpersonateUser(getLocation(ctx), (Expression) visit(ctx.expression()));
- }
-
- // ********************** query expressions ********************
-
- @Override
- public Node visitQuery(SqlBaseParser.QueryContext context)
- {
- Query body = (Query) visit(context.queryNoWith());
-
- return new Query(
- getLocation(context),
- visitIfPresent(context.with(), With.class),
- body.getQueryBody(),
- body.getOrderBy(),
- body.getOffset(),
- body.getLimit());
- }
-
- @Override
- public Node visitWith(SqlBaseParser.WithContext context)
- {
- return new With(getLocation(context), context.RECURSIVE() != null, visit(context.namedQuery(), WithQuery.class));
- }
-
- @Override
- public Node visitNamedQuery(SqlBaseParser.NamedQueryContext context)
- {
- Optional> columns = Optional.empty();
- if (context.columnAliases() != null) {
- columns = Optional.of(visit(context.columnAliases().identifier(), Identifier.class));
- }
-
- return new WithQuery(
- getLocation(context),
- (Identifier) visit(context.name),
- (Query) visit(context.query()),
- columns);
- }
-
- @Override
- public Node visitQueryNoWith(SqlBaseParser.QueryNoWithContext context)
- {
- QueryBody term = (QueryBody) visit(context.queryTerm());
-
- Optional orderBy = Optional.empty();
- if (context.ORDER() != null) {
- orderBy = Optional.of(new OrderBy(getLocation(context.ORDER()), visit(context.sortItem(), SortItem.class)));
- }
-
- Optional offset = Optional.empty();
- if (context.OFFSET() != null) {
- Expression rowCount;
- if (context.offset.INTEGER_VALUE() != null) {
- rowCount = new LongLiteral(getLocation(context.offset.INTEGER_VALUE()), context.offset.getText());
- }
- else {
- rowCount = new Parameter(getLocation(context.offset.QUESTION_MARK()), parameterPosition);
- parameterPosition++;
- }
- offset = Optional.of(new Offset(Optional.of(getLocation(context.OFFSET())), rowCount));
- }
-
- Optional limit = Optional.empty();
- if (context.FETCH() != null) {
- Optional rowCount = Optional.empty();
- if (context.fetchFirst != null) {
- if (context.fetchFirst.INTEGER_VALUE() != null) {
- rowCount = Optional.of(new LongLiteral(getLocation(context.fetchFirst.INTEGER_VALUE()), context.fetchFirst.getText()));
- }
- else {
- rowCount = Optional.of(new Parameter(getLocation(context.fetchFirst.QUESTION_MARK()), parameterPosition));
- parameterPosition++;
- }
- }
- limit = Optional.of(new FetchFirst(Optional.of(getLocation(context.FETCH())), rowCount, context.TIES() != null));
- }
- else if (context.LIMIT() != null) {
- if (context.limit == null) {
- throw new IllegalStateException("Missing LIMIT value");
- }
- Expression rowCount;
- if (context.limit.ALL() != null) {
- rowCount = new AllRows(getLocation(context.limit.ALL()));
- }
- else if (context.limit.string() != null) {
- // for pg style limit clause
- StringLiteral literal = (StringLiteral) visit(context.limit.string());
- rowCount = new LongLiteral(literal.getLocation().get(), literal.getValue());
- }
- else if (context.limit.rowCount().INTEGER_VALUE() != null) {
- rowCount = new LongLiteral(getLocation(context.limit.rowCount().INTEGER_VALUE()), context.limit.getText());
- }
- else {
- rowCount = new Parameter(getLocation(context.limit.rowCount().QUESTION_MARK()), parameterPosition);
- parameterPosition++;
- }
-
- limit = Optional.of(new Limit(Optional.of(getLocation(context.LIMIT())), rowCount));
- }
-
- if (term instanceof QuerySpecification) {
- // When we have a simple query specification
- // followed by order by, offset, limit or fetch,
- // fold the order by, limit, offset or fetch clauses
- // into the query specification (analyzer/planner
- // expects this structure to resolve references with respect
- // to columns defined in the query specification)
- QuerySpecification query = (QuerySpecification) term;
-
- return new Query(
- getLocation(context),
- Optional.empty(),
- new QuerySpecification(
- getLocation(context),
- query.getSelect(),
- query.getFrom(),
- query.getWhere(),
- query.getGroupBy(),
- query.getHaving(),
- query.getWindows(),
- orderBy,
- offset,
- limit),
- Optional.empty(),
- Optional.empty(),
- Optional.empty());
- }
-
- return new Query(
- getLocation(context),
- Optional.empty(),
- term,
- orderBy,
- offset,
- limit);
- }
-
- @Override
- public Node visitQuerySpecification(SqlBaseParser.QuerySpecificationContext context)
- {
- Optional from = Optional.empty();
- List selectItems = visit(context.selectItem(), SelectItem.class);
-
- List relations = visit(context.relation(), Relation.class);
- if (!relations.isEmpty()) {
- // synthesize implicit join nodes
- Iterator iterator = relations.iterator();
- Relation relation = iterator.next();
-
- while (iterator.hasNext()) {
- relation = new Join(getLocation(context), Join.Type.IMPLICIT, relation, iterator.next(), Optional.empty());
- }
-
- from = Optional.of(relation);
- }
-
- return new QuerySpecification(
- getLocation(context),
- new Select(getLocation(context.SELECT()), isDistinct(context.setQuantifier()), selectItems),
- from,
- visitIfPresent(context.where, Expression.class),
- visitIfPresent(context.groupBy(), GroupBy.class),
- visitIfPresent(context.having, Expression.class),
- visit(context.windowDefinition(), WindowDefinition.class),
- Optional.empty(),
- Optional.empty(),
- Optional.empty());
- }
-
- @Override
- public Node visitGroupBy(SqlBaseParser.GroupByContext context)
- {
- return new GroupBy(getLocation(context), isDistinct(context.setQuantifier()), visit(context.groupingElement(), GroupingElement.class));
- }
-
- @Override
- public Node visitSingleGroupingSet(SqlBaseParser.SingleGroupingSetContext context)
- {
- return new SimpleGroupBy(getLocation(context), visit(context.groupingSet().expression(), Expression.class));
- }
-
- @Override
- public Node visitRollup(SqlBaseParser.RollupContext context)
- {
- return new Rollup(getLocation(context), visit(context.expression(), Expression.class));
- }
-
- @Override
- public Node visitCube(SqlBaseParser.CubeContext context)
- {
- return new Cube(getLocation(context), visit(context.expression(), Expression.class));
- }
-
- @Override
- public Node visitMultipleGroupingSets(SqlBaseParser.MultipleGroupingSetsContext context)
- {
- return new GroupingSets(getLocation(context), context.groupingSet().stream()
- .map(groupingSet -> visit(groupingSet.expression(), Expression.class))
- .collect(toList()));
- }
-
- @Override
- public Node visitWindowSpecification(SqlBaseParser.WindowSpecificationContext context)
- {
- Optional orderBy = Optional.empty();
- if (context.ORDER() != null) {
- orderBy = Optional.of(new OrderBy(getLocation(context.ORDER()), visit(context.sortItem(), SortItem.class)));
- }
-
- return new WindowSpecification(
- getLocation(context),
- visitIfPresent(context.existingWindowName, Identifier.class),
- visit(context.partition, Expression.class),
- orderBy,
- visitIfPresent(context.windowFrame(), WindowFrame.class));
- }
-
- @Override
- public Node visitWindowDefinition(SqlBaseParser.WindowDefinitionContext context)
- {
- return new WindowDefinition(
- getLocation(context),
- (Identifier) visit(context.name),
- (WindowSpecification) visit(context.windowSpecification()));
- }
-
- @Override
- public Node visitSetOperation(SqlBaseParser.SetOperationContext context)
- {
- QueryBody left = (QueryBody) visit(context.left);
- QueryBody right = (QueryBody) visit(context.right);
-
- boolean distinct = context.setQuantifier() == null || context.setQuantifier().DISTINCT() != null;
-
- switch (context.operator.getType()) {
- case SqlBaseLexer.UNION:
- return new Union(getLocation(context.UNION()), ImmutableList.of(left, right), distinct);
- case SqlBaseLexer.INTERSECT:
- return new Intersect(getLocation(context.INTERSECT()), ImmutableList.of(left, right), distinct);
- case SqlBaseLexer.EXCEPT:
- return new Except(getLocation(context.EXCEPT()), left, right, distinct);
- }
-
- throw new IllegalArgumentException("Unsupported set operation: " + context.operator.getText());
- }
-
- @Override
- public Node visitSelectAll(SqlBaseParser.SelectAllContext context)
- {
- List aliases = ImmutableList.of();
- if (context.columnAliases() != null) {
- aliases = visit(context.columnAliases().identifier(), Identifier.class);
- }
-
- return new AllColumns(
- getLocation(context),
- visitIfPresent(context.primaryExpression(), Expression.class),
- aliases);
- }
-
- @Override
- public Node visitSelectSingle(SqlBaseParser.SelectSingleContext context)
- {
- return new SingleColumn(
- getLocation(context),
- (Expression) visit(context.expression()),
- visitIfPresent(context.identifier(), Identifier.class));
- }
-
- @Override
- public Node visitTable(SqlBaseParser.TableContext context)
- {
- return new Table(getLocation(context), getQualifiedName(context.qualifiedName()));
- }
-
- @Override
- public Node visitSubquery(SqlBaseParser.SubqueryContext context)
- {
- return new TableSubquery(getLocation(context), (Query) visit(context.queryNoWith()));
- }
-
- @Override
- public Node visitInlineTable(SqlBaseParser.InlineTableContext context)
- {
- return new Values(getLocation(context), visit(context.expression(), Expression.class));
- }
-
- @Override
- public Node visitExplain(SqlBaseParser.ExplainContext context)
- {
- return new Explain(getLocation(context), (Statement) visit(context.statement()), visit(context.explainOption(), ExplainOption.class));
- }
-
- @Override
- public Node visitExplainAnalyze(SqlBaseParser.ExplainAnalyzeContext context)
- {
- return new ExplainAnalyze(getLocation(context), context.VERBOSE() != null, (Statement) visit(context.statement()));
- }
-
- @Override
- public Node visitExplainFormat(SqlBaseParser.ExplainFormatContext context)
- {
- switch (context.value.getType()) {
- case SqlBaseLexer.GRAPHVIZ:
- return new ExplainFormat(getLocation(context), ExplainFormat.Type.GRAPHVIZ);
- case SqlBaseLexer.TEXT:
- return new ExplainFormat(getLocation(context), ExplainFormat.Type.TEXT);
- case SqlBaseLexer.JSON:
- return new ExplainFormat(getLocation(context), ExplainFormat.Type.JSON);
- }
-
- throw new IllegalArgumentException("Unsupported EXPLAIN format: " + context.value.getText());
- }
-
- @Override
- public Node visitExplainType(SqlBaseParser.ExplainTypeContext context)
- {
- switch (context.value.getType()) {
- case SqlBaseLexer.LOGICAL:
- return new ExplainType(getLocation(context), ExplainType.Type.LOGICAL);
- case SqlBaseLexer.DISTRIBUTED:
- return new ExplainType(getLocation(context), ExplainType.Type.DISTRIBUTED);
- case SqlBaseLexer.VALIDATE:
- return new ExplainType(getLocation(context), ExplainType.Type.VALIDATE);
- case SqlBaseLexer.IO:
- return new ExplainType(getLocation(context), ExplainType.Type.IO);
- }
-
- throw new IllegalArgumentException("Unsupported EXPLAIN type: " + context.value.getText());
- }
-
- @Override
- public Node visitShowTables(SqlBaseParser.ShowTablesContext context)
- {
- return new ShowTables(
- getLocation(context),
- Optional.ofNullable(context.qualifiedName())
- .map(this::getQualifiedName),
- getTextIfPresent(context.pattern)
- .map(AstBuilder::unquote),
- getTextIfPresent(context.escape)
- .map(AstBuilder::unquote));
- }
-
- @Override
- public Node visitShowSchemas(SqlBaseParser.ShowSchemasContext context)
- {
- return new ShowSchemas(
- getLocation(context),
- visitIfPresent(context.identifier(), Identifier.class),
- getTextIfPresent(context.pattern)
- .map(AstBuilder::unquote),
- getTextIfPresent(context.escape)
- .map(AstBuilder::unquote));
- }
-
- @Override
- public Node visitShowCatalogs(SqlBaseParser.ShowCatalogsContext context)
- {
- return new ShowCatalogs(getLocation(context),
- getTextIfPresent(context.pattern)
- .map(AstBuilder::unquote),
- getTextIfPresent(context.escape)
- .map(AstBuilder::unquote));
- }
-
- @Override
- public Node visitShowColumns(SqlBaseParser.ShowColumnsContext context)
- {
- return new ShowColumns(
- getLocation(context),
- getQualifiedName(context.qualifiedName()),
- getTextIfPresent(context.pattern)
- .map(AstBuilder::unquote),
- getTextIfPresent(context.escape)
- .map(AstBuilder::unquote));
- }
-
- @Override
- public Node visitShowStats(SqlBaseParser.ShowStatsContext context)
- {
- return new ShowStats(Optional.of(getLocation(context)), new Table(getQualifiedName(context.qualifiedName())));
- }
-
- @Override
- public Node visitShowStatsForQuery(SqlBaseParser.ShowStatsForQueryContext context)
- {
- Query query = (Query) visit(context.query());
- return new ShowStats(Optional.of(getLocation(context)), new TableSubquery(query));
- }
-
- @Override
- public Node visitShowCreateSchema(SqlBaseParser.ShowCreateSchemaContext context)
- {
- return new ShowCreate(getLocation(context), ShowCreate.Type.SCHEMA, getQualifiedName(context.qualifiedName()));
- }
-
- @Override
- public Node visitShowCreateView(SqlBaseParser.ShowCreateViewContext context)
- {
- return new ShowCreate(getLocation(context), ShowCreate.Type.VIEW, getQualifiedName(context.qualifiedName()));
- }
-
- @Override
- public Node visitShowCreateMaterializedView(SqlBaseParser.ShowCreateMaterializedViewContext context)
- {
- return new ShowCreate(getLocation(context), ShowCreate.Type.MATERIALIZED_VIEW, getQualifiedName(context.qualifiedName()));
- }
-
- @Override
- public Node visitShowFunctions(SqlBaseParser.ShowFunctionsContext context)
- {
- return new ShowFunctions(getLocation(context),
- getTextIfPresent(context.pattern)
- .map(AstBuilder::unquote),
- getTextIfPresent(context.escape)
- .map(AstBuilder::unquote));
- }
-
- @Override
- public Node visitShowSession(SqlBaseParser.ShowSessionContext context)
- {
- return new ShowSession(getLocation(context),
- getTextIfPresent(context.pattern)
- .map(AstBuilder::unquote),
- getTextIfPresent(context.escape)
- .map(AstBuilder::unquote));
- }
-
- @Override
- public Node visitSetSession(SqlBaseParser.SetSessionContext context)
- {
- return new SetSession(getLocation(context), getQualifiedName(context.qualifiedName()), (Expression) visit(context.expression()));
- }
-
- @Override
- public Node visitResetSession(SqlBaseParser.ResetSessionContext context)
- {
- return new ResetSession(getLocation(context), getQualifiedName(context.qualifiedName()));
- }
-
- @Override
- public Node visitCreateRole(SqlBaseParser.CreateRoleContext context)
- {
- return new CreateRole(
- getLocation(context),
- (Identifier) visit(context.name),
- getGrantorSpecificationIfPresent(context.grantor()),
- visitIfPresent(context.catalog, Identifier.class));
- }
-
- @Override
- public Node visitDropRole(SqlBaseParser.DropRoleContext context)
- {
- return new DropRole(
- getLocation(context),
- (Identifier) visit(context.name),
- visitIfPresent(context.catalog, Identifier.class));
- }
-
- @Override
- public Node visitGrantRoles(SqlBaseParser.GrantRolesContext context)
- {
- return new GrantRoles(
- getLocation(context),
- ImmutableSet.copyOf(getIdentifiers(context.roles().identifier())),
- ImmutableSet.copyOf(getPrincipalSpecifications(context.principal())),
- context.OPTION() != null,
- getGrantorSpecificationIfPresent(context.grantor()),
- visitIfPresent(context.catalog, Identifier.class));
- }
-
- @Override
- public Node visitRevokeRoles(SqlBaseParser.RevokeRolesContext context)
- {
- return new RevokeRoles(
- getLocation(context),
- ImmutableSet.copyOf(getIdentifiers(context.roles().identifier())),
- ImmutableSet.copyOf(getPrincipalSpecifications(context.principal())),
- context.OPTION() != null,
- getGrantorSpecificationIfPresent(context.grantor()),
- visitIfPresent(context.catalog, Identifier.class));
- }
-
- @Override
- public Node visitSetRole(SqlBaseParser.SetRoleContext context)
- {
- SetRole.Type type = SetRole.Type.ROLE;
- if (context.ALL() != null) {
- type = SetRole.Type.ALL;
- }
- else if (context.NONE() != null) {
- type = SetRole.Type.NONE;
- }
- return new SetRole(
- getLocation(context),
- type,
- getIdentifierIfPresent(context.role),
- visitIfPresent(context.catalog, Identifier.class));
- }
-
- @Override
- public Node visitGrant(SqlBaseParser.GrantContext context)
- {
- Optional> privileges;
- if (context.ALL() != null) {
- privileges = Optional.empty();
- }
- else {
- privileges = Optional.of(context.privilege().stream()
- .map(SqlBaseParser.PrivilegeContext::getText)
- .collect(toList()));
- }
-
- Optional type;
- if (context.SCHEMA() != null) {
- type = Optional.of(GrantOnType.SCHEMA);
- }
- else if (context.TABLE() != null) {
- type = Optional.of(GrantOnType.TABLE);
- }
- else {
- type = Optional.empty();
- }
-
- return new Grant(
- getLocation(context),
- privileges,
- type,
- getQualifiedName(context.qualifiedName()),
- getPrincipalSpecification(context.grantee),
- context.OPTION() != null);
- }
-
- @Override
- public Node visitDeny(SqlBaseParser.DenyContext context)
- {
- Optional> privileges;
- if (context.ALL() != null) {
- privileges = Optional.empty();
- }
- else {
- privileges = Optional.of(context.privilege().stream()
- .map(SqlBaseParser.PrivilegeContext::getText)
- .collect(toList()));
- }
-
- Optional type;
- if (context.SCHEMA() != null) {
- type = Optional.of(GrantOnType.SCHEMA);
- }
- else if (context.TABLE() != null) {
- type = Optional.of(GrantOnType.TABLE);
- }
- else {
- type = Optional.empty();
- }
-
- return new Deny(
- getLocation(context),
- privileges,
- type,
- getQualifiedName(context.qualifiedName()),
- getPrincipalSpecification(context.grantee));
- }
-
- @Override
- public Node visitRevoke(SqlBaseParser.RevokeContext context)
- {
- Optional> privileges;
- if (context.ALL() != null) {
- privileges = Optional.empty();
- }
- else {
- privileges = Optional.of(context.privilege().stream()
- .map(SqlBaseParser.PrivilegeContext::getText)
- .collect(toList()));
- }
-
- Optional type;
- if (context.SCHEMA() != null) {
- type = Optional.of(GrantOnType.SCHEMA);
- }
- else if (context.TABLE() != null) {
- type = Optional.of(GrantOnType.TABLE);
- }
- else {
- type = Optional.empty();
- }
-
- return new Revoke(
- getLocation(context),
- context.OPTION() != null,
- privileges,
- type,
- getQualifiedName(context.qualifiedName()),
- getPrincipalSpecification(context.grantee));
- }
-
- @Override
- public Node visitShowGrants(SqlBaseParser.ShowGrantsContext context)
- {
- Optional tableName = Optional.empty();
-
- if (context.qualifiedName() != null) {
- tableName = Optional.of(getQualifiedName(context.qualifiedName()));
- }
-
- return new ShowGrants(
- getLocation(context),
- context.TABLE() != null,
- tableName);
- }
-
- @Override
- public Node visitShowRoles(SqlBaseParser.ShowRolesContext context)
- {
- return new ShowRoles(
- getLocation(context),
- getIdentifierIfPresent(context.identifier()),
- context.CURRENT() != null);
- }
-
- @Override
- public Node visitShowRoleGrants(SqlBaseParser.ShowRoleGrantsContext context)
- {
- return new ShowRoleGrants(
- getLocation(context),
- getIdentifierIfPresent(context.identifier()));
- }
-
- @Override
- public Node visitSetPath(SqlBaseParser.SetPathContext context)
- {
- return new SetPath(getLocation(context), (PathSpecification) visit(context.pathSpecification()));
- }
-
- @Override
- public Node visitSetTimeZone(SqlBaseParser.SetTimeZoneContext context)
- {
- Optional timeZone = Optional.empty();
- if (context.expression() != null) {
- timeZone = Optional.of((Expression) visit(context.expression()));
- }
- return new SetTimeZone(getLocation(context), timeZone);
- }
-
- // ***************** boolean expressions ******************
-
- @Override
- public Node visitLogicalNot(SqlBaseParser.LogicalNotContext context)
- {
- return new NotExpression(getLocation(context), (Expression) visit(context.booleanExpression()));
- }
-
- @Override
- public Node visitOr(SqlBaseParser.OrContext context)
- {
- List terms = flatten(context, element -> {
- if (element instanceof SqlBaseParser.OrContext) {
- SqlBaseParser.OrContext or = (SqlBaseParser.OrContext) element;
- return Optional.of(or.booleanExpression());
- }
-
- return Optional.empty();
- });
-
- return new LogicalExpression(getLocation(context), LogicalExpression.Operator.OR, visit(terms, Expression.class));
- }
-
- @Override
- public Node visitAnd(SqlBaseParser.AndContext context)
- {
- List terms = flatten(context, element -> {
- if (element instanceof SqlBaseParser.AndContext) {
- SqlBaseParser.AndContext and = (SqlBaseParser.AndContext) element;
- return Optional.of(and.booleanExpression());
- }
-
- return Optional.empty();
- });
-
- return new LogicalExpression(getLocation(context), LogicalExpression.Operator.AND, visit(terms, Expression.class));
- }
-
- private static List flatten(ParserRuleContext root, Function>> extractChildren)
- {
- List result = new ArrayList<>();
- Deque pending = new ArrayDeque<>();
- pending.push(root);
-
- while (!pending.isEmpty()) {
- ParserRuleContext next = pending.pop();
-
- Optional> children = extractChildren.apply(next);
- if (!children.isPresent()) {
- result.add(next);
- }
- else {
- for (int i = children.get().size() - 1; i >= 0; i--) {
- pending.push(children.get().get(i));
- }
- }
- }
-
- return result;
- }
-
- // *************** from clause *****************
-
- @Override
- public Node visitJoinRelation(SqlBaseParser.JoinRelationContext context)
- {
- Relation left = (Relation) visit(context.left);
- Relation right;
-
- if (context.CROSS() != null) {
- right = (Relation) visit(context.right);
- return new Join(getLocation(context), Join.Type.CROSS, left, right, Optional.empty());
- }
-
- JoinCriteria criteria;
- if (context.NATURAL() != null) {
- right = (Relation) visit(context.right);
- criteria = new NaturalJoin();
- }
- else {
- right = (Relation) visit(context.rightRelation);
- if (context.joinCriteria().ON() != null) {
- criteria = new JoinOn((Expression) visit(context.joinCriteria().booleanExpression()));
- }
- else if (context.joinCriteria().USING() != null) {
- criteria = new JoinUsing(visit(context.joinCriteria().identifier(), Identifier.class));
- }
- else {
- throw new IllegalArgumentException("Unsupported join criteria");
- }
- }
-
- Join.Type joinType;
- if (context.joinType().LEFT() != null) {
- joinType = Join.Type.LEFT;
- }
- else if (context.joinType().RIGHT() != null) {
- joinType = Join.Type.RIGHT;
- }
- else if (context.joinType().FULL() != null) {
- joinType = Join.Type.FULL;
- }
- else {
- joinType = Join.Type.INNER;
- }
-
- return new Join(getLocation(context), joinType, left, right, Optional.of(criteria));
- }
-
- @Override
- public Node visitSampledRelation(SqlBaseParser.SampledRelationContext context)
- {
- Relation child = (Relation) visit(context.patternRecognition());
-
- if (context.TABLESAMPLE() == null) {
- return child;
- }
-
- return new SampledRelation(
- getLocation(context),
- child,
- getSamplingMethod((Token) context.sampleType().getChild(0).getPayload()),
- (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 = Optional.empty();
- if (context.ORDER() != null) {
- orderBy = Optional.of(new OrderBy(getLocation(context.ORDER()), visit(context.sortItem(), SortItem.class)));
- }
-
- Optional 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 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 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)
- {
- Relation child = (Relation) visit(context.relationPrimary());
-
- if (context.identifier() == null) {
- return child;
- }
-
- List aliases = null;
- if (context.columnAliases() != null) {
- aliases = visit(context.columnAliases().identifier(), Identifier.class);
- }
-
- return new AliasedRelation(getLocation(context), child, (Identifier) visit(context.identifier()), aliases);
- }
-
- @Override
- public Node visitTableName(SqlBaseParser.TableNameContext context)
- {
- if (context.queryPeriod() != null) {
- return new Table(getLocation(context), getQualifiedName(context.qualifiedName()), (QueryPeriod) visit(context.queryPeriod()));
- }
- return new Table(getLocation(context), getQualifiedName(context.qualifiedName()));
- }
-
- @Override
- public Node visitSubqueryRelation(SqlBaseParser.SubqueryRelationContext context)
- {
- return new TableSubquery(getLocation(context), (Query) visit(context.query()));
- }
-
- @Override
- public Node visitUnnest(SqlBaseParser.UnnestContext context)
- {
- checkPgSchema(context.IDENTIFIER()); // pg syntax
-
- return new Unnest(getLocation(context), visit(context.expression(), Expression.class), context.ORDINALITY() != null);
- }
-
- /**
- * postgre sql syntax
- */
- @Override
- public Node visitFunctionRelation(SqlBaseParser.FunctionRelationContext context)
- {
- QualifiedName name = getQualifiedName(context.functionExpression().qualifiedName());
-
- // wren function: metric roll_up and duckdb table function
- if (name.toString().equalsIgnoreCase("roll_up") || isDuckDBTableFunction(name.toString())) {
- List arguments = visit(context.functionExpression().expression(), Expression.class);
- return new FunctionRelation(getLocation(context), name, arguments);
- }
-
- for (PgSetReturnFunction pgSetReturnFunction : PgSetReturnFunction.values()) {
- if (name.toString().equals(pgSetReturnFunction.getPgFuncName())) {
- return new Unnest(ImmutableList.of(functionCall(pgSetReturnFunction.getRemoteFuncName(), visit(context.functionExpression().expression(), Expression.class))), false);
- }
- }
- Query query = simpleQuery(selectList(
- ImmutableList.of(functionCall(name.toString(), visit(context.functionExpression().expression(), Expression.class))),
- ImmutableList.of(name.toString())));
- return new TableSubquery(getLocation(context), query);
- }
-
- public boolean isDuckDBTableFunction(String functionName)
- {
- return DUCKDB_TABLE_FUNCTIONS.contains(functionName);
- }
-
- @Override
- public Node visitPathRelation(SqlBaseParser.PathRelationContext ctx)
- {
- return new PathRelation(Optional.of(getLocation(ctx)), ctx.string().getText());
- }
-
- @Override
- public Node visitLateral(SqlBaseParser.LateralContext context)
- {
- return new Lateral(getLocation(context), (Query) visit(context.query()));
- }
-
- @Override
- public Node visitParenthesizedRelation(SqlBaseParser.ParenthesizedRelationContext context)
- {
- return visit(context.relation());
- }
-
- // ********************* predicates *******************
-
- @Override
- public Node visitPredicated(SqlBaseParser.PredicatedContext context)
- {
- if (context.predicate() != null) {
- return visit(context.predicate());
- }
-
- return visit(context.valueExpression);
- }
-
- @Override
- public Node visitComparison(SqlBaseParser.ComparisonContext context)
- {
- checkPgSchema(context.IDENTIFIER()); // pg syntax
-
- return new ComparisonExpression(
- getLocation(context.comparisonOperator()),
- getComparisonOperator(((TerminalNode) context.comparisonOperator().getChild(0)).getSymbol()),
- (Expression) visit(context.value),
- (Expression) visit(context.right));
- }
-
- /**
- * postgre sql syntax
- */
- @Override
- public Node visitPosixComparison(SqlBaseParser.PosixComparisonContext context)
- {
- if (!isNull(context.quotedRegexMatch())) {
- checkPgSchema(context.quotedRegexMatch().IDENTIFIER());
- }
-
- Expression value = (Expression) visit(context.value);
- Expression pattern = (Expression) visit(context.pattern);
-
- List args = (isNull(context.ASTERISK())) ? // if asterisk is null, means case-sensitive.
- ImmutableList.of(value, pattern) :
- ImmutableList.of(functionCall("lower", value), functionCall("lower", pattern));
-
- Expression function = functionCall("regexp_like", args);
- return (isNull(context.NOT())) ? function : new NotExpression(getLocation(context), function);
- }
-
- @Override
- public Node visitDistinctFrom(SqlBaseParser.DistinctFromContext context)
- {
- Expression expression = new ComparisonExpression(
- getLocation(context),
- ComparisonExpression.Operator.IS_DISTINCT_FROM,
- (Expression) visit(context.value),
- (Expression) visit(context.right));
-
- if (context.NOT() != null) {
- expression = new NotExpression(getLocation(context), expression);
- }
-
- return expression;
- }
-
- @Override
- public Node visitBetween(SqlBaseParser.BetweenContext context)
- {
- Expression expression = new BetweenPredicate(
- getLocation(context),
- (Expression) visit(context.value),
- (Expression) visit(context.lower),
- (Expression) visit(context.upper));
-
- if (context.NOT() != null) {
- expression = new NotExpression(getLocation(context), expression);
- }
-
- return expression;
- }
-
- @Override
- public Node visitNullPredicate(SqlBaseParser.NullPredicateContext context)
- {
- Expression child = (Expression) visit(context.value);
-
- if (context.NOT() == null) {
- return new IsNullPredicate(getLocation(context), child);
- }
-
- return new IsNotNullPredicate(getLocation(context), child);
- }
-
- @Override
- public Node visitLike(SqlBaseParser.LikeContext context)
- {
- Expression result = new LikePredicate(
- getLocation(context),
- (Expression) visit(context.value),
- (Expression) visit(context.pattern),
- visitIfPresent(context.escape, Expression.class));
-
- if (context.NOT() != null) {
- result = new NotExpression(getLocation(context), result);
- }
-
- return result;
- }
-
- @Override
- public Node visitInList(SqlBaseParser.InListContext context)
- {
- Expression result = new InPredicate(
- getLocation(context),
- (Expression) visit(context.value),
- new InListExpression(getLocation(context), visit(context.expression(), Expression.class)));
-
- if (context.NOT() != null) {
- result = new NotExpression(getLocation(context), result);
- }
-
- return result;
- }
-
- @Override
- public Node visitInSubquery(SqlBaseParser.InSubqueryContext context)
- {
- Expression result = new InPredicate(
- getLocation(context),
- (Expression) visit(context.value),
- new SubqueryExpression(getLocation(context), (Query) visit(context.query())));
-
- if (context.NOT() != null) {
- result = new NotExpression(getLocation(context), result);
- }
-
- return result;
- }
-
- @Override
- public Node visitExists(SqlBaseParser.ExistsContext context)
- {
- return new ExistsPredicate(getLocation(context), new SubqueryExpression(getLocation(context), (Query) visit(context.query())));
- }
-
- @Override
- public Node visitQuantifiedComparison(SqlBaseParser.QuantifiedComparisonContext context)
- {
- SqlBaseParser.FunctionExpressionContext functionExpression = context.functionExpression();
- // postgre sql syntax
- if (functionExpression != null) {
- QualifiedName functionName = getQualifiedName(functionExpression.qualifiedName());
-
- Query query = simpleQuery(
- selectAll(ImmutableList.of(new AllColumns())),
- new Unnest(ImmutableList.of(functionCall(functionName.toString(), visit(functionExpression.expression(), Expression.class))), false));
-
- return new QuantifiedComparisonExpression(
- getLocation(context.comparisonOperator()),
- getComparisonOperator(((TerminalNode) context.comparisonOperator().getChild(0)).getSymbol()),
- getComparisonQuantifier(((TerminalNode) context.comparisonQuantifier().getChild(0)).getSymbol()),
- (Expression) visit(context.value),
- new SubqueryExpression(getLocation(context.functionExpression()), query));
- }
-
- return new QuantifiedComparisonExpression(
- getLocation(context.comparisonOperator()),
- getComparisonOperator(((TerminalNode) context.comparisonOperator().getChild(0)).getSymbol()),
- getComparisonQuantifier(((TerminalNode) context.comparisonQuantifier().getChild(0)).getSymbol()),
- (Expression) visit(context.value),
- new SubqueryExpression(getLocation(context.query()), (Query) visit(context.query())));
- }
-
- // ************** value expressions **************
-
- @Override
- public Node visitArithmeticUnary(SqlBaseParser.ArithmeticUnaryContext context)
- {
- Expression child = (Expression) visit(context.valueExpression());
-
- switch (context.operator.getType()) {
- case SqlBaseLexer.MINUS:
- return ArithmeticUnaryExpression.negative(getLocation(context), child);
- case SqlBaseLexer.PLUS:
- return ArithmeticUnaryExpression.positive(getLocation(context), child);
- default:
- throw new UnsupportedOperationException("Unsupported sign: " + context.operator.getText());
- }
- }
-
- @Override
- public Node visitArithmeticBinary(SqlBaseParser.ArithmeticBinaryContext context)
- {
- checkPgSchema(context.IDENTIFIER()); // pg syntax
-
- return new ArithmeticBinaryExpression(
- getLocation(context.operator),
- getArithmeticBinaryOperator(context.operator),
- (Expression) visit(context.left),
- (Expression) visit(context.right));
- }
-
- @Override
- public Node visitConcatenation(SqlBaseParser.ConcatenationContext context)
- {
- return new FunctionCall(
- getLocation(context.CONCAT()),
- QualifiedName.of("concat"), ImmutableList.of(
- (Expression) visit(context.left),
- (Expression) visit(context.right)));
- }
-
- @Override
- public Node visitAtTimeZone(SqlBaseParser.AtTimeZoneContext context)
- {
- return new AtTimeZone(
- getLocation(context.AT()),
- (Expression) visit(context.valueExpression()),
- (Expression) visit(context.timeZoneSpecifier()));
- }
-
- @Override
- public Node visitTimeZoneInterval(SqlBaseParser.TimeZoneIntervalContext context)
- {
- return visit(context.interval());
- }
-
- @Override
- public Node visitTimeZoneString(SqlBaseParser.TimeZoneStringContext context)
- {
- return visit(context.string());
- }
-
- // ********************* primary expressions **********************
-
- @Override
- public Node visitParenthesizedExpression(SqlBaseParser.ParenthesizedExpressionContext context)
- {
- return visit(context.expression());
- }
-
- @Override
- public Node visitRowConstructor(SqlBaseParser.RowConstructorContext context)
- {
- return new Row(getLocation(context), visit(context.expression(), Expression.class));
- }
-
- @Override
- public Node visitArrayConstructor(SqlBaseParser.ArrayConstructorContext context)
- {
- return new ArrayConstructor(getLocation(context), visit(context.expression(), Expression.class));
- }
-
- @Override
- public Node visitCast(SqlBaseParser.CastContext context)
- {
- checkPgSchema(context.IDENTIFIER()); // pg syntax
-
- boolean isTryCast = context.TRY_CAST() != null;
- boolean isPostgreStyle = context.PG_CAST() != null;
- if (isPostgreStyle) {
- return new Cast(getLocation(context), (Expression) visit(context.primaryExpression()), (DataType) visit(context.type()), isTryCast);
- }
- return new Cast(getLocation(context), (Expression) visit(context.expression()), (DataType) visit(context.type()), isTryCast);
- }
-
- @Override
- public Node visitSpecialDateTimeFunction(SqlBaseParser.SpecialDateTimeFunctionContext context)
- {
- CurrentTime.Function function = getDateTimeFunctionType(context.name);
-
- if (context.precision != null) {
- return new CurrentTime(getLocation(context), function, Integer.parseInt(context.precision.getText()));
- }
-
- 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)
- {
- return new CurrentUser(getLocation(context.CURRENT_USER()));
- }
-
- @Override
- public Node visitCurrentPath(SqlBaseParser.CurrentPathContext context)
- {
- return new CurrentPath(getLocation(context.CURRENT_PATH()));
- }
-
- @Override
- public Node visitExtract(SqlBaseParser.ExtractContext context)
- {
- String fieldString = context.identifier().getText();
- Extract.Field field;
- try {
- field = new Extract.Field(fieldString.toUpperCase(ENGLISH));
- }
- catch (IllegalArgumentException e) {
- throw parseError("Invalid EXTRACT field: " + fieldString, context);
- }
- return new Extract(getLocation(context), (Expression) visit(context.valueExpression()), field);
- }
-
- /**
- * Returns the corresponding {@link FunctionCall} for the `LISTAGG` primary expression.
- *
- * Although the syntax tree should represent the structure of the original parsed query
- * as closely as possible and any semantic interpretation should be part of the
- * analysis/planning phase, in case of `LISTAGG` aggregation function it is more pragmatic
- * now to create a synthetic {@link FunctionCall} expression during the parsing of the syntax tree.
- *
- * @param context `LISTAGG` expression context
- */
- @Override
- public Node visitListagg(SqlBaseParser.ListaggContext context)
- {
- Optional window = Optional.empty();
- OrderBy orderBy = new OrderBy(visit(context.sortItem(), SortItem.class));
- boolean distinct = isDistinct(context.setQuantifier());
-
- Expression expression = (Expression) visit(context.expression());
- StringLiteral separator = context.string() == null ? new StringLiteral(getLocation(context), "") : (StringLiteral) (visit(context.string()));
- BooleanLiteral overflowError = new BooleanLiteral(getLocation(context), "true");
- StringLiteral overflowFiller = new StringLiteral(getLocation(context), "...");
- BooleanLiteral showOverflowEntryCount = new BooleanLiteral(getLocation(context), "false");
-
- SqlBaseParser.ListAggOverflowBehaviorContext overflowBehavior = context.listAggOverflowBehavior();
- if (overflowBehavior != null) {
- if (overflowBehavior.ERROR() != null) {
- overflowError = new BooleanLiteral(getLocation(context), "true");
- }
- else if (overflowBehavior.TRUNCATE() != null) {
- overflowError = new BooleanLiteral(getLocation(context), "false");
- if (overflowBehavior.string() != null) {
- overflowFiller = (StringLiteral) (visit(overflowBehavior.string()));
- }
- SqlBaseParser.ListaggCountIndicationContext listaggCountIndicationContext = overflowBehavior.listaggCountIndication();
- if (listaggCountIndicationContext.WITH() != null) {
- showOverflowEntryCount = new BooleanLiteral(getLocation(context), "true");
- }
- else if (listaggCountIndicationContext.WITHOUT() != null) {
- showOverflowEntryCount = new BooleanLiteral(getLocation(context), "false");
- }
- }
- }
-
- List arguments = ImmutableList.of(expression, separator, overflowError, overflowFiller, showOverflowEntryCount);
-
- //TODO model this as a ListAgg node in the AST
- return new FunctionCall(
- Optional.of(getLocation(context)),
- QualifiedName.of("LISTAGG"),
- window,
- Optional.empty(),
- Optional.of(orderBy),
- distinct,
- Optional.empty(),
- Optional.empty(),
- arguments);
- }
-
- @Override
- public Node visitSubstring(SqlBaseParser.SubstringContext context)
- {
- return new FunctionCall(getLocation(context), QualifiedName.of("substr"), visit(context.valueExpression(), Expression.class));
- }
-
- @Override
- public Node visitPosition(SqlBaseParser.PositionContext context)
- {
- List arguments = Lists.reverse(visit(context.valueExpression(), Expression.class));
- return new FunctionCall(getLocation(context), QualifiedName.of("strpos"), arguments);
- }
-
- @Override
- public Node visitNormalize(SqlBaseParser.NormalizeContext context)
- {
- Expression str = (Expression) visit(context.valueExpression());
- String normalForm = Optional.ofNullable(context.normalForm()).map(ParserRuleContext::getText).orElse("NFC");
- return new FunctionCall(
- getLocation(context),
- QualifiedName.of(ImmutableList.of(new Identifier("normalize", true))), // delimited to avoid ambiguity with NORMALIZE SQL construct
- ImmutableList.of(str, new StringLiteral(getLocation(context), normalForm)));
- }
-
- @Override
- public Node visitSubscript(SqlBaseParser.SubscriptContext context)
- {
- return new SubscriptExpression(getLocation(context), (Expression) visit(context.value), (Expression) visit(context.index));
- }
-
- @Override
- public Node visitSubqueryExpression(SqlBaseParser.SubqueryExpressionContext context)
- {
- return new SubqueryExpression(getLocation(context), (Query) visit(context.query()));
- }
-
- @Override
- public Node visitDereference(SqlBaseParser.DereferenceContext context)
- {
- return new DereferenceExpression(
- getLocation(context),
- (Expression) visit(context.base),
- (Identifier) visit(context.fieldName));
- }
-
- @Override
- public Node visitColumnReference(SqlBaseParser.ColumnReferenceContext context)
- {
- return visit(context.identifier());
- }
-
- @Override
- public Node visitSimpleCase(SqlBaseParser.SimpleCaseContext context)
- {
- return new SimpleCaseExpression(
- getLocation(context),
- (Expression) visit(context.operand),
- visit(context.whenClause(), WhenClause.class),
- visitIfPresent(context.elseExpression, Expression.class));
- }
-
- @Override
- public Node visitSearchedCase(SqlBaseParser.SearchedCaseContext context)
- {
- return new SearchedCaseExpression(
- getLocation(context),
- visit(context.whenClause(), WhenClause.class),
- visitIfPresent(context.elseExpression, Expression.class));
- }
-
- @Override
- public Node visitWhenClause(SqlBaseParser.WhenClauseContext context)
- {
- return new WhenClause(getLocation(context), (Expression) visit(context.condition), (Expression) visit(context.result));
- }
-
- @Override
- public Node visitFunctionCall(SqlBaseParser.FunctionCallContext context)
- {
- Optional filter = visitIfPresent(context.filter(), Expression.class);
- Optional window = visitIfPresent(context.over(), Window.class);
-
- Optional orderBy = Optional.empty();
- if (context.ORDER() != null) {
- orderBy = Optional.of(new OrderBy(visit(context.sortItem(), SortItem.class)));
- }
-
- QualifiedName name = getQualifiedName(context.qualifiedName());
-
- boolean distinct = isDistinct(context.setQuantifier());
-
- 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;
- if (context.expression().size() == 3) {
- elseExpression = (Expression) visit(context.expression(2));
- }
-
- return new IfExpression(
- getLocation(context),
- (Expression) visit(context.expression(0)),
- (Expression) visit(context.expression(1)),
- elseExpression);
- }
-
- if (name.toString().equalsIgnoreCase("nullif")) {
- check(context.expression().size() == 2, "Invalid number of arguments for 'nullif' function", context);
- 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(
- getLocation(context),
- (Expression) visit(context.expression(0)),
- (Expression) visit(context.expression(1)));
- }
-
- if (name.toString().equalsIgnoreCase("coalesce")) {
- check(context.expression().size() >= 2, "The 'coalesce' function must have at least two arguments", context);
- 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));
- }
-
- if (name.toString().equalsIgnoreCase("try")) {
- check(context.expression().size() == 1, "The 'try' function must have exactly one argument", context);
- 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())));
- }
-
- if (name.toString().equalsIgnoreCase("format")) {
- check(context.expression().size() >= 2, "The 'format' function must have at least two arguments", context);
- 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));
- }
-
- if (name.toString().equalsIgnoreCase("$internal$bind")) {
- check(context.expression().size() >= 1, "The '$internal$bind' function must have at least one arguments", context);
- 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;
- List arguments = context.expression().stream()
- .map(this::visit)
- .map(Expression.class::cast)
- .collect(toImmutableList());
-
- return new BindExpression(
- getLocation(context),
- arguments.subList(0, numValues),
- arguments.get(numValues));
- }
-
- Optional nulls = Optional.empty();
- if (nullTreatment != null) {
- if (nullTreatment.IGNORE() != null) {
- nulls = Optional.of(NullTreatment.IGNORE);
- }
- else if (nullTreatment.RESPECT() != null) {
- nulls = Optional.of(NullTreatment.RESPECT);
- }
- }
-
- Optional 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));
- }
- }
-
- List arguments = visit(context.expression(), Expression.class);
- if (context.label != null) {
- arguments = ImmutableList.of(new DereferenceExpression(getLocation(context.label), (Identifier) visit(context.label)));
- }
-
- return new FunctionCall(
- Optional.of(getLocation(context)),
- name,
- window,
- filter,
- orderBy,
- distinct,
- nulls,
- mode,
- arguments);
- }
-
- @Override
- public Node visitMeasure(SqlBaseParser.MeasureContext context)
- {
- return new WindowOperation(getLocation(context), (Identifier) visit(context.identifier()), (Window) visit(context.over()));
- }
-
- @Override
- public Node visitLambda(SqlBaseParser.LambdaContext context)
- {
- List arguments = visit(context.identifier(), Identifier.class).stream()
- .map(LambdaArgumentDeclaration::new)
- .collect(toList());
-
- Expression body = (Expression) visit(context.expression());
-
- return new LambdaExpression(getLocation(context), arguments, body);
- }
-
- @Override
- public Node visitFilter(SqlBaseParser.FilterContext context)
- {
- return visit(context.booleanExpression());
- }
-
- @Override
- public Node visitOver(SqlBaseParser.OverContext context)
- {
- if (context.windowName != null) {
- return new WindowReference(getLocation(context), (Identifier) visit(context.windowName));
- }
-
- return visit(context.windowSpecification());
- }
-
- @Override
- public Node visitColumnDefinition(SqlBaseParser.ColumnDefinitionContext context)
- {
- Optional comment = Optional.empty();
- if (context.COMMENT() != null) {
- comment = Optional.of(((StringLiteral) visit(context.string())).getValue());
- }
-
- List properties = ImmutableList.of();
- if (context.properties() != null) {
- properties = visit(context.properties().propertyAssignments().property(), Property.class);
- }
-
- boolean nullable = context.NOT() == null;
-
- return new ColumnDefinition(
- getLocation(context),
- (Identifier) visit(context.identifier()),
- (DataType) visit(context.type()),
- nullable,
- properties,
- comment);
- }
-
- @Override
- public Node visitLikeClause(SqlBaseParser.LikeClauseContext context)
- {
- return new LikeClause(
- getLocation(context),
- getQualifiedName(context.qualifiedName()),
- Optional.ofNullable(context.optionType)
- .map(AstBuilder::getPropertiesOption));
- }
-
- @Override
- public Node visitSortItem(SqlBaseParser.SortItemContext context)
- {
- return new SortItem(
- getLocation(context),
- (Expression) visit(context.expression()),
- Optional.ofNullable(context.ordering)
- .map(AstBuilder::getOrderingType)
- .orElse(SortItem.Ordering.ASCENDING),
- Optional.ofNullable(context.nullOrdering)
- .map(AstBuilder::getNullOrderingType)
- .orElse(SortItem.NullOrdering.UNDEFINED));
- }
-
- @Override
- public Node visitWindowFrame(SqlBaseParser.WindowFrameContext context)
- {
- Optional 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));
- }
-
- return new WindowFrame(
- getLocation(context),
- getFrameType(context.frameExtent().frameType),
- (FrameBound) visit(context.frameExtent().start),
- visitIfPresent(context.frameExtent().end, FrameBound.class),
- visit(context.measureDefinition(), MeasureDefinition.class),
- visitIfPresent(context.skipTo(), SkipTo.class),
- searchMode,
- visitIfPresent(context.rowPattern(), RowPattern.class),
- visit(context.subsetDefinition(), SubsetDefinition.class),
- visit(context.variableDefinition(), VariableDefinition.class));
- }
-
- @Override
- public Node visitUnboundedFrame(SqlBaseParser.UnboundedFrameContext context)
- {
- return new FrameBound(getLocation(context), getUnboundedFrameBoundType(context.boundType));
- }
-
- @Override
- public Node visitBoundedFrame(SqlBaseParser.BoundedFrameContext context)
- {
- return new FrameBound(getLocation(context), getBoundedFrameBoundType(context.boundType), (Expression) visit(context.expression()));
- }
-
- @Override
- public Node visitCurrentRowBound(SqlBaseParser.CurrentRowBoundContext context)
- {
- return new FrameBound(getLocation(context), FrameBound.Type.CURRENT_ROW);
- }
-
- @Override
- public Node visitGroupingOperation(SqlBaseParser.GroupingOperationContext context)
- {
- List arguments = context.qualifiedName().stream()
- .map(this::getQualifiedName)
- .collect(toList());
-
- return new GroupingOperation(Optional.of(getLocation(context)), arguments);
- }
-
- @Override
- public Node visitUnquotedIdentifier(SqlBaseParser.UnquotedIdentifierContext context)
- {
- return new Identifier(getLocation(context), context.getText(), false);
- }
-
- @Override
- public Node visitQuotedIdentifier(SqlBaseParser.QuotedIdentifierContext context)
- {
- String token = context.getText();
- String identifier = token.substring(1, token.length() - 1)
- .replace("\"\"", "\"");
-
- return new Identifier(getLocation(context), identifier, true);
- }
-
- @Override
- public Node visitPatternAlternation(SqlBaseParser.PatternAlternationContext context)
- {
- List parts = visit(context.rowPattern(), RowPattern.class);
- return new PatternAlternation(getLocation(context), parts);
- }
-
- @Override
- public Node visitPatternConcatenation(SqlBaseParser.PatternConcatenationContext context)
- {
- List 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 atLeast = Optional.empty();
- Optional 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
- public Node visitNullLiteral(SqlBaseParser.NullLiteralContext context)
- {
- return new NullLiteral(getLocation(context));
- }
-
- @Override
- public Node visitBasicStringLiteral(SqlBaseParser.BasicStringLiteralContext context)
- {
- return new StringLiteral(getLocation(context), unquote(context.STRING().getText()));
- }
-
- @Override
- public Node visitUnicodeStringLiteral(SqlBaseParser.UnicodeStringLiteralContext context)
- {
- return new StringLiteral(getLocation(context), decodeUnicodeLiteral(context));
- }
-
- @Override
- public Node visitEscapedCharsStringLiteral(SqlBaseParser.EscapedCharsStringLiteralContext ctx)
- {
- String text = ctx.ESCAPED_STRING().getText();
- return new StringLiteral(getLocation(ctx), replaceEscapedChars(unquote(text.substring(1))));
- }
-
- @Override
- public Node visitBinaryLiteral(SqlBaseParser.BinaryLiteralContext context)
- {
- String raw = context.BINARY_LITERAL().getText();
- return new BinaryLiteral(getLocation(context), unquote(raw.substring(1)));
- }
-
- @Override
- public Node visitTypeConstructor(SqlBaseParser.TypeConstructorContext context)
- {
- checkPgSchema(context.IDENTIFIER()); // pg syntax
-
- String value = ((StringLiteral) visit(context.string())).getValue();
-
- if (context.DOUBLE() != null) {
- // TODO: Temporary hack that should be removed with new planner.
- return new GenericLiteral(getLocation(context), "DOUBLE", value);
- }
-
- String type = context.identifier().getText();
- if (type.equalsIgnoreCase("time")) {
- return new TimeLiteral(getLocation(context), value);
- }
- if (type.equalsIgnoreCase("timestamp")) {
- return new TimestampLiteral(getLocation(context), value);
- }
- if (type.equalsIgnoreCase("decimal")) {
- return new DecimalLiteral(getLocation(context), value);
- }
- // 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
- if (type.equalsIgnoreCase("interval")) {
- return IntervalLiteralUtil.parse(getLocation(context), value);
- }
- // for PostgreSQL wire protocol, handle bytea binary pattern
- if (type.equalsIgnoreCase("bytea") && value.startsWith("\\x")) {
- return new BinaryLiteral(getLocation(context), value.substring(2));
- }
-
- return new GenericLiteral(getLocation(context), type, value);
- }
-
- @Override
- public Node visitIntegerLiteral(SqlBaseParser.IntegerLiteralContext context)
- {
- return new LongLiteral(getLocation(context), context.getText());
- }
-
- @Override
- public Node visitDecimalLiteral(SqlBaseParser.DecimalLiteralContext context)
- {
- switch (parsingOptions.getDecimalLiteralTreatment()) {
- case AS_DOUBLE:
- return new DoubleLiteral(getLocation(context), context.getText());
- case AS_DECIMAL:
- return new DecimalLiteral(getLocation(context), context.getText());
- case REJECT:
- throw new ParsingException("Unexpected decimal literal: " + context.getText());
- }
- throw new AssertionError("Unreachable");
- }
-
- @Override
- public Node visitDoubleLiteral(SqlBaseParser.DoubleLiteralContext context)
- {
- return new DoubleLiteral(getLocation(context), context.getText());
- }
-
- @Override
- public Node visitBooleanValue(SqlBaseParser.BooleanValueContext context)
- {
- return new BooleanLiteral(getLocation(context), context.getText());
- }
-
- @Override
- public Node visitInterval(SqlBaseParser.IntervalContext context)
- {
- return new IntervalLiteral(
- getLocation(context),
- ((StringLiteral) visit(context.string())).getValue(),
- Optional.ofNullable(context.sign)
- .map(AstBuilder::getIntervalSign)
- .orElse(IntervalLiteral.Sign.POSITIVE),
- getIntervalFieldType((Token) context.from.getChild(0).getPayload()),
- Optional.ofNullable(context.to)
- .map((x) -> x.getChild(0).getPayload())
- .map(Token.class::cast)
- .map(AstBuilder::getIntervalFieldType));
- }
-
- @Override
- public Node visitParameter(SqlBaseParser.ParameterContext context)
- {
- io.trino.sql.tree.Parameter parameter = new io.trino.sql.tree.Parameter(getLocation(context), parameterPosition);
- parameterPosition++;
- return parameter;
- }
-
- // ***************** arguments *****************
-
- @Override
- public Node visitPositionalArgument(SqlBaseParser.PositionalArgumentContext context)
- {
- return new CallArgument(getLocation(context), (Expression) visit(context.expression()));
- }
-
- @Override
- public Node visitNamedArgument(SqlBaseParser.NamedArgumentContext context)
- {
- return new CallArgument(getLocation(context), (Identifier) visit(context.identifier()), (Expression) visit(context.expression()));
- }
-
- @Override
- public Node visitQualifiedArgument(SqlBaseParser.QualifiedArgumentContext context)
- {
- return new PathElement(getLocation(context), (Identifier) visit(context.identifier(0)), (Identifier) visit(context.identifier(1)));
- }
-
- @Override
- public Node visitUnqualifiedArgument(SqlBaseParser.UnqualifiedArgumentContext context)
- {
- return new PathElement(getLocation(context), (Identifier) visit(context.identifier()));
- }
-
- @Override
- public Node visitPathSpecification(SqlBaseParser.PathSpecificationContext context)
- {
- return new PathSpecification(getLocation(context), visit(context.pathElement(), PathElement.class));
- }
-
- @Override
- public Node visitRowType(SqlBaseParser.RowTypeContext context)
- {
- List fields = context.rowField().stream()
- .map(this::visit)
- .map(RowDataType.Field.class::cast)
- .collect(toImmutableList());
-
- return new RowDataType(getLocation(context), fields);
- }
-
- @Override
- public Node visitRowField(SqlBaseParser.RowFieldContext context)
- {
- return new RowDataType.Field(
- getLocation(context),
- visitIfPresent(context.identifier(), Identifier.class),
- (DataType) visit(context.type()));
- }
-
- @Override
- public Node visitGenericType(SqlBaseParser.GenericTypeContext context)
- {
- List parameters = context.typeParameter().stream()
- .map(this::visit)
- .map(DataTypeParameter.class::cast)
- .collect(toImmutableList());
-
- return new GenericDataType(getLocation(context), (Identifier) visit(context.identifier()), parameters);
- }
-
- @Override
- public Node visitTypeParameter(SqlBaseParser.TypeParameterContext context)
- {
- if (context.INTEGER_VALUE() != null) {
- return new NumericParameter(getLocation(context), context.getText());
- }
-
- return new TypeParameter((DataType) visit(context.type()));
- }
-
- @Override
- public Node visitIntervalType(SqlBaseParser.IntervalTypeContext context)
- {
- String from = context.from.getText();
- String to = getTextIfPresent(context.to)
- .orElse(from);
-
- return new IntervalDayTimeDataType(
- getLocation(context),
- IntervalDayTimeDataType.Field.valueOf(from.toUpperCase(ENGLISH)),
- IntervalDayTimeDataType.Field.valueOf(to.toUpperCase(ENGLISH)));
- }
-
- @Override
- public Node visitDateTimeType(SqlBaseParser.DateTimeTypeContext context)
- {
- DateTimeDataType.Type type;
-
- if (context.base.getType() == TIME) {
- type = DateTimeDataType.Type.TIME;
- }
- else if (context.base.getType() == TIMESTAMP) {
- type = DateTimeDataType.Type.TIMESTAMP;
- }
- else {
- throw new ParsingException("Unexpected datetime type: " + context.getText());
- }
-
- return new DateTimeDataType(
- getLocation(context),
- type,
- context.WITH() != null,
- visitIfPresent(context.precision, DataTypeParameter.class));
- }
-
- @Override
- public Node visitDoublePrecisionType(SqlBaseParser.DoublePrecisionTypeContext context)
- {
- return new GenericDataType(
- getLocation(context),
- new Identifier(getLocation(context.DOUBLE()), context.DOUBLE().getText(), false),
- ImmutableList.of());
- }
-
- @Override
- public Node visitLegacyArrayType(SqlBaseParser.LegacyArrayTypeContext context)
- {
- return new GenericDataType(
- getLocation(context),
- new Identifier(getLocation(context.ARRAY()), context.ARRAY().getText(), false),
- ImmutableList.of(new TypeParameter((DataType) visit(context.type()))));
- }
-
- @Override
- public Node visitLegacyMapType(SqlBaseParser.LegacyMapTypeContext context)
- {
- return new GenericDataType(
- getLocation(context),
- new Identifier(getLocation(context.MAP()), context.MAP().getText(), false),
- ImmutableList.of(
- new TypeParameter((DataType) visit(context.keyType)),
- new TypeParameter((DataType) visit(context.valueType))));
- }
-
- @Override
- public Node visitArrayType(SqlBaseParser.ArrayTypeContext context)
- {
- if (context.INTEGER_VALUE() != null) {
- throw new UnsupportedOperationException("Explicit array size not supported");
- }
-
- return new GenericDataType(
- getLocation(context),
- new Identifier(getLocation(context.ARRAY()), context.ARRAY().getText(), false),
- ImmutableList.of(new TypeParameter((DataType) visit(context.type()))));
- }
-
- @Override
- public Node visitQueryPeriod(SqlBaseParser.QueryPeriodContext context)
- {
- QueryPeriod.RangeType type = getRangeType((Token) context.rangeType().getChild(0).getPayload());
- Expression marker = (Expression) visit(context.valueExpression());
- return new QueryPeriod(getLocation(context), type, marker);
- }
-
- @Override
- public Node visitValueExpressionDefault(SqlBaseParser.ValueExpressionDefaultContext context)
- {
- // This is for pg wire protocol.
- // We don't really support collate clause, so we just let it pass and do nothing.
- if (context.children.size() == 2 && context.children.get(1) instanceof SqlBaseParser.CollateClauseContext) {
- context.children.remove(1);
- }
- return super.visitValueExpressionDefault(context);
- }
-
- // ***************** helpers *****************
-
- @Override
- protected Node defaultResult()
- {
- return null;
- }
-
- @Override
- protected Node aggregateResult(Node aggregate, Node nextResult)
- {
- if (nextResult == null) {
- throw new UnsupportedOperationException("not yet implemented");
- }
-
- if (aggregate == null) {
- return nextResult;
- }
-
- throw new UnsupportedOperationException("not yet implemented");
- }
-
- private enum UnicodeDecodeState
- {
- EMPTY,
- ESCAPED,
- UNICODE_SEQUENCE
- }
-
- private enum PgSetReturnFunction
- {
- // TODO: support other remote database
- // https://github.com/Canner/canner-metric-layer/issues/62
- // the array generating function in bigquery call 'generate_array`.
- GENERATE_SERIES("generate_series", "generate_array");
-
- private final String pgFuncName;
- private final String prestoFuncName;
-
- PgSetReturnFunction(String pgFuncName, String prestoFuncName)
- {
- this.pgFuncName = pgFuncName;
- this.prestoFuncName = prestoFuncName;
- }
-
- public String getPgFuncName()
- {
- return pgFuncName;
- }
-
- public String getRemoteFuncName()
- {
- return prestoFuncName;
- }
- }
-
- private static String decodeUnicodeLiteral(SqlBaseParser.UnicodeStringLiteralContext context)
- {
- char escape;
- if (context.UESCAPE() != null) {
- String escapeString = unquote(context.STRING().getText());
- check(!escapeString.isEmpty(), "Empty Unicode escape character", context);
- check(escapeString.length() == 1, "Invalid Unicode escape character: " + escapeString, context);
- escape = escapeString.charAt(0);
- check(isValidUnicodeEscape(escape), "Invalid Unicode escape character: " + escapeString, context);
- }
- else {
- escape = '\\';
- }
-
- String rawContent = unquote(context.UNICODE_STRING().getText().substring(2));
- StringBuilder unicodeStringBuilder = new StringBuilder();
- StringBuilder escapedCharacterBuilder = new StringBuilder();
- int charactersNeeded = 0;
- UnicodeDecodeState state = UnicodeDecodeState.EMPTY;
- for (int i = 0; i < rawContent.length(); i++) {
- char ch = rawContent.charAt(i);
- switch (state) {
- case EMPTY:
- if (ch == escape) {
- state = UnicodeDecodeState.ESCAPED;
- }
- else {
- unicodeStringBuilder.append(ch);
- }
- break;
- case ESCAPED:
- if (ch == escape) {
- unicodeStringBuilder.append(escape);
- state = UnicodeDecodeState.EMPTY;
- }
- else if (ch == '+') {
- state = UnicodeDecodeState.UNICODE_SEQUENCE;
- charactersNeeded = 6;
- }
- else if (isHexDigit(ch)) {
- state = UnicodeDecodeState.UNICODE_SEQUENCE;
- charactersNeeded = 4;
- escapedCharacterBuilder.append(ch);
- }
- else {
- throw parseError("Invalid hexadecimal digit: " + ch, context);
- }
- break;
- case UNICODE_SEQUENCE:
- check(isHexDigit(ch), "Incomplete escape sequence: " + escapedCharacterBuilder.toString(), context);
- escapedCharacterBuilder.append(ch);
- if (charactersNeeded == escapedCharacterBuilder.length()) {
- String currentEscapedCode = escapedCharacterBuilder.toString();
- escapedCharacterBuilder.setLength(0);
- int codePoint = Integer.parseInt(currentEscapedCode, 16);
- check(Character.isValidCodePoint(codePoint), "Invalid escaped character: " + currentEscapedCode, context);
- if (Character.isSupplementaryCodePoint(codePoint)) {
- unicodeStringBuilder.appendCodePoint(codePoint);
- }
- else {
- char currentCodePoint = (char) codePoint;
- check(!Character.isSurrogate(currentCodePoint), format("Invalid escaped character: %s. Escaped character is a surrogate. Use '\\+123456' instead.", currentEscapedCode), context);
- unicodeStringBuilder.append(currentCodePoint);
- }
- state = UnicodeDecodeState.EMPTY;
- charactersNeeded = -1;
- }
- else {
- check(charactersNeeded > escapedCharacterBuilder.length(), "Unexpected escape sequence length: " + escapedCharacterBuilder.length(), context);
- }
- break;
- default:
- throw new UnsupportedOperationException();
- }
- }
-
- check(state == UnicodeDecodeState.EMPTY, "Incomplete escape sequence: " + escapedCharacterBuilder.toString(), context);
- return unicodeStringBuilder.toString();
- }
-
- private Optional visitIfPresent(ParserRuleContext context, Class clazz)
- {
- return Optional.ofNullable(context)
- .map(this::visit)
- .map(clazz::cast);
- }
-
- private List visit(List extends ParserRuleContext> contexts, Class clazz)
- {
- return contexts.stream()
- .map(this::visit)
- .map(clazz::cast)
- .collect(toList());
- }
-
- private static String unquote(String value)
- {
- return value.substring(1, value.length() - 1)
- .replace("''", "'");
- }
-
- private static LikeClause.PropertiesOption getPropertiesOption(Token token)
- {
- switch (token.getType()) {
- case SqlBaseLexer.INCLUDING:
- return LikeClause.PropertiesOption.INCLUDING;
- case SqlBaseLexer.EXCLUDING:
- return LikeClause.PropertiesOption.EXCLUDING;
- }
- throw new IllegalArgumentException("Unsupported LIKE option type: " + token.getText());
- }
-
- private QualifiedName getQualifiedName(SqlBaseParser.QualifiedNameContext context)
- {
- return QualifiedName.of(visit(context.identifier(), Identifier.class));
- }
-
- private static boolean isDistinct(SqlBaseParser.SetQuantifierContext setQuantifier)
- {
- return setQuantifier != null && setQuantifier.DISTINCT() != null;
- }
-
- private static boolean isHexDigit(char c)
- {
- return ((c >= '0') && (c <= '9')) ||
- ((c >= 'A') && (c <= 'F')) ||
- ((c >= 'a') && (c <= 'f'));
- }
-
- private static boolean isValidUnicodeEscape(char c)
- {
- return c < 0x7F && c > 0x20 && !isHexDigit(c) && c != '"' && c != '+' && c != '\'';
- }
-
- private static Optional getTextIfPresent(ParserRuleContext context)
- {
- return Optional.ofNullable(context)
- .map(ParseTree::getText);
- }
-
- private Optional getIdentifierIfPresent(ParserRuleContext context)
- {
- return Optional.ofNullable(context).map(c -> (Identifier) visit(c));
- }
-
- private static ArithmeticBinaryExpression.Operator getArithmeticBinaryOperator(Token operator)
- {
- switch (operator.getType()) {
- case SqlBaseLexer.PLUS:
- return ArithmeticBinaryExpression.Operator.ADD;
- case SqlBaseLexer.MINUS:
- return ArithmeticBinaryExpression.Operator.SUBTRACT;
- case SqlBaseLexer.ASTERISK:
- return ArithmeticBinaryExpression.Operator.MULTIPLY;
- case SqlBaseLexer.SLASH:
- return ArithmeticBinaryExpression.Operator.DIVIDE;
- case SqlBaseLexer.PERCENT:
- return ArithmeticBinaryExpression.Operator.MODULUS;
- }
-
- throw new UnsupportedOperationException("Unsupported operator: " + operator.getText());
- }
-
- private static ComparisonExpression.Operator getComparisonOperator(Token symbol)
- {
- switch (symbol.getType()) {
- case SqlBaseLexer.EQ:
- return ComparisonExpression.Operator.EQUAL;
- case SqlBaseLexer.NEQ:
- return ComparisonExpression.Operator.NOT_EQUAL;
- case SqlBaseLexer.LT:
- return ComparisonExpression.Operator.LESS_THAN;
- case SqlBaseLexer.LTE:
- return ComparisonExpression.Operator.LESS_THAN_OR_EQUAL;
- case SqlBaseLexer.GT:
- return ComparisonExpression.Operator.GREATER_THAN;
- case SqlBaseLexer.GTE:
- return ComparisonExpression.Operator.GREATER_THAN_OR_EQUAL;
- }
-
- throw new IllegalArgumentException("Unsupported operator: " + symbol.getText());
- }
-
- private static CurrentTime.Function getDateTimeFunctionType(Token token)
- {
- switch (token.getType()) {
- case SqlBaseLexer.CURRENT_DATE:
- return CurrentTime.Function.DATE;
- case SqlBaseLexer.CURRENT_TIME:
- return CurrentTime.Function.TIME;
- case SqlBaseLexer.CURRENT_TIMESTAMP:
- return CurrentTime.Function.TIMESTAMP;
- case SqlBaseLexer.LOCALTIME:
- return CurrentTime.Function.LOCALTIME;
- case SqlBaseLexer.LOCALTIMESTAMP:
- return CurrentTime.Function.LOCALTIMESTAMP;
- }
-
- throw new IllegalArgumentException("Unsupported special function: " + token.getText());
- }
-
- private static IntervalLiteral.IntervalField getIntervalFieldType(Token token)
- {
- switch (token.getType()) {
- case SqlBaseLexer.YEAR:
- return IntervalLiteral.IntervalField.YEAR;
- case SqlBaseLexer.MONTH:
- return IntervalLiteral.IntervalField.MONTH;
- case SqlBaseLexer.DAY:
- return IntervalLiteral.IntervalField.DAY;
- case SqlBaseLexer.HOUR:
- return IntervalLiteral.IntervalField.HOUR;
- case SqlBaseLexer.MINUTE:
- return IntervalLiteral.IntervalField.MINUTE;
- case SqlBaseLexer.SECOND:
- return IntervalLiteral.IntervalField.SECOND;
- }
-
- throw new IllegalArgumentException("Unsupported interval field: " + token.getText());
- }
-
- private static IntervalLiteral.Sign getIntervalSign(Token token)
- {
- switch (token.getType()) {
- case SqlBaseLexer.MINUS:
- return IntervalLiteral.Sign.NEGATIVE;
- case SqlBaseLexer.PLUS:
- return IntervalLiteral.Sign.POSITIVE;
- }
-
- throw new IllegalArgumentException("Unsupported sign: " + token.getText());
- }
-
- private static WindowFrame.Type getFrameType(Token type)
- {
- switch (type.getType()) {
- case SqlBaseLexer.RANGE:
- return WindowFrame.Type.RANGE;
- case SqlBaseLexer.ROWS:
- return WindowFrame.Type.ROWS;
- case SqlBaseLexer.GROUPS:
- return WindowFrame.Type.GROUPS;
- }
-
- throw new IllegalArgumentException("Unsupported frame type: " + type.getText());
- }
-
- private static FrameBound.Type getBoundedFrameBoundType(Token token)
- {
- switch (token.getType()) {
- case SqlBaseLexer.PRECEDING:
- return FrameBound.Type.PRECEDING;
- case SqlBaseLexer.FOLLOWING:
- return FrameBound.Type.FOLLOWING;
- }
-
- throw new IllegalArgumentException("Unsupported bound type: " + token.getText());
- }
-
- private static FrameBound.Type getUnboundedFrameBoundType(Token token)
- {
- switch (token.getType()) {
- case SqlBaseLexer.PRECEDING:
- return FrameBound.Type.UNBOUNDED_PRECEDING;
- case SqlBaseLexer.FOLLOWING:
- return FrameBound.Type.UNBOUNDED_FOLLOWING;
- }
-
- throw new IllegalArgumentException("Unsupported bound type: " + token.getText());
- }
-
- private static SampledRelation.Type getSamplingMethod(Token token)
- {
- switch (token.getType()) {
- case SqlBaseLexer.BERNOULLI:
- return SampledRelation.Type.BERNOULLI;
- case SqlBaseLexer.SYSTEM:
- return SampledRelation.Type.SYSTEM;
- }
-
- throw new IllegalArgumentException("Unsupported sampling method: " + token.getText());
- }
-
- private static SortItem.NullOrdering getNullOrderingType(Token token)
- {
- switch (token.getType()) {
- case SqlBaseLexer.FIRST:
- return SortItem.NullOrdering.FIRST;
- case SqlBaseLexer.LAST:
- return SortItem.NullOrdering.LAST;
- }
-
- throw new IllegalArgumentException("Unsupported ordering: " + token.getText());
- }
-
- private static SortItem.Ordering getOrderingType(Token token)
- {
- switch (token.getType()) {
- case SqlBaseLexer.ASC:
- return SortItem.Ordering.ASCENDING;
- case SqlBaseLexer.DESC:
- return SortItem.Ordering.DESCENDING;
- }
-
- throw new IllegalArgumentException("Unsupported ordering: " + token.getText());
- }
-
- private static QuantifiedComparisonExpression.Quantifier getComparisonQuantifier(Token symbol)
- {
- switch (symbol.getType()) {
- case SqlBaseLexer.ALL:
- return QuantifiedComparisonExpression.Quantifier.ALL;
- case SqlBaseLexer.ANY:
- return QuantifiedComparisonExpression.Quantifier.ANY;
- case SqlBaseLexer.SOME:
- return QuantifiedComparisonExpression.Quantifier.SOME;
- }
-
- throw new IllegalArgumentException("Unsupported quantifier: " + symbol.getText());
- }
-
- private List getIdentifiers(List identifiers)
- {
- return identifiers.stream().map(context -> (Identifier) visit(context)).collect(toList());
- }
-
- private List getPrincipalSpecifications(List principals)
- {
- return principals.stream().map(this::getPrincipalSpecification).collect(toList());
- }
-
- private Optional getGrantorSpecificationIfPresent(SqlBaseParser.GrantorContext context)
- {
- return Optional.ofNullable(context).map(this::getGrantorSpecification);
- }
-
- private GrantorSpecification getGrantorSpecification(SqlBaseParser.GrantorContext context)
- {
- if (context instanceof SqlBaseParser.SpecifiedPrincipalContext) {
- return new GrantorSpecification(GrantorSpecification.Type.PRINCIPAL, Optional.of(getPrincipalSpecification(((SqlBaseParser.SpecifiedPrincipalContext) context).principal())));
- }
- else if (context instanceof SqlBaseParser.CurrentUserGrantorContext) {
- return new GrantorSpecification(GrantorSpecification.Type.CURRENT_USER, Optional.empty());
- }
- else if (context instanceof SqlBaseParser.CurrentRoleGrantorContext) {
- return new GrantorSpecification(GrantorSpecification.Type.CURRENT_ROLE, Optional.empty());
- }
- else {
- throw new IllegalArgumentException("Unsupported grantor: " + context);
- }
- }
-
- private PrincipalSpecification getPrincipalSpecification(SqlBaseParser.PrincipalContext context)
- {
- if (context instanceof SqlBaseParser.UnspecifiedPrincipalContext) {
- return new PrincipalSpecification(PrincipalSpecification.Type.UNSPECIFIED, (Identifier) visit(((SqlBaseParser.UnspecifiedPrincipalContext) context).identifier()));
- }
- else if (context instanceof SqlBaseParser.UserPrincipalContext) {
- return new PrincipalSpecification(PrincipalSpecification.Type.USER, (Identifier) visit(((SqlBaseParser.UserPrincipalContext) context).identifier()));
- }
- else if (context instanceof SqlBaseParser.RolePrincipalContext) {
- return new PrincipalSpecification(PrincipalSpecification.Type.ROLE, (Identifier) visit(((SqlBaseParser.RolePrincipalContext) context).identifier()));
- }
- else {
- throw new IllegalArgumentException("Unsupported principal: " + context);
- }
- }
-
- private static void check(boolean condition, String message, ParserRuleContext context)
- {
- if (!condition) {
- throw parseError(message, context);
- }
- }
-
- public static NodeLocation getLocation(TerminalNode terminalNode)
- {
- requireNonNull(terminalNode, "terminalNode is null");
- return getLocation(terminalNode.getSymbol());
- }
-
- public static NodeLocation getLocation(ParserRuleContext parserRuleContext)
- {
- requireNonNull(parserRuleContext, "parserRuleContext is null");
- return getLocation(parserRuleContext.getStart());
- }
-
- public static NodeLocation getLocation(Token token)
- {
- requireNonNull(token, "token is null");
- return new NodeLocation(token.getLine(), token.getCharPositionInLine() + 1);
- }
-
- private static ParsingException parseError(String message, ParserRuleContext context)
- {
- return new ParsingException(message, null, context.getStart().getLine(), context.getStart().getCharPositionInLine() + 1);
- }
-
- private static QueryPeriod.RangeType getRangeType(Token token)
- {
- switch (token.getType()) {
- case SqlBaseLexer.TIMESTAMP:
- return QueryPeriod.RangeType.TIMESTAMP;
- case SqlBaseLexer.VERSION:
- return QueryPeriod.RangeType.VERSION;
- }
- throw new IllegalArgumentException("Unsupported query period range type: " + token.getText());
- }
-
- /**
- * PostgreSQL syntax
- */
- private static void checkPgSchema(TerminalNode identifier)
- {
- if (isNull(identifier) || identifier.getText().equals("pg_catalog")) {
- return;
- }
-
- throw new IllegalArgumentException("Unsupported pg schema");
- }
-}
diff --git a/trino-parser/src/main/java/io/trino/sql/parser/CaseInsensitiveStream.java b/trino-parser/src/main/java/io/trino/sql/parser/CaseInsensitiveStream.java
deleted file mode 100644
index 8a0d665dd..000000000
--- a/trino-parser/src/main/java/io/trino/sql/parser/CaseInsensitiveStream.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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.parser;
-
-import org.antlr.v4.runtime.CharStream;
-import org.antlr.v4.runtime.IntStream;
-import org.antlr.v4.runtime.misc.Interval;
-
-public class CaseInsensitiveStream
- implements CharStream
-{
- private final CharStream stream;
-
- public CaseInsensitiveStream(CharStream stream)
- {
- this.stream = stream;
- }
-
- @Override
- public String getText(Interval interval)
- {
- return stream.getText(interval);
- }
-
- @Override
- public void consume()
- {
- stream.consume();
- }
-
- @Override
- public int LA(int i)
- {
- int result = stream.LA(i);
-
- switch (result) {
- case 0:
- case IntStream.EOF:
- return result;
- default:
- return Character.toUpperCase(result);
- }
- }
-
- @Override
- public int mark()
- {
- return stream.mark();
- }
-
- @Override
- public void release(int marker)
- {
- stream.release(marker);
- }
-
- @Override
- public int index()
- {
- return stream.index();
- }
-
- @Override
- public void seek(int index)
- {
- stream.seek(index);
- }
-
- @Override
- public int size()
- {
- return stream.size();
- }
-
- @Override
- public String getSourceName()
- {
- return stream.getSourceName();
- }
-}
diff --git a/trino-parser/src/main/java/io/trino/sql/parser/DelimiterLexer.java b/trino-parser/src/main/java/io/trino/sql/parser/DelimiterLexer.java
deleted file mode 100644
index 20a73c62f..000000000
--- a/trino-parser/src/main/java/io/trino/sql/parser/DelimiterLexer.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * 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.parser;
-
-import com.google.common.collect.ImmutableSet;
-import org.antlr.v4.runtime.CharStream;
-import org.antlr.v4.runtime.IntStream;
-import org.antlr.v4.runtime.LexerNoViableAltException;
-import org.antlr.v4.runtime.Token;
-
-import java.util.Set;
-
-/**
- * This is a special-purpose lexer that can identify custom delimiters in addition to every other
- * token in the SQL grammar.
- *
- * The code in nextToken() is a copy of the implementation in org.antlr.v4.runtime.Lexer, with a
- * bit added to match the token before the default behavior is invoked.
- */
-class DelimiterLexer
- extends SqlBaseLexer
-{
- private final Set delimiters;
-
- public DelimiterLexer(CharStream input, Set delimiters)
- {
- super(input);
- this.delimiters = ImmutableSet.copyOf(delimiters);
- }
-
- @Override
- public Token nextToken()
- {
- if (_input == null) {
- throw new IllegalStateException("nextToken requires a non-null input stream.");
- }
-
- // Mark start location in char stream so unbuffered streams are
- // guaranteed at least have text of current token
- int tokenStartMarker = _input.mark();
- try {
- outer:
- while (true) {
- if (_hitEOF) {
- emitEOF();
- return _token;
- }
-
- _token = null;
- _channel = Token.DEFAULT_CHANNEL;
- _tokenStartCharIndex = _input.index();
- _tokenStartCharPositionInLine = getInterpreter().getCharPositionInLine();
- _tokenStartLine = getInterpreter().getLine();
- _text = null;
- do {
- _type = Token.INVALID_TYPE;
- int ttype = -1;
-
- // This entire method is copied from org.antlr.v4.runtime.Lexer, with the following bit
- // added to match the delimiters before we attempt to match the token
- boolean found = false;
- for (String terminator : delimiters) {
- if (match(terminator)) {
- ttype = SqlBaseParser.DELIMITER;
- found = true;
- break;
- }
- }
-
- if (!found) {
- try {
- ttype = getInterpreter().match(_input, _mode);
- }
- catch (LexerNoViableAltException e) {
- notifyListeners(e); // report error
- recover(e);
- ttype = SKIP;
- }
- }
-
- if (_input.LA(1) == IntStream.EOF) {
- _hitEOF = true;
- }
- if (_type == Token.INVALID_TYPE) {
- _type = ttype;
- }
- if (_type == SKIP) {
- continue outer;
- }
- }
- while (_type == MORE);
- if (_token == null) {
- emit();
- }
- return _token;
- }
- }
- finally {
- // make sure we release marker after match or
- // unbuffered char stream will keep buffering
- _input.release(tokenStartMarker);
- }
- }
-
- private boolean match(String delimiter)
- {
- for (int i = 0; i < delimiter.length(); i++) {
- if (_input.LA(i + 1) != delimiter.charAt(i)) {
- return false;
- }
- }
- _input.seek(_input.index() + delimiter.length());
- return true;
- }
-}
diff --git a/trino-parser/src/main/java/io/trino/sql/parser/ErrorHandler.java b/trino-parser/src/main/java/io/trino/sql/parser/ErrorHandler.java
deleted file mode 100644
index f11601cc2..000000000
--- a/trino-parser/src/main/java/io/trino/sql/parser/ErrorHandler.java
+++ /dev/null
@@ -1,436 +0,0 @@
-/*
- * 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.parser;
-
-import com.google.common.collect.ImmutableSet;
-import org.antlr.v4.runtime.BaseErrorListener;
-import org.antlr.v4.runtime.NoViableAltException;
-import org.antlr.v4.runtime.Parser;
-import org.antlr.v4.runtime.RecognitionException;
-import org.antlr.v4.runtime.Recognizer;
-import org.antlr.v4.runtime.RuleContext;
-import org.antlr.v4.runtime.Token;
-import org.antlr.v4.runtime.TokenStream;
-import org.antlr.v4.runtime.Vocabulary;
-import org.antlr.v4.runtime.atn.ATN;
-import org.antlr.v4.runtime.atn.ATNState;
-import org.antlr.v4.runtime.atn.NotSetTransition;
-import org.antlr.v4.runtime.atn.PrecedencePredicateTransition;
-import org.antlr.v4.runtime.atn.RuleStartState;
-import org.antlr.v4.runtime.atn.RuleStopState;
-import org.antlr.v4.runtime.atn.RuleTransition;
-import org.antlr.v4.runtime.atn.Transition;
-import org.antlr.v4.runtime.atn.WildcardTransition;
-import org.antlr.v4.runtime.misc.IntervalSet;
-
-import java.util.ArrayDeque;
-import java.util.Deque;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.logging.Logger;
-import java.util.stream.Collectors;
-
-import static com.google.common.base.MoreObjects.firstNonNull;
-import static java.lang.String.format;
-import static java.util.logging.Level.SEVERE;
-import static org.antlr.v4.runtime.atn.ATNState.RULE_START;
-
-class ErrorHandler
- extends BaseErrorListener
-{
- private static final Logger LOG = Logger.getLogger(ErrorHandler.class.getName());
-
- private final Map specialRules;
- private final Map specialTokens;
- private final Set ignoredRules;
-
- private ErrorHandler(Map specialRules, Map specialTokens, Set ignoredRules)
- {
- this.specialRules = new HashMap<>(specialRules);
- this.specialTokens = specialTokens;
- this.ignoredRules = new HashSet<>(ignoredRules);
- }
-
- @Override
- public void syntaxError(Recognizer, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String message, RecognitionException e)
- {
- try {
- Parser parser = (Parser) recognizer;
-
- ATN atn = parser.getATN();
-
- ATNState currentState;
- Token currentToken;
- RuleContext context;
-
- if (e != null) {
- currentState = atn.states.get(e.getOffendingState());
- currentToken = e.getOffendingToken();
- context = e.getCtx();
-
- if (e instanceof NoViableAltException) {
- currentToken = ((NoViableAltException) e).getStartToken();
- }
- }
- else {
- currentState = atn.states.get(parser.getState());
- currentToken = parser.getCurrentToken();
- context = parser.getContext();
- }
-
- Analyzer analyzer = new Analyzer(parser, specialRules, specialTokens, ignoredRules);
- Result result = analyzer.process(currentState, currentToken.getTokenIndex(), context);
-
- // pick the candidate tokens associated largest token index processed (i.e., the path that consumed the most input)
- String expected = result.getExpected().stream()
- .sorted()
- .collect(Collectors.joining(", "));
-
- message = format("mismatched input '%s'. Expecting: %s", parser.getTokenStream().get(result.getErrorTokenIndex()).getText(), expected);
- }
- catch (Exception exception) {
- LOG.log(SEVERE, "Unexpected failure when handling parsing error. This is likely a bug in the implementation", exception);
- }
-
- throw new ParsingException(message, e, line, charPositionInLine + 1);
- }
-
- private static class ParsingState
- {
- public final ATNState state;
- public final int tokenIndex;
- public final boolean suppressed;
- public final Parser parser;
-
- public ParsingState(ATNState state, int tokenIndex, boolean suppressed, Parser parser)
- {
- this.state = state;
- this.tokenIndex = tokenIndex;
- this.suppressed = suppressed;
- this.parser = parser;
- }
-
- @Override
- public boolean equals(Object o)
- {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
- ParsingState that = (ParsingState) o;
- return tokenIndex == that.tokenIndex &&
- state.equals(that.state);
- }
-
- @Override
- public int hashCode()
- {
- return Objects.hash(state, tokenIndex);
- }
-
- @Override
- public String toString()
- {
- Token token = parser.getTokenStream().get(tokenIndex);
-
- String text = firstNonNull(token.getText(), "?");
- if (text != null) {
- text = text.replace("\\", "\\\\");
- text = text.replace("\n", "\\n");
- text = text.replace("\r", "\\r");
- text = text.replace("\t", "\\t");
- }
-
- return format(
- "%s%s:%s @ %s:<%s>:%s",
- suppressed ? "-" : "+",
- parser.getRuleNames()[state.ruleIndex],
- state.stateNumber,
- tokenIndex,
- parser.getVocabulary().getSymbolicName(token.getType()),
- text);
- }
- }
-
- private static class Analyzer
- {
- private final Parser parser;
- private final ATN atn;
- private final Vocabulary vocabulary;
- private final Map specialRules;
- private final Map specialTokens;
- private final Set ignoredRules;
- private final TokenStream stream;
-
- private int furthestTokenIndex = -1;
- private final Set candidates = new HashSet<>();
-
- private final Map> memo = new HashMap<>();
-
- public Analyzer(
- Parser parser,
- Map specialRules,
- Map specialTokens,
- Set ignoredRules)
- {
- this.parser = parser;
- this.stream = parser.getTokenStream();
- this.atn = parser.getATN();
- this.vocabulary = parser.getVocabulary();
- this.specialRules = specialRules;
- this.specialTokens = specialTokens;
- this.ignoredRules = ignoredRules;
- }
-
- public Result process(ATNState currentState, int tokenIndex, RuleContext context)
- {
- RuleStartState startState = atn.ruleToStartState[currentState.ruleIndex];
-
- if (isReachable(currentState, startState)) {
- // We've been dropped inside a rule in a state that's reachable via epsilon transitions. This is,
- // effectively, equivalent to starting at the beginning (or immediately outside) the rule.
- // In that case, backtrack to the beginning to be able to take advantage of logic that remaps
- // some rules to well-known names for reporting purposes
- currentState = startState;
- }
-
- Set endTokens = process(new ParsingState(currentState, tokenIndex, false, parser), 0);
- Set nextTokens = new HashSet<>();
- while (!endTokens.isEmpty() && context.invokingState != -1) {
- for (int endToken : endTokens) {
- ATNState nextState = ((RuleTransition) atn.states.get(context.invokingState).transition(0)).followState;
- nextTokens.addAll(process(new ParsingState(nextState, endToken, false, parser), 0));
- }
- context = context.parent;
- endTokens = nextTokens;
- }
-
- return new Result(furthestTokenIndex, candidates);
- }
-
- private boolean isReachable(ATNState target, RuleStartState from)
- {
- Deque activeStates = new ArrayDeque<>();
- activeStates.add(from);
-
- while (!activeStates.isEmpty()) {
- ATNState current = activeStates.pop();
-
- if (current.stateNumber == target.stateNumber) {
- return true;
- }
-
- for (int i = 0; i < current.getNumberOfTransitions(); i++) {
- Transition transition = current.transition(i);
-
- if (transition.isEpsilon()) {
- activeStates.push(transition.target);
- }
- }
- }
-
- return false;
- }
-
- private Set process(ParsingState start, int precedence)
- {
- Set result = memo.get(start);
- if (result != null) {
- return result;
- }
-
- ImmutableSet.Builder endTokens = ImmutableSet.builder();
-
- // Simulates the ATN by consuming input tokens and walking transitions.
- // The ATN can be in multiple states (similar to an NFA)
- Deque activeStates = new ArrayDeque<>();
- activeStates.add(start);
-
- while (!activeStates.isEmpty()) {
- ParsingState current = activeStates.pop();
-
- ATNState state = current.state;
- int tokenIndex = current.tokenIndex;
- boolean suppressed = current.suppressed;
-
- while (stream.get(tokenIndex).getChannel() == Token.HIDDEN_CHANNEL) {
- // Ignore whitespace
- tokenIndex++;
- }
- int currentToken = stream.get(tokenIndex).getType();
-
- if (state.getStateType() == RULE_START) {
- int rule = state.ruleIndex;
-
- if (specialRules.containsKey(rule)) {
- if (!suppressed) {
- record(tokenIndex, specialRules.get(rule));
- }
- suppressed = true;
- }
- else if (ignoredRules.contains(rule)) {
- // TODO expand ignored rules like we expand special rules
- continue;
- }
- }
-
- if (state instanceof RuleStopState) {
- endTokens.add(tokenIndex);
- continue;
- }
-
- for (int i = 0; i < state.getNumberOfTransitions(); i++) {
- Transition transition = state.transition(i);
-
- if (transition instanceof RuleTransition) {
- RuleTransition ruleTransition = (RuleTransition) transition;
- for (int endToken : process(new ParsingState(ruleTransition.target, tokenIndex, suppressed, parser), ruleTransition.precedence)) {
- activeStates.push(new ParsingState(ruleTransition.followState, endToken, suppressed, parser));
- }
- }
- else if (transition instanceof PrecedencePredicateTransition) {
- if (precedence < ((PrecedencePredicateTransition) transition).precedence) {
- activeStates.push(new ParsingState(transition.target, tokenIndex, suppressed, parser));
- }
- }
- else if (transition.isEpsilon()) {
- activeStates.push(new ParsingState(transition.target, tokenIndex, suppressed, parser));
- }
- else if (transition instanceof WildcardTransition) {
- throw new UnsupportedOperationException("not yet implemented: wildcard transition");
- }
- else {
- IntervalSet labels = transition.label();
-
- if (transition instanceof NotSetTransition) {
- labels = labels.complement(IntervalSet.of(Token.MIN_USER_TOKEN_TYPE, atn.maxTokenType));
- }
-
- // Surprisingly, TokenStream (i.e. BufferedTokenStream) may not have loaded all the tokens from the
- // underlying stream. TokenStream.get() does not force tokens to be buffered -- it just returns what's
- // in the current buffer, or fail with an IndexOutOfBoundsError. Since Antlr decided the error occurred
- // within the current set of buffered tokens, stop when we reach the end of the buffer.
- if (labels.contains(currentToken) && tokenIndex < stream.size() - 1) {
- activeStates.push(new ParsingState(transition.target, tokenIndex + 1, false, parser));
- }
- else {
- if (!suppressed) {
- record(tokenIndex, getTokenNames(labels));
- }
- }
- }
- }
- }
-
- result = endTokens.build();
- memo.put(start, result);
- return result;
- }
-
- private void record(int tokenIndex, String label)
- {
- record(tokenIndex, ImmutableSet.of(label));
- }
-
- private void record(int tokenIndex, Set labels)
- {
- if (tokenIndex >= furthestTokenIndex) {
- if (tokenIndex > furthestTokenIndex) {
- candidates.clear();
- furthestTokenIndex = tokenIndex;
- }
-
- candidates.addAll(labels);
- }
- }
-
- private Set getTokenNames(IntervalSet tokens)
- {
- Set names = new HashSet<>();
- for (int i = 0; i < tokens.size(); i++) {
- int token = tokens.get(i);
- if (token == Token.EOF) {
- names.add("");
- }
- else {
- names.add(specialTokens.getOrDefault(token, vocabulary.getDisplayName(token)));
- }
- }
-
- return names;
- }
- }
-
- public static Builder builder()
- {
- return new Builder();
- }
-
- public static class Builder
- {
- private final Map specialRules = new HashMap<>();
- private final Map specialTokens = new HashMap<>();
- private final Set ignoredRules = new HashSet<>();
-
- public Builder specialRule(int ruleId, String name)
- {
- specialRules.put(ruleId, name);
- return this;
- }
-
- public Builder specialToken(int tokenId, String name)
- {
- specialTokens.put(tokenId, name);
- return this;
- }
-
- public Builder ignoredRule(int ruleId)
- {
- ignoredRules.add(ruleId);
- return this;
- }
-
- public ErrorHandler build()
- {
- return new ErrorHandler(specialRules, specialTokens, ignoredRules);
- }
- }
-
- private static class Result
- {
- private final int errorTokenIndex;
- private final Set expected;
-
- public Result(int errorTokenIndex, Set expected)
- {
- this.errorTokenIndex = errorTokenIndex;
- this.expected = expected;
- }
-
- public int getErrorTokenIndex()
- {
- return errorTokenIndex;
- }
-
- public Set getExpected()
- {
- return expected;
- }
- }
-}
diff --git a/trino-parser/src/main/java/io/trino/sql/parser/ParsingException.java b/trino-parser/src/main/java/io/trino/sql/parser/ParsingException.java
deleted file mode 100644
index 3882d54f0..000000000
--- a/trino-parser/src/main/java/io/trino/sql/parser/ParsingException.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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.parser;
-
-import io.trino.sql.tree.NodeLocation;
-import org.antlr.v4.runtime.RecognitionException;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static java.lang.String.format;
-
-public class ParsingException
- extends RuntimeException
-{
- private final int line;
- private final int column;
-
- public ParsingException(String message, RecognitionException cause, int line, int column)
- {
- super(message, cause);
- checkArgument(line > 0, "line must be > 0");
- checkArgument(column > 0, "column must be > 0");
-
- this.line = line;
- this.column = column;
- }
-
- public ParsingException(String message)
- {
- this(message, null, 1, 1);
- }
-
- public ParsingException(String message, NodeLocation nodeLocation)
- {
- this(message, null, nodeLocation.getLineNumber(), nodeLocation.getColumnNumber());
- }
-
- public int getLineNumber()
- {
- return line;
- }
-
- public int getColumnNumber()
- {
- return column;
- }
-
- public String getErrorMessage()
- {
- return super.getMessage();
- }
-
- @Override
- public String getMessage()
- {
- return format("line %s:%s: %s", getLineNumber(), getColumnNumber(), getErrorMessage());
- }
-}
diff --git a/trino-parser/src/main/java/io/trino/sql/parser/ParsingOptions.java b/trino-parser/src/main/java/io/trino/sql/parser/ParsingOptions.java
deleted file mode 100644
index 4f0b203fe..000000000
--- a/trino-parser/src/main/java/io/trino/sql/parser/ParsingOptions.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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.parser;
-
-import static java.util.Objects.requireNonNull;
-
-public class ParsingOptions
-{
- public enum DecimalLiteralTreatment
- {
- AS_DOUBLE,
- AS_DECIMAL,
- REJECT
- }
-
- private final DecimalLiteralTreatment decimalLiteralTreatment;
-
- public ParsingOptions()
- {
- this(DecimalLiteralTreatment.REJECT);
- }
-
- public ParsingOptions(DecimalLiteralTreatment decimalLiteralTreatment)
- {
- this.decimalLiteralTreatment = requireNonNull(decimalLiteralTreatment, "decimalLiteralTreatment is null");
- }
-
- public DecimalLiteralTreatment getDecimalLiteralTreatment()
- {
- return decimalLiteralTreatment;
- }
-}
diff --git a/trino-parser/src/main/java/io/trino/sql/parser/RefreshableSqlBaseParserInitializer.java b/trino-parser/src/main/java/io/trino/sql/parser/RefreshableSqlBaseParserInitializer.java
deleted file mode 100644
index 91a207d15..000000000
--- a/trino-parser/src/main/java/io/trino/sql/parser/RefreshableSqlBaseParserInitializer.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.parser;
-
-import javax.annotation.concurrent.ThreadSafe;
-
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.BiConsumer;
-
-@ThreadSafe
-public final class RefreshableSqlBaseParserInitializer
- implements BiConsumer
-{
- private final AtomicReference caches = new AtomicReference<>();
-
- public RefreshableSqlBaseParserInitializer()
- {
- refresh();
- }
-
- public void refresh()
- {
- caches.set(new SqlBaseParserAndLexerATNCaches());
- }
-
- @Override
- public void accept(SqlBaseLexer lexer, SqlBaseParser parser)
- {
- SqlBaseParserAndLexerATNCaches caches = this.caches.get();
- caches.lexer.configureLexer(lexer);
- caches.parser.configureParser(parser);
- }
-
- private static final class SqlBaseParserAndLexerATNCaches
- {
- public final AntlrATNCacheFields lexer = new AntlrATNCacheFields(SqlBaseLexer._ATN);
- public final AntlrATNCacheFields parser = new AntlrATNCacheFields(SqlBaseParser._ATN);
- }
-}
diff --git a/trino-parser/src/main/java/io/trino/sql/parser/SqlParser.java b/trino-parser/src/main/java/io/trino/sql/parser/SqlParser.java
deleted file mode 100644
index 3b8c856de..000000000
--- a/trino-parser/src/main/java/io/trino/sql/parser/SqlParser.java
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * 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.parser;
-
-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;
-import org.antlr.v4.runtime.CommonToken;
-import org.antlr.v4.runtime.CommonTokenStream;
-import org.antlr.v4.runtime.DefaultErrorStrategy;
-import org.antlr.v4.runtime.InputMismatchException;
-import org.antlr.v4.runtime.Parser;
-import org.antlr.v4.runtime.ParserRuleContext;
-import org.antlr.v4.runtime.RecognitionException;
-import org.antlr.v4.runtime.Recognizer;
-import org.antlr.v4.runtime.Token;
-import org.antlr.v4.runtime.atn.PredictionMode;
-import org.antlr.v4.runtime.misc.Pair;
-import org.antlr.v4.runtime.misc.ParseCancellationException;
-import org.antlr.v4.runtime.tree.TerminalNode;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.function.BiConsumer;
-import java.util.function.Function;
-
-import static java.util.Objects.requireNonNull;
-
-public class SqlParser
-{
- private static final BaseErrorListener LEXER_ERROR_LISTENER = new BaseErrorListener()
- {
- @Override
- public void syntaxError(Recognizer, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String message, RecognitionException e)
- {
- throw new ParsingException(message, e, line, charPositionInLine + 1);
- }
- };
- private static final BiConsumer DEFAULT_PARSER_INITIALIZER = (SqlBaseLexer lexer, SqlBaseParser parser) -> {};
-
- private static final ErrorHandler PARSER_ERROR_HANDLER = ErrorHandler.builder()
- .specialRule(SqlBaseParser.RULE_expression, "")
- .specialRule(SqlBaseParser.RULE_booleanExpression, "")
- .specialRule(SqlBaseParser.RULE_valueExpression, "")
- .specialRule(SqlBaseParser.RULE_primaryExpression, "")
- .specialRule(SqlBaseParser.RULE_predicate, "")
- .specialRule(SqlBaseParser.RULE_identifier, "")
- .specialRule(SqlBaseParser.RULE_string, "")
- .specialRule(SqlBaseParser.RULE_query, "")
- .specialRule(SqlBaseParser.RULE_type, "")
- .specialToken(SqlBaseLexer.INTEGER_VALUE, "")
- .ignoredRule(SqlBaseParser.RULE_nonReserved)
- .build();
-
- private final BiConsumer initializer;
-
- public SqlParser()
- {
- this(DEFAULT_PARSER_INITIALIZER);
- }
-
- public SqlParser(BiConsumer initializer)
- {
- this.initializer = requireNonNull(initializer, "initializer is null");
- }
-
- public Statement createStatement(String sql, ParsingOptions parsingOptions)
- {
- return (Statement) invokeParser("statement", sql, SqlBaseParser::singleStatement, parsingOptions);
- }
-
- public Expression createExpression(String expression, ParsingOptions parsingOptions)
- {
- return (Expression) invokeParser("expression", expression, SqlBaseParser::standaloneExpression, parsingOptions);
- }
-
- public DataType createType(String expression)
- {
- return (DataType) invokeParser("type", expression, SqlBaseParser::standaloneType, new ParsingOptions());
- }
-
- public PathSpecification createPathSpecification(String expression)
- {
- 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 parseFunction, ParsingOptions parsingOptions)
- {
- try {
- SqlBaseLexer lexer = new SqlBaseLexer(new CaseInsensitiveStream(CharStreams.fromString(sql)));
- CommonTokenStream tokenStream = new CommonTokenStream(lexer);
- SqlBaseParser parser = new SqlBaseParser(tokenStream);
- initializer.accept(lexer, parser);
-
- // Override the default error strategy to not attempt inserting or deleting a token.
- // Otherwise, it messes up error reporting
- parser.setErrorHandler(new DefaultErrorStrategy()
- {
- @Override
- public Token recoverInline(Parser recognizer)
- throws RecognitionException
- {
- if (nextTokensContext == null) {
- throw new InputMismatchException(recognizer);
- }
- else {
- throw new InputMismatchException(recognizer, nextTokensState, nextTokensContext);
- }
- }
- });
-
- parser.addParseListener(new PostProcessor(Arrays.asList(parser.getRuleNames()), parser));
-
- lexer.removeErrorListeners();
- lexer.addErrorListener(LEXER_ERROR_LISTENER);
-
- parser.removeErrorListeners();
- parser.addErrorListener(PARSER_ERROR_HANDLER);
-
- ParserRuleContext tree;
- try {
- // first, try parsing with potentially faster SLL mode
- parser.getInterpreter().setPredictionMode(PredictionMode.SLL);
- tree = parseFunction.apply(parser);
- }
- catch (ParseCancellationException ex) {
- // if we fail, parse with LL mode
- tokenStream.seek(0); // rewind input stream
- parser.reset();
-
- parser.getInterpreter().setPredictionMode(PredictionMode.LL);
- tree = parseFunction.apply(parser);
- }
-
- return new AstBuilder(parsingOptions).visit(tree);
- }
- catch (StackOverflowError e) {
- throw new ParsingException(name + " is too large (stack overflow while parsing)");
- }
- }
-
- private static class PostProcessor
- extends SqlBaseBaseListener
- {
- private final List ruleNames;
- private final SqlBaseParser parser;
-
- public PostProcessor(List ruleNames, SqlBaseParser parser)
- {
- this.ruleNames = ruleNames;
- this.parser = parser;
- }
-
- @Override
- public void exitQuotedIdentifier(SqlBaseParser.QuotedIdentifierContext context)
- {
- Token token = context.QUOTED_IDENTIFIER().getSymbol();
- if (token.getText().length() == 2) { // empty identifier
- throw new ParsingException("Zero-length delimited identifier not allowed", null, token.getLine(), token.getCharPositionInLine() + 1);
- }
- }
-
- @Override
- public void exitBackQuotedIdentifier(SqlBaseParser.BackQuotedIdentifierContext context)
- {
- Token token = context.BACKQUOTED_IDENTIFIER().getSymbol();
- throw new ParsingException(
- "backquoted identifiers are not supported; use double quotes to quote identifiers",
- null,
- token.getLine(),
- token.getCharPositionInLine() + 1);
- }
-
- @Override
- public void exitDigitIdentifier(SqlBaseParser.DigitIdentifierContext context)
- {
- Token token = context.DIGIT_IDENTIFIER().getSymbol();
- throw new ParsingException(
- "identifiers must not start with a digit; surround the identifier with double quotes",
- null,
- token.getLine(),
- token.getCharPositionInLine() + 1);
- }
-
- @Override
- public void exitNonReserved(SqlBaseParser.NonReservedContext context)
- {
- // we can't modify the tree during rule enter/exit event handling unless we're dealing with a terminal.
- // Otherwise, ANTLR gets confused and fires spurious notifications.
- if (!(context.getChild(0) instanceof TerminalNode)) {
- int rule = ((ParserRuleContext) context.getChild(0)).getRuleIndex();
- throw new AssertionError("nonReserved can only contain tokens. Found nested rule: " + ruleNames.get(rule));
- }
-
- // replace nonReserved words with IDENT tokens
- context.getParent().removeLastChild();
-
- Token token = (Token) context.getChild(0).getPayload();
- Token newToken = new CommonToken(
- new Pair<>(token.getTokenSource(), token.getInputStream()),
- SqlBaseLexer.IDENTIFIER,
- token.getChannel(),
- token.getStartIndex(),
- token.getStopIndex());
-
- context.getParent().addChild(parser.createTerminalNode(context.getParent(), newToken));
- }
- }
-}
diff --git a/trino-parser/src/main/java/io/trino/sql/parser/StatementSplitter.java b/trino-parser/src/main/java/io/trino/sql/parser/StatementSplitter.java
deleted file mode 100644
index 7385a2b2b..000000000
--- a/trino-parser/src/main/java/io/trino/sql/parser/StatementSplitter.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * 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.parser;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import org.antlr.v4.runtime.CharStream;
-import org.antlr.v4.runtime.CharStreams;
-import org.antlr.v4.runtime.Token;
-import org.antlr.v4.runtime.TokenSource;
-
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
-
-import static java.util.Objects.requireNonNull;
-
-public class StatementSplitter
-{
- private final List completeStatements;
- private final String partialStatement;
-
- public StatementSplitter(String sql)
- {
- this(sql, ImmutableSet.of(";"));
- }
-
- public StatementSplitter(String sql, Set delimiters)
- {
- TokenSource tokens = getLexer(sql, delimiters);
- ImmutableList.Builder list = ImmutableList.builder();
- StringBuilder sb = new StringBuilder();
- while (true) {
- Token token = tokens.nextToken();
- if (token.getType() == Token.EOF) {
- break;
- }
- if (token.getType() == SqlBaseParser.DELIMITER) {
- String statement = sb.toString().trim();
- if (!statement.isEmpty()) {
- list.add(new Statement(statement, token.getText()));
- }
- sb = new StringBuilder();
- }
- else {
- sb.append(token.getText());
- }
- }
- this.completeStatements = list.build();
- this.partialStatement = sb.toString().trim();
- }
-
- public List getCompleteStatements()
- {
- return completeStatements;
- }
-
- public String getPartialStatement()
- {
- return partialStatement;
- }
-
- public static String squeezeStatement(String sql)
- {
- TokenSource tokens = getLexer(sql, ImmutableSet.of());
- StringBuilder sb = new StringBuilder();
- while (true) {
- Token token = tokens.nextToken();
- if (token.getType() == Token.EOF) {
- break;
- }
- if (token.getType() == SqlBaseLexer.WS) {
- sb.append(' ');
- }
- else {
- sb.append(token.getText());
- }
- }
- return sb.toString().trim();
- }
-
- public static boolean isEmptyStatement(String sql)
- {
- TokenSource tokens = getLexer(sql, ImmutableSet.of());
- while (true) {
- Token token = tokens.nextToken();
- if (token.getType() == Token.EOF) {
- return true;
- }
- if (token.getChannel() != Token.HIDDEN_CHANNEL) {
- return false;
- }
- }
- }
-
- public static TokenSource getLexer(String sql, Set terminators)
- {
- requireNonNull(sql, "sql is null");
- CharStream stream = new CaseInsensitiveStream(CharStreams.fromString(sql));
- return new DelimiterLexer(stream, terminators);
- }
-
- public static class Statement
- {
- private final String statement;
- private final String terminator;
-
- public Statement(String statement, String terminator)
- {
- this.statement = requireNonNull(statement, "statement is null");
- this.terminator = requireNonNull(terminator, "terminator is null");
- }
-
- public String statement()
- {
- return statement;
- }
-
- public String terminator()
- {
- return terminator;
- }
-
- @Override
- public boolean equals(Object obj)
- {
- if (this == obj) {
- return true;
- }
- if ((obj == null) || (getClass() != obj.getClass())) {
- return false;
- }
- Statement o = (Statement) obj;
- return Objects.equals(statement, o.statement) &&
- Objects.equals(terminator, o.terminator);
- }
-
- @Override
- public int hashCode()
- {
- return Objects.hash(statement, terminator);
- }
-
- @Override
- public String toString()
- {
- return statement + terminator;
- }
- }
-}
diff --git a/trino-parser/src/main/java/io/trino/sql/testing/TreeAssertions.java b/trino-parser/src/main/java/io/trino/sql/testing/TreeAssertions.java
deleted file mode 100644
index f57151532..000000000
--- a/trino-parser/src/main/java/io/trino/sql/testing/TreeAssertions.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * 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.testing;
-
-import com.google.common.base.Joiner;
-import com.google.common.collect.ImmutableList;
-import io.trino.sql.parser.ParsingException;
-import io.trino.sql.parser.ParsingOptions;
-import io.trino.sql.parser.SqlParser;
-import io.trino.sql.tree.DefaultTraversalVisitor;
-import io.trino.sql.tree.Node;
-import io.trino.sql.tree.Statement;
-
-import javax.annotation.Nullable;
-
-import java.util.List;
-
-import static io.trino.sql.SqlFormatter.formatSql;
-import static io.trino.sql.parser.ParsingOptions.DecimalLiteralTreatment.AS_DOUBLE;
-import static java.lang.String.format;
-
-public final class TreeAssertions
-{
- private TreeAssertions() {}
-
- public static void assertFormattedSql(SqlParser sqlParser, Node expected)
- {
- ParsingOptions parsingOptions = new ParsingOptions(AS_DOUBLE /* anything */);
- assertFormattedSql(sqlParser, parsingOptions, expected);
- }
-
- public static void assertFormattedSql(SqlParser sqlParser, ParsingOptions parsingOptions, Node expected)
- {
- String formatted = formatSql(expected);
-
- // verify round-trip of formatting already-formatted SQL
- Statement actual = parseFormatted(sqlParser, parsingOptions, formatted, expected);
- assertEquals(formatSql(actual), formatted);
-
- // compare parsed tree with parsed tree of formatted SQL
- if (!actual.equals(expected)) {
- // simplify finding the non-equal part of the tree
- assertListEquals(linearizeTree(actual), linearizeTree(expected));
- }
- assertEquals(actual, expected);
- }
-
- private static Statement parseFormatted(SqlParser sqlParser, ParsingOptions parsingOptions, String sql, Node tree)
- {
- try {
- return sqlParser.createStatement(sql, parsingOptions);
- }
- catch (ParsingException e) {
- String message = format("failed to parse formatted SQL: %s\nerror: %s\ntree: %s", sql, e.getMessage(), tree);
- throw new AssertionError(message, e);
- }
- }
-
- private static List linearizeTree(Node tree)
- {
- ImmutableList.Builder nodes = ImmutableList.builder();
- new DefaultTraversalVisitor()
- {
- @Override
- public Void process(Node node, @Nullable Void context)
- {
- super.process(node, context);
- nodes.add(node);
- return null;
- }
- }.process(tree, null);
- return nodes.build();
- }
-
- private static void assertListEquals(List actual, List expected)
- {
- if (actual.size() != expected.size()) {
- throw new AssertionError(format("Lists not equal in size%n%s", formatLists(actual, expected)));
- }
- if (!actual.equals(expected)) {
- throw new AssertionError(format("Lists not equal at index %s%n%s",
- differingIndex(actual, expected), formatLists(actual, expected)));
- }
- }
-
- private static String formatLists(List actual, List expected)
- {
- Joiner joiner = Joiner.on("\n ");
- return format("Actual [%s]:%n %s%nExpected [%s]:%n %s%n",
- actual.size(), joiner.join(actual),
- expected.size(), joiner.join(expected));
- }
-
- private static int differingIndex(List actual, List expected)
- {
- for (int i = 0; i < actual.size(); i++) {
- if (!actual.get(i).equals(expected.get(i))) {
- return i;
- }
- }
- return actual.size();
- }
-
- private static void assertEquals(T actual, T expected)
- {
- if (!actual.equals(expected)) {
- throw new AssertionError(format("expected [%s] but found [%s]", expected, actual));
- }
- }
-}
diff --git a/trino-parser/src/main/java/io/trino/sql/tree/AddColumn.java b/trino-parser/src/main/java/io/trino/sql/tree/AddColumn.java
deleted file mode 100644
index 5ed85a0f0..000000000
--- a/trino-parser/src/main/java/io/trino/sql/tree/AddColumn.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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 AddColumn
- extends Statement
-{
- private final QualifiedName name;
- private final ColumnDefinition column;
- private final boolean tableExists;
- private final boolean columnNotExists;
-
- public AddColumn(QualifiedName name, ColumnDefinition column, boolean tableExists, boolean columnNotExists)
- {
- this(Optional.empty(), name, column, tableExists, columnNotExists);
- }
-
- public AddColumn(NodeLocation location, QualifiedName name, ColumnDefinition column, boolean tableExists, boolean columnNotExists)
- {
- this(Optional.of(location), name, column, tableExists, columnNotExists);
- }
-
- private AddColumn(Optional location, QualifiedName name, ColumnDefinition column, boolean tableExists, boolean columnNotExists)
- {
- super(location);
- this.name = requireNonNull(name, "name is null");
- this.column = requireNonNull(column, "column is null");
- this.tableExists = tableExists;
- this.columnNotExists = columnNotExists;
- }
-
- public QualifiedName getName()
- {
- return name;
- }
-
- public ColumnDefinition getColumn()
- {
- return column;
- }
-
- public boolean isTableExists()
- {
- return tableExists;
- }
-
- public boolean isColumnNotExists()
- {
- return columnNotExists;
- }
-
- @Override
- public R accept(AstVisitor visitor, C context)
- {
- return visitor.visitAddColumn(this, context);
- }
-
- @Override
- public List getChildren()
- {
- return ImmutableList.of(column);
- }
-
- @Override
- public int hashCode()
- {
- return Objects.hash(name, column);
- }
-
- @Override
- public boolean equals(Object obj)
- {
- if (this == obj) {
- return true;
- }
- if ((obj == null) || (getClass() != obj.getClass())) {
- return false;
- }
- AddColumn o = (AddColumn) obj;
- return Objects.equals(name, o.name) &&
- Objects.equals(column, o.column);
- }
-
- @Override
- public String toString()
- {
- return toStringHelper(this)
- .add("name", name)
- .add("column", column)
- .toString();
- }
-}
diff --git a/trino-parser/src/main/java/io/trino/sql/tree/AliasedRelation.java b/trino-parser/src/main/java/io/trino/sql/tree/AliasedRelation.java
deleted file mode 100644
index ab05f2fc0..000000000
--- a/trino-parser/src/main/java/io/trino/sql/tree/AliasedRelation.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * 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 AliasedRelation
- extends Relation
-{
- private final Relation relation;
- private final Identifier alias;
- private final List columnNames;
-
- public AliasedRelation(Relation relation, Identifier alias, List columnNames)
- {
- this(Optional.empty(), relation, alias, columnNames);
- }
-
- public AliasedRelation(NodeLocation location, Relation relation, Identifier alias, List columnNames)
- {
- this(Optional.of(location), relation, alias, columnNames);
- }
-
- private AliasedRelation(Optional location, Relation relation, Identifier alias, List columnNames)
- {
- super(location);
- requireNonNull(relation, "relation is null");
- requireNonNull(alias, "alias is null");
-
- this.relation = relation;
- this.alias = alias;
- this.columnNames = columnNames;
- }
-
- public Relation getRelation()
- {
- return relation;
- }
-
- public Identifier getAlias()
- {
- return alias;
- }
-
- public List getColumnNames()
- {
- return columnNames;
- }
-
- @Override
- public R accept(AstVisitor visitor, C context)
- {
- return visitor.visitAliasedRelation(this, context);
- }
-
- @Override
- public List getChildren()
- {
- return ImmutableList.of(relation);
- }
-
- @Override
- public String toString()
- {
- return toStringHelper(this)
- .add("relation", relation)
- .add("alias", alias)
- .add("columnNames", columnNames)
- .omitNullValues()
- .toString();
- }
-
- @Override
- public boolean equals(Object o)
- {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
-
- AliasedRelation that = (AliasedRelation) o;
- return Objects.equals(relation, that.relation) &&
- Objects.equals(alias, that.alias) &&
- Objects.equals(columnNames, that.columnNames);
- }
-
- @Override
- public int hashCode()
- {
- return Objects.hash(relation, alias, columnNames);
- }
-
- @Override
- public boolean shallowEquals(Node other)
- {
- if (!sameClass(this, other)) {
- return false;
- }
-
- AliasedRelation otherRelation = (AliasedRelation) other;
- return alias.equals(otherRelation.alias) && Objects.equals(columnNames, otherRelation.columnNames);
- }
-}
diff --git a/trino-parser/src/main/java/io/trino/sql/tree/AllColumns.java b/trino-parser/src/main/java/io/trino/sql/tree/AllColumns.java
deleted file mode 100644
index eeecac138..000000000
--- a/trino-parser/src/main/java/io/trino/sql/tree/AllColumns.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * 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.base.Joiner;
-import com.google.common.collect.ImmutableList;
-
-import java.util.List;
-import java.util.Objects;
-import java.util.Optional;
-
-import static java.util.Objects.requireNonNull;
-
-public class AllColumns
- extends SelectItem
-{
- private final List aliases;
- private final Optional target;
-
- public AllColumns()
- {
- this(Optional.empty(), Optional.empty(), ImmutableList.of());
- }
-
- public AllColumns(Expression target)
- {
- this(Optional.empty(), Optional.of(target), ImmutableList.of());
- }
-
- public AllColumns(Expression target, List aliases)
- {
- this(Optional.empty(), Optional.of(target), aliases);
- }
-
- public AllColumns(NodeLocation location, Optional target, List aliases)
- {
- this(Optional.of(location), target, aliases);
- }
-
- public AllColumns(Optional location, Optional