@@ -668,11 +668,68 @@ class Table_read_cursor : public Rowid_seq_cursor
668
668
// todo: should move_to() also read row here?
669
669
};
670
670
671
+
671
672
/*
672
- TODO: We should also have a cursor that reads table rows and
673
- stays within the current partition.
673
+ A cursor which only moves within a partition. The scan stops at the partition
674
+ end, and it needs an explicit command to move to the next partition.
674
675
*/
675
676
677
+ class Partition_read_cursor
678
+ {
679
+ Table_read_cursor tbl_cursor;
680
+ Group_bound_tracker bound_tracker;
681
+ bool end_of_partition;
682
+ public:
683
+ void init (THD *thd, READ_RECORD *info, SQL_I_List<ORDER> *partition_list)
684
+ {
685
+ tbl_cursor.init (info);
686
+ bound_tracker.init (thd, partition_list);
687
+ end_of_partition= false ;
688
+ }
689
+
690
+ /*
691
+ Informs the cursor that we need to move into the next partition.
692
+ The next partition is provided in two ways:
693
+ - in table->record[0]..
694
+ - rownum parameter has the row number.
695
+ */
696
+ void on_next_partition (int rownum)
697
+ {
698
+ /* Remember the sort key value from the new partition */
699
+ bound_tracker.check_if_next_group ();
700
+ end_of_partition= false ;
701
+ }
702
+
703
+ /*
704
+ Moves to a new row. The row is assumed to be within the current partition
705
+ */
706
+ void move_to (int rownum) { tbl_cursor.move_to (rownum); }
707
+
708
+ /*
709
+ This returns -1 when end of partition was reached.
710
+ */
711
+ int get_next ()
712
+ {
713
+ int res;
714
+ if (end_of_partition)
715
+ return -1 ;
716
+ if ((res= tbl_cursor.get_next ()))
717
+ return res;
718
+
719
+ if (bound_tracker.compare_with_cache ())
720
+ {
721
+ end_of_partition= true ;
722
+ return -1 ;
723
+ }
724
+ return 0 ;
725
+ }
726
+
727
+ bool restore_last_row ()
728
+ {
729
+ return tbl_cursor.restore_last_row ();
730
+ }
731
+ };
732
+
676
733
// ///////////////////////////////////////////////////////////////////////////
677
734
678
735
@@ -686,6 +743,27 @@ class Table_read_cursor : public Rowid_seq_cursor
686
743
The cursor also assumes that the current row moves forward through the
687
744
partition and will move to the next adjacent partition after this one.
688
745
746
+ List of all cursor classes:
747
+ Frame_cursor
748
+ Frame_range_n_top
749
+ Frame_range_n_bottom
750
+
751
+ Frame_range_current_row_top
752
+ Frame_range_current_row_bottom
753
+
754
+ Frame_n_rows_preceding
755
+ Frame_n_rows_following
756
+
757
+ Frame_rows_current_row_top = Frame_n_rows_preceding(0)
758
+ Frame_rows_current_row_bottom
759
+
760
+ // These handle both RANGE and ROWS-type bounds
761
+ Frame_unbounded_preceding
762
+ Frame_unbounded_following
763
+
764
+ // This is not used as a frame bound, it counts rows in the partition:
765
+ Frame_unbounded_following_set_count : public Frame_unbounded_following
766
+
689
767
@todo
690
768
- if we want to allocate this on the MEM_ROOT we should make sure
691
769
it is not re-allocated for every subquery execution.
@@ -852,7 +930,7 @@ class Frame_range_n_top : public Frame_cursor
852
930
853
931
class Frame_range_n_bottom : public Frame_cursor
854
932
{
855
- Table_read_cursor cursor;
933
+ Partition_read_cursor cursor;
856
934
857
935
Cached_item_item *range_expr;
858
936
@@ -861,7 +939,6 @@ class Frame_range_n_bottom: public Frame_cursor
861
939
862
940
const bool is_preceding;
863
941
864
- Group_bound_tracker bound_tracker;
865
942
bool end_of_partition;
866
943
867
944
/*
@@ -878,7 +955,7 @@ class Frame_range_n_bottom: public Frame_cursor
878
955
SQL_I_List<ORDER> *partition_list,
879
956
SQL_I_List<ORDER> *order_list)
880
957
{
881
- cursor.init (info);
958
+ cursor.init (thd, info, partition_list );
882
959
883
960
DBUG_ASSERT (order_list->elements == 1 );
884
961
Item *src_expr= order_list->first ->item [0 ];
@@ -900,16 +977,14 @@ class Frame_range_n_bottom: public Frame_cursor
900
977
item_add= new (thd->mem_root ) Item_func_plus (thd, src_expr, n_val);
901
978
902
979
item_add->fix_fields (thd, &item_add);
903
-
904
- bound_tracker.init (thd, partition_list);
905
980
}
906
981
907
982
void pre_next_partition (longlong rownum, Item_sum* item)
908
983
{
909
984
// Save the value of FUNC(current_row)
910
985
range_expr->fetch_value_from (item_add);
911
986
912
- bound_tracker. check_if_next_group ( );
987
+ cursor. on_next_partition (rownum );
913
988
end_of_partition= false ;
914
989
}
915
990
@@ -950,11 +1025,6 @@ class Frame_range_n_bottom: public Frame_cursor
950
1025
int res;
951
1026
while (!(res= cursor.get_next ()))
952
1027
{
953
- if (bound_tracker.check_if_next_group ())
954
- {
955
- end_of_partition= true ;
956
- break ;
957
- }
958
1028
if (order_direction * range_expr->cmp_read_only () < 0 )
959
1029
break ;
960
1030
item->add ();
@@ -981,7 +1051,8 @@ class Frame_range_n_bottom: public Frame_cursor
981
1051
982
1052
class Frame_range_current_row_bottom : public Frame_cursor
983
1053
{
984
- Table_read_cursor cursor;
1054
+ Partition_read_cursor cursor;
1055
+
985
1056
Group_bound_tracker peer_tracker;
986
1057
987
1058
bool dont_move;
@@ -990,14 +1061,15 @@ class Frame_range_current_row_bottom: public Frame_cursor
990
1061
SQL_I_List<ORDER> *partition_list,
991
1062
SQL_I_List<ORDER> *order_list)
992
1063
{
993
- cursor.init (info);
1064
+ cursor.init (thd, info, partition_list );
994
1065
peer_tracker.init (thd, order_list);
995
1066
}
996
1067
997
1068
void pre_next_partition (longlong rownum, Item_sum* item)
998
1069
{
999
1070
// Save the value of the current_row
1000
1071
peer_tracker.check_if_next_group ();
1072
+ cursor.on_next_partition (rownum);
1001
1073
if (rownum != 0 )
1002
1074
{
1003
1075
// Add the current row now because our cursor has already seen it
@@ -1160,17 +1232,19 @@ class Frame_unbounded_preceding : public Frame_cursor
1160
1232
1161
1233
class Frame_unbounded_following : public Frame_cursor
1162
1234
{
1163
-
1164
1235
protected:
1165
- Table_read_cursor cursor;
1166
- Group_bound_tracker bound_tracker;
1236
+ Partition_read_cursor cursor;
1167
1237
1168
1238
public:
1169
1239
void init (THD *thd, READ_RECORD *info, SQL_I_List<ORDER> *partition_list,
1170
1240
SQL_I_List<ORDER> *order_list)
1171
1241
{
1172
- cursor.init (info);
1173
- bound_tracker.init (thd, partition_list);
1242
+ cursor.init (thd, info, partition_list);
1243
+ }
1244
+
1245
+ void pre_next_partition (longlong rownum, Item_sum* item)
1246
+ {
1247
+ cursor.on_next_partition (rownum);
1174
1248
}
1175
1249
1176
1250
void next_partition (longlong rownum, Item_sum* item)
@@ -1181,15 +1255,11 @@ class Frame_unbounded_following : public Frame_cursor
1181
1255
if (cursor.get_next ())
1182
1256
return ;
1183
1257
}
1184
- /* Remember which partition we are in */
1185
- bound_tracker.check_if_next_group ();
1186
1258
item->add ();
1187
1259
1188
1260
/* Walk to the end of the partition, updating the SUM function */
1189
1261
while (!cursor.get_next ())
1190
1262
{
1191
- if (bound_tracker.check_if_next_group ())
1192
- break ;
1193
1263
item->add ();
1194
1264
}
1195
1265
}
@@ -1203,6 +1273,9 @@ class Frame_unbounded_following : public Frame_cursor
1203
1273
1204
1274
class Frame_unbounded_following_set_count : public Frame_unbounded_following
1205
1275
{
1276
+ public:
1277
+ // pre_next_partition is inherited
1278
+
1206
1279
void next_partition (longlong rownum, Item_sum* item)
1207
1280
{
1208
1281
ulonglong num_rows_in_partition= 0 ;
@@ -1214,13 +1287,9 @@ class Frame_unbounded_following_set_count : public Frame_unbounded_following
1214
1287
}
1215
1288
num_rows_in_partition++;
1216
1289
1217
- /* Remember which partition we are in */
1218
- bound_tracker.check_if_next_group ();
1219
1290
/* Walk to the end of the partition, find how many rows there are. */
1220
1291
while (!cursor.get_next ())
1221
1292
{
1222
- if (bound_tracker.check_if_next_group ())
1223
- break ;
1224
1293
num_rows_in_partition++;
1225
1294
}
1226
1295
@@ -1368,14 +1437,8 @@ class Frame_n_rows_following : public Frame_cursor
1368
1437
const bool is_top_bound;
1369
1438
const ha_rows n_rows;
1370
1439
1371
- Table_read_cursor cursor;
1440
+ Partition_read_cursor cursor;
1372
1441
bool at_partition_end;
1373
-
1374
- /*
1375
- This cursor reaches partition end before the main cursor has reached it.
1376
- bound_tracker is used to detect partition end.
1377
- */
1378
- Group_bound_tracker bound_tracker;
1379
1442
public:
1380
1443
Frame_n_rows_following (bool is_top_bound_arg, ha_rows n_rows_arg) :
1381
1444
is_top_bound (is_top_bound_arg), n_rows(n_rows_arg)
@@ -1386,17 +1449,15 @@ class Frame_n_rows_following : public Frame_cursor
1386
1449
void init (THD *thd, READ_RECORD *info, SQL_I_List<ORDER> *partition_list,
1387
1450
SQL_I_List<ORDER> *order_list)
1388
1451
{
1389
- cursor.init (info);
1452
+ cursor.init (thd, info, partition_list );
1390
1453
at_partition_end= false ;
1391
- bound_tracker.init (thd, partition_list);
1392
1454
}
1393
1455
1394
1456
void pre_next_partition (longlong rownum, Item_sum* item)
1395
1457
{
1396
1458
at_partition_end= false ;
1397
1459
1398
- // Fetch current partition value
1399
- bound_tracker.check_if_next_group ();
1460
+ cursor.on_next_partition (rownum);
1400
1461
1401
1462
if (rownum != 0 )
1402
1463
{
@@ -1434,15 +1495,10 @@ class Frame_n_rows_following : public Frame_cursor
1434
1495
{
1435
1496
if (!cursor.get_next ())
1436
1497
{
1437
- if (bound_tracker. check_if_next_group ())
1438
- at_partition_end= true ;
1498
+ if (is_top_bound) // this is frame start endpoint
1499
+ item-> remove () ;
1439
1500
else
1440
- {
1441
- if (is_top_bound) // this is frame start endpoint
1442
- item->remove ();
1443
- else
1444
- item->add ();
1445
- }
1501
+ item->add ();
1446
1502
}
1447
1503
else
1448
1504
at_partition_end= true ;
0 commit comments