Skip to content

Commit

Permalink
Preserve large numbers in query transformations
Browse files Browse the repository at this point in the history
In GraphQL source text, you can write an integer outside the int32 range
if a float is expected. apollo-rs parses these numbers as
`hir::Value::Int` because at that time, the expected type of the value is
not known, especially because it's possible to parse queries without
knowledge of the schema.

In the defer label transformation, any apollo-rs `hir::Value::Int` was
treated as an i32. This would cause an error if it's one such large integer.
The fully proper way to convert `hir::Value` to another type (ie. encoder or
serde_json, as is done elsewhere) would be to match on the actual
GraphQL type expected by the schema. But the simpler thing to do is to
just use a Float if the value is too big for an Int. This will
round-trip correctly.
  • Loading branch information
goto-bus-stop committed Sep 13, 2023
1 parent 43ddab8 commit 5b0f608
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 3 deletions.
15 changes: 15 additions & 0 deletions apollo-router/src/query_planner/labeler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,18 @@ pub(crate) fn directive(

Ok(encoder_directive)
}

#[cfg(test)]
mod tests {
use super::add_defer_labels;
use apollo_compiler::ApolloCompiler;

#[test]
fn large_float_written_as_int() {
let mut compiler = ApolloCompiler::new();
compiler.add_type_system("type Query { field(id: Float): String! }", "schema.graphql");
let file_id = compiler.add_executable(r#"{ field(id: 1234567890123) }"#, "query.graphql");
let result = add_defer_labels(file_id, &compiler).unwrap();
insta::assert_snapshot!(result);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
source: apollo-router/src/query_planner/labeler.rs
expression: result
---
query {
field(id: 1234567890123)
}

7 changes: 4 additions & 3 deletions apollo-router/src/spec/query/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,9 +369,10 @@ pub(crate) fn ty(hir: &hir::Type) -> apollo_encoder::Type_ {
pub(crate) fn value(hir: &hir::Value) -> Result<apollo_encoder::Value, BoxError> {
Ok(match hir {
hir::Value::Variable(val) => apollo_encoder::Value::Variable(val.name().into()),
hir::Value::Int { value, .. } => {
apollo_encoder::Value::Int(value.to_i32_checked().ok_or("Int value overflows i32")?)
}
hir::Value::Int { value, .. } => value
.to_i32_checked()
.map(apollo_encoder::Value::Int)
.unwrap_or_else(|| apollo_encoder::Value::Float(value.get())),
hir::Value::Float { value, .. } => apollo_encoder::Value::Float(value.get()),
hir::Value::String { value, .. } => apollo_encoder::Value::String(value.clone()),
hir::Value::Boolean { value, .. } => apollo_encoder::Value::Boolean(*value),
Expand Down

0 comments on commit 5b0f608

Please sign in to comment.