@Test public void testLimitAll() { Query valuesQuery = query(values( row(new LongLiteral("1"), new StringLiteral("1")), row(new LongLiteral("2"), new StringLiteral("2")))); assertStatement("SELECT * FROM (VALUES (1, '1'), (2, '2')) LIMIT ALL", simpleQuery(selectList(new AllColumns()), subquery(valuesQuery), Optional.empty(), ImmutableList.of(), Optional.empty(), ImmutableList.of(), Optional.of("ALL"))); }
@Test public void testWith() throws Exception { assertStatement("WITH a (t, u) AS (SELECT * FROM x), b AS (SELECT * FROM y) TABLE z", new Query(Optional.of(new With(false, ImmutableList.of( new WithQuery("a", simpleQuery(selectList(new AllColumns()), table(QualifiedName.of("x"))), ImmutableList.of("t", "u")), new WithQuery("b", simpleQuery(selectList(new AllColumns()), table(QualifiedName.of("y"))), null)))), new Table(QualifiedName.of("z")), ImmutableList.of(), Optional.<String>empty(), Optional.<Approximate>empty())); assertStatement("WITH RECURSIVE a AS (SELECT * FROM x) TABLE y", new Query(Optional.of(new With(true, ImmutableList.of( new WithQuery("a", simpleQuery(selectList(new AllColumns()), table(QualifiedName.of("x"))), null)))), new Table(QualifiedName.of("y")), ImmutableList.of(), Optional.<String>empty(), Optional.<Approximate>empty())); }
@Test public void testExplain() throws Exception { assertStatement("EXPLAIN SELECT * FROM t", new Explain(simpleQuery(selectList(new AllColumns()), table(QualifiedName.of("t"))), ImmutableList.of())); assertStatement("EXPLAIN (TYPE LOGICAL) SELECT * FROM t", new Explain( simpleQuery(selectList(new AllColumns()), table(QualifiedName.of("t"))), ImmutableList.of(new ExplainType(ExplainType.Type.LOGICAL)))); assertStatement("EXPLAIN (TYPE LOGICAL, FORMAT TEXT) SELECT * FROM t", new Explain( simpleQuery(selectList(new AllColumns()), table(QualifiedName.of("t"))), ImmutableList.of( new ExplainType(ExplainType.Type.LOGICAL), new ExplainFormat(ExplainFormat.Type.TEXT)))); }
@Test public void testUnnest() throws Exception { assertStatement("SELECT * FROM t CROSS JOIN UNNEST(a)", simpleQuery( selectList(new AllColumns()), new Join( Join.Type.CROSS, new Table(QualifiedName.of("t")), new Unnest(ImmutableList.of(new QualifiedNameReference(QualifiedName.of("a"))), false), Optional.empty()))); assertStatement("SELECT * FROM t CROSS JOIN UNNEST(a) WITH ORDINALITY", simpleQuery( selectList(new AllColumns()), new Join( Join.Type.CROSS, new Table(QualifiedName.of("t")), new Unnest(ImmutableList.of(new QualifiedNameReference(QualifiedName.of("a"))), true), Optional.empty()))); }
@Override protected String visitAllColumns(AllColumns node, Void context) { if (node.getPrefix().isPresent()) { return node.getPrefix().get() + ".*"; } return "*"; }
@Override protected String visitAllColumns(AllColumns node, StackableAstVisitorContext<Integer> indent) { if (node.getPrefix().isPresent()) { return node.getPrefix().get() + ".*"; } return "*"; }
@Override protected Void visitAllColumns(AllColumns node, Integer context) { builder.append(node.toString()); return null; }
@Override protected RelationType visitShowCatalogs(ShowCatalogs node, AnalysisContext context) { List<Expression> rows = metadata.getCatalogNames().keySet().stream() .map(name -> row(new StringLiteral(name))) .collect(toList()); Query query = simpleQuery( selectList(new AllColumns()), aliased(new Values(rows), "catalogs", ImmutableList.of("Catalog"))); return process(query, context); }
private RelationType computeOutputDescriptor(QuerySpecification node, RelationType inputTupleDescriptor) { ImmutableList.Builder<Field> outputFields = ImmutableList.builder(); for (SelectItem item : node.getSelect().getSelectItems()) { if (item instanceof AllColumns) { // expand * and T.* Optional<QualifiedName> starPrefix = ((AllColumns) item).getPrefix(); for (Field field : inputTupleDescriptor.resolveFieldsWithPrefix(starPrefix)) { outputFields.add(Field.newUnqualified(field.getName(), field.getType())); } } else if (item instanceof SingleColumn) { SingleColumn column = (SingleColumn) item; Expression expression = column.getExpression(); Optional<String> alias = column.getAlias(); if (!alias.isPresent()) { QualifiedName name = null; if (expression instanceof QualifiedNameReference) { name = ((QualifiedNameReference) expression).getName(); } else if (expression instanceof DereferenceExpression) { name = DereferenceExpression.getQualifiedName((DereferenceExpression) expression); } if (name != null) { alias = Optional.of(getLast(name.getOriginalParts())); } } outputFields.add(Field.newUnqualified(alias, analysis.getType(expression))); // TODO don't use analysis as a side-channel. Use outputExpressions to look up the type } else { throw new IllegalArgumentException("Unsupported SelectItem type: " + item.getClass().getName()); } } return new RelationType(outputFields.build()); }
@Override public Node visitSelectAll(SqlBaseParser.SelectAllContext context) { if (context.qualifiedName() != null) { return new AllColumns(getLocation(context), getQualifiedName(context.qualifiedName())); } return new AllColumns(getLocation(context)); }
@Override protected String visitAllColumns(AllColumns node, Boolean unmangleNames) { if (node.getPrefix().isPresent()) { return node.getPrefix().get() + ".*"; } return "*"; }
@Test public void testValues() { Query valuesQuery = query(values( row(new StringLiteral("a"), new LongLiteral("1"), new DoubleLiteral("2.2")), row(new StringLiteral("b"), new LongLiteral("2"), new DoubleLiteral("3.3")))); assertStatement("VALUES ('a', 1, 2.2), ('b', 2, 3.3)", valuesQuery); assertStatement("SELECT * FROM (VALUES ('a', 1, 2.2), ('b', 2, 3.3))", simpleQuery( selectList(new AllColumns()), subquery(valuesQuery))); }
@Test public void testInsertInto() throws Exception { QualifiedName table = QualifiedName.of("a"); Query query = simpleQuery(selectList(new AllColumns()), table(QualifiedName.of("t"))); assertStatement("INSERT INTO a SELECT * FROM t", new Insert(table, Optional.empty(), query)); assertStatement("INSERT INTO a (c1, c2) SELECT * FROM t", new Insert(table, Optional.of(ImmutableList.of("c1", "c2")), query)); }
@Test public void testCreateView() throws Exception { assertStatement("CREATE VIEW a AS SELECT * FROM t", new CreateView( QualifiedName.of("a"), simpleQuery(selectList(new AllColumns()), table(QualifiedName.of("t"))), false)); assertStatement("CREATE OR REPLACE VIEW a AS SELECT * FROM t", new CreateView( QualifiedName.of("a"), simpleQuery(selectList(new AllColumns()), table(QualifiedName.of("t"))), true)); }
@Test public void testImplicitJoin() throws Exception { assertStatement("SELECT * FROM a, b", simpleQuery(selectList(new AllColumns()), new Join(Join.Type.IMPLICIT, new Table(QualifiedName.of("a")), new Table(QualifiedName.of("b")), Optional.<JoinCriteria>empty()))); }
@Test public void testJoinPrecedence() { assertStatement("SELECT * FROM a CROSS JOIN b LEFT JOIN c ON true", simpleQuery( selectList(new AllColumns()), new Join( Join.Type.LEFT, new Join( Join.Type.CROSS, new Table(QualifiedName.of("a")), new Table(QualifiedName.of("b")), Optional.empty() ), new Table(QualifiedName.of("c")), Optional.of(new JoinOn(BooleanLiteral.TRUE_LITERAL))))); assertStatement("SELECT * FROM a CROSS JOIN b NATURAL JOIN c CROSS JOIN d NATURAL JOIN e", simpleQuery( selectList(new AllColumns()), new Join( Join.Type.INNER, new Join( Join.Type.CROSS, new Join( Join.Type.INNER, new Join( Join.Type.CROSS, new Table(QualifiedName.of("a")), new Table(QualifiedName.of("b")), Optional.empty() ), new Table(QualifiedName.of("c")), Optional.of(new NaturalJoin())), new Table(QualifiedName.of("d")), Optional.empty() ), new Table(QualifiedName.of("e")), Optional.of(new NaturalJoin())))); }
private List<FieldOrExpression> analyzeSelect(QuerySpecification node, RelationType tupleDescriptor, AnalysisContext context) { ImmutableList.Builder<FieldOrExpression> outputExpressionBuilder = ImmutableList.builder(); for (SelectItem item : node.getSelect().getSelectItems()) { if (item instanceof AllColumns) { // expand * and T.* Optional<QualifiedName> starPrefix = ((AllColumns) item).getPrefix(); List<Field> fields = tupleDescriptor.resolveFieldsWithPrefix(starPrefix); if (fields.isEmpty()) { if (starPrefix.isPresent()) { throw new SemanticException(MISSING_TABLE, item, "Table '%s' not found", starPrefix.get()); } else { throw new SemanticException(WILDCARD_WITHOUT_FROM, item, "SELECT * not allowed in queries without FROM clause"); } } for (Field field : fields) { int fieldIndex = tupleDescriptor.indexOf(field); outputExpressionBuilder.add(new FieldOrExpression(fieldIndex)); if (node.getSelect().isDistinct() && !field.getType().isComparable()) { throw new SemanticException(TYPE_MISMATCH, node.getSelect(), "DISTINCT can only be applied to comparable types (actual: %s)", field.getType()); } } } else if (item instanceof SingleColumn) { SingleColumn column = (SingleColumn) item; ExpressionAnalysis expressionAnalysis = analyzeExpression(column.getExpression(), tupleDescriptor, context); analysis.recordSubqueries(node, expressionAnalysis); outputExpressionBuilder.add(new FieldOrExpression(column.getExpression())); Type type = expressionAnalysis.getType(column.getExpression()); if (node.getSelect().isDistinct() && !type.isComparable()) { throw new SemanticException(TYPE_MISMATCH, node.getSelect(), "DISTINCT can only be applied to comparable types (actual: %s): %s", type, column.getExpression()); } } else { throw new IllegalArgumentException("Unsupported SelectItem type: " + item.getClass().getName()); } } ImmutableList<FieldOrExpression> result = outputExpressionBuilder.build(); analysis.setOutputExpressions(node, result); return result; }