MCPcopy Create free account
hub / github.com/NodeDB-Lab/nodedb / plan_update_from

Function plan_update_from

nodedb-sql/src/planner/dml_update_delete.rs:60–176  ·  view source on GitHub ↗

Plan `UPDATE target SET ... FROM src WHERE target.col = src.col ...`.

(update: &ast::Update, catalog: &dyn SqlCatalog)

Source from the content-addressed store, hash-verified

58
59/// Plan `UPDATE target SET ... FROM src WHERE target.col = src.col ...`.
60fn plan_update_from(update: &ast::Update, catalog: &dyn SqlCatalog) -> Result<Vec<SqlPlan>> {
61 let target_name = extract_table_name_from_table_with_joins(&update.table)?;
62
63 // Extract alias for the target table if present.
64 let target_alias: Option<String> = match &update.table.relation {
65 ast::TableFactor::Table { alias, .. } => alias.as_ref().map(|a| normalize_ident(&a.name)),
66 _ => None,
67 };
68 let target_ref = target_alias.as_deref().unwrap_or(target_name.as_str());
69
70 let from_kind = update.from.as_ref().expect("caller ensures from.is_some()");
71 let from_tables: &Vec<ast::TableWithJoins> = match from_kind {
72 ast::UpdateTableFromKind::AfterSet(tables)
73 | ast::UpdateTableFromKind::BeforeSet(tables) => tables,
74 };
75
76 // Reject multi-table FROM.
77 if from_tables.len() > 1 {
78 return Err(SqlError::Unsupported {
79 detail: format!(
80 "UPDATE ... FROM with {} source tables is not supported; \
81 only a single FROM table is accepted",
82 from_tables.len()
83 ),
84 });
85 }
86 let from_table = from_tables.first().ok_or_else(|| SqlError::Parse {
87 detail: "UPDATE ... FROM requires at least one source table".into(),
88 })?;
89
90 // Reject subquery in FROM.
91 let source_name = match &from_table.relation {
92 ast::TableFactor::Table { name, .. } => normalize_object_name_checked(name)?,
93 ast::TableFactor::Derived { .. } => {
94 return Err(SqlError::Unsupported {
95 detail: "UPDATE ... FROM (subquery) is not supported; \
96 use a CTE: WITH cte AS (SELECT ...) UPDATE t SET ... FROM cte WHERE ..."
97 .into(),
98 });
99 }
100 _ => {
101 return Err(SqlError::Unsupported {
102 detail: "non-table relation in UPDATE ... FROM is not supported".into(),
103 });
104 }
105 };
106 // Reject joins in the FROM source.
107 if !from_table.joins.is_empty() {
108 return Err(SqlError::Unsupported {
109 detail: "JOIN in UPDATE ... FROM source is not supported; \
110 use a CTE to pre-join the source"
111 .into(),
112 });
113 }
114
115 let source_alias: Option<String> = match &from_table.relation {
116 ast::TableFactor::Table { alias, .. } => alias.as_ref().map(|a| normalize_ident(&a.name)),
117 _ => None,

Callers 1

plan_updateFunction · 0.85

Calls 15

normalize_identFunction · 0.85
convert_assignmentsFunction · 0.85
extract_join_predicateFunction · 0.85
resolve_engine_rulesFunction · 0.85
firstMethod · 0.80
as_refMethod · 0.45
as_strMethod · 0.45
expectMethod · 0.45
lenMethod · 0.45
is_emptyMethod · 0.45

Tested by

no test coverage detected