Files
turso/vendored/sqlite3-parser/src/to_sql_string/stmt/insert.rs
2025-07-12 18:58:55 +03:00

149 lines
5.0 KiB
Rust

use crate::{ast, to_sql_string::ToSqlString};
impl ToSqlString for ast::Insert {
fn to_sql_string<C: crate::to_sql_string::ToSqlContext>(&self, context: &C) -> String {
format!(
"{}INSERT {}INTO {} {}{}{}",
self.with.as_ref().map_or("".to_string(), |with| format!(
"{} ",
with.to_sql_string(context)
)),
self.or_conflict
.map_or("".to_string(), |conflict| format!("OR {conflict} ")),
self.tbl_name.to_sql_string(context),
self.columns
.as_ref()
.map_or("".to_string(), |col_names| format!(
"({}) ",
col_names
.iter()
.map(|name| name.0.clone())
.collect::<Vec<_>>()
.join(", ")
)),
self.body.to_sql_string(context),
self.returning
.as_ref()
.map_or("".to_string(), |returning| format!(
" RETURNING {}",
returning
.iter()
.map(|col| col.to_sql_string(context))
.collect::<Vec<_>>()
.join(", ")
))
)
}
}
impl ToSqlString for ast::InsertBody {
fn to_sql_string<C: crate::to_sql_string::ToSqlContext>(&self, context: &C) -> String {
match self {
Self::DefaultValues => "DEFAULT VALUES".to_string(),
Self::Select(select, upsert) => format!(
"{}{}",
select.to_sql_string(context),
upsert.as_ref().map_or("".to_string(), |upsert| format!(
" {}",
upsert.to_sql_string(context)
)),
),
}
}
}
#[cfg(test)]
mod tests {
use crate::to_sql_string_test;
// Basic INSERT with all columns
to_sql_string_test!(
test_insert_basic,
"INSERT INTO employees (id, name, salary) VALUES (1, 'John Doe', 50000);"
);
// INSERT with multiple rows
to_sql_string_test!(
test_insert_multiple_rows,
"INSERT INTO employees (id, name, salary) VALUES (1, 'John Doe', 50000), (2, 'Jane Smith', 60000);"
);
// INSERT with specific columns
to_sql_string_test!(
test_insert_specific_columns,
"INSERT INTO employees (name, salary) VALUES ('Alice Brown', 55000);"
);
// INSERT with DEFAULT VALUES
to_sql_string_test!(
test_insert_default_values,
"INSERT INTO employees DEFAULT VALUES;"
);
// INSERT with SELECT subquery
to_sql_string_test!(
test_insert_select_subquery,
"INSERT INTO employees (id, name, salary) SELECT id, name, salary FROM temp_employees WHERE salary > 40000;"
);
// INSERT with ON CONFLICT IGNORE
to_sql_string_test!(
test_insert_on_conflict_ignore,
"INSERT INTO employees (id, name, salary) VALUES (1, 'John Doe', 50000) ON CONFLICT(id) DO NOTHING;"
);
// INSERT with ON CONFLICT REPLACE
to_sql_string_test!(
test_insert_on_conflict_replace,
"INSERT INTO employees (id, name, salary) VALUES (1, 'John Doe', 50000) ON CONFLICT(id) DO UPDATE SET name = excluded.name, salary = excluded.salary;"
);
// INSERT with RETURNING clause
to_sql_string_test!(
test_insert_with_returning,
"INSERT INTO employees (id, name, salary) VALUES (1, 'John Doe', 50000) RETURNING id, name;"
);
// INSERT with NULL values
to_sql_string_test!(
test_insert_with_null,
"INSERT INTO employees (id, name, salary, department_id) VALUES (1, 'John Doe', NULL, NULL);"
);
// INSERT with expression in VALUES
to_sql_string_test!(
test_insert_with_expression,
"INSERT INTO employees (id, name, salary) VALUES (1, 'John Doe', 50000 * 1.1);"
);
// INSERT into schema-qualified table
to_sql_string_test!(
test_insert_schema_qualified,
"INSERT INTO main.employees (id, name, salary) VALUES (1, 'John Doe', 50000);"
);
// INSERT with subquery and JOIN
to_sql_string_test!(
test_insert_subquery_join,
"INSERT INTO employees (id, name, department_id) SELECT e.id, e.name, d.id FROM temp_employees e JOIN departments d ON e.dept_name = d.name;"
);
// INSERT with all columns from SELECT
to_sql_string_test!(
test_insert_all_columns_select,
"INSERT INTO employees SELECT * FROM temp_employees;"
);
// INSERT with ON CONFLICT and WHERE clause
to_sql_string_test!(
test_insert_on_conflict_where,
"INSERT INTO employees (id, name, salary) VALUES (1, 'John Doe', 50000) ON CONFLICT(id) DO UPDATE SET salary = excluded.salary WHERE excluded.salary > employees.salary;"
);
// INSERT with quoted column names (reserved words)
to_sql_string_test!(
test_insert_quoted_columns,
"INSERT INTO employees (\"select\", \"from\") VALUES (1, 'data');"
);
}