mirror of
https://github.com/t8y2/dbx.git
synced 2026-10-02 02:34:42 +08:00
fix(dameng): wrap identity columns when pasting table data
This commit is contained in:
@@ -334,6 +334,7 @@ export interface CopyTableDataSqlOptions {
|
||||
columns?: string[];
|
||||
postgresOverridingSystemValue?: boolean;
|
||||
sqlserverIdentityInsert?: boolean;
|
||||
damengIdentityInsert?: boolean;
|
||||
normalizeNewTargetName?: boolean;
|
||||
/** Quote character reported by the connected server, for types whose quote is not fixed by the
|
||||
* database type alone (Cloud Spanner's two dialects differ). Mirrors `identifierQuote` on the
|
||||
|
||||
@@ -18,6 +18,7 @@ export interface TableDataCopyColumnOptions {
|
||||
columns: string[];
|
||||
postgresOverridingSystemValue: boolean;
|
||||
sqlserverIdentityInsert: boolean;
|
||||
damengIdentityInsert: boolean;
|
||||
}
|
||||
|
||||
export interface TablePasteFeedback {
|
||||
@@ -88,6 +89,7 @@ export function tableDataCopyColumnOptions(databaseType: DatabaseType | undefine
|
||||
columns: writableColumns.map((column) => column.name),
|
||||
postgresOverridingSystemValue: databaseType === "postgres" && writableColumns.some(isIdentityColumn),
|
||||
sqlserverIdentityInsert: databaseType === "sqlserver" && writableColumns.some(isIdentityColumn),
|
||||
damengIdentityInsert: databaseType === "dameng" && writableColumns.some(isIdentityColumn),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -241,6 +241,8 @@ pub struct CopyTableDataSqlOptions {
|
||||
#[serde(default)]
|
||||
pub sqlserver_identity_insert: bool,
|
||||
#[serde(default)]
|
||||
pub dameng_identity_insert: bool,
|
||||
#[serde(default)]
|
||||
pub normalize_new_target_name: bool,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub identifier_quote: Option<String>,
|
||||
@@ -895,7 +897,10 @@ pub fn build_copy_table_data_sql(options: CopyTableDataSqlOptions) -> String {
|
||||
let insert_sql = format!(
|
||||
"INSERT INTO {target} ({target_column_list}){postgres_override} SELECT {source_column_list} FROM {source};"
|
||||
);
|
||||
if options.sqlserver_identity_insert && options.database_type == Some(DatabaseType::SqlServer) {
|
||||
let needs_identity_insert = (options.sqlserver_identity_insert
|
||||
&& options.database_type == Some(DatabaseType::SqlServer))
|
||||
|| (options.dameng_identity_insert && options.database_type == Some(DatabaseType::Dameng));
|
||||
if needs_identity_insert {
|
||||
return format!("SET IDENTITY_INSERT {target} ON;\n{insert_sql}\nSET IDENTITY_INSERT {target} OFF;");
|
||||
}
|
||||
insert_sql
|
||||
@@ -2554,6 +2559,7 @@ mod tests {
|
||||
columns: None,
|
||||
postgres_overriding_system_value: false,
|
||||
sqlserver_identity_insert: false,
|
||||
dameng_identity_insert: false,
|
||||
normalize_new_target_name: false,
|
||||
identifier_quote: None,
|
||||
}),
|
||||
@@ -2568,6 +2574,7 @@ mod tests {
|
||||
columns: Some(vec!["id".to_string(), "name".to_string()]),
|
||||
postgres_overriding_system_value: false,
|
||||
sqlserver_identity_insert: false,
|
||||
dameng_identity_insert: false,
|
||||
normalize_new_target_name: false,
|
||||
identifier_quote: None,
|
||||
}),
|
||||
@@ -2582,6 +2589,7 @@ mod tests {
|
||||
columns: Some(vec!["id".to_string(), "name".to_string()]),
|
||||
postgres_overriding_system_value: true,
|
||||
sqlserver_identity_insert: false,
|
||||
dameng_identity_insert: false,
|
||||
normalize_new_target_name: false,
|
||||
identifier_quote: None,
|
||||
}),
|
||||
@@ -2596,11 +2604,40 @@ mod tests {
|
||||
columns: Some(vec!["id".to_string(), "name".to_string()]),
|
||||
postgres_overriding_system_value: false,
|
||||
sqlserver_identity_insert: true,
|
||||
dameng_identity_insert: false,
|
||||
normalize_new_target_name: false,
|
||||
identifier_quote: None,
|
||||
}),
|
||||
"SET IDENTITY_INSERT [dbo].[users_copy] ON;\nINSERT INTO [dbo].[users_copy] ([id], [name]) SELECT [id], [name] FROM [dbo].[users];\nSET IDENTITY_INSERT [dbo].[users_copy] OFF;"
|
||||
);
|
||||
{
|
||||
let dameng = build_copy_table_data_sql(CopyTableDataSqlOptions {
|
||||
database_type: Some(DatabaseType::Dameng),
|
||||
schema: Some("DCSS".to_string()),
|
||||
source_name: "users".to_string(),
|
||||
target_name: "users_copy".to_string(),
|
||||
columns: Some(vec!["id".to_string(), "name".to_string()]),
|
||||
postgres_overriding_system_value: false,
|
||||
sqlserver_identity_insert: false,
|
||||
dameng_identity_insert: true,
|
||||
normalize_new_target_name: false,
|
||||
identifier_quote: None,
|
||||
});
|
||||
assert!(dameng.starts_with("SET IDENTITY_INSERT "), "dameng copy should enable identity insert: {dameng}");
|
||||
assert!(dameng.ends_with("OFF;"), "dameng copy should disable identity insert: {dameng}");
|
||||
assert!(
|
||||
dameng.contains("INSERT INTO ") && dameng.contains(" SELECT "),
|
||||
"dameng copy should carry an INSERT..SELECT: {dameng}"
|
||||
);
|
||||
// Dameng rejects assigning an identity column unless a column list is specified.
|
||||
assert!(
|
||||
dameng.contains("(\"id\", \"name\")")
|
||||
|| dameng.contains("(`id`, `name`)")
|
||||
|| dameng.contains("(id, name)")
|
||||
|| dameng.contains("([id], [name])"),
|
||||
"dameng copy must use an explicit column list: {dameng}"
|
||||
);
|
||||
}
|
||||
assert_eq!(
|
||||
build_copy_table_data_sql(CopyTableDataSqlOptions {
|
||||
database_type: Some(DatabaseType::Dameng),
|
||||
@@ -2610,6 +2647,7 @@ mod tests {
|
||||
columns: None,
|
||||
postgres_overriding_system_value: false,
|
||||
sqlserver_identity_insert: false,
|
||||
dameng_identity_insert: false,
|
||||
normalize_new_target_name: true,
|
||||
identifier_quote: None,
|
||||
}),
|
||||
@@ -2624,6 +2662,7 @@ mod tests {
|
||||
columns: None,
|
||||
postgres_overriding_system_value: false,
|
||||
sqlserver_identity_insert: false,
|
||||
dameng_identity_insert: false,
|
||||
normalize_new_target_name: false,
|
||||
identifier_quote: None,
|
||||
}),
|
||||
@@ -2638,6 +2677,7 @@ mod tests {
|
||||
columns: Some(vec!["user_id".to_string(), "userName".to_string(), "order total".to_string()]),
|
||||
postgres_overriding_system_value: false,
|
||||
sqlserver_identity_insert: false,
|
||||
dameng_identity_insert: false,
|
||||
normalize_new_target_name: true,
|
||||
identifier_quote: None,
|
||||
}),
|
||||
@@ -2652,6 +2692,7 @@ mod tests {
|
||||
columns: Some(vec!["user_id".to_string()]),
|
||||
postgres_overriding_system_value: false,
|
||||
sqlserver_identity_insert: false,
|
||||
dameng_identity_insert: false,
|
||||
normalize_new_target_name: false,
|
||||
identifier_quote: None,
|
||||
}),
|
||||
@@ -2711,6 +2752,7 @@ mod tests {
|
||||
columns: Some(vec!["user_id".to_string(), "userName".to_string()]),
|
||||
postgres_overriding_system_value: false,
|
||||
sqlserver_identity_insert: false,
|
||||
dameng_identity_insert: false,
|
||||
normalize_new_target_name: true,
|
||||
identifier_quote: None,
|
||||
});
|
||||
|
||||
+12
@@ -66,16 +66,25 @@ test("table data copy uses only writable columns for first-class databases", ()
|
||||
columns: ["id", "name"],
|
||||
postgresOverridingSystemValue: false,
|
||||
sqlserverIdentityInsert: true,
|
||||
damengIdentityInsert: false,
|
||||
});
|
||||
assert.deepEqual(tableDataCopyColumnOptions("dameng", columns), {
|
||||
columns: ["id", "name"],
|
||||
postgresOverridingSystemValue: false,
|
||||
sqlserverIdentityInsert: false,
|
||||
damengIdentityInsert: true,
|
||||
});
|
||||
assert.deepEqual(tableDataCopyColumnOptions("postgres", [{ ...columns[0], extra: "generated always as identity" }, { ...columns[1] }, { ...columns[2], extra: "generated always as (name) stored" }]), {
|
||||
columns: ["id", "name"],
|
||||
postgresOverridingSystemValue: true,
|
||||
sqlserverIdentityInsert: false,
|
||||
damengIdentityInsert: false,
|
||||
});
|
||||
assert.deepEqual(tableDataCopyColumnOptions("mysql", [{ ...columns[0], extra: "auto_increment" }, { ...columns[1] }, { ...columns[2], extra: "STORED GENERATED" }, column("expr_default", "DEFAULT_GENERATED"), column("expr_default_on_update", "DEFAULT_GENERATED on update CURRENT_TIMESTAMP"), column("virtual_full_name", "VIRTUAL GENERATED"), column("stored_full_name", "GENERATED ALWAYS AS (concat(first_name, ' ', last_name)) STORED")]), {
|
||||
columns: ["id", "name", "expr_default", "expr_default_on_update"],
|
||||
postgresOverridingSystemValue: false,
|
||||
sqlserverIdentityInsert: false,
|
||||
damengIdentityInsert: false,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -94,15 +103,18 @@ test("table data copy skips only SQL Server rowversion types", () => {
|
||||
columns: ["id", "name", "fixed_binary", "variable_binary"],
|
||||
postgresOverridingSystemValue: false,
|
||||
sqlserverIdentityInsert: true,
|
||||
damengIdentityInsert: false,
|
||||
});
|
||||
assert.deepEqual(tableDataCopyColumnOptions("postgres", [column("updated_at", "timestamp")]), {
|
||||
columns: ["updated_at"],
|
||||
postgresOverridingSystemValue: false,
|
||||
sqlserverIdentityInsert: false,
|
||||
damengIdentityInsert: false,
|
||||
});
|
||||
assert.deepEqual(tableDataCopyColumnOptions("mysql", [column("updated_at", "timestamp")]), {
|
||||
columns: ["updated_at"],
|
||||
postgresOverridingSystemValue: false,
|
||||
sqlserverIdentityInsert: false,
|
||||
damengIdentityInsert: false,
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user