From fc4af818044babd1503f030fb77323bcffcd70f7 Mon Sep 17 00:00:00 2001 From: Zoran Cvetkov Date: Wed, 29 Nov 2023 15:04:03 +0200 Subject: [PATCH] lifetimes --- graph/src/data/store/id.rs | 2 +- store/postgres/src/block_range.rs | 10 +- store/postgres/src/relational_queries.rs | 262 ++++++++++++----------- 3 files changed, 141 insertions(+), 133 deletions(-) diff --git a/graph/src/data/store/id.rs b/graph/src/data/store/id.rs index d50479b0bfe..5c72db25fcd 100644 --- a/graph/src/data/store/id.rs +++ b/graph/src/data/store/id.rs @@ -345,7 +345,7 @@ impl IdList { } } - pub fn index(&self, index: usize) -> IdRef<'_> { + pub fn index<'b>(&'b self, index: usize) -> IdRef<'b> { match self { IdList::String(ids) => IdRef::String(&ids[index]), IdList::Bytes(ids) => IdRef::Bytes(ids[index].as_slice()), diff --git a/store/postgres/src/block_range.rs b/store/postgres/src/block_range.rs index 674b8316670..238b0be1eab 100644 --- a/store/postgres/src/block_range.rs +++ b/store/postgres/src/block_range.rs @@ -173,14 +173,14 @@ impl<'a> BlockRangeColumn<'a> { /// whether the brin index should be used. If `true`, the brin index is not used. pub fn contains<'b>( &'b self, - mut out: AstPass<'b, 'b, Pg>, + out: &mut AstPass<'_, 'b, Pg>, filters_by_id: bool, ) -> QueryResult<()> { out.unsafe_to_cache_prepared(); match self { BlockRangeColumn::Mutable { table, block, .. } => { - self.name(&mut out); + self.name(out); out.push_sql(" @> "); out.push_bind_param::(block)?; @@ -211,7 +211,7 @@ impl<'a> BlockRangeColumn<'a> { out.push_sql("true"); Ok(()) } else { - self.name(&mut out); + self.name(out); out.push_sql(" <= "); out.push_bind_param::(block) } @@ -255,7 +255,7 @@ impl<'a> BlockRangeColumn<'a> { /// # Panics /// /// If the underlying table is immutable, this method will panic - pub fn clamp<'b>(&'b self, out: &mut AstPass<'b, 'b, Pg>) -> QueryResult<()> { + pub fn clamp<'b>(&'b self, out: &mut AstPass<'_, 'b, Pg>) -> QueryResult<()> { match self { BlockRangeColumn::Mutable { block, .. } => { self.name(out); @@ -282,7 +282,7 @@ impl<'a> BlockRangeColumn<'a> { /// Output an expression that matches all rows that have been changed /// after `block` (inclusive) - pub(crate) fn changed_since<'b>(&'b self, out: &mut AstPass<'b, 'b, Pg>) -> QueryResult<()> { + pub(crate) fn changed_since<'b>(&'b self, out: &mut AstPass<'_, 'b, Pg>) -> QueryResult<()> { match self { BlockRangeColumn::Mutable { block, .. } => { out.push_sql("lower("); diff --git a/store/postgres/src/relational_queries.rs b/store/postgres/src/relational_queries.rs index 0b203fae46c..657bd0f45ef 100644 --- a/store/postgres/src/relational_queries.rs +++ b/store/postgres/src/relational_queries.rs @@ -549,6 +549,7 @@ struct QueryValue<'a>(&'a Value, &'a ColumnType); impl<'a> QueryFragment for QueryValue<'a> { fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> QueryResult<()> { + let out = &mut out; out.unsafe_to_cache_prepared(); let column_type = self.1; @@ -644,11 +645,7 @@ impl<'a> QueryFragment for QueryValue<'a> { out.push_bind_param::(slice) } Value::BigInt(i) => { - let big_int = i.to_string(); - let mut out = out.reborrow(); - let bind = &big_int; - out.reborrow().push_bind_param::(bind)?; - let mut out = out.reborrow(); + out.reborrow().push_bind_param::(&i.to_string())?; //let mut out = out.reborrow(); out.push_sql("::numeric"); Ok(()) @@ -791,7 +788,7 @@ impl<'a> PrefixComparison<'a> { self.push_value_prefix(out.reborrow()) } - fn push_full_cmp(&self, op: Comparison, mut out: AstPass) -> QueryResult<()> { + fn push_full_cmp(&self, op: Comparison, mut out: AstPass<'a, '_, Pg>) -> QueryResult<()> { out.push_identifier(self.column.name.as_str())?; out.push_sql(op.as_str()); QueryValue(self.text, &self.column.column_type).walk_ast(out) @@ -1016,8 +1013,9 @@ impl<'a> QueryFilter<'a> { entity_type: &'a EntityType, filter: &'a EntityFilter, derived: bool, - mut out: AstPass, + mut out: AstPass<'a, '_, Pg>, ) -> QueryResult<()> { + let out = &mut out; let child_table = self .layout .table_for_entity(entity_type) @@ -1513,7 +1511,7 @@ impl<'a> QueryFragment for FindQuery<'a> { out.push_bind_param::(&self.key.causality_region)?; out.push_sql(" and "); } - BlockRangeColumn::new(self.table, "e.", self.block).contains(out, true) + BlockRangeColumn::new(self.table, "e.", self.block).contains(&mut out, true) } } @@ -1540,7 +1538,7 @@ pub struct FindChangesQuery<'a> { } impl<'a> QueryFragment for FindChangesQuery<'a> { - fn walk_ast(&self, mut out: AstPass) -> QueryResult<()> { + fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> QueryResult<()> { out.unsafe_to_cache_prepared(); for (i, table) in self.tables.iter().enumerate() { @@ -1589,6 +1587,7 @@ pub struct FindPossibleDeletionsQuery<'a> { impl<'a> QueryFragment for FindPossibleDeletionsQuery<'a> { fn walk_ast(&self, mut out: AstPass) -> QueryResult<()> { + let out = &mut out; out.unsafe_to_cache_prepared(); for (i, table) in self.tables.iter().enumerate() { @@ -1636,7 +1635,7 @@ pub struct FindManyQuery<'a> { } impl<'a> QueryFragment for FindManyQuery<'a> { - fn walk_ast(&self, mut out: AstPass) -> QueryResult<()> { + fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> QueryResult<()> { out.unsafe_to_cache_prepared(); // Generate @@ -1666,7 +1665,7 @@ impl<'a> QueryFragment for FindManyQuery<'a> { out.push_bind_param::(cr)?; out.push_sql(" and "); } - BlockRangeColumn::new(table, "e.", self.block).contains(out, true)?; + BlockRangeColumn::new(table, "e.", self.block).contains(&mut out, true)?; } Ok(()) } @@ -1695,7 +1694,7 @@ pub struct FindDerivedQuery<'a> { } impl<'a> QueryFragment for FindDerivedQuery<'a> { - fn walk_ast(&self, mut out: AstPass) -> QueryResult<()> { + fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> QueryResult<()> { out.unsafe_to_cache_prepared(); let DerivedEntityQuery { @@ -1737,7 +1736,7 @@ impl<'a> QueryFragment for FindDerivedQuery<'a> { out.push_bind_param::(causality_region)?; out.push_sql(" and "); } - BlockRangeColumn::new(self.table, "e.", self.block).contains(out, false) + BlockRangeColumn::new(self.table, "e.", self.block).contains(&mut out, false) } } @@ -1870,11 +1869,11 @@ impl<'a> InsertQuery<'a> { /// Output the literal value of the block range `[block,..)`, mostly for /// generating an insert statement containing the block range column - pub fn literal_range_current( + pub fn literal_range_current<'b>( table: &Table, block: BlockNumber, end: Option, - out: &mut AstPass, + out: &mut AstPass<'_, 'b, Pg>, ) -> QueryResult<()> { if table.immutable { out.push_bind_param::(&block) @@ -1890,6 +1889,7 @@ impl<'a> InsertQuery<'a> { impl<'a> QueryFragment for InsertQuery<'a> { fn walk_ast(&self, mut out: AstPass) -> QueryResult<()> { + let out = &mut out; out.unsafe_to_cache_prepared(); // Construct a query @@ -1932,7 +1932,7 @@ impl<'a> QueryFragment for InsertQuery<'a> { QueryValue(value, &column.column_type).walk_ast(out.reborrow())?; out.push_sql(", "); } - Self::literal_range_current(&self.table, row.block, row.end, &mut out)?; + Self::literal_range_current(&self.table, row.block, row.end, out)?; if self.table.has_causality_region { out.push_sql(", "); out.push_bind_param::(&row.causality_region)?; @@ -1982,7 +1982,7 @@ impl<'a> ConflictingEntityQuery<'a> { } impl<'a> QueryFragment for ConflictingEntityQuery<'a> { - fn walk_ast(&self, mut out: AstPass) -> QueryResult<()> { + fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> QueryResult<()> { out.unsafe_to_cache_prepared(); // Construct a query @@ -2092,11 +2092,11 @@ impl<'a> ParentLimit<'a> { } } - fn restrict(&self, mut out: AstPass) -> QueryResult<()> { + fn restrict<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> QueryResult<()> { if let ParentLimit::Ranked(sort_key, range) = self { out.push_sql(" "); sort_key.order_by(&mut out, false)?; - range.walk_ast(out)?; + range.walk_ast(out.reborrow())?; } Ok(()) } @@ -2178,7 +2178,7 @@ impl<'a> FilterWindow<'a> { } } - fn and_filter(&self, out: &mut AstPass) -> QueryResult<()> { + fn and_filter(&'a self, out: &mut AstPass<'_, 'a, Pg>) -> QueryResult<()> { if let Some(filter) = &self.query_filter { out.push_sql("\n and "); filter.walk_ast(out.reborrow())? @@ -2186,12 +2186,12 @@ impl<'a> FilterWindow<'a> { Ok(()) } - fn children_type_a( - &self, + fn children_type_a<'b>( + &'b self, column: &Column, - limit: ParentLimit<'_>, + limit: ParentLimit<'b>, block: BlockNumber, - out: &mut AstPass, + out: &mut AstPass<'_, 'b, Pg>, ) -> QueryResult<()> { assert!(column.is_list()); @@ -2213,7 +2213,7 @@ impl<'a> FilterWindow<'a> { out.push_sql(" from "); out.push_sql(self.table.qualified_name.as_str()); out.push_sql(" c where "); - BlockRangeColumn::new(self.table, "c.", block).contains(out.reborrow(), false)?; + BlockRangeColumn::new(self.table, "c.", block).contains(out, false)?; limit.filter(out.reborrow()); out.push_sql(" and p.id = any(c."); out.push_identifier(column.name.as_str())?; @@ -2224,12 +2224,12 @@ impl<'a> FilterWindow<'a> { Ok(()) } - fn child_type_a( - &self, + fn child_type_a<'b>( + &'b self, column: &Column, - limit: ParentLimit<'_>, + limit: ParentLimit<'b>, block: BlockNumber, - out: &mut AstPass, + out: &mut AstPass<'_, 'b, Pg>, ) -> QueryResult<()> { assert!(column.is_list()); @@ -2249,7 +2249,7 @@ impl<'a> FilterWindow<'a> { out.push_sql(") as p(id), "); out.push_sql(self.table.qualified_name.as_str()); out.push_sql(" c where "); - BlockRangeColumn::new(self.table, "c.", block).contains(out.reborrow(), false)?; + BlockRangeColumn::new(self.table, "c.", block).contains(out, false)?; limit.filter(out.reborrow()); out.push_sql(" and c."); out.push_identifier(column.name.as_str())?; @@ -2265,12 +2265,12 @@ impl<'a> FilterWindow<'a> { Ok(()) } - fn children_type_b( - &self, + fn children_type_b<'b>( + &'b self, column: &Column, - limit: ParentLimit<'_>, + limit: ParentLimit<'b>, block: BlockNumber, - out: &mut AstPass, + out: &mut AstPass<'_, 'b, Pg>, ) -> QueryResult<()> { assert!(!column.is_list()); @@ -2292,7 +2292,7 @@ impl<'a> FilterWindow<'a> { out.push_sql(" from "); out.push_sql(self.table.qualified_name.as_str()); out.push_sql(" c where "); - BlockRangeColumn::new(self.table, "c.", block).contains(out.reborrow(), false)?; + BlockRangeColumn::new(self.table, "c.", block).contains(out, false)?; limit.filter(out.reborrow()); out.push_sql(" and p.id = c."); out.push_identifier(column.name.as_str())?; @@ -2302,12 +2302,12 @@ impl<'a> FilterWindow<'a> { Ok(()) } - fn child_type_b( - &self, + fn child_type_b<'b>( + &'b self, column: &Column, - limit: ParentLimit<'_>, + limit: ParentLimit<'b>, block: BlockNumber, - out: &mut AstPass, + out: &mut AstPass<'_, 'b, Pg>, ) -> QueryResult<()> { assert!(!column.is_list()); @@ -2322,7 +2322,7 @@ impl<'a> FilterWindow<'a> { out.push_sql(") as p(id), "); out.push_sql(self.table.qualified_name.as_str()); out.push_sql(" c where "); - BlockRangeColumn::new(self.table, "c.", block).contains(out.reborrow(), false)?; + BlockRangeColumn::new(self.table, "c.", block).contains(out, false)?; limit.filter(out.reborrow()); out.push_sql(" and p.id = c."); out.push_identifier(column.name.as_str())?; @@ -2332,11 +2332,11 @@ impl<'a> FilterWindow<'a> { } fn children_type_c<'b>( - &self, - child_ids: &[IdList], - limit: ParentLimit<'_>, + &'b self, + child_ids: &'b [IdList], + limit: ParentLimit<'b>, block: BlockNumber, - mut out: AstPass<'_, 'b, Pg>, + out: &mut AstPass<'_, 'b, Pg>, ) -> QueryResult<()> { out.push_sql("\n/* children_type_c */ "); @@ -2366,21 +2366,21 @@ impl<'a> FilterWindow<'a> { } else { out.push_sql("("); } - parent_id.push_bind_param(&mut out)?; + parent_id.push_bind_param(out)?; out.push_sql(","); - child_ids.push_bind_param(&mut out)?; + child_ids.push_bind_param(out)?; out.push_sql(")"); } out.push_sql(") as p(id, child_ids)"); out.push_sql(" cross join lateral (select "); - write_column_names(&self.column_names, self.table, None, &mut out)?; + write_column_names(&self.column_names, self.table, None, out)?; out.push_sql(" from "); out.push_sql(self.table.qualified_name.as_str()); out.push_sql(" c where "); - BlockRangeColumn::new(self.table, "c.", block).contains(out.reborrow(), true)?; + BlockRangeColumn::new(self.table, "c.", block).contains(out, true); limit.filter(out.reborrow()); out.push_sql(" and c.id = any(p.child_ids)"); - self.and_filter(&mut out)?; + self.and_filter(out)?; limit.restrict(out.reborrow())?; out.push_sql(") c"); } else { @@ -2391,7 +2391,7 @@ impl<'a> FilterWindow<'a> { // where false) c out.push_sql("from unnest(array[]::text[]) as p(id) cross join (select "); - write_column_names(&self.column_names, self.table, None, &mut out)?; + write_column_names(&self.column_names, self.table, None, out)?; out.push_sql(" from "); out.push_sql(self.table.qualified_name.as_str()); out.push_sql(" c where false) c"); @@ -2399,12 +2399,12 @@ impl<'a> FilterWindow<'a> { Ok(()) } - fn child_type_d( - &self, - child_ids: &IdList, - limit: ParentLimit<'_>, + fn child_type_d<'b>( + &'b self, + child_ids: &'b IdList, + limit: ParentLimit<'b>, block: BlockNumber, - mut out: AstPass, + out: &mut AstPass<'_, 'b, Pg>, ) -> QueryResult<()> { // Generate // from rows from (unnest({parent_ids}), unnest({child_ids})) as p(id, child_id), @@ -2413,13 +2413,13 @@ impl<'a> FilterWindow<'a> { // and .. other conditions on c .. out.push_sql("\n/* child_type_d */ from rows from (unnest("); - self.ids.push_bind_param(&mut out)?; + self.ids.push_bind_param(out)?; out.push_sql("), unnest("); - child_ids.push_bind_param(&mut out)?; + child_ids.push_bind_param(out)?; out.push_sql(")) as p(id, child_id), "); out.push_sql(self.table.qualified_name.as_str()); out.push_sql(" c where "); - BlockRangeColumn::new(self.table, "c.", block).contains(out.reborrow(), true)?; + BlockRangeColumn::new(self.table, "c.", block).contains(out, true)?; limit.filter(out.reborrow()); // Include a constraint on the child IDs as a set if the size of the set @@ -2430,35 +2430,35 @@ impl<'a> FilterWindow<'a> { if child_set.len() <= ENV_VARS.store.typed_children_set_size { out.push_sql(" and c.id = any("); - child_set.push_bind_param(&mut out)?; + child_set.push_bind_param(out)?; out.push_sql(")"); } } out.push_sql(" and "); out.push_sql("c.id = p.child_id"); - self.and_filter(&mut out)?; - limit.single_limit(self.ids.len(), &mut out); + self.and_filter(out)?; + limit.single_limit(self.ids.len(), out); Ok(()) } - fn children( - &self, - limit: ParentLimit<'_>, + fn children<'b>( + &'b self, + limit: ParentLimit<'b>, block: BlockNumber, - mut out: AstPass, + out: &mut AstPass<'_, 'b, Pg>, ) -> QueryResult<()> { match &self.link { TableLink::Direct(column, multiplicity) => { use ChildMultiplicity::*; if column.is_list() { match multiplicity { - Many => self.children_type_a(column, limit, block, &mut out), - Single => self.child_type_a(column, limit, block, &mut out), + Many => self.children_type_a(column, limit, block, out), + Single => self.child_type_a(column, limit, block, out), } } else { match multiplicity { - Many => self.children_type_b(column, limit, block, &mut out), - Single => self.child_type_b(column, limit, block, &mut out), + Many => self.children_type_b(column, limit, block, out), + Single => self.child_type_b(column, limit, block, out), } } } @@ -2474,18 +2474,18 @@ impl<'a> FilterWindow<'a> { /// Select a basic subset of columns from the child table for use in /// the `matches` CTE of queries that need to retrieve entities of /// different types or entities that link differently to their parents - fn children_uniform( - &self, + fn children_uniform<'b>( + &'b self, sort_key: &SortKey, block: BlockNumber, - mut out: AstPass, + mut out: AstPass<'_, 'b, Pg>, ) -> QueryResult<()> { out.push_sql("select '"); out.push_sql(self.table.object.as_str()); out.push_sql("' as entity, c.id, c.vid, p.id::text as "); out.push_sql(&*PARENT_ID); sort_key.select(&mut out, SelectStatementLevel::InnerStatement)?; - self.children(ParentLimit::Outer, block, out) + self.children(ParentLimit::Outer, block, &mut out) } /// Collect all the parent id's from all windows @@ -3322,7 +3322,11 @@ impl<'a> SortKey<'a> { /// Generate /// order by [name direction], id - fn order_by(&self, out: &mut AstPass, use_sort_key_alias: bool) -> QueryResult<()> { + fn order_by<'b>( + &'b self, + out: &mut AstPass<'_, 'b, Pg>, + use_sort_key_alias: bool, + ) -> QueryResult<()> { match self { SortKey::None => Ok(()), SortKey::IdAsc(br_column) => { @@ -3443,7 +3447,11 @@ impl<'a> SortKey<'a> { /// TODO: Let's think how to detect if we need to use sort_key$ alias or not /// A boolean (use_sort_key_alias) is not a good idea and prone to errors. /// We could make it the standard and always use sort_key$ alias. - fn order_by_parent(&self, out: &mut AstPass, use_sort_key_alias: bool) -> QueryResult<()> { + fn order_by_parent<'b>( + &'b self, + out: &mut AstPass<'_, 'b, Pg>, + use_sort_key_alias: bool, + ) -> QueryResult<()> { fn order_by_parent_id(out: &mut AstPass) { out.push_sql("order by "); out.push_sql(&*PARENT_ID); @@ -3486,14 +3494,14 @@ impl<'a> SortKey<'a> { /// Generate /// [name direction,] id - fn sort_expr( + fn sort_expr<'b>( column: &Column, - value: &Option<&str>, + value: &'b Option<&str>, direction: &str, column_prefix: Option<&str>, rest_prefix: Option<&str>, use_sort_key_alias: bool, - out: &mut AstPass, + out: &mut AstPass<'_, 'b, Pg>, ) -> QueryResult<()> { if column.is_primary_key() { // This shouldn't happen since we'd use SortKey::IdAsc/Desc @@ -3526,7 +3534,7 @@ impl<'a> SortKey<'a> { out.push_sql(", to_tsquery("); - out.push_bind_param::(&value.unwrap())?; + out.push_bind_param::(value.unwrap())?; out.push_sql("))"); } _ => { @@ -3849,17 +3857,17 @@ impl<'a> FilterQuery<'a> { /// and query_filter /// Only used when the query is against a `FilterCollection::All`, i.e. /// when we do not need to window - fn filtered_rows( - &self, - table: &Table, - table_filter: &Option>, - mut out: AstPass, + fn filtered_rows<'b>( + &'b self, + table: &'b Table, + table_filter: &'b Option>, + out: &mut AstPass<'_, 'b, Pg>, ) -> QueryResult<()> { out.push_sql("\n from "); out.push_sql(table.qualified_name.as_str()); out.push_sql(" c"); - self.sort_key.add_child(self.block, &mut out)?; + self.sort_key.add_child(self.block, out)?; out.push_sql("\n where "); @@ -3895,19 +3903,19 @@ impl<'a> FilterQuery<'a> { /// where block_range @> $block /// and filter /// order by .. limit .. skip ..) c - fn query_no_window_one_entity( - &self, - table: &Table, - filter: &Option, - mut out: AstPass, + fn query_no_window_one_entity<'b>( + &'b self, + table: &'b Table, + filter: &'b Option, + out: &mut AstPass<'_, 'b, Pg>, column_names: &AttributeNames, ) -> QueryResult<()> { - Self::select_entity_and_data(table, &mut out); + Self::select_entity_and_data(table, out); out.push_sql(" from (select "); - write_column_names(column_names, table, Some("c."), &mut out)?; - self.filtered_rows(table, filter, out.reborrow())?; + write_column_names(column_names, table, Some("c."), out)?; + self.filtered_rows(table, filter, out)?; out.push_sql("\n "); - self.sort_key.order_by(&mut out, false)?; + self.sort_key.order_by(out, false)?; self.range.walk_ast(out.reborrow())?; out.push_sql(") c"); Ok(()) @@ -3920,10 +3928,10 @@ impl<'a> FilterQuery<'a> { /// from (select c.*, p.id as g$parent_id from {window.children(...)}) c /// order by c.g$parent_id, {sort_key} /// limit {first} offset {skip} - fn query_window_one_entity( - &self, - window: &FilterWindow, - mut out: AstPass, + fn query_window_one_entity<'b>( + &'b self, + window: &'b FilterWindow, + mut out: AstPass<'_, 'b, Pg>, ) -> QueryResult<()> { Self::select_entity_and_data(window.table, &mut out); out.push_sql(" from (\n"); @@ -3932,7 +3940,7 @@ impl<'a> FilterQuery<'a> { window.children( ParentLimit::Ranked(&self.sort_key, &self.range), self.block, - out.reborrow(), + &mut out, )?; out.push_sql(") c"); out.push_sql("\n "); @@ -3941,9 +3949,9 @@ impl<'a> FilterQuery<'a> { /// No windowing, but multiple entity types fn query_no_window<'b>( - &self, - entities: &[(&Table, Option, AttributeNames)], - mut out: AstPass<'_, 'b, Pg>, + &'b self, + entities: &'b [(&Table, Option, AttributeNames)], + out: &mut AstPass<'_, 'b, Pg>, ) -> QueryResult<()> { // We have multiple tables which might have different schemas since // the entity_types come from implementing the same interface. We @@ -3984,12 +3992,12 @@ impl<'a> FilterQuery<'a> { out.push_sql(table.object.as_str()); out.push_sql("' as entity, c.id, c.vid"); self.sort_key - .select(&mut out, SelectStatementLevel::InnerStatement)?; // here - self.filtered_rows(table, filter, out.reborrow())?; + .select(out, SelectStatementLevel::InnerStatement)?; // here + self.filtered_rows(table, filter, out)?; } out.push_sql("\n "); - self.sort_key.order_by(&mut out, true)?; - self.range.walk_ast(out)?; + self.sort_key.order_by(out, true)?; + self.range.walk_ast(out.reborrow())?; out.push_sql(")\n"); @@ -3999,28 +4007,28 @@ impl<'a> FilterQuery<'a> { out.push_sql("\nunion all\n"); } out.push_sql("select m.entity, "); - jsonb_build_object(column_names, "c", table, &mut out)?; + jsonb_build_object(column_names, "c", table, out)?; out.push_sql(" as data, c.id"); self.sort_key - .select(&mut out, SelectStatementLevel::OuterStatement)?; + .select(out, SelectStatementLevel::OuterStatement)?; out.push_sql("\n from "); out.push_sql(table.qualified_name.as_str()); out.push_sql(" c,"); out.push_sql(" matches m"); out.push_sql("\n where c.vid = m.vid and m.entity = "); - out.push_bind_param::(&table.object.as_str())?; + out.push_bind_param::(table.object.as_str())?; } out.push_sql("\n "); - self.sort_key.order_by(&mut out, true)?; + self.sort_key.order_by(out, true)?; Ok(()) } /// Multiple windows - fn query_window( - &self, - windows: &[FilterWindow], - parent_ids: &IdList, - mut out: AstPass, + fn query_window<'b>( + &'b self, + windows: &'b [FilterWindow], + parent_ids: &'b IdList, + out: &mut AstPass<'_, 'b, Pg>, ) -> QueryResult<()> { // Note that a CTE is an optimization fence, and since we use // `matches` multiple times, we actually want to materialize it first @@ -4051,7 +4059,7 @@ impl<'a> FilterQuery<'a> { out.push_sql("with matches as ("); out.push_sql("select c.* from "); out.push_sql("unnest("); - parent_ids.push_bind_param(&mut out)?; + parent_ids.push_bind_param(out)?; out.push_sql(") as q(id)\n"); out.push_sql(" cross join lateral ("); for (i, window) in windows.iter().enumerate() { @@ -4061,7 +4069,7 @@ impl<'a> FilterQuery<'a> { window.children_uniform(&self.sort_key, self.block, out.reborrow())?; } out.push_sql("\n"); - self.sort_key.order_by(&mut out, true)?; + self.sort_key.order_by(out, true)?; self.range.walk_ast(out.reborrow())?; out.push_sql(") c)\n"); @@ -4089,7 +4097,7 @@ impl<'a> FilterQuery<'a> { out.push_sql("\nunion all\n"); } out.push_sql("select m.*, "); - jsonb_build_object(&window.column_names, "c", window.table, &mut out)?; + jsonb_build_object(&window.column_names, "c", window.table, out)?; out.push_sql("|| jsonb_build_object('g$parent_id', m.g$parent_id) as data"); out.push_sql("\n from "); out.push_sql(window.table.qualified_name.as_str()); @@ -4098,12 +4106,12 @@ impl<'a> FilterQuery<'a> { out.push_sql("'"); } out.push_sql("\n "); - self.sort_key.order_by_parent(&mut out, true) + self.sort_key.order_by_parent(out, true) } } impl<'a> QueryFragment for FilterQuery<'a> { - fn walk_ast(&self, mut out: AstPass) -> QueryResult<()> { + fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> QueryResult<()> { out.unsafe_to_cache_prepared(); if self.collection.is_empty() { return Ok(()); @@ -4135,14 +4143,14 @@ impl<'a> QueryFragment for FilterQuery<'a> { let (table, filter, column_names) = entities .first() .expect("a query always uses at least one table"); - self.query_no_window_one_entity(table, filter, out, column_names) + self.query_no_window_one_entity(table, filter, &mut out, column_names) } else { - self.query_no_window(entities, out) + self.query_no_window(entities, &mut out) } } FilterCollection::SingleWindow(window) => self.query_window_one_entity(window, out), FilterCollection::MultiWindow(windows, parent_ids) => { - self.query_window(windows, parent_ids, out) + self.query_window(windows, parent_ids, &mut out) } } } @@ -4192,7 +4200,7 @@ impl<'a> ClampRangeQuery<'a> { } impl<'a> QueryFragment for ClampRangeQuery<'a> { - fn walk_ast(&self, mut out: AstPass) -> QueryResult<()> { + fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> QueryResult<()> { // update table // set block_range = int4range(lower(block_range), $block) // where id in (id1, id2, ..., idN) @@ -4261,7 +4269,7 @@ impl<'a> RevertRemoveQuery<'a> { } impl<'a> QueryFragment for RevertRemoveQuery<'a> { - fn walk_ast(&self, mut out: AstPass) -> QueryResult<()> { + fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> QueryResult<()> { out.unsafe_to_cache_prepared(); // Construct a query @@ -4312,7 +4320,7 @@ impl<'a> RevertClampQuery<'a> { } impl<'a> QueryFragment for RevertClampQuery<'a> { - fn walk_ast(&self, mut out: AstPass) -> QueryResult<()> { + fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> QueryResult<()> { out.unsafe_to_cache_prepared(); // Construct a query @@ -4429,7 +4437,7 @@ impl<'a> CopyEntityBatchQuery<'a> { } impl<'a> QueryFragment for CopyEntityBatchQuery<'a> { - fn walk_ast(&self, mut out: AstPass) -> QueryResult<()> { + fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> QueryResult<()> { out.unsafe_to_cache_prepared(); // Construct a query