@@ -1450,94 +1450,182 @@ impl<'a> FilterWindow<'a> {
1450
1450
} )
1451
1451
}
1452
1452
1453
- fn expand_parents ( & self , out : & mut AstPass < Pg > ) -> QueryResult < ( ) > {
1454
- match & self . link {
1455
- TableLink :: Direct ( column) => {
1456
- // Type A and B
1457
- // unnest($parent_ids) as p(id)
1458
- out. push_sql ( "unnest(" ) ;
1459
- column. bind_ids ( & self . ids , out) ?;
1460
- out. push_sql ( ") as p(id)" ) ;
1461
- }
1462
- // For types C and D we always treat the parent ids as strings,
1463
- // regardless of the actual IdType of the parent since we never
1464
- // compare them to anything, and solely copy them through to the
1465
- // result so that they can be matched up with the parent object
1466
- // by the GraphQL query execution
1467
- TableLink :: Parent ( ParentIds :: List ( child_ids) ) => {
1468
- // Type C
1469
- // unnest($parent_ids, $child_id_matrix) as p(id, child_ids)
1470
- out. push_sql ( "rows from (unnest(" ) ;
1471
- out. push_bind_param :: < Array < Text > , _ > ( & self . ids ) ?;
1472
- out. push_sql ( "), reduce_dim(" ) ;
1473
- self . table . primary_key ( ) . push_matrix ( & child_ids, out) ?;
1474
- out. push_sql ( ")) as p(id, child_ids)" ) ;
1475
- }
1476
- TableLink :: Parent ( ParentIds :: Scalar ( child_ids) ) => {
1477
- // Type D
1478
- // unnest($parent_ids, $child_ids) as p(id, child_id)
1479
- out. push_sql ( "unnest(" ) ;
1480
- out. push_bind_param :: < Array < Text > , _ > ( & self . ids ) ?;
1481
- out. push_sql ( "," ) ;
1482
- self . table . primary_key ( ) . bind_ids ( & child_ids, out) ?;
1483
- out. push_sql ( ") as p(id, child_id)" ) ;
1484
- }
1453
+ fn and_filter ( & self , mut out : AstPass < Pg > ) -> QueryResult < ( ) > {
1454
+ if let Some ( filter) = & self . query_filter {
1455
+ out. push_sql ( "\n and " ) ;
1456
+ filter. walk_ast ( out) ?
1485
1457
}
1486
1458
Ok ( ( ) )
1487
1459
}
1488
1460
1489
- fn linked_children ( & self , out : & mut AstPass < Pg > ) -> QueryResult < ( ) > {
1490
- out. push_sql ( " and " ) ;
1491
- match & self . link {
1492
- TableLink :: Direct ( column) => {
1493
- if column. is_list ( ) {
1494
- // Type A
1495
- // p.id = any(c.{parent_field})
1496
- out. push_sql ( "p.id = any(c." ) ;
1497
- out. push_identifier ( column. name . as_str ( ) ) ?;
1498
- out. push_sql ( ")" ) ;
1499
- } else {
1500
- // Type B
1501
- // p.id = c.{parent_field}
1502
- out. push_sql ( "p.id = c." ) ;
1503
- out. push_identifier ( column. name . as_str ( ) ) ?;
1504
- }
1505
- }
1506
- TableLink :: Parent ( ParentIds :: List ( _) ) => {
1507
- // Type C
1508
- out. push_sql ( "c.id = any(p.child_ids)" ) ;
1509
- }
1510
- TableLink :: Parent ( ParentIds :: Scalar ( _) ) => {
1511
- // Type D
1512
- out. push_sql ( "c.id = p.child_id" ) ;
1513
- }
1514
- }
1461
+ fn children_type_a (
1462
+ & self ,
1463
+ column : & Column ,
1464
+ limit : ParentLimit < ' _ > ,
1465
+ block : BlockNumber ,
1466
+ out : & mut AstPass < Pg > ,
1467
+ ) -> QueryResult < ( ) > {
1468
+ assert ! ( column. is_list( ) ) ;
1469
+
1470
+ // Generate
1471
+ // from unnest({parent_ids}) as p(id)
1472
+ // cross join lateral
1473
+ // (select *
1474
+ // from children c
1475
+ // where p.id = any(c.{parent_field})
1476
+ // and .. other conditions on c ..
1477
+ // order by c.{sort_key}
1478
+ // limit {first} offset {skip}) c
1479
+ // order by c.{sort_key}
1480
+
1481
+ out. push_sql ( "\n from unnest(" ) ;
1482
+ column. bind_ids ( & self . ids , out) ?;
1483
+ out. push_sql ( ") as p(id) cross join lateral (select * from " ) ;
1484
+ out. push_sql ( self . table . qualified_name . as_str ( ) ) ;
1485
+ out. push_sql ( " c where " ) ;
1486
+ BlockRangeContainsClause :: new ( "c." , block) . walk_ast ( out. reborrow ( ) ) ?;
1487
+ limit. filter ( out) ;
1488
+ out. push_sql ( " and p.id = any(c." ) ;
1489
+ out. push_identifier ( column. name . as_str ( ) ) ?;
1490
+ out. push_sql ( ")" ) ;
1491
+ self . and_filter ( out. reborrow ( ) ) ?;
1492
+ limit. restrict ( out) ?;
1493
+ out. push_sql ( ") c" ) ;
1515
1494
Ok ( ( ) )
1516
1495
}
1517
1496
1518
- fn children (
1497
+ fn children_type_b (
1519
1498
& self ,
1499
+ column : & Column ,
1520
1500
limit : ParentLimit < ' _ > ,
1521
1501
block : BlockNumber ,
1522
- mut out : AstPass < Pg > ,
1502
+ out : & mut AstPass < Pg > ,
1523
1503
) -> QueryResult < ( ) > {
1504
+ assert ! ( !column. is_list( ) ) ;
1505
+
1506
+ // Generate
1507
+ // from unnest({parent_ids}) as p(id)
1508
+ // cross join lateral
1509
+ // (select *
1510
+ // from children c
1511
+ // where p.id = c.{parent_field}
1512
+ // and .. other conditions on c ..
1513
+ // order by c.{sort_key}
1514
+ // limit {first} offset {skip}) c
1515
+ // order by c.{sort_key}
1516
+
1517
+ out. push_sql ( "\n from unnest(" ) ;
1518
+ column. bind_ids ( & self . ids , out) ?;
1519
+ out. push_sql ( ") as p(id) cross join lateral (select * from " ) ;
1520
+ out. push_sql ( self . table . qualified_name . as_str ( ) ) ;
1521
+ out. push_sql ( " c where " ) ;
1522
+ BlockRangeContainsClause :: new ( "c." , block) . walk_ast ( out. reborrow ( ) ) ?;
1523
+ limit. filter ( out) ;
1524
+ out. push_sql ( " and p.id = c." ) ;
1525
+ out. push_identifier ( column. name . as_str ( ) ) ?;
1526
+ self . and_filter ( out. reborrow ( ) ) ?;
1527
+ limit. restrict ( out) ?;
1528
+ out. push_sql ( ") c" ) ;
1529
+ Ok ( ( ) )
1530
+ }
1531
+
1532
+ fn children_type_c (
1533
+ & self ,
1534
+ child_ids : & Vec < Vec < Option < SafeString > > > ,
1535
+ limit : ParentLimit < ' _ > ,
1536
+ block : BlockNumber ,
1537
+ out : & mut AstPass < Pg > ,
1538
+ ) -> QueryResult < ( ) > {
1539
+ // Generate
1540
+ // from rows from (unnest({parent_ids}), reduce_dim({child_id_matrix}))
1541
+ // as p(id, child_ids)
1542
+ // cross join lateral
1543
+ // (select *
1544
+ // from children c
1545
+ // where c.id = any(p.child_ids)
1546
+ // and .. other conditions on c ..
1547
+ // order by c.{sort_key}
1548
+ // limit {first} offset {skip}) c
1549
+ // order by c.{sort_key}
1550
+
1524
1551
out. push_sql ( "\n from " ) ;
1525
- self . expand_parents ( & mut out) ?;
1552
+ out. push_sql ( "rows from (unnest(" ) ;
1553
+ out. push_bind_param :: < Array < Text > , _ > ( & self . ids ) ?;
1554
+ out. push_sql ( "), reduce_dim(" ) ;
1555
+ self . table . primary_key ( ) . push_matrix ( & child_ids, out) ?;
1556
+ out. push_sql ( ")) as p(id, child_ids)" ) ;
1526
1557
out. push_sql ( " cross join lateral (select * from " ) ;
1527
1558
out. push_sql ( self . table . qualified_name . as_str ( ) ) ;
1528
1559
out. push_sql ( " c where " ) ;
1529
1560
BlockRangeContainsClause :: new ( "c." , block) . walk_ast ( out. reborrow ( ) ) ?;
1530
- limit. filter ( & mut out) ;
1531
- self . linked_children ( & mut out) ?;
1532
- if let Some ( filter) = & self . query_filter {
1533
- out. push_sql ( "\n and " ) ;
1534
- filter. walk_ast ( out. reborrow ( ) ) ?
1535
- }
1536
- limit. restrict ( & mut out) ?;
1561
+ limit. filter ( out) ;
1562
+ out. push_sql ( " and c.id = any(p.child_ids)" ) ;
1563
+ self . and_filter ( out. reborrow ( ) ) ?;
1564
+ limit. restrict ( out) ?;
1537
1565
out. push_sql ( ") c" ) ;
1538
1566
Ok ( ( ) )
1539
1567
}
1540
1568
1569
+ fn children_type_d (
1570
+ & self ,
1571
+ child_ids : & Vec < String > ,
1572
+ limit : ParentLimit < ' _ > ,
1573
+ block : BlockNumber ,
1574
+ out : & mut AstPass < Pg > ,
1575
+ ) -> QueryResult < ( ) > {
1576
+ // Generate
1577
+ // select c.*, p.id as parent_id
1578
+ // from rows from (unnest({parent_ids}), unnest({child_ids})) as p(id, child_id)
1579
+ // cross join lateral
1580
+ // (select *
1581
+ // from children c
1582
+ // where c.id = p.child_id
1583
+ // and .. other conditions on c ..
1584
+ // order by c.{sort_key}
1585
+ // limit {first} offset {skip}) c
1586
+ // order by c.{sort_key}
1587
+
1588
+ out. push_sql ( "\n from unnest(" ) ;
1589
+ out. push_bind_param :: < Array < Text > , _ > ( & self . ids ) ?;
1590
+ out. push_sql ( "," ) ;
1591
+ self . table . primary_key ( ) . bind_ids ( & child_ids, out) ?;
1592
+ out. push_sql ( ") as p(id, child_id)" ) ;
1593
+ out. push_sql ( " cross join lateral (select * from " ) ;
1594
+ out. push_sql ( self . table . qualified_name . as_str ( ) ) ;
1595
+ out. push_sql ( " c where " ) ;
1596
+ BlockRangeContainsClause :: new ( "c." , block) . walk_ast ( out. reborrow ( ) ) ?;
1597
+ limit. filter ( out) ;
1598
+ out. push_sql ( " and " ) ;
1599
+ out. push_sql ( "c.id = p.child_id" ) ;
1600
+ self . and_filter ( out. reborrow ( ) ) ?;
1601
+ limit. restrict ( out) ?;
1602
+ out. push_sql ( ") c" ) ;
1603
+ Ok ( ( ) )
1604
+ }
1605
+
1606
+ fn children (
1607
+ & self ,
1608
+ limit : ParentLimit < ' _ > ,
1609
+ block : BlockNumber ,
1610
+ mut out : AstPass < Pg > ,
1611
+ ) -> QueryResult < ( ) > {
1612
+ match & self . link {
1613
+ TableLink :: Direct ( column) => {
1614
+ if column. is_list ( ) {
1615
+ self . children_type_a ( column, limit, block, & mut out)
1616
+ } else {
1617
+ self . children_type_b ( column, limit, block, & mut out)
1618
+ }
1619
+ }
1620
+ TableLink :: Parent ( ParentIds :: List ( child_ids) ) => {
1621
+ self . children_type_c ( child_ids, limit, block, & mut out)
1622
+ }
1623
+ TableLink :: Parent ( ParentIds :: Scalar ( child_ids) ) => {
1624
+ self . children_type_d ( child_ids, limit, block, & mut out)
1625
+ }
1626
+ }
1627
+ }
1628
+
1541
1629
/// Select a basic subset of columns from the child table for use in
1542
1630
/// the `matches` CTE of queries that need to retrieve entities of
1543
1631
/// different types or entities that link differently to their parents
0 commit comments