public static void printStatement(String sql) { println(sql.trim()); println(""); System.out.println("STATE Printing CommonTree toString..."); CommonTree tree = VeroSqlParser.parseStatement(sql); println(TreePrinter.treeToString(tree)); println(""); System.out.println("STATE Printing AST toString..."); Statement statement = VeroSqlParser.createStatement(tree); println(statement.toString()); println(""); System.out.println("STATE Printing Format sql toString..."); // TODO: support formatting all statement types if (statement instanceof Query) { println(FormatterFactory.getSqlFormatter().formatSql(statement)); println(""); } println(repeat("=", 60)); println(""); }
@Override public ResultSet executeQuery(String sql) throws SQLException { //System.out.println("QUERY: ["+sql+"]"); if(connection.getSchema() == null) throw new SQLException("No active index set for this driver. Pleas specify an active index or alias by executing 'USE <index/alias>' first"); sql = sql.replaceAll("\r", " ").replaceAll("\n", " "); com.facebook.presto.sql.tree.Statement statement = parser.createStatement(sql); if(statement instanceof Query){ if(this.result != null) this.result.close(); queryState.buildRequest(sql, ((Query)statement).getQueryBody(), connection.getSchema()); this.result = queryState.execute(); return this.result; }else if(statement instanceof Explain){ String ex = queryState.explain(sql, (Explain)statement, connection.getSchema()); if(this.result != null) this.result.close(); Heading heading = new Heading(); heading.add(new Column("Explanation")); ESResultSet rs = new ESResultSet(heading, 1, 1); List<Object> row = rs.getNewRow(); row.set(0, ex); rs.add(row); this.result = rs; return result; }else throw new SQLException("Provided query is not a SELECT or EXPLAIN query"); }
private String getFormattedSql(CreateView statement) { Query query = statement.getQuery(); String sql = formatSql(query); // verify round-trip Statement parsed; try { parsed = sqlParser.createStatement(sql); } catch (ParsingException e) { throw new PrestoException(INTERNAL_ERROR, "Formatted query does not parse: " + query); } if (!query.equals(parsed)) { throw new PrestoException(INTERNAL_ERROR, "Query does not round-trip: " + query); } return sql; }
@Override protected PlanBuilder visitQuery(Query query, Void context) { PlanBuilder builder = planQueryBody(query); builder = appendSemiJoins(builder, analysis.getInPredicates(query)); builder = appendScalarSubqueryJoins(builder, analysis.getScalarSubqueries(query)); List<FieldOrExpression> orderBy = analysis.getOrderByExpressions(query); List<FieldOrExpression> outputs = analysis.getOutputExpressions(query); builder = project(builder, Iterables.concat(orderBy, outputs)); builder = sort(builder, query); builder = project(builder, analysis.getOutputExpressions(query)); builder = limit(builder, query); return builder; }
@Override protected RelationType visitShowColumns(ShowColumns showColumns, AnalysisContext context) { QualifiedObjectName tableName = createQualifiedObjectName(session, showColumns, showColumns.getTable()); if (!metadata.getView(session, tableName).isPresent() && !metadata.getTableHandle(session, tableName).isPresent()) { throw new SemanticException(MISSING_TABLE, showColumns, "Table '%s' does not exist", tableName); } Query query = simpleQuery( selectList( aliasedName("column_name", "Column"), aliasedName("data_type", "Type"), aliasedNullToEmpty("comment", "Comment")), from(tableName.getCatalogName(), TABLE_COLUMNS), logicalAnd( equal(nameReference("table_schema"), new StringLiteral(tableName.getSchemaName())), equal(nameReference("table_name"), new StringLiteral(tableName.getObjectName()))), ordering(ascending("ordinal_position"))); return process(query, context); }
@Override protected RelationType visitQuery(Query node, AnalysisContext parentContext) { AnalysisContext context = new AnalysisContext(parentContext); if (node.getApproximate().isPresent()) { if (!experimentalSyntaxEnabled) { throw new SemanticException(NOT_SUPPORTED, node, "approximate queries are not enabled"); } context.setApproximate(true); } analyzeWith(node, context); RelationType descriptor = process(node.getQueryBody(), context); analyzeOrderBy(node, descriptor, context); // Input fields == Output fields analysis.setOutputDescriptor(node, descriptor); analysis.setOutputExpressions(node, descriptorToFields(descriptor)); analysis.setQuery(node); return descriptor; }
@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())); }
protected CompletableFuture<List<SchemaField>> metadata(RequestContext context, String query) { StringBuilder builder = new StringBuilder(); Query queryStatement = (Query) SqlUtil.parseSql(query); CompletableFuture<List<SchemaField>> f = new CompletableFuture<>(); try { new RakamSqlFormatter.Formatter(builder, qualifiedName -> queryExecutor.formatTableReference(context.project, qualifiedName, Optional.empty(), ImmutableMap.of()), escapeIdentifier) .process(queryStatement, 1); } catch (Exception e) { f.completeExceptionally(e); } QueryExecution execution = queryExecutor.executeRawQuery(context, builder.toString() + " limit 0", ZoneOffset.UTC, ImmutableMap.of()); execution.getResult().thenAccept(result -> { if (result.isFailed()) { f.completeExceptionally(new RakamException(result.getError().message, INTERNAL_SERVER_ERROR)); } else { f.complete(result.getMetadata()); } }); return f; }
@Test(enabled = false) public void testName() throws Exception { String s = "select count(*) from test where ali = 5"; Statement statement = new SqlParser().createStatement(s); Analysis analysis = new Analysis(statement, ImmutableList.of(), false); Session build = Session.builder(new SessionPropertyManager()) .setQueryId(QueryId.valueOf("test")) .setCatalog("test") .setCatalog("test") .setCatalog("test") .build(); QueryPlanner queryPlanner = new QueryPlanner(analysis, new SymbolAllocator(), new PlanNodeIdAllocator(), null, null, build); RelationPlan plan = queryPlanner.plan((Query) statement); // EffectivePredicateExtractor.extract(plan.getRoot(), ImmutableMap.of(new Symbol("ali"), BIGINT)); EffectivePredicateExtractor.extract(plan.getRoot()); }
@Override protected Void visitQuery(Query node, Integer indent) { if (node.getWith().isPresent()) { With with = node.getWith().get(); append(indent, "WITH"); if (with.isRecursive()) { builder.append(" RECURSIVE"); } builder.append("\n "); Iterator<WithQuery> queries = with.getQueries().iterator(); while (queries.hasNext()) { WithQuery query = queries.next(); append(indent, query.getName()); query.getColumnNames().ifPresent(columnNames -> appendAliasColumns(builder, columnNames)); builder.append(" AS "); process(new TableSubquery(query.getQuery()), indent); builder.append('\n'); if (queries.hasNext()) { builder.append(", "); } } } processRelation(node.getQueryBody(), indent); if (node.getOrderBy().isPresent()) { append(indent, "ORDER BY " + formatSortItems(node.getOrderBy().get().getSortItems(), parameters, indent)) .append('\n'); } if (node.getLimit().isPresent()) { append(indent, "LIMIT " + node.getLimit().get()) .append('\n'); } return null; }
@Override public int executeUpdate(String sql) throws SQLException { //System.out.println("QUERY: ["+sql+"]"); sql = sql.replaceAll("\r", " ").replaceAll("\n", " ").trim(); // custom stuff to support UPDATE statements since Presto does not parse it if(sql.toLowerCase().startsWith("update")){ return updateState.execute(sql); } com.facebook.presto.sql.tree.Statement statement = parser.createStatement(sql); if(statement instanceof Query) throw new SQLException("A regular query cannot be executed as an Update"); if(statement instanceof Insert){ //if(connection.getSchema() == null) throw new SQLException("No active index set for this driver. Pleas specify an active index or alias by executing 'USE <index/alias>' first"); return updateState.execute(sql, (Insert)statement, connection.getSchema()); }else if(statement instanceof Delete){ if(connection.getSchema() == null) throw new SQLException("No active index set for this driver. Pleas specify an active index or alias by executing 'USE <index/alias>' first"); return updateState.execute(sql, (Delete)statement, connection.getSchema()); }else if(statement instanceof CreateTable){ return updateState.execute(sql, (CreateTable)statement, connection.getSchema()); }else if(statement instanceof CreateTableAsSelect){ return updateState.execute(sql, (CreateTableAsSelect)statement, connection.getSchema()); }else if(statement instanceof CreateView){ return updateState.execute(sql, (CreateView)statement, connection.getSchema()); }else if(statement instanceof Use){ connection.setSchema( ((Use)statement).getSchema()); //connection.getTypeMap(); // updates the type mappings found in properties return 0; }else if(statement instanceof DropTable){ return updateState.execute(sql, (DropTable)statement); }else if(statement instanceof DropView){ return updateState.execute(sql, (DropView)statement); }throw new SQLFeatureNotSupportedException("Unable to parse provided update sql"); }
private PlanBuilder planQueryBody(Query query) { RelationPlan relationPlan = new RelationPlanner(analysis, symbolAllocator, idAllocator, metadata, session) .process(query.getQueryBody(), null); TranslationMap translations = new TranslationMap(relationPlan, analysis); // Make field->symbol mapping from underlying relation plan available for translations // This makes it possible to rewrite FieldOrExpressions that reference fields from the QuerySpecification directly translations.setFieldMappings(relationPlan.getOutputSymbols()); return new PlanBuilder(translations, relationPlan.getRoot(), relationPlan.getSampleWeight()); }
@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)); }
@Override protected RelationPlan visitQuery(Query node, Void context) { PlanBuilder subPlan = new QueryPlanner(analysis, symbolAllocator, idAllocator, metadata, session).process(node, null); ImmutableList.Builder<Symbol> outputSymbols = ImmutableList.builder(); for (FieldOrExpression fieldOrExpression : analysis.getOutputExpressions(node)) { outputSymbols.add(subPlan.translate(fieldOrExpression)); } return new RelationPlan(subPlan.getRoot(), analysis.getOutputDescriptor(node), outputSymbols.build(), subPlan.getSampleWeight()); }
public Query getNamedQuery(String name) { Query result = namedQueries.get(name); if (result == null && parent != null) { return parent.getNamedQuery(name); } return result; }
public void registerNamedQuery(Table tableReference, Query query) { requireNonNull(tableReference, "tableReference is null"); requireNonNull(query, "query is null"); namedQueries.put(tableReference, query); }
@Override protected RelationType visitShowSchemas(ShowSchemas node, AnalysisContext context) { if (!node.getCatalog().isPresent() && !session.getCatalog().isPresent()) { throw new SemanticException(CATALOG_NOT_SPECIFIED, node, "Catalog must be specified when session catalog is not set"); } Query query = simpleQuery( selectList(aliasedName("schema_name", "Schema")), from(node.getCatalog().orElseGet(() -> session.getCatalog().get()), TABLE_SCHEMATA), ordering(ascending("schema_name"))); return process(query, context); }
@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); }
@Override protected RelationType visitShowFunctions(ShowFunctions node, AnalysisContext context) { ImmutableList.Builder<Expression> rows = ImmutableList.builder(); for (SqlFunction function : metadata.listFunctions()) { if (function.getSignature().getKind() == APPROXIMATE_AGGREGATE) { continue; } rows.add(row( new StringLiteral(function.getSignature().getName()), new StringLiteral(function.getSignature().getReturnType().toString()), new StringLiteral(Joiner.on(", ").join(function.getSignature().getArgumentTypes())), new StringLiteral(getFunctionType(function)), function.isDeterministic() ? TRUE_LITERAL : FALSE_LITERAL, new StringLiteral(nullToEmpty(function.getDescription())))); } Map<String, String> columns = ImmutableMap.<String, String>builder() .put("function_name", "Function") .put("return_type", "Return Type") .put("argument_types", "Argument Types") .put("function_type", "Function Type") .put("deterministic", "Deterministic") .put("description", "Description") .build(); Query query = simpleQuery( selectAll(columns.entrySet().stream() .map(entry -> aliasedName(entry.getKey(), entry.getValue())) .collect(toImmutableList())), aliased(new Values(rows.build()), "functions", ImmutableList.copyOf(columns.keySet())), ordering( ascending("function_name"), ascending("return_type"), ascending("argument_types"), ascending("function_type"))); return process(query, context); }
@Override protected RelationType visitShowSession(ShowSession node, AnalysisContext context) { ImmutableList.Builder<Expression> rows = ImmutableList.builder(); List<SessionPropertyValue> sessionProperties = metadata.getSessionPropertyManager().getAllSessionProperties(session); for (SessionPropertyValue sessionProperty : sessionProperties) { if (sessionProperty.isHidden()) { continue; } String value = sessionProperty.getValue(); String defaultValue = sessionProperty.getDefaultValue(); rows.add(row( new StringLiteral(sessionProperty.getFullyQualifiedName()), new StringLiteral(nullToEmpty(value)), new StringLiteral(nullToEmpty(defaultValue)), new StringLiteral(sessionProperty.getType()), new StringLiteral(sessionProperty.getDescription()), TRUE_LITERAL)); } // add bogus row so we can support empty sessions StringLiteral empty = new StringLiteral(""); rows.add(row(empty, empty, empty, empty, empty, FALSE_LITERAL)); Query query = simpleQuery( selectList( aliasedName("name", "Name"), aliasedName("value", "Value"), aliasedName("default", "Default"), aliasedName("type", "Type"), aliasedName("description", "Description")), aliased( new Values(rows.build()), "session", ImmutableList.of("name", "value", "default", "type", "description", "include")), nameReference("include")); return process(query, context); }
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 analyzeWith(Query node, AnalysisContext context) { // analyze WITH clause if (!node.getWith().isPresent()) { return; } With with = node.getWith().get(); if (with.isRecursive()) { throw new SemanticException(NOT_SUPPORTED, with, "Recursive WITH queries are not supported"); } for (WithQuery withQuery : with.getQueries()) { if (withQuery.getColumnNames() != null && !withQuery.getColumnNames().isEmpty()) { throw new SemanticException(NOT_SUPPORTED, withQuery, "Column alias not supported in WITH queries"); } Query query = withQuery.getQuery(); process(query, context); String name = withQuery.getName(); if (context.isNamedQueryDeclared(name)) { throw new SemanticException(DUPLICATE_RELATION, withQuery, "WITH query name '%s' specified more than once", name); } context.addNamedQuery(name, query); } }
@Override public Node visitInsertInto(SqlBaseParser.InsertIntoContext context) { return new Insert( getQualifiedName(context.qualifiedName()), Optional.ofNullable(getColumnAliases(context.columnAliases())), (Query) visit(context.query())); }
@Override public Node visitCreateView(SqlBaseParser.CreateViewContext context) { return new CreateView( getLocation(context), getQualifiedName(context.qualifiedName()), (Query) visit(context.query()), context.REPLACE() != null); }
@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.getLimit(), body.getApproximate()); }
@Override public Node visitQueryNoWith(SqlBaseParser.QueryNoWithContext context) { QueryBody term = (QueryBody) visit(context.queryTerm()); if (term instanceof QuerySpecification) { // When we have a simple query specification // followed by order by limit, fold the order by and limit // 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.<With>empty(), new QuerySpecification( getLocation(context), query.getSelect(), query.getFrom(), query.getWhere(), query.getGroupBy(), query.getHaving(), visit(context.sortItem(), SortItem.class), getTextIfPresent(context.limit)), ImmutableList.of(), Optional.<String>empty(), getTextIfPresent(context.confidence) .map(confidence -> new Approximate(getLocation(context), confidence))); } return new Query( getLocation(context), Optional.<With>empty(), term, visit(context.sortItem(), SortItem.class), getTextIfPresent(context.limit), getTextIfPresent(context.confidence) .map(confidence -> new Approximate(getLocation(context), confidence))); }
public static Query simpleQuery(Select select, Relation from, Optional<Expression> where, List<GroupingElement> groupBy, Optional<Expression> having, List<SortItem> ordering, Optional<String> limit) { return query(new QuerySpecification( select, Optional.of(from), where, groupBy, having, ordering, limit)); }
public static Query query(QueryBody body) { return new Query( Optional.empty(), body, ImmutableList.of(), Optional.empty(), Optional.empty()); }
@Test public void testIntersect() { assertStatement("SELECT 123 INTERSECT DISTINCT SELECT 123 INTERSECT ALL SELECT 123", new Query( Optional.empty(), new Intersect(ImmutableList.of( new Intersect(ImmutableList.of(createSelect123(), createSelect123()), true), createSelect123() ), false), ImmutableList.of(), Optional.empty(), Optional.empty())); }
@Test public void testUnion() { assertStatement("SELECT 123 UNION DISTINCT SELECT 123 UNION ALL SELECT 123", new Query( Optional.empty(), new Union(ImmutableList.of( new Union(ImmutableList.of(createSelect123(), createSelect123()), true), createSelect123() ), false), ImmutableList.<SortItem>of(), Optional.empty(), Optional.empty())); }
@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)); }
@SuppressWarnings("unchecked") public int execute(String update) throws SQLException { Matcher matcher = updateRegex.matcher(update); if(!matcher.find()) throw new SQLException("Unable to parse UPDATE statement"); // get index and type to update String index = statement.getConnection().getSchema(); String type = matcher.group(1); if(matcher.group(2) != null){ index = type; type = matcher.group(2); } // get fields and values to update try{ Map<String, Object> fieldValues = new HashMap<String, Object>(); SqlParser parser = new SqlParser(); String[] parts = matcher.group(3).replaceAll(",\\s*([\"|\\w|\\.]+\\s*=)", "<-SPLIT->$1").split("<-SPLIT->"); for(String p : parts){ ComparisonExpression comparison = (ComparisonExpression) parser.createExpression(p); String field = comparison.getLeft().toString().replaceAll("\"", ""); field = Heading.findOriginal(matcher.group(3), field, "", "\\s*="); Object value = getLiteralValue(comparison.getRight()); if(field.indexOf('.') == -1) { fieldValues.put(field, value); continue; } // create nested object Map<String, Object> map = fieldValues; String[] objectDef = field.split("\\."); for(int k=0; k<objectDef.length; k++){ String key = objectDef[k]; if(k == objectDef.length-1) map.put(key, value); else{ if(!map.containsKey(key)) map.put(key, new HashMap<String, Object>()); map = (Map<String, Object>)map.get(key); } } } // get ID's for documents to be updated String select = "SELECT _id FROM "+type+" WHERE "+matcher.group(4); Query query = (Query)new SqlParser().createStatement(select); this.queryState.buildRequest(select, query.getQueryBody(), index); ResultSet rs = this.queryState.execute(); // execute updates in batch mode based on id's returned int maxRequestsPerBulk = Utils.getIntProp(props, Utils.PROP_FETCH_SIZE, 2500); List<UpdateRequestBuilder> indexReqs = new ArrayList<UpdateRequestBuilder>(); int updateCount = 0; while(rs != null){ while(rs.next()){ String id = rs.getString(1); indexReqs.add( client.prepareUpdate(index, type, id).setDoc(fieldValues) ); if(indexReqs.size() >= maxRequestsPerBulk){ updateCount += this.execute(indexReqs, maxRequestsPerBulk); indexReqs.clear(); } } rs.close(); rs = queryState.moreResults(true); } if(indexReqs.size() > 0) updateCount += this.execute(indexReqs, maxRequestsPerBulk); return updateCount; }catch(Exception e){ throw new SQLException("Unable to execute UPDATE due to "+e.getMessage(),e); } }
private PlanBuilder sort(PlanBuilder subPlan, Query node) { return sort(subPlan, node.getOrderBy(), node.getLimit(), analysis.getOrderByExpressions(node)); }
private PlanBuilder limit(PlanBuilder subPlan, Query node) { return limit(subPlan, node.getOrderBy(), node.getLimit()); }
public void addNamedQuery(String name, Query query) { Preconditions.checkState(!namedQueries.containsKey(name), "Named query already registered: %s", name); namedQueries.put(name, query); }
public Query getQuery() { return query; }
public void setQuery(Query query) { this.query = query; }
public Query getNamedQuery(Table table) { return namedQueries.get(table); }