fix(sqlserver): wrap identity INSERTs in exported SQL scripts
This commit is contained in:
1 file changed
+38
-5
@@ -1211,10 +1211,14 @@ pub fn build_export_insert_statements(options: BuildExportInsertStatementsOption
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ");
|
||||
let mut statements = Vec::new();
|
||||
let needs_dameng_identity_insert = options.database_type == Some(DatabaseType::Dameng)
|
||||
&& insert_columns.iter().any(|(index, _, _)| {
|
||||
is_identity_column_extra(options.column_extras.get(*index).and_then(|value| value.as_deref()))
|
||||
});
|
||||
// Dameng and SQL Server both reject explicit values for identity columns
|
||||
// unless `SET IDENTITY_INSERT <table> ON` wraps the statement (SQL Server
|
||||
// error 544), so exported INSERTs must carry the wrapper.
|
||||
let needs_identity_insert_wrapper =
|
||||
matches!(options.database_type, Some(DatabaseType::Dameng) | Some(DatabaseType::SqlServer))
|
||||
&& insert_columns.iter().any(|(index, _, _)| {
|
||||
is_identity_column_extra(options.column_extras.get(*index).and_then(|value| value.as_deref()))
|
||||
});
|
||||
|
||||
let statement_prefix = format!("INSERT INTO {table} ({columns}) VALUES ");
|
||||
let statement_overhead_bytes = export_sql_statement_bytes(options.database_type, &statement_prefix) + 1;
|
||||
@@ -1233,7 +1237,7 @@ pub fn build_export_insert_statements(options: BuildExportInsertStatementsOption
|
||||
insert_sql.push_str(&statement_prefix);
|
||||
insert_sql.push_str(values);
|
||||
insert_sql.push(';');
|
||||
if needs_dameng_identity_insert {
|
||||
if needs_identity_insert_wrapper {
|
||||
statements.push(wrap_dameng_identity_insert_sql_for_table(&insert_sql, &table));
|
||||
} else {
|
||||
statements.push(insert_sql);
|
||||
@@ -5695,6 +5699,35 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sqlserver_identity_export_inserts_enable_identity_insert() {
|
||||
// The SQL Server column metadata reports `identity(seed,increment)`;
|
||||
// explicit values for such columns are rejected with error 544 unless
|
||||
// the INSERT is wrapped in SET IDENTITY_INSERT.
|
||||
let statements = build_export_insert_statements(BuildExportInsertStatementsOptions {
|
||||
database_type: Some(DatabaseType::SqlServer),
|
||||
identifier_quote: None,
|
||||
schema: Some("dbo".to_string()),
|
||||
table_name: Some("events".to_string()),
|
||||
qualified_table_name: None,
|
||||
columns: vec!["id".to_string(), "name".to_string()],
|
||||
column_types: vec![Some("int".to_string()), Some("nvarchar(50)".to_string())],
|
||||
column_extras: vec![Some("identity(1,1)".to_string()), None],
|
||||
spatial_columns: Vec::new(),
|
||||
spatial_values: Vec::new(),
|
||||
rows: vec![vec![json!(1), json!("Ada")]],
|
||||
batch_size: Some(10),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
statements,
|
||||
vec![
|
||||
"SET IDENTITY_INSERT [dbo].[events] ON;\nINSERT INTO [dbo].[events] ([id], [name]) VALUES (1, N'Ada');\nSET IDENTITY_INSERT [dbo].[events] OFF;"
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn builds_database_sql_export_with_ddl_before_data() {
|
||||
let sql = build_database_sql_export(BuildDatabaseSqlExportOptions {
|
||||
|
||||
Reference in new issue
Block a user