-
Notifications
You must be signed in to change notification settings - Fork 24.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
SQL: Enhance checks for inexact fields (#39427)
For functions: move checks for `text` fields without underlying `keyword` fields or with many of them (ambiguity) to the type resolution stage. For Order By/Group By: move checks to the `Verifier` to catch early before `QueryTranslator` or execution. Closes: #38501 Fixes: #35203
- Loading branch information
Showing
44 changed files
with
495 additions
and
248 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
129 changes: 129 additions & 0 deletions
129
x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/TypeResolutions.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
package org.elasticsearch.xpack.sql.expression; | ||
|
||
import org.elasticsearch.xpack.sql.type.DataType; | ||
import org.elasticsearch.xpack.sql.type.DataTypes; | ||
import org.elasticsearch.xpack.sql.type.EsField; | ||
|
||
import java.util.Locale; | ||
import java.util.StringJoiner; | ||
import java.util.function.Predicate; | ||
|
||
import static org.elasticsearch.common.logging.LoggerMessageFormat.format; | ||
import static org.elasticsearch.xpack.sql.expression.Expression.TypeResolution; | ||
import static org.elasticsearch.xpack.sql.expression.Expressions.ParamOrdinal; | ||
import static org.elasticsearch.xpack.sql.expression.Expressions.name; | ||
import static org.elasticsearch.xpack.sql.type.DataType.BOOLEAN; | ||
|
||
public final class TypeResolutions { | ||
|
||
private TypeResolutions() {} | ||
|
||
public static TypeResolution isBoolean(Expression e, String operationName, ParamOrdinal paramOrd) { | ||
return isType(e, dt -> dt == BOOLEAN, operationName, paramOrd, "boolean"); | ||
} | ||
|
||
public static TypeResolution isInteger(Expression e, String operationName, ParamOrdinal paramOrd) { | ||
return isType(e, DataType::isInteger, operationName, paramOrd, "integer"); | ||
} | ||
|
||
public static TypeResolution isNumeric(Expression e, String operationName, ParamOrdinal paramOrd) { | ||
return isType(e, DataType::isNumeric, operationName, paramOrd, "numeric"); | ||
} | ||
|
||
public static TypeResolution isString(Expression e, String operationName, ParamOrdinal paramOrd) { | ||
return isType(e, DataType::isString, operationName, paramOrd, "string"); | ||
} | ||
|
||
public static TypeResolution isDate(Expression e, String operationName, ParamOrdinal paramOrd) { | ||
return isType(e, DataType::isDateBased, operationName, paramOrd, "date"); | ||
} | ||
|
||
public static TypeResolution isNumericOrDate(Expression e, String operationName, ParamOrdinal paramOrd) { | ||
return isType(e, dt -> dt.isNumeric() || dt.isDateBased(), operationName, paramOrd, "date", "numeric"); | ||
} | ||
|
||
public static TypeResolution isExact(Expression e, String message) { | ||
if (e instanceof FieldAttribute) { | ||
EsField.Exact exact = ((FieldAttribute) e).getExactInfo(); | ||
if (exact.hasExact() == false) { | ||
return new TypeResolution(format(null, message, e.dataType().esType, exact.errorMsg())); | ||
} | ||
} | ||
return TypeResolution.TYPE_RESOLVED; | ||
} | ||
|
||
public static TypeResolution isExact(Expression e, String operationName, ParamOrdinal paramOrd) { | ||
if (e instanceof FieldAttribute) { | ||
EsField.Exact exact = ((FieldAttribute) e).getExactInfo(); | ||
if (exact.hasExact() == false) { | ||
return new TypeResolution(format(null, "[{}] cannot operate on {}field of data type [{}]: {}", | ||
operationName, | ||
paramOrd == null || paramOrd == ParamOrdinal.DEFAULT ? | ||
"" : paramOrd.name().toLowerCase(Locale.ROOT) + " argument ", | ||
e.dataType().esType, exact.errorMsg())); | ||
} | ||
} | ||
return TypeResolution.TYPE_RESOLVED; | ||
} | ||
|
||
public static TypeResolution isStringAndExact(Expression e, String operationName, ParamOrdinal paramOrd) { | ||
TypeResolution resolution = isString(e, operationName, paramOrd); | ||
if (resolution.unresolved()) { | ||
return resolution; | ||
} | ||
|
||
return isExact(e, operationName, paramOrd); | ||
} | ||
|
||
public static TypeResolution isFoldable(Expression e, String operationName, ParamOrdinal paramOrd) { | ||
if (!e.foldable()) { | ||
return new TypeResolution(format(null, "{}argument of [{}] must be a constant, received [{}]", | ||
paramOrd == null || paramOrd == ParamOrdinal.DEFAULT ? "" : paramOrd.name().toLowerCase(Locale.ROOT) + " ", | ||
operationName, | ||
Expressions.name(e))); | ||
} | ||
return TypeResolution.TYPE_RESOLVED; | ||
} | ||
|
||
public static TypeResolution isNotFoldable(Expression e, String operationName, ParamOrdinal paramOrd) { | ||
if (e.foldable()) { | ||
return new TypeResolution(format(null, "{}argument of [{}] must be a table column, found constant [{}]", | ||
paramOrd == null || paramOrd == ParamOrdinal.DEFAULT ? "" : paramOrd.name().toLowerCase(Locale.ROOT) + " ", | ||
operationName, | ||
Expressions.name(e))); | ||
} | ||
return TypeResolution.TYPE_RESOLVED; | ||
} | ||
|
||
public static TypeResolution isType(Expression e, | ||
Predicate<DataType> predicate, | ||
String operationName, | ||
ParamOrdinal paramOrd, | ||
String... acceptedTypes) { | ||
return predicate.test(e.dataType()) || DataTypes.isNull(e.dataType())? | ||
TypeResolution.TYPE_RESOLVED : | ||
new TypeResolution(format(null, "{}argument of [{}] must be [{}], found value [{}] type [{}]", | ||
paramOrd == null || paramOrd == ParamOrdinal.DEFAULT ? "" : paramOrd.name().toLowerCase(Locale.ROOT) + " ", | ||
operationName, | ||
acceptedTypesForErrorMsg(acceptedTypes), | ||
name(e), | ||
e.dataType().esType)); | ||
} | ||
|
||
private static String acceptedTypesForErrorMsg(String... acceptedTypes) { | ||
StringJoiner sj = new StringJoiner(", "); | ||
for (int i = 0; i < acceptedTypes.length - 1; i++) { | ||
sj.add(acceptedTypes[i]); | ||
} | ||
if (acceptedTypes.length > 1) { | ||
return sj.toString() + " or " + acceptedTypes[acceptedTypes.length - 1]; | ||
} else { | ||
return acceptedTypes[0]; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.