|
70 | 70 | import org.apache.ignite.internal.processors.query.calcite.schema.IgniteTable; |
71 | 71 | import org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlDecimalLiteral; |
72 | 72 | import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory; |
| 73 | +import org.apache.ignite.internal.processors.query.calcite.type.OtherType; |
73 | 74 | import org.apache.ignite.internal.processors.query.calcite.util.IgniteResource; |
74 | 75 | import org.apache.ignite.internal.util.typedef.F; |
75 | 76 | import org.jetbrains.annotations.Nullable; |
@@ -102,20 +103,25 @@ public class IgniteSqlValidator extends SqlValidatorImpl { |
102 | 103 | } |
103 | 104 |
|
104 | 105 | /** Dynamic parameters. */ |
105 | | - Object[] parameters; |
| 106 | + @Nullable private final Object[] parameters; |
106 | 107 |
|
107 | 108 | /** |
108 | 109 | * Creates a validator. |
109 | 110 | * |
110 | 111 | * @param opTab Operator table |
111 | 112 | * @param catalogReader Catalog reader |
112 | 113 | * @param typeFactory Type factory |
113 | | - * @param config Config |
| 114 | + * @param cfg Config |
114 | 115 | * @param parameters Dynamic parameters |
115 | 116 | */ |
116 | | - public IgniteSqlValidator(SqlOperatorTable opTab, CalciteCatalogReader catalogReader, |
117 | | - IgniteTypeFactory typeFactory, SqlValidator.Config config, Object[] parameters) { |
118 | | - super(opTab, catalogReader, typeFactory, config); |
| 117 | + public IgniteSqlValidator( |
| 118 | + SqlOperatorTable opTab, |
| 119 | + CalciteCatalogReader catalogReader, |
| 120 | + IgniteTypeFactory typeFactory, |
| 121 | + SqlValidator.Config cfg, |
| 122 | + @Nullable Object[] parameters |
| 123 | + ) { |
| 124 | + super(opTab, catalogReader, typeFactory, cfg); |
119 | 125 |
|
120 | 126 | this.parameters = parameters; |
121 | 127 | } |
@@ -534,9 +540,47 @@ private boolean isSystemFieldName(String alias) { |
534 | 540 | || QueryUtils.VAL_FIELD_NAME.equalsIgnoreCase(alias); |
535 | 541 | } |
536 | 542 |
|
| 543 | + /** {@inheritDoc} */ |
| 544 | + @Override public RelDataType deriveType(SqlValidatorScope scope, SqlNode expr) { |
| 545 | + if (expr instanceof SqlDynamicParam) { |
| 546 | + RelDataType type = deriveDynamicParameterType((SqlDynamicParam)expr); |
| 547 | + |
| 548 | + if (type != null) |
| 549 | + return type; |
| 550 | + } |
| 551 | + |
| 552 | + return super.deriveType(scope, expr); |
| 553 | + } |
| 554 | + |
| 555 | + /** @return A derived type or {@code null} if unable to determine. */ |
| 556 | + @Nullable private RelDataType deriveDynamicParameterType(SqlDynamicParam node) { |
| 557 | + RelDataType type = getValidatedNodeTypeIfKnown(node); |
| 558 | + |
| 559 | + // Do not clarify the widest type for any value. |
| 560 | + if (type instanceof OtherType) |
| 561 | + return type; |
| 562 | + |
| 563 | + if (parameters == null || node.getIndex() >= parameters.length) |
| 564 | + return null; |
| 565 | + |
| 566 | + Object val = parameters[node.getIndex()]; |
| 567 | + |
| 568 | + if (val == null && type != null) |
| 569 | + return type; |
| 570 | + |
| 571 | + type = val == null |
| 572 | + ? typeFactory.createSqlType(SqlTypeName.NULL) |
| 573 | + : typeFactory().createTypeWithNullability(typeFactory().toSql(typeFactory().createType(val.getClass())), true); |
| 574 | + |
| 575 | + setValidatedNodeType(node, type); |
| 576 | + |
| 577 | + return type; |
| 578 | + } |
| 579 | + |
537 | 580 | /** {@inheritDoc} */ |
538 | 581 | @Override protected void inferUnknownTypes(RelDataType inferredType, SqlValidatorScope scope, SqlNode node) { |
539 | | - if (inferDynamicParamType(inferredType, node)) |
| 582 | + if (node instanceof SqlDynamicParam && unknownType.equals(inferredType) |
| 583 | + && deriveDynamicParameterType((SqlDynamicParam)node) != null) |
540 | 584 | return; |
541 | 585 |
|
542 | 586 | if (node instanceof SqlCall) { |
@@ -583,40 +627,6 @@ else if (operandTypeChecker instanceof FamilyOperandTypeChecker) { |
583 | 627 | super.inferUnknownTypes(inferredType, scope, node); |
584 | 628 | } |
585 | 629 |
|
586 | | - /** |
587 | | - * Tries to set actual type of dynamic parameter if {@code node} is a {@link SqlDynamicParam} and if its index |
588 | | - * is actual to {@link #parameters}. |
589 | | - * |
590 | | - * @return {@code True} if a new type was set. {@code False} otherwise. |
591 | | - */ |
592 | | - private boolean inferDynamicParamType(RelDataType inferredType, SqlNode node) { |
593 | | - if (parameters == null || !(node instanceof SqlDynamicParam) || ((SqlDynamicParam)node).getIndex() >= parameters.length) |
594 | | - return false; |
595 | | - |
596 | | - Object val = parameters[((SqlDynamicParam)node).getIndex()]; |
597 | | - |
598 | | - if (val == null) { |
599 | | - if (inferredType.equals(unknownType)) { |
600 | | - setValidatedNodeType(node, typeFactory().createSqlType(SqlTypeName.NULL)); |
601 | | - |
602 | | - return true; |
603 | | - } |
604 | | - |
605 | | - return false; |
606 | | - } |
607 | | - |
608 | | - RelDataType valType = typeFactory().toSql(typeFactory().createType(val.getClass())); |
609 | | - |
610 | | - assert !unknownType.equals(valType); |
611 | | - |
612 | | - if (unknownType.equals(inferredType) || valType.getFamily().equals(inferredType.getFamily())) |
613 | | - setValidatedNodeType(node, valType); |
614 | | - else |
615 | | - setValidatedNodeType(node, inferredType); |
616 | | - |
617 | | - return true; |
618 | | - } |
619 | | - |
620 | 630 | /** {@inheritDoc} */ |
621 | 631 | @Override public SqlLiteral resolveLiteral(SqlLiteral literal) { |
622 | 632 | if (literal instanceof SqlNumericLiteral && literal.createSqlType(typeFactory).getSqlTypeName() == SqlTypeName.BIGINT) { |
|
0 commit comments