alex-plekhanov commented on code in PR #10153: URL: https://github.com/apache/ignite/pull/10153#discussion_r1007982697
########## modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/IndexFirstLastScan.java: ########## @@ -0,0 +1,105 @@ +/* + * 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.exec; + +import org.apache.calcite.util.ImmutableBitSet; +import org.apache.calcite.util.ImmutableIntList; +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.IgniteException; +import org.apache.ignite.internal.cache.query.index.sorted.IndexKeyType; +import org.apache.ignite.internal.cache.query.index.sorted.IndexRow; +import org.apache.ignite.internal.cache.query.index.sorted.inline.IndexQueryContext; +import org.apache.ignite.internal.cache.query.index.sorted.inline.InlineIndexImpl; +import org.apache.ignite.internal.processors.cache.persistence.tree.BPlusTree; +import org.apache.ignite.internal.processors.cache.persistence.tree.io.BPlusIO; +import org.apache.ignite.internal.processors.query.calcite.schema.CacheTableDescriptor; +import org.apache.ignite.internal.util.lang.GridCursor; +import org.jetbrains.annotations.Nullable; + +/** + * Takes only first or last index value excluding nulls. + */ +public class IndexFirstLastScan<Row> extends IndexScan<Row> { + /** + * @param first {@code True} to take first index value. {@code False} to take last value. + * @param ectx Execution context. + * @param desc Table descriptor. + * @param idx Phisycal index. + * @param idxFieldMapping Mapping from index keys to row fields. + * @param parts Mapping from index keys to row fields. + * @param requiredColumns Required columns. + */ + public IndexFirstLastScan(boolean first, Review Comment: NL after `(` ########## modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/IndexFirstLastScan.java: ########## @@ -0,0 +1,105 @@ +/* + * 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.exec; + +import org.apache.calcite.util.ImmutableBitSet; +import org.apache.calcite.util.ImmutableIntList; +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.IgniteException; +import org.apache.ignite.internal.cache.query.index.sorted.IndexKeyType; +import org.apache.ignite.internal.cache.query.index.sorted.IndexRow; +import org.apache.ignite.internal.cache.query.index.sorted.inline.IndexQueryContext; +import org.apache.ignite.internal.cache.query.index.sorted.inline.InlineIndexImpl; +import org.apache.ignite.internal.processors.cache.persistence.tree.BPlusTree; +import org.apache.ignite.internal.processors.cache.persistence.tree.io.BPlusIO; +import org.apache.ignite.internal.processors.query.calcite.schema.CacheTableDescriptor; +import org.apache.ignite.internal.util.lang.GridCursor; +import org.jetbrains.annotations.Nullable; + +/** + * Takes only first or last index value excluding nulls. + */ +public class IndexFirstLastScan<Row> extends IndexScan<Row> { + /** + * @param first {@code True} to take first index value. {@code False} to take last value. + * @param ectx Execution context. + * @param desc Table descriptor. + * @param idx Phisycal index. + * @param idxFieldMapping Mapping from index keys to row fields. + * @param parts Mapping from index keys to row fields. + * @param requiredColumns Required columns. + */ + public IndexFirstLastScan(boolean first, + ExecutionContext<Row> ectx, + CacheTableDescriptor desc, + InlineIndexImpl idx, + ImmutableIntList idxFieldMapping, + int[] parts, + @Nullable ImmutableBitSet requiredColumns) { Review Comment: NL before `)` ########## modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/schema/IgniteIndex.java: ########## @@ -94,4 +94,16 @@ public <Row> Iterable<Row> scan( * @return Index records number for {@code group}. */ public long count(ExecutionContext<?> ectx, ColocationGroup grp); + + /** + * Takes only first or last not-null index value. + * + * @param first {@code True} to take first index not-null value. {@code False} for last. + * @param ectx Execution context. + * @param grp Colocation group. + * @param requiredColumns Required columns. + * @return Index records for {@code grp}. + */ + public <Row> Iterable<Row> firstOrLast(boolean first, ExecutionContext<Row> ectx, ColocationGroup grp, Review Comment: Codestyle: each parameter should be on it's own line. ########## modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/schema/SystemViewIndexImpl.java: ########## @@ -101,6 +102,12 @@ public SystemViewIndexImpl(SystemViewTableImpl tbl) { return tbl.descriptor().systemView().size(); } + /** {@inheritDoc} */ + @Override public <Row> Iterable<Row> firstOrLast(boolean first, ExecutionContext<Row> ectx, ColocationGroup grp, Review Comment: Codestyle: each parameter should be on it's own line. ########## modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/inline/InlineIndexImpl.java: ########## @@ -639,5 +658,48 @@ private static class SegmentedIndexCursor implements GridCursor<IndexRow> { @Override public IndexRow get() throws IgniteCheckedException { return head; } + + /** */ + protected Queue<GridCursor<IndexRow>> cursorsQueue(GridCursor<IndexRow>[] cursors) + throws IgniteCheckedException { + PriorityQueue<GridCursor<IndexRow>> q = new PriorityQueue<>(cursors.length, cursorComp); + + for (GridCursor<IndexRow> c: cursors) { + if (c.next()) + q.add(c); + } + + return q; + } + } + + /** First-only, single-value-only segmented cursor. */ + private static class FirstSegmentSingleValueIndexCursor extends SegmentedIndexCursor { Review Comment: Why `FirstSegment`? It takes min/max from all segments, not first. I think `SingleValueSegmentedIndexCursor` will be better. ########## modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/inline/InlineIndexImpl.java: ########## @@ -639,5 +658,48 @@ private static class SegmentedIndexCursor implements GridCursor<IndexRow> { @Override public IndexRow get() throws IgniteCheckedException { return head; } + + /** */ + protected Queue<GridCursor<IndexRow>> cursorsQueue(GridCursor<IndexRow>[] cursors) + throws IgniteCheckedException { + PriorityQueue<GridCursor<IndexRow>> q = new PriorityQueue<>(cursors.length, cursorComp); + + for (GridCursor<IndexRow> c: cursors) { + if (c.next()) + q.add(c); + } + + return q; + } + } + + /** First-only, single-value-only segmented cursor. */ + private static class FirstSegmentSingleValueIndexCursor extends SegmentedIndexCursor { + /** + * @param cursors + * @param idxDef + */ + FirstSegmentSingleValueIndexCursor( + GridCursor<IndexRow>[] cursors, SortedIndexDefinition idxDef) throws IgniteCheckedException { + super(cursors, idxDef); + } + + /** {@inheritDoc} */ + @Override protected Queue<GridCursor<IndexRow>> cursorsQueue( Review Comment: Codestyle: each parameter should be on it's own line. ########## modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/inline/InlineIndexImpl.java: ########## @@ -639,5 +658,48 @@ private static class SegmentedIndexCursor implements GridCursor<IndexRow> { @Override public IndexRow get() throws IgniteCheckedException { return head; } + + /** */ + protected Queue<GridCursor<IndexRow>> cursorsQueue(GridCursor<IndexRow>[] cursors) + throws IgniteCheckedException { + PriorityQueue<GridCursor<IndexRow>> q = new PriorityQueue<>(cursors.length, cursorComp); + + for (GridCursor<IndexRow> c: cursors) { + if (c.next()) + q.add(c); + } + + return q; + } + } + + /** First-only, single-value-only segmented cursor. */ + private static class FirstSegmentSingleValueIndexCursor extends SegmentedIndexCursor { + /** + * @param cursors + * @param idxDef Review Comment: If there is no description these lines should be removed. ########## modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/IndexFirstLastScan.java: ########## @@ -0,0 +1,105 @@ +/* + * 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.exec; + +import org.apache.calcite.util.ImmutableBitSet; +import org.apache.calcite.util.ImmutableIntList; +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.IgniteException; +import org.apache.ignite.internal.cache.query.index.sorted.IndexKeyType; +import org.apache.ignite.internal.cache.query.index.sorted.IndexRow; +import org.apache.ignite.internal.cache.query.index.sorted.inline.IndexQueryContext; +import org.apache.ignite.internal.cache.query.index.sorted.inline.InlineIndexImpl; +import org.apache.ignite.internal.processors.cache.persistence.tree.BPlusTree; +import org.apache.ignite.internal.processors.cache.persistence.tree.io.BPlusIO; +import org.apache.ignite.internal.processors.query.calcite.schema.CacheTableDescriptor; +import org.apache.ignite.internal.util.lang.GridCursor; +import org.jetbrains.annotations.Nullable; + +/** + * Takes only first or last index value excluding nulls. + */ +public class IndexFirstLastScan<Row> extends IndexScan<Row> { + /** + * @param first {@code True} to take first index value. {@code False} to take last value. + * @param ectx Execution context. + * @param desc Table descriptor. + * @param idx Phisycal index. + * @param idxFieldMapping Mapping from index keys to row fields. + * @param parts Mapping from index keys to row fields. + * @param requiredColumns Required columns. + */ + public IndexFirstLastScan(boolean first, + ExecutionContext<Row> ectx, + CacheTableDescriptor desc, + InlineIndexImpl idx, + ImmutableIntList idxFieldMapping, + int[] parts, + @Nullable ImmutableBitSet requiredColumns) { + super(ectx, desc, new FirstLastIndexWrapper(idx, first), idxFieldMapping, parts, null, null, null, + requiredColumns); + } + + /** {@inheritDoc} */ + @Override protected IndexQueryContext indexQueryContext() { + IndexQueryContext res = super.indexQueryContext(); + + BPlusTree.TreeRowClosure<IndexRow, IndexRow> f = res.rowFilter(); + + return new IndexQueryContext(res.cacheFilter(), new BPlusTree.TreeRowClosure<IndexRow, IndexRow>() { + /** + * {@inheritDoc} + */ + @Override public boolean apply(BPlusTree<IndexRow, IndexRow> tree, BPlusIO<IndexRow> io, long pageAddr, + int idx) throws IgniteCheckedException { + if (f != null && !f.apply(tree, io, pageAddr, idx)) + return false; + + return io.getLookupRow(tree, pageAddr, idx).key(0).type() != IndexKeyType.NULL; + } + }, res.mvccSnapshot()); + } + + /** */ + private static class FirstLastIndexWrapper extends IndexScan.TreeIndexWrapper { + /** */ + private final boolean first; + + /** + * @param idx Index + * @param first {@code True} to take first index value. {@code False} to take last value. + */ + protected FirstLastIndexWrapper(InlineIndexImpl idx, boolean first) { + super(idx); + this.first = first; + } + + /** {@inheritDoc} */ + @Override public GridCursor<IndexRow> find(IndexRow lower, IndexRow upper, boolean lowerInclude, Review Comment: Codestyle: each parameter should be on it's own line. ########## modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/LogicalRelImplementor.java: ########## @@ -419,6 +422,57 @@ public LogicalRelImplementor( } } + /** {@inheritDoc} */ + @Override public Node<Row> visit(IgniteIndexBound idxBndRel) { + IgniteTable tbl = idxBndRel.getTable().unwrap(IgniteTable.class); + IgniteIndex idx = tbl.getIndex(idxBndRel.indexName()); + IgniteTypeFactory typeFactory = ctx.getTypeFactory(); + ColocationGroup grp = ctx.group(idxBndRel.sourceId()); + ImmutableBitSet requiredColumns = idxBndRel.requiredColumns(); + RelDataType rowType = tbl.getRowType(typeFactory, requiredColumns); + + if (idx != null && !tbl.isIndexRebuildInProgress()) + return new ScanNode<>(ctx, rowType, idx.firstOrLast(idxBndRel.first(), ctx, grp, requiredColumns)); + else { + assert requiredColumns.asList().size() == 1; + + RexBuilder b = new RexBuilder(typeFactory); + + Iterable<Row> rowsIter = tbl.scan( + ctx, + grp, + expressionFactory.predicate(b.makeCall(SqlStdOperatorTable.IS_NOT_NULL, + b.makeLocalRef(rowType.getFieldList().get(0).getType(), 0)), rowType), Review Comment: ```suggestion r -> ctx.rowHandler().get(0, r) != null, ``` ########## modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/inline/InlineIndexImpl.java: ########## @@ -121,6 +124,27 @@ public InlineIndexImpl(GridCacheContext<?, ?> cctx, SortedIndexDefinition def, I } } + /** + * Takes only one not-null-valued first or last index record. + */ + public GridCursor<IndexRow> takeFirstOrLast(IndexQueryContext qryCtx, boolean first) throws IgniteCheckedException { Review Comment: `findFirstOrLast` to match other methods? Perhaps move declaration to `SortedSegmentedIndex`? In this case in `IndexFirstLastScan` idx can be used without casting to `IgniteIndexImpl` (and interface can be used instead of class) ########## modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/schema/CacheIndexImpl.java: ########## @@ -117,6 +119,19 @@ public Index queryIndex() { return Collections.emptyList(); } + /** {@inheritDoc} */ + @Override public <Row> Iterable<Row> firstOrLast(boolean first, ExecutionContext<Row> ectx, ColocationGroup grp, Review Comment: Codestyle: each parameter should be on it's own line. ########## modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/IndexFirstLastScan.java: ########## @@ -0,0 +1,105 @@ +/* + * 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.exec; + +import org.apache.calcite.util.ImmutableBitSet; +import org.apache.calcite.util.ImmutableIntList; +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.IgniteException; +import org.apache.ignite.internal.cache.query.index.sorted.IndexKeyType; +import org.apache.ignite.internal.cache.query.index.sorted.IndexRow; +import org.apache.ignite.internal.cache.query.index.sorted.inline.IndexQueryContext; +import org.apache.ignite.internal.cache.query.index.sorted.inline.InlineIndexImpl; +import org.apache.ignite.internal.processors.cache.persistence.tree.BPlusTree; +import org.apache.ignite.internal.processors.cache.persistence.tree.io.BPlusIO; +import org.apache.ignite.internal.processors.query.calcite.schema.CacheTableDescriptor; +import org.apache.ignite.internal.util.lang.GridCursor; +import org.jetbrains.annotations.Nullable; + +/** + * Takes only first or last index value excluding nulls. + */ +public class IndexFirstLastScan<Row> extends IndexScan<Row> { + /** + * @param first {@code True} to take first index value. {@code False} to take last value. + * @param ectx Execution context. + * @param desc Table descriptor. + * @param idx Phisycal index. + * @param idxFieldMapping Mapping from index keys to row fields. + * @param parts Mapping from index keys to row fields. + * @param requiredColumns Required columns. + */ + public IndexFirstLastScan(boolean first, + ExecutionContext<Row> ectx, + CacheTableDescriptor desc, + InlineIndexImpl idx, + ImmutableIntList idxFieldMapping, + int[] parts, + @Nullable ImmutableBitSet requiredColumns) { + super(ectx, desc, new FirstLastIndexWrapper(idx, first), idxFieldMapping, parts, null, null, null, + requiredColumns); + } + + /** {@inheritDoc} */ + @Override protected IndexQueryContext indexQueryContext() { + IndexQueryContext res = super.indexQueryContext(); + + BPlusTree.TreeRowClosure<IndexRow, IndexRow> f = res.rowFilter(); + + return new IndexQueryContext(res.cacheFilter(), new BPlusTree.TreeRowClosure<IndexRow, IndexRow>() { + /** + * {@inheritDoc} + */ + @Override public boolean apply(BPlusTree<IndexRow, IndexRow> tree, BPlusIO<IndexRow> io, long pageAddr, + int idx) throws IgniteCheckedException { + if (f != null && !f.apply(tree, io, pageAddr, idx)) + return false; + + return io.getLookupRow(tree, pageAddr, idx).key(0).type() != IndexKeyType.NULL; + } + }, res.mvccSnapshot()); Review Comment: `getLookupRow` reads full cache row, it can be not effective, I propose to try to read the inlined value first: ```suggestion List<InlineIndexKeyType> inlineKeyTypes = idx.segment(0).rowHandler().inlineIndexKeyTypes(); InlineIndexKeyType keyType = F.isEmpty(inlineKeyTypes) ? null : inlineKeyTypes.get(0); return new IndexQueryContext(res.cacheFilter(), new BPlusTree.TreeRowClosure<IndexRow, IndexRow>() { /** {@inheritDoc} */ @Override public boolean apply( BPlusTree<IndexRow, IndexRow> tree, BPlusIO<IndexRow> io, long pageAddr, int idx ) throws IgniteCheckedException { if (f != null && !f.apply(tree, io, pageAddr, idx)) return false; if (keyType != null && io instanceof InlineIO) { IndexKey key = keyType.get(pageAddr, io.offset(idx), ((InlineIO)io).inlineSize()); if (key != null) return key == NullIndexKey.INSTANCE; }; return io.getLookupRow(tree, pageAddr, idx).key(0).type() != IndexKeyType.NULL; } }, res.mvccSnapshot()); ``` ########## modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/inline/InlineIndexImpl.java: ########## @@ -121,6 +124,27 @@ public InlineIndexImpl(GridCacheContext<?, ?> cctx, SortedIndexDefinition def, I } } + /** + * Takes only one not-null-valued first or last index record. Review Comment: `not-null-valued` - it can be null, depends on qryCtx ########## modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/IndexMinMaxRule.java: ########## @@ -0,0 +1,95 @@ +/* + * 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.rule; + +import org.apache.calcite.plan.RelOptRuleCall; +import org.apache.calcite.plan.RelRule; +import org.apache.calcite.sql.SqlAggFunction; +import org.apache.calcite.sql.SqlKind; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteAggregate; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteIndexBound; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteIndexScan; +import org.apache.ignite.internal.processors.query.calcite.schema.IgniteIndex; +import org.apache.ignite.internal.processors.query.calcite.schema.IgniteTable; +import org.apache.ignite.internal.processors.query.calcite.trait.RewindabilityTrait; +import org.apache.ignite.internal.util.typedef.F; +import org.immutables.value.Value; + +/** + * Tries to optimize MIN() and MAX() so that it takes only first or last not-null index record. + */ [email protected] +public class IndexMinMaxRule extends RelRule<IndexMinMaxRule.Config> { + /** */ + public static final IndexMinMaxRule INSTANCE = Config.DEFAULT.toRule(); + + /** Ctor. */ + private IndexMinMaxRule(IndexMinMaxRule.Config cfg) { + super(cfg); + } + + /** */ + @Override public void onMatch(RelOptRuleCall call) { + IgniteAggregate aggr = call.rel(0); + IgniteIndexScan idxScan = call.rel(1); + IgniteTable table = idxScan.getTable().unwrap(IgniteTable.class); + IgniteIndex idx = table.getIndex(idxScan.indexName()); + + if ( + table.isIndexRebuildInProgress() || + idxScan.condition() != null || + idxScan.projects() != null || + aggr.getGroupCount() > 0 || + aggr.getAggCallList().stream().filter(a -> a.getAggregation().getKind() == SqlKind.MIN + || a.getAggregation().getKind() == SqlKind.MAX).count() != 1 || + idx.collation().getFieldCollations().isEmpty() || + idx.collation().getFieldCollations().get(0).getFieldIndex() != idxScan.requiredColumns().asList().get(0) Review Comment: `asList().get(0)` -> `nextSetBit(0)`? ########## modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/inline/InlineIndexImpl.java: ########## @@ -639,5 +658,48 @@ private static class SegmentedIndexCursor implements GridCursor<IndexRow> { @Override public IndexRow get() throws IgniteCheckedException { return head; } + + /** */ + protected Queue<GridCursor<IndexRow>> cursorsQueue(GridCursor<IndexRow>[] cursors) + throws IgniteCheckedException { + PriorityQueue<GridCursor<IndexRow>> q = new PriorityQueue<>(cursors.length, cursorComp); + + for (GridCursor<IndexRow> c: cursors) { + if (c.next()) + q.add(c); + } + + return q; + } + } + + /** First-only, single-value-only segmented cursor. */ + private static class FirstSegmentSingleValueIndexCursor extends SegmentedIndexCursor { + /** + * @param cursors + * @param idxDef + */ + FirstSegmentSingleValueIndexCursor( Review Comment: Codestyle: each parameter should be on it's own line. -- 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]
