Improve DateTime script template

When dealing with TZ, the script is reused across extractors by
externalizing the tz & chronofield

Original commit: elastic/x-pack-elasticsearch@9e63ea8cd8
This commit is contained in:
Costin Leau 2017-10-28 13:35:16 +03:00
parent a7b559c825
commit 66719f7a92
2 changed files with 24 additions and 20 deletions

View File

@ -62,8 +62,9 @@ public abstract class ArithmeticFunction extends BinaryScalarFunction {
@Override
protected ScriptTemplate asScriptFrom(ScriptTemplate leftScript, ScriptTemplate rightScript) {
return new ScriptTemplate(format(Locale.ROOT, "(%s) %s (%s)", leftScript.template(), operation.symbol(), rightScript.template()),
paramsBuilder().script(leftScript.params()).script(rightScript.params()).build(),
dataType());
paramsBuilder()
.script(leftScript.params()).script(rightScript.params())
.build(), dataType());
}
protected final BinaryArithmeticProcessorDefinition makeProcessorDefinition() {

View File

@ -15,6 +15,7 @@ import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.DateTimeP
import org.elasticsearch.xpack.sql.expression.function.scalar.processor.definition.ProcessorDefinition;
import org.elasticsearch.xpack.sql.expression.function.scalar.processor.definition.ProcessorDefinitions;
import org.elasticsearch.xpack.sql.expression.function.scalar.processor.definition.UnaryProcessorDefinition;
import org.elasticsearch.xpack.sql.expression.function.scalar.script.ParamsBuilder;
import org.elasticsearch.xpack.sql.expression.function.scalar.script.ScriptTemplate;
import org.elasticsearch.xpack.sql.tree.Location;
import org.elasticsearch.xpack.sql.type.DataType;
@ -22,9 +23,7 @@ import org.elasticsearch.xpack.sql.type.DataTypes;
import org.joda.time.DateTimeZone;
import java.time.temporal.ChronoField;
import java.util.Locale;
import static java.lang.String.format;
import static org.elasticsearch.xpack.sql.expression.function.scalar.script.ParamsBuilder.paramsBuilder;
import static org.elasticsearch.xpack.sql.expression.function.scalar.script.ScriptTemplate.formatTemplate;
@ -64,30 +63,34 @@ public abstract class DateTimeFunction extends UnaryScalarFunction implements Ti
@Override
protected ScriptTemplate asScriptFrom(FieldAttribute field) {
return new ScriptTemplate(createTemplate(),
paramsBuilder()
.variable(field.name())
.build(),
dataType());
}
@Override
protected String chainScalarTemplate(String template) {
throw new UnsupportedOperationException();
}
private String createTemplate() {
ParamsBuilder params = paramsBuilder();
String template = null;
if (DateTimeZone.UTC.equals(timeZone)) {
return formatTemplate("doc[{}].value.get" + extractFunction() + "()");
// TODO: it would be nice to be able to externalize the extract function and reuse the script across all extractors
template = formatTemplate("doc[{}].value.get" + extractFunction() + "()");
params.variable(field.name());
} else {
// TODO ewwww
/* This uses the Java 8 time API because Painless doesn't whitelist creation of new
* Joda classes. */
// ideally JodaTime should be used since that's internally used and there are subtle differences between that and the JDK API
String asInstant = formatTemplate("Instant.ofEpochMilli(doc[{}].value.millis)");
return format(Locale.ROOT, "ZonedDateTime.ofInstant(%s, ZoneId.of(\"%s\")).get(ChronoField.%s)", asInstant, timeZone.getID(), chronoField().name());
// all variables are externalized to reuse the script across invocations
// the actual script is ZonedDateTime.ofInstant(Instant.ofEpochMilli(<insert doc field>.value.millis), ZoneId.of(<insert user tz>)).get(ChronoField.get(MONTH_OF_YEAR))
template = formatTemplate("ZonedDateTime.ofInstant(Instant.ofEpochMilli(doc[{}].value.millis), ZoneId.of({})).get(ChronoField.valueOf({}))");
params.variable(field.name())
.variable(timeZone.getID())
.variable(chronoField().name());
}
return new ScriptTemplate(template, params.build(), dataType());
}
@Override
protected String chainScalarTemplate(String template) {
throw new UnsupportedOperationException();
}
protected String extractFunction() {