@Override public void visit(Select obj) { visitNodes(obj.getFrom()); visitNodes(obj.getDerivedColumns()); visitNode(obj.getWhere()); visitNode(obj.getGroupBy()); visitNode(obj.getHaving()); visitNode(obj.getOrderBy()); visitNode(obj.getLimit()); if (this.doScanEvaluation) { HashMap<String, String> options = buildTableMetadata( this.scanTable.getName(), this.scanTable.getColumns(), this.ef.getEncoding()); options.put(EvaluatorIterator.QUERYSTRING, SQLStringVisitor.getSQLString(obj.getWhere())); IteratorSetting it = new IteratorSetting(1, EvaluatorIterator.class, options); this.scanIterators.add(it); } if (this.selectColumns.size() < this.scanTable.getColumns().size()) { HashMap<String, String> options = buildTableMetadata(this.scanTable.getName(), this.selectColumns, this.ef.getEncoding()); IteratorSetting it = new IteratorSetting(iteratorPriority++, LimitProjectionIterator.class, options); this.scanIterators.add(it); } }
@Override public List<?> translateCommand(Command command, ExecutionContext context) { if (command instanceof Insert) { try { handleInsertSequences((Insert) command); } catch (TranslatorException e) { throw new RuntimeException(e); } } if (!(command instanceof QueryExpression)) { return null; } QueryExpression queryCommand = (QueryExpression) command; if (queryCommand.getLimit() == null) { return null; } Limit limit = queryCommand.getLimit(); queryCommand.setLimit(null); if (command instanceof Select) { Select select = (Select) command; TableReference tr = select.getFrom().get(0); if (tr instanceof NamedTable && isDual((NamedTable) tr)) { if (limit.getRowOffset() > 0 || limit.getRowLimit() == 0) { // no data select.setWhere( new Comparison( new Literal(1, TypeFacility.RUNTIME_TYPES.INTEGER), new Literal(0, TypeFacility.RUNTIME_TYPES.INTEGER), Operator.EQ)); return null; } return null; // dual does not allow a limit } } List<Object> parts = new ArrayList<Object>(); parts.add("SELECT "); // $NON-NLS-1$ /* * if all of the columns are aliased, assume that names matter - it actually only seems to matter for * the first query of a set op when there is a order by. Rather than adding logic to traverse up, * we just use the projected names */ boolean allAliased = true; for (DerivedColumn selectSymbol : queryCommand.getProjectedQuery().getDerivedColumns()) { if (selectSymbol.getAlias() == null) { allAliased = false; break; } } if (allAliased) { String[] columnNames = queryCommand.getColumnNames(); for (int i = 0; i < columnNames.length; i++) { if (i > 0) { parts.add(", "); // $NON-NLS-1$ } parts.add(columnNames[i]); } } else { parts.add("*"); // $NON-NLS-1$ } if (limit.getRowOffset() > 0) { parts.add(" FROM (SELECT VIEW_FOR_LIMIT.*, ROWNUM ROWNUM_ FROM ("); // $NON-NLS-1$ } else { parts.add(" FROM ("); // $NON-NLS-1$ } parts.add(queryCommand); if (limit.getRowOffset() > 0) { parts.add(") VIEW_FOR_LIMIT WHERE ROWNUM <= "); // $NON-NLS-1$ parts.add(limit.getRowLimit() + limit.getRowOffset()); parts.add(") WHERE ROWNUM_ > "); // $NON-NLS-1$ parts.add(limit.getRowOffset()); } else { parts.add(") WHERE ROWNUM <= "); // $NON-NLS-1$ parts.add(limit.getRowLimit()); } return parts; }