Search in sources :

Example 1 with SqlShuttle

use of org.apache.calcite.sql.util.SqlShuttle in project calcite by apache.

the class SqlTesterImpl method buildQuery2.

/**
 * Builds a query that extracts all literals as columns in an underlying
 * select.
 *
 * <p>For example,</p>
 *
 * <blockquote>{@code 1 < 5}</blockquote>
 *
 * <p>becomes</p>
 *
 * <blockquote>{@code SELECT p0 < p1
 * FROM (VALUES (1, 5)) AS t(p0, p1)}</blockquote>
 *
 * <p>Null literals don't have enough type information to be extracted.
 * We push down {@code CAST(NULL AS type)} but raw nulls such as
 * {@code CASE 1 WHEN 2 THEN 'a' ELSE NULL END} are left as is.</p>
 *
 * @param expression Scalar expression
 * @return Query that evaluates a scalar expression
 */
private String buildQuery2(String expression) {
    // "values (1 < 5)"
    // becomes
    // "select p0 < p1 from (values (1, 5)) as t(p0, p1)"
    SqlNode x;
    final String sql = "values (" + expression + ")";
    try {
        x = parseQuery(sql);
    } catch (SqlParseException e) {
        throw new RuntimeException(e);
    }
    final Collection<SqlNode> literalSet = new LinkedHashSet<>();
    x.accept(new SqlShuttle() {

        private final List<SqlOperator> ops = ImmutableList.of(SqlStdOperatorTable.LITERAL_CHAIN, SqlStdOperatorTable.LOCALTIME, SqlStdOperatorTable.LOCALTIMESTAMP, SqlStdOperatorTable.CURRENT_TIME, SqlStdOperatorTable.CURRENT_TIMESTAMP);

        @Override
        public SqlNode visit(SqlLiteral literal) {
            if (!isNull(literal) && literal.getTypeName() != SqlTypeName.SYMBOL) {
                literalSet.add(literal);
            }
            return literal;
        }

        @Override
        public SqlNode visit(SqlCall call) {
            final SqlOperator operator = call.getOperator();
            if (operator == SqlStdOperatorTable.CAST && isNull(call.operand(0))) {
                literalSet.add(call);
                return call;
            } else if (ops.contains(operator)) {
                // literal"
                return call;
            } else {
                return super.visit(call);
            }
        }

        private boolean isNull(SqlNode sqlNode) {
            return sqlNode instanceof SqlLiteral && ((SqlLiteral) sqlNode).getTypeName() == SqlTypeName.NULL;
        }
    });
    final List<SqlNode> nodes = new ArrayList<>(literalSet);
    Collections.sort(nodes, new Comparator<SqlNode>() {

        public int compare(SqlNode o1, SqlNode o2) {
            final SqlParserPos pos0 = o1.getParserPosition();
            final SqlParserPos pos1 = o2.getParserPosition();
            int c = -Utilities.compare(pos0.getLineNum(), pos1.getLineNum());
            if (c != 0) {
                return c;
            }
            return -Utilities.compare(pos0.getColumnNum(), pos1.getColumnNum());
        }
    });
    String sql2 = sql;
    final List<Pair<String, String>> values = new ArrayList<>();
    int p = 0;
    for (SqlNode literal : nodes) {
        final SqlParserPos pos = literal.getParserPosition();
        final int start = SqlParserUtil.lineColToIndex(sql, pos.getLineNum(), pos.getColumnNum());
        final int end = SqlParserUtil.lineColToIndex(sql, pos.getEndLineNum(), pos.getEndColumnNum()) + 1;
        String param = "p" + (p++);
        values.add(Pair.of(sql2.substring(start, end), param));
        sql2 = sql2.substring(0, start) + param + sql2.substring(end);
    }
    if (values.isEmpty()) {
        values.add(Pair.of("1", "p0"));
    }
    return "select " + sql2.substring("values (".length(), sql2.length() - 1) + " from (values (" + Util.commaList(Pair.left(values)) + ")) as t(" + Util.commaList(Pair.right(values)) + ")";
}
Also used : LinkedHashSet(java.util.LinkedHashSet) SqlShuttle(org.apache.calcite.sql.util.SqlShuttle) SqlParseException(org.apache.calcite.sql.parser.SqlParseException) SqlParserPos(org.apache.calcite.sql.parser.SqlParserPos) SqlOperator(org.apache.calcite.sql.SqlOperator) SqlCall(org.apache.calcite.sql.SqlCall) ArrayList(java.util.ArrayList) SqlLiteral(org.apache.calcite.sql.SqlLiteral) SqlNode(org.apache.calcite.sql.SqlNode) Pair(org.apache.calcite.util.Pair)

Example 2 with SqlShuttle

use of org.apache.calcite.sql.util.SqlShuttle in project flink by apache.

the class SqlValidatorImpl method getParameterRowType.

public RelDataType getParameterRowType(SqlNode sqlQuery) {
    // NOTE: We assume that bind variables occur in depth-first tree
    // traversal in the same order that they occurred in the SQL text.
    final List<RelDataType> types = new ArrayList<>();
    // NOTE: but parameters on fetch/offset would be counted twice
    // as they are counted in the SqlOrderBy call and the inner SqlSelect call
    final Set<SqlNode> alreadyVisited = new HashSet<>();
    sqlQuery.accept(new SqlShuttle() {

        @Override
        public SqlNode visit(SqlDynamicParam param) {
            if (alreadyVisited.add(param)) {
                RelDataType type = getValidatedNodeType(param);
                types.add(type);
            }
            return param;
        }
    });
    return typeFactory.createStructType(types, new AbstractList<String>() {

        @Override
        public String get(int index) {
            return "?" + index;
        }

        @Override
        public int size() {
            return types.size();
        }
    });
}
Also used : SqlShuttle(org.apache.calcite.sql.util.SqlShuttle) SqlDynamicParam(org.apache.calcite.sql.SqlDynamicParam) ArrayList(java.util.ArrayList) RelDataType(org.apache.calcite.rel.type.RelDataType) BitString(org.apache.calcite.util.BitString) SqlNode(org.apache.calcite.sql.SqlNode) HashSet(java.util.HashSet)

Example 3 with SqlShuttle

use of org.apache.calcite.sql.util.SqlShuttle in project calcite by apache.

the class SqlValidatorImpl method getParameterRowType.

public RelDataType getParameterRowType(SqlNode sqlQuery) {
    // NOTE: We assume that bind variables occur in depth-first tree
    // traversal in the same order that they occurred in the SQL text.
    final List<RelDataType> types = new ArrayList<>();
    // NOTE: but parameters on fetch/offset would be counted twice
    // as they are counted in the SqlOrderBy call and the inner SqlSelect call
    final Set<SqlNode> alreadyVisited = new HashSet<>();
    sqlQuery.accept(new SqlShuttle() {

        @Override
        public SqlNode visit(SqlDynamicParam param) {
            if (alreadyVisited.add(param)) {
                RelDataType type = getValidatedNodeType(param);
                types.add(type);
            }
            return param;
        }
    });
    return typeFactory.createStructType(types, new AbstractList<String>() {

        @Override
        public String get(int index) {
            return "?" + index;
        }

        @Override
        public int size() {
            return types.size();
        }
    });
}
Also used : SqlShuttle(org.apache.calcite.sql.util.SqlShuttle) SqlDynamicParam(org.apache.calcite.sql.SqlDynamicParam) ArrayList(java.util.ArrayList) RelDataType(org.apache.calcite.rel.type.RelDataType) BitString(org.apache.calcite.util.BitString) SqlNode(org.apache.calcite.sql.SqlNode) LinkedHashSet(java.util.LinkedHashSet) HashSet(java.util.HashSet)

Aggregations

ArrayList (java.util.ArrayList)3 SqlNode (org.apache.calcite.sql.SqlNode)3 SqlShuttle (org.apache.calcite.sql.util.SqlShuttle)3 HashSet (java.util.HashSet)2 LinkedHashSet (java.util.LinkedHashSet)2 RelDataType (org.apache.calcite.rel.type.RelDataType)2 SqlDynamicParam (org.apache.calcite.sql.SqlDynamicParam)2 BitString (org.apache.calcite.util.BitString)2 SqlCall (org.apache.calcite.sql.SqlCall)1 SqlLiteral (org.apache.calcite.sql.SqlLiteral)1 SqlOperator (org.apache.calcite.sql.SqlOperator)1 SqlParseException (org.apache.calcite.sql.parser.SqlParseException)1 SqlParserPos (org.apache.calcite.sql.parser.SqlParserPos)1 Pair (org.apache.calcite.util.Pair)1