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<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(", ");
|
.join(", ");
|
||||||
let mut statements = Vec::new();
|
let mut statements = Vec::new();
|
||||||
let needs_dameng_identity_insert = options.database_type == Some(DatabaseType::Dameng)
|
// Dameng and SQL Server both reject explicit values for identity columns
|
||||||
&& insert_columns.iter().any(|(index, _, _)| {
|
// unless `SET IDENTITY_INSERT <table> ON` wraps the statement (SQL Server
|
||||||
is_identity_column_extra(options.column_extras.get(*index).and_then(|value| value.as_deref()))
|
// 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_prefix = format!("INSERT INTO {table} ({columns}) VALUES ");
|
||||||
let statement_overhead_bytes = export_sql_statement_bytes(options.database_type, &statement_prefix) + 1;
|
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(&statement_prefix);
|
||||||
insert_sql.push_str(values);
|
insert_sql.push_str(values);
|
||||||
insert_sql.push(';');
|
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));
|
statements.push(wrap_dameng_identity_insert_sql_for_table(&insert_sql, &table));
|
||||||
} else {
|
} else {
|
||||||
statements.push(insert_sql);
|
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]
|
#[test]
|
||||||
fn builds_database_sql_export_with_ddl_before_data() {
|
fn builds_database_sql_export_with_ddl_before_data() {
|
||||||
let sql = build_database_sql_export(BuildDatabaseSqlExportOptions {
|
let sql = build_database_sql_export(BuildDatabaseSqlExportOptions {
|
||||||
|
|||||||
Reference in new issue
Block a user