alex-plekhanov commented on code in PR #10291: URL: https://github.com/apache/ignite/pull/10291#discussion_r993100506
########## modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/DynamicParamTypeExtractor.java: ########## @@ -0,0 +1,215 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.query.calcite.prepare; + +import java.lang.reflect.Type; +import java.util.Collection; +import java.util.List; +import java.util.SortedMap; +import java.util.TreeMap; +import com.google.common.collect.ImmutableList; +import org.apache.calcite.rel.type.RelDataType; +import org.apache.calcite.rex.RexDynamicParam; +import org.apache.calcite.rex.RexNode; +import org.apache.calcite.rex.RexShuttle; +import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata; +import org.apache.ignite.internal.processors.query.calcite.prepare.bounds.MultiBounds; +import org.apache.ignite.internal.processors.query.calcite.prepare.bounds.RangeBounds; +import org.apache.ignite.internal.processors.query.calcite.prepare.bounds.SearchBounds; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteCorrelatedNestedLoopJoin; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteFilter; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteHashIndexSpool; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteIndexScan; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteMergeJoin; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteNestedLoopJoin; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteProject; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteRel; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteSortedIndexSpool; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableModify; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableScan; +import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory; + +/** */ +public class DynamicParamTypeExtractor extends IgniteRelShuttle { + /** */ + private final SortedMap<Integer, RexDynamicParam> acc = new TreeMap<>(); + + /** */ + private final DynamicParamsShuttle paramsShuttle = new DynamicParamsShuttle(); + + /** */ + public static ParamsMetadata go(IgniteRel root) { + DynamicParamTypeExtractor extractor = new DynamicParamTypeExtractor(); + + extractor.visit(root); + + return new ParamsMetadata(extractor.acc.values()); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteFilter rel) { + paramsShuttle.apply(rel.getCondition()); + + return super.visit(rel); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteProject rel) { + paramsShuttle.apply(rel.getProjects()); + + return super.visit(rel); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteNestedLoopJoin rel) { + paramsShuttle.apply(rel.getCondition()); + + return super.visit(rel); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteCorrelatedNestedLoopJoin rel) { + paramsShuttle.apply(rel.getCondition()); + + return super.visit(rel); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteMergeJoin rel) { + paramsShuttle.apply(rel.getCondition()); + + return super.visit(rel); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteIndexScan rel) { + paramsShuttle.apply(rel.projects()); + paramsShuttle.apply(rel.condition()); + paramsShuttle.apply(rel.searchBounds()); Review Comment: Search bounds are extracted from `condition`, it's not required to process them additionally, let's remove it here and for IgniteSortedIndexSpool/IgniteHashIndexSpool ########## modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/DynamicParamTypeExtractor.java: ########## @@ -0,0 +1,215 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.query.calcite.prepare; + +import java.lang.reflect.Type; +import java.util.Collection; +import java.util.List; +import java.util.SortedMap; +import java.util.TreeMap; +import com.google.common.collect.ImmutableList; +import org.apache.calcite.rel.type.RelDataType; +import org.apache.calcite.rex.RexDynamicParam; +import org.apache.calcite.rex.RexNode; +import org.apache.calcite.rex.RexShuttle; +import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata; +import org.apache.ignite.internal.processors.query.calcite.prepare.bounds.MultiBounds; +import org.apache.ignite.internal.processors.query.calcite.prepare.bounds.RangeBounds; +import org.apache.ignite.internal.processors.query.calcite.prepare.bounds.SearchBounds; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteCorrelatedNestedLoopJoin; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteFilter; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteHashIndexSpool; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteIndexScan; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteMergeJoin; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteNestedLoopJoin; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteProject; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteRel; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteSortedIndexSpool; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableModify; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableScan; +import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory; + +/** */ +public class DynamicParamTypeExtractor extends IgniteRelShuttle { Review Comment: Let's create some universal rex processor for ignite rel nodes and pass RexShuttle to it (perhaps it will be helpful somewhere) ########## modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/CalciteQueryProcessor.java: ########## @@ -365,6 +372,57 @@ public PrepareServiceImpl prepareService() { return cursors; } + /** {@inheritDoc} */ + @Override public List<T2<List<GridQueryFieldMetadata>, List<GridQueryFieldMetadata>>> queryMetadata( Review Comment: Let's use different methods for parameters meta and result set meta. It's not clear (and even not described in javadoc) what is returned by `T2` class. Both of these metadata never used after a single call, so there are no reasons to get it by a single common method. ########## modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java: ########## @@ -3121,6 +3123,75 @@ public List<FieldsQueryCursor<List<?>>> querySqlFields( }); } + /** */ + public List<JdbcParameterMeta> parameterMetaData( + @Nullable final GridCacheContext<?, ?> cctx, Review Comment: Looks like `cctx` is always `null` ########## modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/DynamicParamTypeExtractor.java: ########## @@ -0,0 +1,215 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.query.calcite.prepare; + +import java.lang.reflect.Type; +import java.util.Collection; +import java.util.List; +import java.util.SortedMap; +import java.util.TreeMap; +import com.google.common.collect.ImmutableList; +import org.apache.calcite.rel.type.RelDataType; +import org.apache.calcite.rex.RexDynamicParam; +import org.apache.calcite.rex.RexNode; +import org.apache.calcite.rex.RexShuttle; +import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata; +import org.apache.ignite.internal.processors.query.calcite.prepare.bounds.MultiBounds; +import org.apache.ignite.internal.processors.query.calcite.prepare.bounds.RangeBounds; +import org.apache.ignite.internal.processors.query.calcite.prepare.bounds.SearchBounds; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteCorrelatedNestedLoopJoin; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteFilter; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteHashIndexSpool; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteIndexScan; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteMergeJoin; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteNestedLoopJoin; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteProject; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteRel; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteSortedIndexSpool; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableModify; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableScan; +import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory; + +/** */ +public class DynamicParamTypeExtractor extends IgniteRelShuttle { + /** */ + private final SortedMap<Integer, RexDynamicParam> acc = new TreeMap<>(); + + /** */ + private final DynamicParamsShuttle paramsShuttle = new DynamicParamsShuttle(); + + /** */ + public static ParamsMetadata go(IgniteRel root) { + DynamicParamTypeExtractor extractor = new DynamicParamTypeExtractor(); + + extractor.visit(root); + + return new ParamsMetadata(extractor.acc.values()); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteFilter rel) { + paramsShuttle.apply(rel.getCondition()); + + return super.visit(rel); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteProject rel) { + paramsShuttle.apply(rel.getProjects()); + + return super.visit(rel); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteNestedLoopJoin rel) { + paramsShuttle.apply(rel.getCondition()); + + return super.visit(rel); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteCorrelatedNestedLoopJoin rel) { + paramsShuttle.apply(rel.getCondition()); + + return super.visit(rel); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteMergeJoin rel) { + paramsShuttle.apply(rel.getCondition()); + + return super.visit(rel); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteIndexScan rel) { + paramsShuttle.apply(rel.projects()); + paramsShuttle.apply(rel.condition()); + paramsShuttle.apply(rel.searchBounds()); + + return super.visit(rel); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteTableScan rel) { + paramsShuttle.apply(rel.projects()); + paramsShuttle.apply(rel.condition()); + + return super.visit(rel); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteSortedIndexSpool rel) { + paramsShuttle.apply(rel.condition()); + paramsShuttle.apply(rel.searchBounds()); + + return super.visit(rel); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteHashIndexSpool rel) { + paramsShuttle.apply(rel.condition()); + paramsShuttle.apply(rel.searchRow()); + + return super.visit(rel); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteTableModify rel) { + paramsShuttle.apply(rel.getSourceExpressionList()); + + return super.visit(rel); + } + + /** */ + private final class DynamicParamsShuttle extends RexShuttle { + /** {@inheritDoc} */ + @Override public RexNode visitDynamicParam(RexDynamicParam param) { + acc.put(param.getIndex(), param); + + return super.visitDynamicParam(param); + } + + /** */ + public void apply(Collection<SearchBounds> bounds) { Review Comment: It's redundant (see previous comment about search bounds) ########## modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java: ########## @@ -3121,6 +3123,75 @@ public List<FieldsQueryCursor<List<?>>> querySqlFields( }); } + /** */ + public List<JdbcParameterMeta> parameterMetaData( + @Nullable final GridCacheContext<?, ?> cctx, + final SqlFieldsQuery qry, + @Nullable final SqlClientContext cliCtx + ) { + + if (!moduleEnabled()) { Review Comment: Let's deduplicate this check (create something like `checkxModuleEnabled()` like already existing `checkxIndexingEnabled()`) ########## modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/DynamicParamTypeExtractor.java: ########## @@ -0,0 +1,215 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.query.calcite.prepare; + +import java.lang.reflect.Type; +import java.util.Collection; +import java.util.List; +import java.util.SortedMap; +import java.util.TreeMap; +import com.google.common.collect.ImmutableList; +import org.apache.calcite.rel.type.RelDataType; +import org.apache.calcite.rex.RexDynamicParam; +import org.apache.calcite.rex.RexNode; +import org.apache.calcite.rex.RexShuttle; +import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata; +import org.apache.ignite.internal.processors.query.calcite.prepare.bounds.MultiBounds; +import org.apache.ignite.internal.processors.query.calcite.prepare.bounds.RangeBounds; +import org.apache.ignite.internal.processors.query.calcite.prepare.bounds.SearchBounds; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteCorrelatedNestedLoopJoin; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteFilter; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteHashIndexSpool; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteIndexScan; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteMergeJoin; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteNestedLoopJoin; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteProject; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteRel; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteSortedIndexSpool; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableModify; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableScan; +import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory; + +/** */ +public class DynamicParamTypeExtractor extends IgniteRelShuttle { + /** */ + private final SortedMap<Integer, RexDynamicParam> acc = new TreeMap<>(); + + /** */ + private final DynamicParamsShuttle paramsShuttle = new DynamicParamsShuttle(); + + /** */ + public static ParamsMetadata go(IgniteRel root) { + DynamicParamTypeExtractor extractor = new DynamicParamTypeExtractor(); + + extractor.visit(root); + + return new ParamsMetadata(extractor.acc.values()); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteFilter rel) { + paramsShuttle.apply(rel.getCondition()); + + return super.visit(rel); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteProject rel) { + paramsShuttle.apply(rel.getProjects()); + + return super.visit(rel); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteNestedLoopJoin rel) { + paramsShuttle.apply(rel.getCondition()); + + return super.visit(rel); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteCorrelatedNestedLoopJoin rel) { + paramsShuttle.apply(rel.getCondition()); + + return super.visit(rel); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteMergeJoin rel) { + paramsShuttle.apply(rel.getCondition()); + + return super.visit(rel); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteIndexScan rel) { + paramsShuttle.apply(rel.projects()); + paramsShuttle.apply(rel.condition()); + paramsShuttle.apply(rel.searchBounds()); + + return super.visit(rel); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteTableScan rel) { + paramsShuttle.apply(rel.projects()); + paramsShuttle.apply(rel.condition()); + + return super.visit(rel); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteSortedIndexSpool rel) { + paramsShuttle.apply(rel.condition()); + paramsShuttle.apply(rel.searchBounds()); + + return super.visit(rel); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteHashIndexSpool rel) { + paramsShuttle.apply(rel.condition()); + paramsShuttle.apply(rel.searchRow()); + + return super.visit(rel); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteTableModify rel) { + paramsShuttle.apply(rel.getSourceExpressionList()); + + return super.visit(rel); + } + + /** */ + private final class DynamicParamsShuttle extends RexShuttle { + /** {@inheritDoc} */ + @Override public RexNode visitDynamicParam(RexDynamicParam param) { + acc.put(param.getIndex(), param); + + return super.visitDynamicParam(param); + } + + /** */ + public void apply(Collection<SearchBounds> bounds) { + if (bounds == null) + return; + + for (SearchBounds b: bounds) { + if (b == null) + continue; + + switch (b.type()) { + case EXACT: + apply(b.condition()); + + break; + case RANGE: + RangeBounds rb = (RangeBounds)b; + + apply(rb.lowerBound()); + apply(rb.upperBound()); + + break; + + case MULTI: + MultiBounds mb = (MultiBounds)b; + + apply(mb.bounds()); + + break; + + } + } + } + } + + /** */ + private static final class ParamsMetadata implements FieldsMetadata { + /** */ + private final Collection<RexDynamicParam> params; + + /** */ + ParamsMetadata(Collection<RexDynamicParam> params) { + this.params = params; + } + + /** {@inheritDoc} */ + @Override public RelDataType rowType() { + return null; + } + + /** {@inheritDoc} */ + @Override public List<GridQueryFieldMetadata> queryFieldsMetadata(IgniteTypeFactory typeFactory) { + return params.stream().map(param -> { + RelDataType paramType = param.getType(); + Type fieldCls = typeFactory.getResultClass(paramType); + + return new CalciteQueryFieldMetadata( + null, + null, + param.getName(), + fieldCls == null ? Void.class.getName() : fieldCls.getTypeName(), + paramType.getPrecision(), + paramType.getScale(), + paramType.isNullable() + ); + }).collect(ImmutableList.toImmutableList()); Review Comment: Let's avoid Guava classes where it possible ########## modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/DynamicParamTypeExtractor.java: ########## @@ -0,0 +1,215 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.query.calcite.prepare; + +import java.lang.reflect.Type; +import java.util.Collection; +import java.util.List; +import java.util.SortedMap; +import java.util.TreeMap; +import com.google.common.collect.ImmutableList; +import org.apache.calcite.rel.type.RelDataType; +import org.apache.calcite.rex.RexDynamicParam; +import org.apache.calcite.rex.RexNode; +import org.apache.calcite.rex.RexShuttle; +import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata; +import org.apache.ignite.internal.processors.query.calcite.prepare.bounds.MultiBounds; +import org.apache.ignite.internal.processors.query.calcite.prepare.bounds.RangeBounds; +import org.apache.ignite.internal.processors.query.calcite.prepare.bounds.SearchBounds; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteCorrelatedNestedLoopJoin; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteFilter; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteHashIndexSpool; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteIndexScan; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteMergeJoin; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteNestedLoopJoin; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteProject; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteRel; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteSortedIndexSpool; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableModify; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableScan; +import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory; + +/** */ +public class DynamicParamTypeExtractor extends IgniteRelShuttle { + /** */ + private final SortedMap<Integer, RexDynamicParam> acc = new TreeMap<>(); + + /** */ + private final DynamicParamsShuttle paramsShuttle = new DynamicParamsShuttle(); + + /** */ + public static ParamsMetadata go(IgniteRel root) { + DynamicParamTypeExtractor extractor = new DynamicParamTypeExtractor(); + + extractor.visit(root); + + return new ParamsMetadata(extractor.acc.values()); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteFilter rel) { + paramsShuttle.apply(rel.getCondition()); + + return super.visit(rel); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteProject rel) { + paramsShuttle.apply(rel.getProjects()); + + return super.visit(rel); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteNestedLoopJoin rel) { + paramsShuttle.apply(rel.getCondition()); + + return super.visit(rel); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteCorrelatedNestedLoopJoin rel) { + paramsShuttle.apply(rel.getCondition()); + + return super.visit(rel); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteMergeJoin rel) { + paramsShuttle.apply(rel.getCondition()); + + return super.visit(rel); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteIndexScan rel) { + paramsShuttle.apply(rel.projects()); + paramsShuttle.apply(rel.condition()); + paramsShuttle.apply(rel.searchBounds()); + + return super.visit(rel); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteTableScan rel) { + paramsShuttle.apply(rel.projects()); + paramsShuttle.apply(rel.condition()); + + return super.visit(rel); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteSortedIndexSpool rel) { + paramsShuttle.apply(rel.condition()); + paramsShuttle.apply(rel.searchBounds()); + + return super.visit(rel); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteHashIndexSpool rel) { + paramsShuttle.apply(rel.condition()); + paramsShuttle.apply(rel.searchRow()); + + return super.visit(rel); + } + + /** {@inheritDoc} */ + @Override public IgniteRel visit(IgniteTableModify rel) { + paramsShuttle.apply(rel.getSourceExpressionList()); + + return super.visit(rel); + } + Review Comment: Perhaps processing of IgniteLimit/IgniteSort/IgniteTableFunctionScan should be added too. ########## modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java: ########## @@ -3121,6 +3123,75 @@ public List<FieldsQueryCursor<List<?>>> querySqlFields( }); } + /** */ + public List<JdbcParameterMeta> parameterMetaData( + @Nullable final GridCacheContext<?, ?> cctx, + final SqlFieldsQuery qry, + @Nullable final SqlClientContext cliCtx + ) { + + if (!moduleEnabled()) { + throw new IgniteException("Failed to execute query because indexing is disabled and no query engine is " + + "configured (consider adding module " + INDEXING.module() + " to classpath or moving it " + + "from 'optional' to 'libs' folder or configuring any query engine with " + + "IgniteConfiguration.SqlConfiguration.QueryEnginesConfiguration property)."); + } + + return executeQuerySafe(cctx, () -> { + final String schemaName = qry.getSchema() == null ? schemaName(cctx) : qry.getSchema(); + + QueryEngine qryEngine = engineForQuery(cliCtx, qry); + + if (qryEngine != null) { + List<T2<List<GridQueryFieldMetadata>, List<GridQueryFieldMetadata>>> meta = qryEngine.queryMetadata( + QueryContext.of(qry, cliCtx), + schemaName, + qry.getSql()); + + return meta.stream() + .flatMap(pair -> pair.getValue().stream().map(JdbcParameterMeta::new)) + .collect(Collectors.toList()); + } + else + return idx.parameterMetaData(schemaName, qry); + + }); + } + + /** */ + public List<GridQueryFieldMetadata> resultSetMetaData( + @Nullable final GridCacheContext<?, ?> cctx, Review Comment: Looks like `cctx` is always `null` -- 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]
