@@ -390,6 +390,10 @@ class DistributedPlannerTest : public ::testing::Test {
390390 find_nodes (node->merge_sort .children [i], type, out);
391391 return ;
392392 }
393+ if (node->type == PlanNodeType::DERIVED_SCAN ) {
394+ find_nodes (node->derived_scan .inner_plan , type, out);
395+ return ;
396+ }
393397 find_nodes (node->left , type, out);
394398 find_nodes (node->right , type, out);
395399 }
@@ -964,3 +968,96 @@ TEST_F(DistributedPlannerTest, WindowGatherCorrectness) {
964968 EXPECT_EQ (dist_rs.row_count (), 15u );
965969 EXPECT_TRUE (compare_results_unordered (local_rs, dist_rs));
966970}
971+
972+ TEST_F (DistributedPlannerTest, DerivedScanIsDistributed) {
973+ Parser<Dialect::MySQL> parser;
974+ const char * sql = " SELECT name FROM (SELECT name, age FROM users WHERE age > 20) AS t" ;
975+ auto pr = parser.parse (sql, std::strlen (sql));
976+ ASSERT_EQ (pr.status , ParseResult::OK );
977+
978+ PlanBuilder<Dialect::MySQL> builder (catalog, parser.arena ());
979+ PlanNode* plan = builder.build (pr.ast );
980+ ASSERT_NE (plan, nullptr );
981+
982+ DistributedPlanner<Dialect::MySQL> dp (shard_map, catalog, parser.arena ());
983+ PlanNode* dist = dp.distribute (plan);
984+ ASSERT_NE (dist, nullptr );
985+
986+ std::vector<PlanNode*> scans, remotes;
987+ find_nodes (dist, PlanNodeType::SCAN , scans);
988+ find_nodes (dist, PlanNodeType::REMOTE_SCAN , remotes);
989+ EXPECT_TRUE (scans.empty ()) << " inner SCAN must be rewritten" ;
990+ EXPECT_FALSE (remotes.empty ());
991+ }
992+
993+ TEST_F (DistributedPlannerTest, DerivedScanCorrectness) {
994+ const char * sql = " SELECT name FROM (SELECT name, age FROM users WHERE age > 20) AS t" ;
995+ auto local_rs = execute_local (sql);
996+ auto dist_rs = execute_distributed (sql);
997+ EXPECT_GT (local_rs.row_count (), 0u );
998+ EXPECT_EQ (local_rs.row_count (), dist_rs.row_count ());
999+ EXPECT_TRUE (compare_results_unordered (local_rs, dist_rs));
1000+ }
1001+
1002+ TEST_F (DistributedPlannerTest, OrderByExpressionDoesNotMergeOnColumnZero) {
1003+ Parser<Dialect::MySQL> parser;
1004+ const char * sql = " SELECT name, age FROM users ORDER BY age + 1" ;
1005+ auto pr = parser.parse (sql, std::strlen (sql));
1006+ ASSERT_EQ (pr.status , ParseResult::OK );
1007+
1008+ PlanBuilder<Dialect::MySQL> builder (catalog, parser.arena ());
1009+ PlanNode* plan = builder.build (pr.ast );
1010+ ASSERT_NE (plan, nullptr );
1011+
1012+ DistributedPlanner<Dialect::MySQL> dp (shard_map, catalog, parser.arena ());
1013+ PlanNode* dist = dp.distribute (plan);
1014+ ASSERT_NE (dist, nullptr );
1015+
1016+ std::vector<PlanNode*> merges;
1017+ find_nodes (dist, PlanNodeType::MERGE_SORT , merges);
1018+ EXPECT_TRUE (merges.empty ()) << " expression ORDER BY must not MERGE_SORT on col 0" ;
1019+
1020+ auto local_rs = execute_local (sql);
1021+ auto dist_rs = execute_distributed (sql);
1022+ EXPECT_EQ (local_rs.row_count (), dist_rs.row_count ());
1023+ EXPECT_TRUE (compare_results_ordered (local_rs, dist_rs));
1024+ }
1025+
1026+ TEST_F (DistributedPlannerTest, OrderByAliasAndPositionCorrectness) {
1027+ const char * sql = " SELECT name AS n, age AS a FROM users ORDER BY a DESC" ;
1028+ auto local_rs = execute_local (sql);
1029+ auto dist_rs = execute_distributed (sql);
1030+ EXPECT_EQ (local_rs.row_count (), 15u );
1031+ EXPECT_TRUE (compare_results_ordered (local_rs, dist_rs));
1032+
1033+ const char * sql2 = " SELECT name, age FROM users ORDER BY 2 DESC" ;
1034+ auto local2 = execute_local (sql2);
1035+ auto dist2 = execute_distributed (sql2);
1036+ EXPECT_TRUE (compare_results_ordered (local2, dist2));
1037+ }
1038+
1039+ TEST_F (DistributedPlannerTest, RemoteSqlLenIsNotTruncated) {
1040+ std::string name (70000 , ' x' );
1041+ std::string sql = " SELECT * FROM users WHERE name = '" + name + " '" ;
1042+ Parser<Dialect::MySQL> parser;
1043+ auto pr = parser.parse (sql.c_str (), sql.size ());
1044+ ASSERT_EQ (pr.status , ParseResult::OK );
1045+
1046+ PlanBuilder<Dialect::MySQL> builder (catalog, parser.arena ());
1047+ PlanNode* plan = builder.build (pr.ast );
1048+ ASSERT_NE (plan, nullptr );
1049+
1050+ DistributedPlanner<Dialect::MySQL> dp (shard_map, catalog, parser.arena ());
1051+ PlanNode* dist = dp.distribute (plan);
1052+ ASSERT_NE (dist, nullptr );
1053+
1054+ std::vector<PlanNode*> remotes;
1055+ find_nodes (dist, PlanNodeType::REMOTE_SCAN , remotes);
1056+ ASSERT_FALSE (remotes.empty ());
1057+ for (auto * rs : remotes) {
1058+ EXPECT_GT (rs->remote_scan .remote_sql_len , 65535u );
1059+ std::string remote (rs->remote_scan .remote_sql , rs->remote_scan .remote_sql_len );
1060+ EXPECT_NE (remote.find (name), std::string::npos);
1061+ EXPECT_EQ (rs->remote_scan .remote_sql_len , remote.size ());
1062+ }
1063+ }
0 commit comments