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)) + ")";
}
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();
}
});
}
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();
}
});
}
Aggregations