diff --git a/src/gausskernel/runtime/executor/nodeStartWithOp.cpp b/src/gausskernel/runtime/executor/nodeStartWithOp.cpp index 4cdd7a09d..1d1bc1fc7 100644 --- a/src/gausskernel/runtime/executor/nodeStartWithOp.cpp +++ b/src/gausskernel/runtime/executor/nodeStartWithOp.cpp @@ -472,6 +472,23 @@ static List* peekNextLevel(TupleTableSlot* startSlot, PlanState* outerNode, int return queue; } +static TupleTableSlot* updateTuplePseudoColumnValue(TupleTableSlot* slot, StartWithOpState *node, + StartWithOpColumnType type, Datum value) +{ + AttrNumber attnum = node->sw_pseudoCols[type]->resno; + int attcount = slot->tts_tupleDescriptor->natts; + bool nulls[attcount] = {false}; + Datum values[attcount] = {0}; + bool replaces[attcount] = {false}; + HeapTuple oldtup = (HeapTuple)slot->tts_tuple; + replaces[attnum - 1] = true; + nulls[attnum - 1] = false; + values[attnum - 1] = value; + HeapTuple newtup = heap_modify_tuple(oldtup, slot->tts_tupleDescriptor, values, nulls, replaces); + slot->tts_tuple = newtup; + heap_freetuple_ext(oldtup); +} + /* * Construct CONNECT BY result set by depth-first order. * @@ -508,24 +525,27 @@ static bool depth_first_connect(int currentLevel, StartWithOpState *node, List* isCycle = true; continue; } + updateTuplePseudoColumnValue(dstSlot, node, SWCOL_ROWNUM, *dfsRowCount + 1); + RecursiveUnionState* runode = castNode(RecursiveUnionState, outerNode); + if (currentLevel == 1 || ExecStartWithRowLevelQual(runode, dstSlot)) { + tuplestore_puttupleslot(outputStore, dstSlot); + (*dfsRowCount)++; + int rowCountBefore = *dfsRowCount; - tuplestore_puttupleslot(outputStore, dstSlot); - (*dfsRowCount)++; - int rowCountBefore = *dfsRowCount; + /* Go into the depth NOW: sibling tuples won't get processed + * until all children are done */ + node->sw_rownum = rowCountBefore; + List* children = peekNextLevel(leader, outerNode, currentLevel); + bool expectCycle = depth_first_connect(currentLevel + 1, node, + children, + dfsRowCount); + if (expectCycle) { + node->sw_cycle_rowmarks = lappend_int(node->sw_cycle_rowmarks, rowCountBefore); + } - /* Go into the depth NOW: sibling tuples won't get processed - * until all children are done */ - node->sw_rownum = rowCountBefore; - List* children = peekNextLevel(leader, outerNode, currentLevel); - bool expectCycle = depth_first_connect(currentLevel + 1, node, - children, - dfsRowCount); - if (expectCycle) { - node->sw_cycle_rowmarks = lappend_int(node->sw_cycle_rowmarks, rowCountBefore); - } - - if (!children) { - node->sw_leaf_rowmarks = lappend_int(node->sw_leaf_rowmarks, rowCountBefore); + if (!children) { + node->sw_leaf_rowmarks = lappend_int(node->sw_leaf_rowmarks, rowCountBefore); + } } } return isCycle; diff --git a/src/test/regress/expected/sw_bugfix-1.out b/src/test/regress/expected/sw_bugfix-1.out index 805991a58..216580cee 100644 --- a/src/test/regress/expected/sw_bugfix-1.out +++ b/src/test/regress/expected/sw_bugfix-1.out @@ -1507,22 +1507,7 @@ SELECT start AS connect, prior AS start FROM CONNECT CONNECT CONNECT BY ROWNUM < 3 | 5 5 | 6 6 | 7 - 1 | 3 - 3 | 4 - 3 | 5 - 5 | 6 - 6 | 7 - 1 | 3 - 3 | 4 - 3 | 5 - 5 | 6 - 6 | 7 - 1 | 3 - 3 | 4 - 3 | 5 - 5 | 6 - 6 | 7 -(24 rows) +(9 rows) DROP TABLE IF EXISTS start; DROP TABLE IF EXISTS connect; @@ -1589,13 +1574,7 @@ select c_int from t_test_array_base connect by c_int[1:2]=array[1,2] and rownum {1,2,NULL,10,11} {1,2,2,10} {1,2,2,10} - {1,2,2,10} - {1,2,2,10} - {1,2,2,10} - {1,2,2,10} - {1,2,2,10} - {1,2,2,10} -(12 rows) +(6 rows) drop table t_test_array_base; -- test invalid columnref diff --git a/src/test/regress/expected/sw_bugfix-2.out b/src/test/regress/expected/sw_bugfix-2.out index 76c218f8b..77eff3d92 100755 --- a/src/test/regress/expected/sw_bugfix-2.out +++ b/src/test/regress/expected/sw_bugfix-2.out @@ -1440,47 +1440,7 @@ SELECT id,pid,name,rownum,level FROM test_hcb_ptb START WITH id=1 CONNECT BY NOC 121 | 111 | 江宁区 | 4 | 4 131 | 121 | 东山街 | 5 | 5 141 | 131 | 江南摩卡 | 6 | 6 - 142 | 131 | 四季云顶 | 7 | 6 - 143 | 131 | 盛世江南 | 8 | 6 - 144 | 131 | 七里香都 | 9 | 6 - 145 | 131 | 西山枫林 | 10 | 6 - 146 | 131 | 醉墨小镇 | 11 | 6 - 147 | 131 | 布拉格调 | 12 | 6 - 148 | 131 | 清幽别院 | 13 | 6 - 149 | 131 | 璀璨天城 | 14 | 6 - 132 | 121 | 秣陵街 | 15 | 5 - 133 | 121 | 汤山街 | 16 | 5 - 135 | 121 | 禄口街 | 17 | 5 - 134 | 121 | 淳化街 | 18 | 5 - 136 | 121 | 江宁街 | 19 | 5 - 137 | 121 | 谷里街 | 20 | 5 - 138 | 121 | 湖熟街 | 21 | 5 - 139 | 121 | 横溪街 | 22 | 5 - 122 | 111 | 雨花台 | 23 | 4 - 123 | 111 | 鼓楼区 | 24 | 4 - 124 | 111 | 玄武区 | 25 | 4 - 125 | 111 | 建邺区 | 26 | 4 - 126 | 111 | 秦淮区 | 27 | 4 - 127 | 111 | 浦口区 | 28 | 4 - 128 | 111 | 浦口区 | 29 | 4 - 129 | 111 | 六合区 | 30 | 4 - 112 | 11 | 宿迁市 | 31 | 3 - 113 | 11 | 徐州市 | 32 | 3 - 114 | 11 | 苏州市 | 33 | 3 - 115 | 11 | 盐城市 | 34 | 3 - 117 | 11 | 常州市 | 35 | 3 - 116 | 11 | 无锡市 | 36 | 3 - 118 | 11 | 连云港 | 37 | 3 - 119 | 11 | 泰州市 | 38 | 3 - 12 | 1 | 山东省 | 39 | 2 - 13 | 1 | 安徽省 | 40 | 2 - 14 | 1 | 河南省 | 41 | 2 - 15 | 1 | 河北省 | 42 | 2 - 16 | 1 | 湖南省 | 43 | 2 - 17 | 1 | 湖北省 | 44 | 2 - 18 | 1 | 贵州省 | 45 | 2 - 19 | 1 | 武汉省 | 46 | 2 -(46 rows) +(6 rows) --test subquery pushdown SELECT subq_0.c1 as c0 @@ -2358,4 +2318,55 @@ select child, level, lpad(' ', level*3, ' ')||child c1 from hier start with pare ERROR: Not support refer startwith Pseudo column in order siblings by. select child, level, lpad(' ', level*3, ' ')||child c1, level c2 from hier start with parent is null connect by prior child = parent ORDER SIBLINGS BY c2; ERROR: Not support refer startwith Pseudo column in order siblings by. -drop table hier; \ No newline at end of file +drop table hier; +-- test connect by rownum clause +drop table if exists t_test_connect_by_rownum; +create table t_test_connect_by_rownum(id char(1)); +insert into t_test_connect_by_rownum values('a'),('b'),('c'); +select id, rownum, level from t_test_connect_by_rownum connect by rownum < 1; + id | rownum | level +----+--------+------- + a | 1 | 1 + b | 2 | 1 + c | 3 | 1 +(3 rows) + +select id, rownum, level from t_test_connect_by_rownum connect by rownum < 2; + id | rownum | level +----+--------+------- + a | 1 | 1 + b | 2 | 1 + c | 3 | 1 +(3 rows) + +select id, rownum, level from t_test_connect_by_rownum connect by rownum < 3; + id | rownum | level +----+--------+------- + a | 1 | 1 + a | 2 | 2 + b | 3 | 1 + c | 4 | 1 +(4 rows) + +select id, rownum, level from t_test_connect_by_rownum connect by rownum < 4; + id | rownum | level +----+--------+------- + a | 1 | 1 + a | 2 | 2 + a | 3 | 3 + b | 4 | 1 + c | 5 | 1 +(5 rows) + +select id, rownum, level from t_test_connect_by_rownum connect by rownum < 5; + id | rownum | level +----+--------+------- + a | 1 | 1 + a | 2 | 2 + a | 3 | 3 + a | 4 | 4 + b | 5 | 1 + c | 6 | 1 +(6 rows) + +drop table t_test_connect_by_rownum; \ No newline at end of file diff --git a/src/test/regress/sql/sw_bugfix-2.sql b/src/test/regress/sql/sw_bugfix-2.sql index ec2127801..430b67463 100644 --- a/src/test/regress/sql/sw_bugfix-2.sql +++ b/src/test/regress/sql/sw_bugfix-2.sql @@ -881,4 +881,15 @@ insert into hier values('China','AK47'); insert into hier values('China','天津'); select child, level, lpad(' ', level*3, ' ')||child c1 from hier start with parent is null connect by prior child = parent ORDER SIBLINGS BY c1; select child, level, lpad(' ', level*3, ' ')||child c1, level c2 from hier start with parent is null connect by prior child = parent ORDER SIBLINGS BY c2; -drop table hier; \ No newline at end of file +drop table hier; + +-- test connect by rownum clause +drop table if exists t_test_connect_by_rownum; +create table t_test_connect_by_rownum(id char(1)); +insert into t_test_connect_by_rownum values('a'),('b'),('c'); +select id, rownum, level from t_test_connect_by_rownum connect by rownum < 1; +select id, rownum, level from t_test_connect_by_rownum connect by rownum < 2; +select id, rownum, level from t_test_connect_by_rownum connect by rownum < 3; +select id, rownum, level from t_test_connect_by_rownum connect by rownum < 4; +select id, rownum, level from t_test_connect_by_rownum connect by rownum < 5; +drop table t_test_connect_by_rownum; \ No newline at end of file