fix: normalize multi-word pg types in build_parameters to fix float8 serialization (#8778)

Multi-word Postgres type names like "double precision" caused the SQL
parser regex to fail (no spaces allowed in type group), falling back to
otyp="text". When Postgres inferred float8 for the column, the
text-typed null couldn't serialize, breaking DB Manager inserts/updates.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Diego Imbert
2026-04-09 15:39:32 +00:00
committed by GitHub
co-authored by Claude Opus 4.6
parent 89920e77f3
commit 3d02be98f7
2 changed files with 26 additions and 4 deletions
@@ -394,12 +394,29 @@ pub struct BreakingFeatures {
// Helper functions
// ---------------------------------------------------------------------------
fn normalize_pg_type(typ: &str) -> &str {
match typ {
"double precision" => "float8",
"character varying" => "varchar",
"time with time zone" => "timetz",
"time without time zone" => "time",
"timestamp with time zone" => "timestamptz",
"timestamp without time zone" => "timestamp",
other => other,
}
}
pub fn build_parameters(columns: &[SimpleColumn], db_type: DbType) -> String {
columns
.iter()
.enumerate()
.map(|(i, col)| {
let base_type = col.datatype.split('(').next().unwrap_or(&col.datatype);
let base_type = if db_type == DbType::Postgresql {
normalize_pg_type(base_type)
} else {
base_type
};
match db_type {
DbType::Postgresql => format!("-- ${} {} ({})", i + 1, col.field, base_type),
DbType::Mysql => format!("-- :{} ({})", col.field, base_type),
+9 -4
View File
@@ -103,7 +103,7 @@ fn otyp_to_pg_type(otyp: &str) -> error::Result<Type> {
"int" | "integer" | "int4" | "serial" => (Type::INT4, Type::INT4_ARRAY),
"bigint" | "bigserial" | "int8" | "serial8" => (Type::INT8, Type::INT8_ARRAY),
"real" | "float4" => (Type::FLOAT4, Type::FLOAT4_ARRAY),
"double" | "float8" => (Type::FLOAT8, Type::FLOAT8_ARRAY),
"double" | "double precision" | "float8" => (Type::FLOAT8, Type::FLOAT8_ARRAY),
"numeric" | "decimal" => (Type::NUMERIC, Type::NUMERIC_ARRAY),
"text" => (Type::TEXT, Type::TEXT_ARRAY),
"varchar" | "character varying" => (Type::VARCHAR, Type::VARCHAR_ARRAY),
@@ -633,7 +633,9 @@ fn convert_vec_val(
"real" | "float4" => Ok(Box::new(map_as_single_type(vec, |v| {
v.as_f64().map(|x| x as f32)
})?)),
"double" | "float8" => Ok(Box::new(map_as_single_type(vec, |v| v.as_f64())?)),
"double" | "double precision" | "float8" => {
Ok(Box::new(map_as_single_type(vec, |v| v.as_f64())?))
}
"uuid" => Ok(Box::new(map_as_single_type(vec, |v| {
v.as_str().map(|x| Uuid::parse_str(x).ok()).flatten()
})?)),
@@ -697,7 +699,7 @@ fn convert_val(
"oid" => Ok(Box::new(None::<u32>)),
"bigint" | "bigserial" | "int8" | "serial8" => Ok(Box::new(None::<i64>)),
"real" | "float4" => Ok(Box::new(None::<f32>)),
"double" | "float8" => Ok(Box::new(None::<f64>)),
"double" | "double precision" | "float8" => Ok(Box::new(None::<f64>)),
"uuid" => Ok(Box::new(None::<Uuid>)),
"date" => Ok(Box::new(None::<chrono::NaiveDate>)),
"time" | "timetz" => Ok(Box::new(None::<chrono::NaiveTime>)),
@@ -731,7 +733,10 @@ fn convert_val(
Value::Number(n) if (arg_t == "real" || arg_t == "float4") && n.as_f64().is_some() => {
Ok(Box::new(n.as_f64().unwrap() as f32))
}
Value::Number(n) if (arg_t == "double" || arg_t == "float8") && n.as_f64().is_some() => {
Value::Number(n)
if (arg_t == "double" || arg_t == "double precision" || arg_t == "float8")
&& n.as_f64().is_some() =>
{
Ok(Box::new(n.as_f64().unwrap()))
}
Value::Number(n) if (arg_t == "numeric" || arg_t == "decimal") && n.is_i64() => Ok(