fix: format PostgreSQL array values as {..} instead of JSON [..] in SQL export
PostgreSQL array columns were serialized as JSON arrays (e.g. [1,2,3])
by serde_json::Value::Array Display, producing invalid SQL literals like
'[1,2,3]' and '[]' instead of PostgreSQL's required '{1,2,3}' and '{}'.
Add format_pg_array_sql_literal helper and apply it to all three SQL
literal formatting paths: escape_value_typed (transfer), format_export_sql_literal
(database_export), and format_grid_sql_literal (data_grid_sql).
This commit is contained in:
parent
98b34a4db2
commit
9008169dd1
|
|
@ -4,6 +4,7 @@ use serde_json::Value;
|
|||
|
||||
use crate::models::connection::DatabaseType;
|
||||
use crate::sql_dialect::quote_table_identifier;
|
||||
use crate::transfer::format_pg_array_sql_literal;
|
||||
|
||||
const DBX_ROWID_COLUMN: &str = "__DBX_ROWID";
|
||||
const DBX_NEO4J_ELEMENT_ID_COLUMN: &str = "__DBX_ELEMENT_ID";
|
||||
|
|
@ -936,6 +937,9 @@ pub fn format_grid_sql_literal(
|
|||
if let Some(number) = value.as_number() {
|
||||
return number.to_string();
|
||||
}
|
||||
if let Some(arr) = value.as_array() {
|
||||
return format_pg_array_sql_literal(arr);
|
||||
}
|
||||
let text = value.as_str().map_or_else(|| value.to_string(), ToString::to_string);
|
||||
if text.is_empty() {
|
||||
return if database_type == Some(DatabaseType::SqlServer) { "N''" } else { "''" }.to_string();
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use tokio::sync::RwLock;
|
|||
|
||||
use crate::models::connection::DatabaseType;
|
||||
use crate::sql_dialect::{qualified_table_name, quote_table_identifier};
|
||||
use crate::transfer::format_pg_array_sql_literal;
|
||||
|
||||
static EXPORT_CANCELLED: std::sync::LazyLock<RwLock<HashSet<String>>> =
|
||||
std::sync::LazyLock::new(|| RwLock::new(HashSet::new()));
|
||||
|
|
@ -125,6 +126,9 @@ pub fn format_export_sql_literal(value: &Value) -> String {
|
|||
if let Some(value) = value.as_bool() {
|
||||
return if value { "TRUE" } else { "FALSE" }.to_string();
|
||||
}
|
||||
if let Some(arr) = value.as_array() {
|
||||
return format_pg_array_sql_literal(arr);
|
||||
}
|
||||
let text = value.as_str().map_or_else(|| value.to_string(), ToString::to_string);
|
||||
format!("'{}'", text.replace('\\', "\\\\").replace('\'', "''"))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ pub fn escape_value_typed(val: &serde_json::Value, db_type: &DatabaseType, colum
|
|||
serde_json::Value::String(s) => {
|
||||
format!("'{}'", format_literal_string(s, db_type, column_type).replace('\\', "\\\\").replace('\'', "''"))
|
||||
}
|
||||
serde_json::Value::Array(arr) => format_pg_array_sql_literal(arr),
|
||||
_ => {
|
||||
let s = val.to_string();
|
||||
format!("'{}'", s.replace('\\', "\\\\").replace('\'', "''"))
|
||||
|
|
@ -115,6 +116,41 @@ pub fn escape_value_typed(val: &serde_json::Value, db_type: &DatabaseType, colum
|
|||
}
|
||||
}
|
||||
|
||||
pub fn format_pg_array_sql_literal(arr: &[serde_json::Value]) -> String {
|
||||
if arr.is_empty() {
|
||||
return "'{}'".to_string();
|
||||
}
|
||||
let elements: Vec<String> = arr.iter().map(format_pg_array_element).collect();
|
||||
let inner = format!("{{{}}}", elements.join(","));
|
||||
format!("'{}'", inner.replace('\\', "\\\\").replace('\'', "''"))
|
||||
}
|
||||
|
||||
fn format_pg_array_element(val: &serde_json::Value) -> String {
|
||||
match val {
|
||||
serde_json::Value::Null => "NULL".to_string(),
|
||||
serde_json::Value::Array(arr) => {
|
||||
if arr.is_empty() {
|
||||
return "{}".to_string();
|
||||
}
|
||||
let elements: Vec<String> = arr.iter().map(format_pg_array_element).collect();
|
||||
format!("{{{}}}", elements.join(","))
|
||||
}
|
||||
serde_json::Value::String(s) => {
|
||||
let escaped = s.replace('\\', "\\\\").replace('"', "\\\"");
|
||||
format!("\"{}\"", escaped)
|
||||
}
|
||||
serde_json::Value::Number(n) => n.to_string(),
|
||||
serde_json::Value::Bool(b) => {
|
||||
if *b { "true".to_string() } else { "false".to_string() }
|
||||
}
|
||||
serde_json::Value::Object(o) => {
|
||||
let json = serde_json::to_string(o).unwrap_or_default();
|
||||
let escaped = json.replace('\\', "\\\\").replace('"', "\\\"");
|
||||
format!("\"{}\"", escaped)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn format_literal_string(value: &str, db_type: &DatabaseType, column_type: Option<&str>) -> String {
|
||||
if is_mysql_datetime_literal_database(db_type) && column_type.map(is_temporal_column_type).unwrap_or(true) {
|
||||
normalize_mysql_temporal_literal(value, column_type).unwrap_or_else(|| value.to_string())
|
||||
|
|
|
|||
Loading…
Reference in New Issue