6464import org .apache .ignite .internal .processors .query .calcite .exec .rel .ProjectNode ;
6565import org .apache .ignite .internal .processors .query .calcite .exec .rel .ScanNode ;
6666import org .apache .ignite .internal .processors .query .calcite .exec .rel .ScanStorageNode ;
67+ import org .apache .ignite .internal .processors .query .calcite .exec .rel .ScanTableRowNode ;
6768import org .apache .ignite .internal .processors .query .calcite .exec .rel .SortAggregateNode ;
6869import org .apache .ignite .internal .processors .query .calcite .exec .rel .SortNode ;
6970import org .apache .ignite .internal .processors .query .calcite .exec .rel .TableSpoolNode ;
116117import org .apache .ignite .internal .processors .query .calcite .util .Commons ;
117118import org .apache .ignite .internal .processors .query .calcite .util .RexUtils ;
118119import org .apache .ignite .internal .util .typedef .F ;
120+ import org .jetbrains .annotations .Nullable ;
119121
120122import static org .apache .calcite .rel .RelDistribution .Type .HASH_DISTRIBUTED ;
121123import static org .apache .ignite .internal .processors .query .calcite .util .TypeUtils .combinedRowType ;
@@ -368,10 +370,10 @@ private boolean hasExchange(RelNode rel) {
368370 ImmutableBitSet requiredColumns = rel .requiredColumns ();
369371 List <SearchBounds > searchBounds = rel .searchBounds ();
370372
371- RelDataType rowType = tbl .getRowType (typeFactory , requiredColumns );
373+ RelDataType inputRowType = tbl .getRowType (typeFactory , requiredColumns );
372374
373- Predicate <Row > filters = condition == null ? null : expressionFactory .predicate (condition , rowType );
374- Function <Row , Row > prj = projects == null ? null : expressionFactory .project (projects , rowType );
375+ Predicate <Row > filters = condition == null ? null : expressionFactory .predicate (condition , inputRowType );
376+ Function <Row , Row > prj = projects == null ? null : expressionFactory .project (projects , inputRowType );
375377 RangeIterable <Row > ranges = searchBounds == null ? null :
376378 expressionFactory .ranges (searchBounds , rel .collation (), tbl .getRowType (typeFactory ));
377379
@@ -382,7 +384,8 @@ private boolean hasExchange(RelNode rel) {
382384 if (idx != null && !tbl .isIndexRebuildInProgress ()) {
383385 Iterable <Row > rowsIter = idx .scan (ctx , grp , ranges , requiredColumns );
384386
385- return new ScanStorageNode <>(tbl .name () + '.' + idx .name (), ctx , rowType , rowsIter , filters , prj );
387+ return createStorageScan (tbl .name () + '.' + idx .name (), rel .getRowType (), inputRowType ,
388+ rowsIter , filters , prj , requiredColumns , rel .conditionColumns ());
386389 }
387390 else {
388391 // Index was invalidated after planning, workaround through table-scan -> sort -> index spool.
@@ -402,12 +405,10 @@ private boolean hasExchange(RelNode rel) {
402405 requiredColumns
403406 );
404407
405- // If there are projects in the scan node - after the scan we already have target row type.
406- if (!spoolNodeRequired && projects != null )
407- rowType = rel .getRowType ();
408+ RelDataType rowType = projNodeRequired ? rel .getRowType () : inputRowType ;
408409
409- Node <Row > node = new ScanStorageNode <> (tbl .name (), ctx , rowType , rowsIter , filterHasCorrelation ? null : filters ,
410- projNodeRequired ? null : prj );
410+ Node <Row > node = createStorageScan (tbl .name (), rowType , inputRowType , rowsIter ,
411+ filterHasCorrelation ? null : filters , projNodeRequired ? null : prj , requiredColumns , rel . conditionColumns () );
411412
412413 RelCollation collation = rel .collation ();
413414
@@ -438,7 +439,7 @@ private boolean hasExchange(RelNode rel) {
438439 remappedSearchBounds .add (searchBounds .get (i ));
439440
440441 // Collation and row type are already remapped taking into account requiredColumns.
441- ranges = expressionFactory .ranges (remappedSearchBounds , collation , rowType );
442+ ranges = expressionFactory .ranges (remappedSearchBounds , collation , inputRowType );
442443 }
443444
444445 IndexSpoolNode <Row > spoolNode = IndexSpoolNode .createTreeSpool (
@@ -548,10 +549,10 @@ private boolean hasExchange(RelNode rel) {
548549 IgniteTable tbl = rel .getTable ().unwrap (IgniteTable .class );
549550 IgniteTypeFactory typeFactory = ctx .getTypeFactory ();
550551
551- RelDataType rowType = tbl .getRowType (typeFactory , requiredColumns );
552+ RelDataType inputRowType = tbl .getRowType (typeFactory , requiredColumns );
552553
553- Predicate <Row > filters = condition == null ? null : expressionFactory .predicate (condition , rowType );
554- Function <Row , Row > prj = projects == null ? null : expressionFactory .project (projects , rowType );
554+ Predicate <Row > filters = condition == null ? null : expressionFactory .predicate (condition , inputRowType );
555+ Function <Row , Row > prj = projects == null ? null : expressionFactory .project (projects , inputRowType );
555556
556557 ColocationGroup grp = ctx .group (rel .sourceId ());
557558
@@ -560,12 +561,14 @@ private boolean hasExchange(RelNode rel) {
560561 if (idx != null && !tbl .isIndexRebuildInProgress ()) {
561562 Iterable <Row > rowsIter = idx .scan (ctx , grp , null , requiredColumns );
562563
563- return new ScanStorageNode <>(tbl .name () + '.' + idx .name (), ctx , rowType , rowsIter , filters , prj );
564+ return createStorageScan (tbl .name () + '.' + idx .name (), rel .getRowType (), inputRowType ,
565+ rowsIter , filters , prj , requiredColumns , rel .conditionColumns ());
564566 }
565567 else {
566568 Iterable <Row > rowsIter = tbl .scan (ctx , grp , requiredColumns );
567569
568- return new ScanStorageNode <>(tbl .name (), ctx , rowType , rowsIter , filters , prj );
570+ return createStorageScan (tbl .name (), rel .getRowType (), inputRowType , rowsIter , filters , prj ,
571+ requiredColumns , rel .conditionColumns ());
569572 }
570573 }
571574
@@ -943,4 +946,46 @@ private Node<Row> visit(RelNode rel) {
943946 public <T extends Node <Row >> T go (IgniteRel rel ) {
944947 return (T )visit (rel );
945948 }
949+
950+ /** */
951+ private ScanStorageNode <Row > createStorageScan (
952+ String storageName ,
953+ RelDataType outputRowType ,
954+ RelDataType inputRowType ,
955+ Iterable <Row > rowsIter ,
956+ @ Nullable Predicate <Row > filter ,
957+ @ Nullable Function <Row , Row > rowTransformer ,
958+ @ Nullable ImmutableBitSet requiredColumns ,
959+ @ Nullable ImmutableBitSet filterColumns
960+ ) {
961+ int fieldsCnt = outputRowType .getFieldCount ();
962+
963+ if (filter == null || filterColumns == null || filterColumns .cardinality () == fieldsCnt
964+ || !(rowsIter instanceof TableRowIterable ))
965+ return new ScanStorageNode <>(storageName , ctx , outputRowType , rowsIter , filter , rowTransformer );
966+
967+ ImmutableBitSet reqCols = requiredColumns == null ? ImmutableBitSet .range (0 , fieldsCnt ) : requiredColumns ;
968+
969+ int [] filterColMapping = reqCols .toArray ();
970+ int [] otherColMapping = filterColMapping .clone ();
971+
972+ for (int i = 0 ; i < filterColMapping .length ; i ++) {
973+ if (filterColumns .get (i ))
974+ otherColMapping [i ] = -1 ;
975+ else
976+ filterColMapping [i ] = -1 ;
977+ }
978+
979+ return new ScanTableRowNode <>(
980+ storageName ,
981+ ctx ,
982+ outputRowType ,
983+ inputRowType ,
984+ (TableRowIterable <Object , Row >)rowsIter ,
985+ filter ,
986+ rowTransformer ,
987+ filterColMapping ,
988+ otherColMapping
989+ );
990+ }
946991}
0 commit comments