From 63d3ed5fb6ce05ca43683586adbdde5b0e9a8ae4 Mon Sep 17 00:00:00 2001 From: Oliver Rice Date: Wed, 31 Jan 2024 12:57:57 -0600 Subject: [PATCH] mvp offset support. requires pagination tests --- src/builder.rs | 24 +++++++++++++++++++++++- src/graphql.rs | 9 +++++++++ src/transpile.rs | 7 ++++++- 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 63a65769..cad865c0 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -743,6 +743,7 @@ pub struct ConnectionBuilder { pub last: Option, pub before: Option, pub after: Option, + pub offset: Option, pub filter: FilterBuilder, pub order_by: OrderByBuilder, @@ -1318,7 +1319,9 @@ where match &type_ { __Type::Connection(xtype) => { // Raise for disallowed arguments - let mut allowed_args = vec!["first", "last", "before", "after", "filter", "orderBy"]; + let mut allowed_args = vec![ + "first", "last", "before", "after", "offset", "filter", "orderBy", + ]; allowed_args.extend(extra_allowed_args); restrict_allowed_arguments(&allowed_args, query_field)?; @@ -1349,6 +1352,24 @@ where } }; + let offset: gson::Value = read_argument( + "offset", + field, + query_field, + variables, + variable_definitions, + )?; + let offset: Option = match offset { + gson::Value::Absent | gson::Value::Null => None, + gson::Value::Number(gson::Number::Integer(n)) if n < 0 => { + return Err("`offset` must be an unsigned integer".to_string()) + } + gson::Value::Number(gson::Number::Integer(n)) => Some(n as u64), + _ => { + return Err("Internal Error: failed to parse validated offset".to_string()); + } + }; + let max_rows: u64 = xtype .schema .context @@ -1434,6 +1455,7 @@ where first, last, before, + offset, after, filter, order_by, diff --git a/src/graphql.rs b/src/graphql.rs index cac4e918..7ae0fff4 100644 --- a/src/graphql.rs +++ b/src/graphql.rs @@ -1050,6 +1050,15 @@ impl ConnectionType { default_value: None, sql_type: None, }, + __InputValue { + name_: "offset".to_string(), + type_: __Type::Scalar(Scalar::Int), + description: Some( + "Query values in the collection after the provided cursor".to_string(), + ), + default_value: None, + sql_type: None, + }, __InputValue { name_: "filter".to_string(), type_: __Type::FilterEntity(FilterEntityType { diff --git a/src/transpile.rs b/src/transpile.rs index 04ad8775..1a2ac3d6 100644 --- a/src/transpile.rs +++ b/src/transpile.rs @@ -463,7 +463,8 @@ impl MutationEntrypoint<'_> for UpdateBuilder { select case when total.total_count > {at_most} then graphql.exception($a$update impacts too many records$a$)::jsonb - else req.res + + end from total @@ -971,6 +972,7 @@ impl ConnectionBuilder { }; let limit = self.limit_clause(); + let offset = self.offset.unwrap_or(0); // initialized assuming forwards pagination let mut has_next_page_query = format!( @@ -987,6 +989,7 @@ impl ConnectionBuilder { order by {order_by_clause} limit ({limit} + 1) + offset ({offset}) ) select count(*) > {limit} from page_plus_1 " @@ -1038,6 +1041,8 @@ impl ConnectionBuilder { {order_by_clause_records} limit {limit} + offset + {offset} ), __total_count(___total_count) as ( select