Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions quaint/src/visitor/mysql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,16 @@ impl<'a> Mysql<'a> {
})?;
Ok(())
}
// Convert BigInt to string to preserve precision when parsed by JavaScript.
(Some(TypeFamily::Int), Some("BIGINT" | "UNSIGNEDBIGINT")) => {
self.write("CONVERT")?;
self.surround_with("(", ")", |s| {
s.visit_expression(expr)?;
s.write(", ")?;
s.write("CHAR")
})?;
Ok(())
}
_ => self.visit_expression(expr),
},
_ => self.visit_expression(expr),
Expand Down Expand Up @@ -717,6 +727,7 @@ fn get_target_table<'a>(query: &Query<'a>) -> Option<Table<'a>> {

#[cfg(test)]
mod tests {
use crate::ast::*;
use crate::visitor::*;

fn expected_values<'a, T>(sql: &'static str, params: Vec<T>) -> (String, Vec<Value<'a>>)
Expand Down Expand Up @@ -816,6 +827,36 @@ mod tests {
);
}

#[test]
fn json_build_object_casts_bigint_to_string() {
let build_json = json_build_object(vec![(
"id".into(),
Column::from("id")
.native_column_type(Some("BIGINT"))
.type_family(TypeFamily::Int)
.into(),
)]);
let query = Select::default().value(build_json);
let (sql, _) = Mysql::build(query).unwrap();

assert_eq!("SELECT JSON_OBJECT('id', CONVERT(`id`, CHAR))", sql);
}

#[test]
fn json_build_object_casts_unsigned_bigint_to_string() {
let build_json = json_build_object(vec![(
"id".into(),
Column::from("id")
.native_column_type(Some("UNSIGNEDBIGINT"))
.type_family(TypeFamily::Int)
.into(),
)]);
let query = Select::default().value(build_json);
let (sql, _) = Mysql::build(query).unwrap();

assert_eq!("SELECT JSON_OBJECT('id', CONVERT(`id`, CHAR))", sql);
}

#[test]
fn equality_with_a_json_value() {
let expected = expected_values(
Expand Down
16 changes: 15 additions & 1 deletion quaint/src/visitor/postgres.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ impl<'a> Postgres<'a> {
}
// Cast BigInt to text to preserve precision when parsed by JavaScript.
// JavaScript's JSON.parse loses precision for integers > 2^53-1.
(Some(TypeFamily::Int), Some("BIGINT")) => {
(Some(TypeFamily::Int), Some("BIGINT" | "INT8")) => {
self.visit_expression(expr)?;
self.write("::text")?;

Expand Down Expand Up @@ -1425,6 +1425,20 @@ mod tests {
assert_eq!(sql, "SELECT JSONB_BUILD_OBJECT('id', \"id\"::text)");
}

#[test]
fn int8() {
let build_json = json_build_object(vec![(
"id".into(),
Column::from("id")
.native_column_type(Some("INT8"))
.type_family(TypeFamily::Int)
.into(),
)]);
let query = Select::default().value(build_json);
let (sql, _) = Postgres::build(query).unwrap();

assert_eq!(sql, "SELECT JSONB_BUILD_OBJECT('id', \"id\"::text)");
}
fn build_json_object(num_fields: u32) -> JsonBuildObject<'static> {
let fields = (1..=num_fields)
.map(|i| (format!("f{i}").into(), Expression::from(i as i64)))
Expand Down
Loading