/*
* Licensed to Crate under one or more contributor license agreements.
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership. Crate licenses this file
* to you under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* However, if you have executed another commercial license agreement
* with Crate these terms will supersede the license and you may use the
* software solely pursuant to the terms of the relevant commercial
* agreement.
*/
package io.crate.testing;
import com.google.common.collect.Ordering;
import io.crate.analyze.OrderBy;
import io.crate.analyze.QuerySpec;
import io.crate.analyze.symbol.Symbol;
import io.crate.analyze.symbol.format.SymbolPrinter;
import java.util.Collection;
import java.util.HashSet;
import java.util.Optional;
public class SQLPrinter {
private static final TestingSymbolPrinter TESTING_SYMBOL_PRINTER = new TestingSymbolPrinter();
public static String print(Object o) {
if (o instanceof QuerySpec) {
return print((QuerySpec) o);
} else if (o instanceof OrderBy) {
return print((OrderBy) o);
} else if (o instanceof Symbol) {
return print((Symbol) o);
} else if (o instanceof HashSet) {
return print(Ordering.usingToString().sortedCopy((HashSet) o));
} else if (o instanceof Collection) {
return print((Collection<Symbol>) o);
} else if (o == null) {
return "null";
}
return o.toString();
}
public static String print(Collection<Symbol> symbols) {
StringBuilder sb = new StringBuilder();
TESTING_SYMBOL_PRINTER.process(symbols, sb);
return sb.toString();
}
public static String print(Symbol symbol) {
StringBuilder sb = new StringBuilder();
TESTING_SYMBOL_PRINTER.process(symbol, sb);
return sb.toString();
}
public static String print(OrderBy orderBy) {
StringBuilder sb = new StringBuilder();
TESTING_SYMBOL_PRINTER.process(orderBy, sb);
return sb.toString();
}
public static String print(QuerySpec spec) {
StringBuilder sb = new StringBuilder();
sb.append("SELECT ");
TESTING_SYMBOL_PRINTER.process(spec.outputs(), sb);
if (spec.where().hasQuery()) {
sb.append(" WHERE ");
TESTING_SYMBOL_PRINTER.process(spec.where().query(), sb);
}
if (spec.groupBy().isPresent()) {
sb.append(" GROUP BY ");
TESTING_SYMBOL_PRINTER.process(spec.groupBy().get(), sb);
}
if (spec.having().isPresent()) {
sb.append(" HAVING ");
TESTING_SYMBOL_PRINTER.process(spec.having().get().query(), sb);
}
if (spec.orderBy().isPresent()) {
sb.append(" ORDER BY ");
TESTING_SYMBOL_PRINTER.process(spec.orderBy().get(), sb);
}
Optional<Symbol> limit = spec.limit();
if (limit.isPresent()) {
sb.append(" LIMIT ");
sb.append(print(limit.get()));
}
Optional<Symbol> offset = spec.offset();
if (offset.isPresent()) {
sb.append(" OFFSET ");
sb.append(print(offset.get()));
}
return sb.toString();
}
/**
* produces same results as with {@link SymbolPrinter#printFullQualified(Symbol)} but is
* able to format other symbols that {@link SymbolPrinter} is not able to.
*/
private static class TestingSymbolPrinter {
public void process(Iterable<? extends Symbol> symbols, StringBuilder sb) {
boolean first = true;
for (Symbol arg : symbols) {
if (!first) {
sb.append(", ");
}
first = false;
process(arg, sb);
}
}
public void process(Symbol symbol, StringBuilder sb) {
sb.append(SymbolPrinter.INSTANCE.printFullQualified(symbol));
}
public void process(OrderBy orderBy, StringBuilder sb) {
int i = 0;
for (Symbol symbol : orderBy.orderBySymbols()) {
if (i > 0) {
sb.append(", ");
}
process(symbol, sb);
if (orderBy.reverseFlags()[i]) {
sb.append(" DESC");
}
Boolean nullsFirst = orderBy.nullsFirst()[i];
if (nullsFirst != null) {
sb.append(" NULLS");
if (nullsFirst) {
sb.append(" FIRST");
} else {
sb.append(" LAST");
}
}
i++;
}
}
}
}