@Override protected List<QuerySource> visitQueryBody(QueryBody node, QueryState state){ ArrayList<QuerySource> relations = new ArrayList<QuerySource>(); if(node instanceof Table){ String table = ((Table)node).getName().toString(); // resolve relations provided in dot notation (schema.index.type) and just get the type for now String[] catIndexType = table.split("\\."); if(catIndexType.length == 1) { relations.add(new QuerySource(table)); }else{ relations.add(new QuerySource(catIndexType[catIndexType.length-1])); } }else if (node instanceof TableSubquery){ TableSubquery ts = (TableSubquery)node; Object alias = state.getValue("table_alias"); Pattern queryRegex = Pattern.compile("from\\s*\\((.+)\\)\\s*(where|as|having|limit|$"+(alias==null ? "":"|"+alias)+")", Pattern.CASE_INSENSITIVE); Matcher m = queryRegex.matcher(state.originalSql()); if(m.find()) { relations.add(new QuerySource(m.group(1), ts.getQuery().getQueryBody())); }else state.addException("Unable to parse provided subquery in FROM clause"); }else state.addException("Unable to parse FROM clause, "+node.getClass().getName()+" is not supported"); return relations; }
@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 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 Void visitTable(Table node, Integer indent) { builder.append(formatName(node.getName())); return null; }
private void processRelation(Relation relation, Integer indent) { if (relation instanceof Table) { builder.append("TABLE ") .append(((Table) relation).getName()) .append('\n'); } else { process(relation, indent); } }
@Override protected RelationPlan visitTable(Table node, Void context) { Query namedQuery = analysis.getNamedQuery(node); if (namedQuery != null) { RelationPlan subPlan = process(namedQuery, null); return new RelationPlan(subPlan.getRoot(), analysis.getOutputDescriptor(node), subPlan.getOutputSymbols(), subPlan.getSampleWeight()); } RelationType descriptor = analysis.getOutputDescriptor(node); TableHandle handle = analysis.getTableHandle(node); ImmutableList.Builder<Symbol> outputSymbolsBuilder = ImmutableList.builder(); ImmutableMap.Builder<Symbol, ColumnHandle> columns = ImmutableMap.builder(); for (Field field : descriptor.getAllFields()) { Symbol symbol = symbolAllocator.newSymbol(field.getName().get(), field.getType()); outputSymbolsBuilder.add(symbol); columns.put(symbol, analysis.getColumn(field)); } List<Symbol> planOutputSymbols = outputSymbolsBuilder.build(); Optional<ColumnHandle> sampleWeightColumn = metadata.getSampleWeightColumnHandle(session, handle); Symbol sampleWeightSymbol = null; if (sampleWeightColumn.isPresent()) { sampleWeightSymbol = symbolAllocator.newSymbol("$sampleWeight", BIGINT); outputSymbolsBuilder.add(sampleWeightSymbol); columns.put(sampleWeightSymbol, sampleWeightColumn.get()); } List<Symbol> nodeOutputSymbols = outputSymbolsBuilder.build(); PlanNode root = new TableScanNode(idAllocator.getNextId(), handle, nodeOutputSymbols, columns.build(), Optional.empty(), TupleDomain.all(), null); return new RelationPlan(root, descriptor, planOutputSymbols, Optional.ofNullable(sampleWeightSymbol)); }
public void registerNamedQuery(Table tableReference, Query query) { requireNonNull(tableReference, "tableReference is null"); requireNonNull(query, "query is null"); namedQueries.put(tableReference, query); }
@Override protected RelationType visitDelete(Delete node, AnalysisContext context) { Table table = node.getTable(); QualifiedObjectName tableName = createQualifiedObjectName(session, table, table.getName()); if (metadata.getView(session, tableName).isPresent()) { throw new SemanticException(NOT_SUPPORTED, node, "Deleting from views is not supported"); } analysis.setUpdateType("DELETE"); analysis.setDelete(node); // Analyzer checks for select permissions but DELETE has a separate permission, so disable access checks // TODO: we shouldn't need to create a new analyzer. The access control should be carried in the context object StatementAnalyzer analyzer = new StatementAnalyzer( analysis, metadata, sqlParser, new AllowAllAccessControl(), session, experimentalSyntaxEnabled, queryExplainer); RelationType descriptor = analyzer.process(table, context); node.getWhere().ifPresent(where -> analyzer.analyzeWhere(node, descriptor, context, where)); accessControl.checkCanDeleteFromTable(session.getRequiredTransactionId(), session.getIdentity(), tableName); return new RelationType(Field.newUnqualified("rows", BIGINT)); }
private Query parseView(String view, QualifiedObjectName name, Table node) { try { Statement statement = sqlParser.createStatement(view); return checkType(statement, Query.class, "parsed view"); } catch (ParsingException e) { throw new SemanticException(VIEW_PARSE_ERROR, node, "Failed parsing stored view '%s': %s", name, e.getMessage()); } }
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); } }
@Override public Node visitDelete(SqlBaseParser.DeleteContext context) { return new Delete( getLocation(context), new Table(getLocation(context), getQualifiedName(context.qualifiedName())), visitIfPresent(context.booleanExpression(), Expression.class)); }
@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())))); }
public TableHandle getTableHandle(Table table) { return tables.get(table); }
public void registerTable(Table table, TableHandle handle) { tables.put(table, handle); }
public Query getNamedQuery(Table table) { return namedQueries.get(table); }
@Override protected Void visitTable(Table node, Integer indent) { builder.append(node.getName().toString()); return null; }
@Override public Node visitTable(SqlBaseParser.TableContext context) { return new Table(getLocation(context), getQualifiedName(context.qualifiedName())); }
@Override public Node visitTableName(SqlBaseParser.TableNameContext context) { return new Table(getLocation(context), getQualifiedName(context.qualifiedName())); }
public static Table table(QualifiedName name) { return new Table(name); }
@Test public void testSelectWithRowType() throws Exception { assertStatement("SELECT col1.f1, col2, col3.f1.f2.f3 FROM table1", new Query( Optional.empty(), new QuerySpecification( selectList( new DereferenceExpression(new QualifiedNameReference(QualifiedName.of("col1")), "f1"), new QualifiedNameReference(QualifiedName.of("col2")), new DereferenceExpression( new DereferenceExpression(new DereferenceExpression(new QualifiedNameReference(QualifiedName.of("col3")), "f1"), "f2"), "f3")), Optional.of(new Table(QualifiedName.of("table1"))), Optional.empty(), ImmutableList.of(), Optional.empty(), ImmutableList.of(), Optional.empty()), ImmutableList.<SortItem>of(), Optional.empty(), Optional.empty())); assertStatement("SELECT col1.f1[0], col2, col3[2].f2.f3, col4[4] FROM table1", new Query( Optional.empty(), new QuerySpecification( selectList( new SubscriptExpression(new DereferenceExpression(new QualifiedNameReference(QualifiedName.of("col1")), "f1"), new LongLiteral("0")), new QualifiedNameReference(QualifiedName.of("col2")), new DereferenceExpression(new DereferenceExpression(new SubscriptExpression(new QualifiedNameReference(QualifiedName.of("col3")), new LongLiteral("2")), "f2"), "f3"), new SubscriptExpression(new QualifiedNameReference(QualifiedName.of("col4")), new LongLiteral("4")) ), Optional.of(new Table(QualifiedName.of("table1"))), Optional.empty(), ImmutableList.of(), Optional.empty(), ImmutableList.of(), Optional.empty()), ImmutableList.<SortItem>of(), Optional.empty(), Optional.empty())); assertStatement("SELECT test_row(11, 12).col0", new Query( Optional.empty(), new QuerySpecification( selectList( new DereferenceExpression(new FunctionCall(QualifiedName.of("test_row"), Lists.newArrayList(new LongLiteral("11"), new LongLiteral("12"))), "col0") ), Optional.empty(), Optional.empty(), ImmutableList.of(), Optional.empty(), ImmutableList.of(), Optional.empty()), ImmutableList.<SortItem>of(), Optional.empty(), Optional.empty())); }