Jackie-Jiang commented on code in PR #13573:
URL: https://github.com/apache/pinot/pull/13573#discussion_r1674562296
##########
pinot-query-planner/src/main/java/org/apache/pinot/calcite/sql/fun/PinotOperatorTable.java:
##########
@@ -46,127 +59,296 @@
* </ul>
*/
@SuppressWarnings("unused") // unused fields are accessed by reflection
-public class PinotOperatorTable extends SqlStdOperatorTable {
-
- private static @MonotonicNonNull PinotOperatorTable _instance;
-
- // TODO: clean up lazy init by using
Suppliers.memorized(this::computeInstance) and make getter wrapped around
- // supplier instance. this should replace all lazy init static objects in
the codebase
- public static synchronized PinotOperatorTable instance() {
- if (_instance == null) {
- // Creates and initializes the standard operator table.
- // Uses two-phase construction, because we can't initialize the
- // table until the constructor of the sub-class has completed.
- _instance = new PinotOperatorTable();
- _instance.initNoDuplicate();
- }
- return _instance;
+public class PinotOperatorTable implements SqlOperatorTable {
+ private static final Supplier<PinotOperatorTable> INSTANCE =
Suppliers.memoize(PinotOperatorTable::new);
+
+ public static PinotOperatorTable instance() {
+ return INSTANCE.get();
}
/**
- * Initialize without duplicate, e.g. when 2 duplicate operator is linked
with the same op
- * {@link org.apache.calcite.sql.SqlKind} it causes problem.
- *
- * <p>This is a direct copy of the {@link
org.apache.calcite.sql.util.ReflectiveSqlOperatorTable} and can be hard to
- * debug, suggest changing to a non-dynamic registration. Dynamic function
support should happen via catalog.
- *
- * This also registers aggregation functions defined in {@link
org.apache.pinot.segment.spi.AggregationFunctionType}
- * which are multistage enabled.
+ * This list includes the supported standard {@link SqlOperator}s defined in
{@link SqlStdOperatorTable}.
+ * NOTE: The operator order follows the same order as defined in {@link
SqlStdOperatorTable} for easier search.
+ * Some operators are commented out and re-declared in {@link
#STANDARD_OPERATORS_WITH_ALIASES}.
+ * TODO: Add more operators as needed.
*/
- public final void initNoDuplicate() {
- // Pinot supports native COALESCE function, thus no need to create CASE
WHEN conversion.
- register(new PinotSqlCoalesceFunction());
- // Ensure ArrayValueConstructor is registered before ArrayQueryConstructor
- register(ARRAY_VALUE_CONSTRUCTOR);
-
- // TODO: reflection based registration is not ideal, we should use a
static list of operators and register them
- // Use reflection to register the expressions stored in public fields.
- for (Field field : getClass().getFields()) {
- try {
- if (SqlFunction.class.isAssignableFrom(field.getType())) {
- SqlFunction op = (SqlFunction) field.get(this);
- if (op != null && notRegistered(op)) {
- register(op);
- }
- } else if (SqlOperator.class.isAssignableFrom(field.getType())) {
- SqlOperator op = (SqlOperator) field.get(this);
- if (op != null && notRegistered(op)) {
- register(op);
- }
- }
- } catch (IllegalArgumentException | IllegalAccessException e) {
- throw Util.throwAsRuntime(Util.causeOrSelf(e));
+ //@formatter:off
+ private static final List<SqlOperator> STANDARD_OPERATORS = List.of(
+ // SET OPERATORS
+ SqlStdOperatorTable.UNION,
+ SqlStdOperatorTable.UNION_ALL,
+ SqlStdOperatorTable.EXCEPT,
+ SqlStdOperatorTable.EXCEPT_ALL,
+ SqlStdOperatorTable.INTERSECT,
+ SqlStdOperatorTable.INTERSECT_ALL,
+
+ // BINARY OPERATORS
+ SqlStdOperatorTable.AND,
+ SqlStdOperatorTable.AS,
+ SqlStdOperatorTable.FILTER,
+ SqlStdOperatorTable.WITHIN_GROUP,
+ SqlStdOperatorTable.WITHIN_DISTINCT,
+ SqlStdOperatorTable.CONCAT,
+ SqlStdOperatorTable.DIVIDE,
+ SqlStdOperatorTable.PERCENT_REMAINDER,
+ SqlStdOperatorTable.DOT,
+ SqlStdOperatorTable.EQUALS,
+ SqlStdOperatorTable.GREATER_THAN,
+ SqlStdOperatorTable.IS_DISTINCT_FROM,
+ SqlStdOperatorTable.IS_NOT_DISTINCT_FROM,
+ SqlStdOperatorTable.GREATER_THAN_OR_EQUAL,
+ SqlStdOperatorTable.IN,
+ SqlStdOperatorTable.NOT_IN,
+ SqlStdOperatorTable.SEARCH,
+ SqlStdOperatorTable.LESS_THAN,
+ SqlStdOperatorTable.LESS_THAN_OR_EQUAL,
+ SqlStdOperatorTable.MINUS,
+ SqlStdOperatorTable.MULTIPLY,
+ SqlStdOperatorTable.NOT_EQUALS,
+ SqlStdOperatorTable.OR,
+ SqlStdOperatorTable.PLUS,
+ SqlStdOperatorTable.INTERVAL,
+
+ // POSTFIX OPERATORS
+ SqlStdOperatorTable.DESC,
+ SqlStdOperatorTable.NULLS_FIRST,
+ SqlStdOperatorTable.NULLS_LAST,
+ SqlStdOperatorTable.IS_NOT_NULL,
+ SqlStdOperatorTable.IS_NULL,
+ SqlStdOperatorTable.IS_NOT_TRUE,
+ SqlStdOperatorTable.IS_TRUE,
+ SqlStdOperatorTable.IS_NOT_FALSE,
+ SqlStdOperatorTable.IS_FALSE,
+ SqlStdOperatorTable.IS_NOT_UNKNOWN,
+ SqlStdOperatorTable.IS_UNKNOWN,
+
+ // PREFIX OPERATORS
+ SqlStdOperatorTable.EXISTS,
+ SqlStdOperatorTable.NOT,
+
+ // AGGREGATE OPERATORS
+ SqlStdOperatorTable.SUM,
+ SqlStdOperatorTable.COUNT,
+ SqlStdOperatorTable.MODE,
+ SqlStdOperatorTable.MIN,
+ SqlStdOperatorTable.MAX,
+ SqlStdOperatorTable.LAST_VALUE,
+ SqlStdOperatorTable.FIRST_VALUE,
+ SqlStdOperatorTable.LEAD,
+ SqlStdOperatorTable.LAG,
+ SqlStdOperatorTable.AVG,
+ SqlStdOperatorTable.STDDEV_POP,
+ SqlStdOperatorTable.COVAR_POP,
+ SqlStdOperatorTable.COVAR_SAMP,
+ SqlStdOperatorTable.STDDEV_SAMP,
+ SqlStdOperatorTable.VAR_POP,
+ SqlStdOperatorTable.VAR_SAMP,
+ SqlStdOperatorTable.SUM0,
+
+ // WINDOW Rank Functions
+ SqlStdOperatorTable.DENSE_RANK,
+ SqlStdOperatorTable.RANK,
+ SqlStdOperatorTable.ROW_NUMBER,
+
+ // SPECIAL OPERATORS
+ SqlStdOperatorTable.BETWEEN,
+ SqlStdOperatorTable.SYMMETRIC_BETWEEN,
+ SqlStdOperatorTable.NOT_BETWEEN,
+ SqlStdOperatorTable.SYMMETRIC_NOT_BETWEEN,
+ SqlStdOperatorTable.NOT_LIKE,
+ SqlStdOperatorTable.LIKE,
+// SqlStdOperatorTable.CASE,
+ SqlStdOperatorTable.OVER,
+
+ // FUNCTIONS
+ // String functions
+ SqlStdOperatorTable.SUBSTRING,
+ SqlStdOperatorTable.REPLACE,
+ SqlStdOperatorTable.TRIM,
+ SqlStdOperatorTable.UPPER,
+ SqlStdOperatorTable.LOWER,
+ // Arithmetic functions
+ SqlStdOperatorTable.POWER,
+ SqlStdOperatorTable.SQRT,
+ SqlStdOperatorTable.MOD,
+// SqlStdOperatorTable.LN,
+ SqlStdOperatorTable.LOG10,
+ SqlStdOperatorTable.ABS,
+ SqlStdOperatorTable.ACOS,
+ SqlStdOperatorTable.ASIN,
+ SqlStdOperatorTable.ATAN,
+ SqlStdOperatorTable.ATAN2,
+ SqlStdOperatorTable.COS,
+ SqlStdOperatorTable.COT,
+ SqlStdOperatorTable.DEGREES,
+ SqlStdOperatorTable.EXP,
+ SqlStdOperatorTable.RADIANS,
+ SqlStdOperatorTable.ROUND,
+ SqlStdOperatorTable.SIGN,
+ SqlStdOperatorTable.SIN,
+ SqlStdOperatorTable.TAN,
+ SqlStdOperatorTable.TRUNCATE,
+ SqlStdOperatorTable.FLOOR,
+ SqlStdOperatorTable.CEIL,
+ SqlStdOperatorTable.TIMESTAMP_ADD,
+ SqlStdOperatorTable.TIMESTAMP_DIFF,
+ SqlStdOperatorTable.CAST,
+
+ SqlStdOperatorTable.EXTRACT,
+ // TODO: The following operators are all rewritten to EXTRACT. Consider
removing them because they are all
+ // supported without rewrite.
+ SqlStdOperatorTable.YEAR,
+ SqlStdOperatorTable.QUARTER,
+ SqlStdOperatorTable.MONTH,
+ SqlStdOperatorTable.WEEK,
+ SqlStdOperatorTable.DAYOFYEAR,
+ SqlStdOperatorTable.DAYOFMONTH,
+ SqlStdOperatorTable.DAYOFWEEK,
+ SqlStdOperatorTable.HOUR,
+ SqlStdOperatorTable.MINUTE,
+ SqlStdOperatorTable.SECOND,
+
+ SqlStdOperatorTable.ITEM,
+ SqlStdOperatorTable.ARRAY_VALUE_CONSTRUCTOR,
+ SqlStdOperatorTable.LISTAGG
+ );
+
+ private static final List<Pair<SqlOperator, List<String>>>
STANDARD_OPERATORS_WITH_ALIASES = List.of(
+ Pair.of(SqlStdOperatorTable.CASE, List.of("CASE", "CASE_WHEN")),
+ Pair.of(SqlStdOperatorTable.LN, List.of("LN", "LOG"))
+ );
+
+ /**
+ * This list includes the customized {@link SqlOperator}s.
+ */
+ private static final List<SqlOperator> PINOT_OPERATORS = List.of(
+ // Placeholder for special predicates
+ new PinotSqlFunction("TEXT_MATCH", ReturnTypes.BOOLEAN,
OperandTypes.CHARACTER_CHARACTER),
+ new PinotSqlFunction("TEXT_CONTAINS", ReturnTypes.BOOLEAN,
OperandTypes.CHARACTER_CHARACTER),
+ new PinotSqlFunction("JSON_MATCH", ReturnTypes.BOOLEAN,
OperandTypes.CHARACTER_CHARACTER),
+ new PinotSqlFunction("VECTOR_SIMILARITY", ReturnTypes.BOOLEAN,
+ OperandTypes.family(List.of(SqlTypeFamily.ARRAY,
SqlTypeFamily.ARRAY, SqlTypeFamily.INTEGER), i -> i == 2)),
+
+ // Placeholder for special functions to handle MV
+ new PinotSqlFunction("ARRAY_TO_MV", opBinding ->
opBinding.getOperandType(0).getComponentType(),
+ OperandTypes.ARRAY),
+
+ // SqlStdOperatorTable.COALESCE without rewrite
+ new SqlFunction("COALESCE", SqlKind.COALESCE,
+
ReturnTypes.LEAST_RESTRICTIVE.andThen(SqlTypeTransforms.LEAST_NULLABLE), null,
OperandTypes.SAME_VARIADIC,
+ SqlFunctionCategory.SYSTEM),
+
+ // The scalar function version returns long instead of Timestamp
+ // TODO: Consider unifying the return type to Timestamp
+ new PinotSqlFunction("FROM_DATE_TIME", ReturnTypes.TIMESTAMP_NULLABLE,
OperandTypes.family(
+ List.of(SqlTypeFamily.CHARACTER, SqlTypeFamily.CHARACTER,
SqlTypeFamily.CHARACTER, SqlTypeFamily.ANY),
+ i -> i > 1))
+ );
+
+ private static final List<Pair<SqlOperator, List<String>>>
PINOT_OPERATORS_WITH_ALIASES = List.of(
+ );
+ //@formatter:on
+
+ // Key is canonical name
+ private final Map<String, SqlOperator> _operatorMap;
+ private final List<SqlOperator> _operatorList;
+
+ private PinotOperatorTable() {
+ Map<String, SqlOperator> operatorMap = new HashMap<>();
Review Comment:
`FunctionRegistry` only contains the scalar function (annotated ones). Added
more javadoc to this class
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]