Skip to content

Commit

Permalink
Fix printing of aliased literals in select list / groupBy / orderBy
Browse files Browse the repository at this point in the history
Literals have to be taken special care of when used in a select list or in a
group by / order by.

- They have to be quoted to resolve their output name
- Their alias has to be resolved in case they have one
  • Loading branch information
mxm committed May 25, 2018
1 parent c8dc72d commit ccec442
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 15 deletions.
3 changes: 3 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,6 @@ Fixes

- Fixed an issue that caused a ``ClassCastException`` to be thrown when querying
the ``sys.health`` table on a cluster that has ``blob`` tables.

- Fixed support for views with aliased literals in select list / groupBy /
orderBy.
39 changes: 24 additions & 15 deletions sql/src/main/java/io/crate/analyze/SQLPrinter.java
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public Void visitUnionSelect(UnionSelect unionSelect, StringBuilder sb) {
@Override
public Void visitOrderedLimitedRelation(OrderedLimitedRelation relation, StringBuilder sb) {
process(relation.childRelation(), sb);
addOrderBy(sb, relation.orderBy());
addOrderBy(sb, relation.orderBy(), relation.outputs(), relation.fields());
clauseAndSymbol(sb, "LIMIT", relation.limit());
clauseAndSymbol(sb, "OFFSET", relation.offset());
return null;
Expand All @@ -122,9 +122,9 @@ private Void printSelect(QueriedRelation relation, StringBuilder sb) {
addOutputs(relation, sb);
addFrom(sb, relation);
clauseAndQuery(sb, "WHERE", relation.where());
addGroupBy(sb, relation.groupBy());
addGroupBy(sb, relation.groupBy(), relation.outputs(), relation.fields());
clauseAndQuery(sb, "HAVING", relation.having());
addOrderBy(sb, relation.orderBy());
addOrderBy(sb, relation.orderBy(), relation.outputs(), relation.fields());
clauseAndSymbol(sb, "LIMIT", relation.limit());
clauseAndSymbol(sb, "OFFSET", relation.offset());
return null;
Expand Down Expand Up @@ -173,14 +173,14 @@ private void clauseAndQuery(StringBuilder sb, String clause, @Nullable QueryClau
clauseAndSymbol(sb, clause, query.query());
}

private void addOrderBy(StringBuilder sb, @Nullable OrderBy orderBy) {
private void addOrderBy(StringBuilder sb, @Nullable OrderBy orderBy, List<Symbol> outputs, List<Field> fields) {
if (orderBy == null || orderBy.orderBySymbols().isEmpty()) {
return;
}
sb.append(" ORDER BY ");
for (int i = 0; i < orderBy.orderBySymbols().size(); i++) {
Symbol symbol = orderBy.orderBySymbols().get(i);
sb.append(printSymbol(symbol));
Symbol orderBySymbol = orderBy.orderBySymbols().get(i);
sb.append(resolveOutputName(orderBySymbol, outputs, fields));
sb.append(" ");
sb.append(orderBy.reverseFlags()[i] ? "DESC" : "ASC");
Boolean nullsFirst = orderBy.nullsFirst()[i];
Expand All @@ -192,19 +192,14 @@ private void addOrderBy(StringBuilder sb, @Nullable OrderBy orderBy) {
}
}

private void addGroupBy(StringBuilder sb, List<Symbol> groupKeys) {
private void addGroupBy(StringBuilder sb, List<Symbol> groupKeys, List<Symbol> outputs, List<Field> fields) {
if (groupKeys.isEmpty()) {
return;
}
sb.append(" GROUP BY ");
for (int i = 0; i < groupKeys.size(); i++) {
Symbol groupKey = groupKeys.get(i);
if (groupKey.symbolType() == SymbolType.LITERAL) {
sb.append(Identifiers.quoteIfNeeded(printSymbol(groupKey)));
} else {
sb.append(printSymbol(groupKey));
}

Symbol groupKeySymbol = groupKeys.get(i);
sb.append(resolveOutputName(groupKeySymbol, outputs, fields));
addCommaIfNotLast(sb, groupKeys.size(), i);
}
}
Expand Down Expand Up @@ -234,7 +229,7 @@ private void addOutput(StringBuilder sb, Field field, Symbol output) {
sb.append(" AS ");
sb.append(field.outputName());
}
} else if (output instanceof Function) {
} else if (output instanceof Function || output instanceof Literal) {
String name = printSymbol(output);
sb.append(name);
if (!name.equals(field.outputName())) {
Expand Down Expand Up @@ -360,6 +355,20 @@ private void printRelation(AnalyzedRelation relation, StringBuilder sb) {
}
}

private String resolveOutputName(Symbol symbol, List<Symbol> outputs, List<Field> fields) {
if (symbol.symbolType() == SymbolType.LITERAL) {
int outputIndex = outputs.indexOf(symbol);
if (outputIndex != -1) {
// If the Literal is aliased, then we have to use that alias
return Identifiers.quoteIfNeeded(fields.get(outputIndex).outputName());
} else {
// Literals have to be quoted (otherwise it would be a positional group by / order by).
return Identifiers.quoteIfNeeded(printSymbol(symbol));
}
}
return printSymbol(symbol);
}

@Override
protected Void visitAnalyzedRelation(AnalyzedRelation relation, StringBuilder context) {
throw new UnsupportedOperationException("Cannot format statement: " + relation);
Expand Down
6 changes: 6 additions & 0 deletions sql/src/test/java/io/crate/analyze/SQLPrinterTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,11 @@ public static Iterable<Object[]> testParameters() {
$("select (select \"user\" from t1 limit 1), x from t1",
"SELECT (SELECT doc.t1.\"user\" FROM doc.t1 LIMIT 1), doc.t1.x FROM doc.t1"),

// scalar values / table functions
$("select 1", "SELECT 1 FROM empty_row()"),
$("select 1 group by 1 order by 1;", "SELECT 1 FROM empty_row() GROUP BY \"1\" ORDER BY \"1\" ASC"),
$("select 2 group by 1 order by 1;", "SELECT 2 FROM empty_row() GROUP BY \"2\" ORDER BY \"2\" ASC"),
$("select 2 as two, 1 as eins group by eins order by eins;", "SELECT 2 AS two, 1 AS eins FROM empty_row() GROUP BY eins ORDER BY eins ASC"),
$("select * from unnest([1, 2])", "SELECT col1 FROM unnest([1, 2])"),
$("select col1 as x from unnest([1, 2])", "SELECT col1 AS x FROM unnest([1, 2])"),
$("select col1 as x from unnest([1, 2]) t", "SELECT col1 AS x FROM unnest([1, 2]) AS t"),
Expand All @@ -126,6 +130,8 @@ public static Iterable<Object[]> testParameters() {

// VIEW (simple)
$("select * from v1", "SELECT doc.v1.x, doc.v1.\"user\" FROM doc.v1"),
// VIEW (alias)
$("select x, \"user\" as u from v1", "SELECT doc.v1.x, doc.v1.\"user\" AS u FROM doc.v1"),
// VIEW (order by)
$("select * from v1 order by \"user\"", "SELECT doc.v1.x, doc.v1.\"user\" FROM doc.v1 ORDER BY doc.v1.\"user\" ASC"),
// VIEW (order by / limit / offset)
Expand Down

0 comments on commit ccec442

Please sign in to comment.