@@ -251,3 +251,67 @@ TEST_F(DmlTest, InsertWithoutColumnList) {
251251 auto rs = run_select (" SELECT * FROM users" );
252252 EXPECT_EQ (rs.rows [3 ].get (0 ).int_val , 6 );
253253}
254+
255+ // ---- Multi-table UPDATE/DELETE plan node tests ----
256+
257+ // Multi-table UPDATE sets original_ast in the plan node
258+ TEST_F (DmlTest, MultiTableUpdateSetsOriginalAst) {
259+ const char * sql = " UPDATE users u JOIN orders o ON u.id = o.user_id SET u.age = 30 WHERE o.total > 100" ;
260+ parser.reset ();
261+ auto r = parser.parse (sql, std::strlen (sql));
262+ ASSERT_EQ (r.status , ParseResult::OK);
263+ ASSERT_NE (r.ast , nullptr );
264+
265+ DmlPlanBuilder<Dialect::MySQL> dml_builder (catalog, parser.arena ());
266+ PlanNode* plan = dml_builder.build (r.ast );
267+ ASSERT_NE (plan, nullptr );
268+ EXPECT_EQ (plan->type , PlanNodeType::UPDATE_PLAN);
269+ EXPECT_NE (plan->update_plan .original_ast , nullptr );
270+ EXPECT_EQ (plan->update_plan .original_ast , r.ast );
271+ }
272+
273+ // Single-table UPDATE leaves original_ast as nullptr
274+ TEST_F (DmlTest, SingleTableUpdateOriginalAstNull) {
275+ const char * sql = " UPDATE users SET age = 30 WHERE id = 1" ;
276+ parser.reset ();
277+ auto r = parser.parse (sql, std::strlen (sql));
278+ ASSERT_EQ (r.status , ParseResult::OK);
279+ ASSERT_NE (r.ast , nullptr );
280+
281+ DmlPlanBuilder<Dialect::MySQL> dml_builder (catalog, parser.arena ());
282+ PlanNode* plan = dml_builder.build (r.ast );
283+ ASSERT_NE (plan, nullptr );
284+ EXPECT_EQ (plan->type , PlanNodeType::UPDATE_PLAN);
285+ EXPECT_EQ (plan->update_plan .original_ast , nullptr );
286+ }
287+
288+ // Multi-table DELETE (MySQL syntax) sets original_ast
289+ TEST_F (DmlTest, MultiTableDeleteSetsOriginalAst) {
290+ const char * sql = " DELETE u FROM users u JOIN orders o ON u.id = o.user_id WHERE o.total > 100" ;
291+ parser.reset ();
292+ auto r = parser.parse (sql, std::strlen (sql));
293+ ASSERT_EQ (r.status , ParseResult::OK);
294+ ASSERT_NE (r.ast , nullptr );
295+
296+ DmlPlanBuilder<Dialect::MySQL> dml_builder (catalog, parser.arena ());
297+ PlanNode* plan = dml_builder.build (r.ast );
298+ ASSERT_NE (plan, nullptr );
299+ EXPECT_EQ (plan->type , PlanNodeType::DELETE_PLAN);
300+ EXPECT_NE (plan->delete_plan .original_ast , nullptr );
301+ EXPECT_EQ (plan->delete_plan .original_ast , r.ast );
302+ }
303+
304+ // Single-table DELETE leaves original_ast as nullptr
305+ TEST_F (DmlTest, SingleTableDeleteOriginalAstNull) {
306+ const char * sql = " DELETE FROM users WHERE id = 1" ;
307+ parser.reset ();
308+ auto r = parser.parse (sql, std::strlen (sql));
309+ ASSERT_EQ (r.status , ParseResult::OK);
310+ ASSERT_NE (r.ast , nullptr );
311+
312+ DmlPlanBuilder<Dialect::MySQL> dml_builder (catalog, parser.arena ());
313+ PlanNode* plan = dml_builder.build (r.ast );
314+ ASSERT_NE (plan, nullptr );
315+ EXPECT_EQ (plan->type , PlanNodeType::DELETE_PLAN);
316+ EXPECT_EQ (plan->delete_plan .original_ast , nullptr );
317+ }
0 commit comments