Skip to content

Commit

Permalink
SQL: Scripting support for casting functions CAST and CONVERT (#36640)
Browse files Browse the repository at this point in the history
  • Loading branch information
astefan authored Dec 17, 2018
1 parent c086639 commit b15f27f
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 10 deletions.
66 changes: 60 additions & 6 deletions x-pack/plugin/sql/qa/src/main/resources/agg.csv-spec
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,66 @@ SELECT MAX(languages) max, MIN(languages) min, SUM(languages) sum, AVG(languages
FROM test_emp GROUP BY languages ORDER BY languages ASC LIMIT 5;

max:bt | min:bt | sum:bt | avg:d | percent:d | percent_rank:d| kurtosis:d | skewness:d
---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------
null |null |null |null |null |null |null |null
1 |1 |15 |1 |1.0 |100.0 |NaN |NaN
2 |2 |38 |2 |2.0 |100.0 |NaN |NaN
3 |3 |51 |3 |3.0 |100.0 |NaN |NaN
4 |4 |72 |4 |4.0 |0.0 |NaN |NaN
---------------+---------------+---------------+--------------+---------------+---------------+---------------+---------------
null |null |null |null |null |null |null |null
1 |1 |15 |1 |1.0 |100.0 |NaN |NaN
2 |2 |38 |2 |2.0 |100.0 |NaN |NaN
3 |3 |51 |3 |3.0 |100.0 |NaN |NaN
4 |4 |72 |4 |4.0 |0.0 |NaN |NaN
;

aggByComplexCastedValue
SELECT CONVERT(CONCAT(LTRIM(CONVERT("emp_no", SQL_VARCHAR)), LTRIM(CONVERT("languages", SQL_VARCHAR))), SQL_BIGINT) AS "TEMP"
FROM "test_emp" GROUP BY "TEMP" ORDER BY "TEMP" LIMIT 20;

TEMP:l
---------------
10020
10021
10022
10023
10024
10025
10026
10027
10028
10029
100012
100025
100034
100045
100051
100063
100074
100082
100091
100104
;

aggAndOrderByCastedValue
SELECT CHAR_LENGTH(SPACE(CAST(languages AS SMALLINT))), COUNT(*) FROM test_emp GROUP BY 1 ORDER BY 1 DESC;

CHAR_LENGTH(SPACE(CAST(languages AS SMALLINT))):i| COUNT(1):l
-------------------------------------------------+---------------
5 |21
4 |18
3 |17
2 |19
1 |15
null |10
;

aggAndOrderByCastedFunctionValue
SELECT ROUND(SQRT(CAST(EXP(languages) AS SMALLINT)), 2), COUNT(*) FROM test_emp GROUP BY 1 ORDER BY 1 DESC;

ROUND(SQRT(CAST(EXP(languages) AS SMALLINT)),2):d| COUNT(1):l
-------------------------------------------------+---------------
12.17 |21
7.42 |18
4.47 |17
2.65 |19
1.73 |15
null |10
;


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,18 @@

import org.elasticsearch.xpack.sql.expression.Expression;
import org.elasticsearch.xpack.sql.expression.gen.processor.Processor;
import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate;
import org.elasticsearch.xpack.sql.tree.Location;
import org.elasticsearch.xpack.sql.tree.NodeInfo;
import org.elasticsearch.xpack.sql.type.DataType;
import org.elasticsearch.xpack.sql.type.DataTypeConversion;
import org.elasticsearch.xpack.sql.type.DataTypes;

import java.util.Locale;
import java.util.Objects;

import static org.elasticsearch.xpack.sql.expression.gen.script.ParamsBuilder.paramsBuilder;

public class Cast extends UnaryScalarFunction {

private final DataType dataType;
Expand Down Expand Up @@ -74,6 +78,18 @@ protected Processor makeProcessor() {
return new CastProcessor(DataTypeConversion.conversionFor(from(), to()));
}

@Override
public ScriptTemplate asScript() {
ScriptTemplate fieldAsScript = asScript(field());
return new ScriptTemplate(
formatTemplate(String.format(Locale.ROOT, "{sql}.cast(%s,{})", fieldAsScript.template())),
paramsBuilder()
.script(fieldAsScript.params())
.variable(dataType.name())
.build(),
dataType());
}

@Override
public int hashCode() {
return Objects.hash(super.hashCode(), dataType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.InProcessor;
import org.elasticsearch.xpack.sql.expression.predicate.regex.RegexProcessor.RegexOperation;
import org.elasticsearch.xpack.sql.type.DataType;
import org.elasticsearch.xpack.sql.type.DataTypeConversion;
import org.elasticsearch.xpack.sql.util.DateUtils;
import org.elasticsearch.xpack.sql.util.StringUtils;

Expand Down Expand Up @@ -458,4 +459,11 @@ public static String substring(String s, Number start, Number length) {
public static String ucase(String s) {
return (String) StringOperation.UCASE.apply(s);
}

//
// Casting
//
public static Object cast(Object value, String typeName) {
return DataTypeConversion.convert(value, DataType.fromTypeName(typeName));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,9 @@ class org.elasticsearch.xpack.sql.expression.function.scalar.whitelist.InternalS
String space(Number)
String substring(String, Number, Number)
String ucase(String)

#
# Casting
#
def cast(Object, String)
}
Original file line number Diff line number Diff line change
Expand Up @@ -240,10 +240,10 @@ public void testGroupKeyTypes_IP() {
assertEquals(EsQueryExec.class, p.getClass());
EsQueryExec ee = (EsQueryExec) p;
assertThat(ee.queryContainer().aggs().asAggBuilder().toString().replaceAll("\\s+", ""),
endsWith("{\"script\":{" +
"\"source\":\"InternalSqlScriptUtils.docValue(doc,params.v0)\",\"lang\":\"painless\"," +
"\"params\":{\"v0\":\"keyword\"}},\"missing_bucket\":true," +
"\"value_type\":\"ip\",\"order\":\"asc\"}}}]}}}"));
endsWith("{\"script\":{\"source\":\"InternalSqlScriptUtils.cast(" +
"InternalSqlScriptUtils.docValue(doc,params.v0),params.v1)\"," +
"\"lang\":\"painless\",\"params\":{\"v0\":\"keyword\",\"v1\":\"IP\"}}," +
"\"missing_bucket\":true,\"value_type\":\"ip\",\"order\":\"asc\"}}}]}}}"));
assertEquals(2, ee.output().size());
assertThat(ee.output().get(0).toString(), startsWith("COUNT(1){a->"));
assertThat(ee.output().get(1).toString(), startsWith("a{s->"));
Expand Down

0 comments on commit b15f27f

Please sign in to comment.