added alias names to lookup queries for merger
This commit is contained in:
@ -374,6 +374,7 @@ The Queryer transforms Postgres into a pre-compiled Semantic Query Engine, desig
|
||||
* **Multi-Table Branching**: If the Physical Table is a parent to other tables (e.g. `organization` has variations `["organization", "bot", "person"]`), the compiler generates a dynamic `CASE WHEN type = '...' THEN ...` query, expanding into sub-queries for each variation. To ensure safe resolution, the compiler dynamically evaluates correlation boundaries: it attempts standard Relational Edge discovery first. If no explicit relational edge exists (indicating pure Table Inheritance rather than a standard foreign-key graph relationship), it safely invokes a **Table Parity Fallback**. This generates an explicit ID correlation constraint (`AND inner.id = outer.id`), perfectly binding the structural variations back to the parent row to eliminate Cartesian products.
|
||||
* **Single-Table Bypass**: If the Physical Table is a leaf node with only one variation (e.g. `person` has variations `["person"]`), the compiler cleanly bypasses `CASE` generation and compiles a simple `SELECT` across the base table, as all schema extensions (e.g. `light.person`, `full.person`) are guaranteed to reside in the exact same physical row.
|
||||
* **Polymorphic Relation Type Filtering**: When a relationship maps to a polymorphic target with variations, the Queryer compiles an `IN` clause containing all allowed table variations (e.g., `counterparty_type IN ('bot', 'organization', 'person')`) rather than matching the base type literal, ensuring all polymorphic types are loaded correctly.
|
||||
* **Tenant Scoping & ReBAC Filtering**: When `jspg_query` compiles root-level or relationship-level entity queries, the generated SQL queries evaluate within the calling PostgreSQL transaction's session configuration (e.g. `auth.organization_ids`, `auth.roles`). The compiled queries seamlessly interact with PostgreSQL Row Level Security (RLS) policies on base tables (such as `agreego.entity`) and pre-materialized Zanzibar graph edges (`agreego.relationship`), ensuring multi-tenant isolation and $O(1)$ query evaluation without requiring manual WHERE scoping logic across every application punc.
|
||||
* **Static Relation Constraints (Kind Constraints)**: When a relationship (such as a nested object or array) is defined with a schema that constrains a field value statically using a `const` or `enum` keyword (for example, `kind` constrained to `"cover"` in a `cover_attachment`), the Queryer automatically extracts these static assertions during AST compilation. It injects them directly as static filters into the SQL subquery's `WHERE` clause (e.g. `AND attachment.kind = 'cover'`), allowing developers to query pre-filtered subsets of related tables natively through the schema.
|
||||
* **Proxy Schema Dereferencing / Resolution**: To support punc endpoints that return non-polymorphic table-backed shapes (using `type: "full.X"` proxy schemas at the root response level), the Queryer compiler automatically dereferences non-table schema pointers to their target schemas prior to checking the types. This allows the Queryer to correctly resolve the table relationship edges pre-compiled on the full schema, while avoiding polluting the database registry with relations on ad-hoc punc response schemas during setup.
|
||||
|
||||
|
||||
@ -1357,10 +1357,10 @@
|
||||
"LEFT JOIN agreego.\"user\" t3 ON t3.id = t1.id",
|
||||
"LEFT JOIN agreego.\"person\" t4 ON t4.id = t1.id",
|
||||
"WHERE",
|
||||
" (\"first_name\" = 'LookupFirst'",
|
||||
" AND \"last_name\" = 'LookupLast'",
|
||||
" AND \"date_of_birth\" = '{{timestamp}}'",
|
||||
" AND \"pronouns\" = 'they/them'))"
|
||||
" (t4.\"first_name\" = 'LookupFirst'",
|
||||
" AND t4.\"last_name\" = 'LookupLast'",
|
||||
" AND t4.\"date_of_birth\" = '{{timestamp}}'",
|
||||
" AND t4.\"pronouns\" = 'they/them'))"
|
||||
],
|
||||
[
|
||||
"INSERT INTO agreego.\"entity\" (",
|
||||
@ -1521,10 +1521,10 @@
|
||||
"LEFT JOIN agreego.\"user\" t3 ON t3.id = t1.id",
|
||||
"LEFT JOIN agreego.\"person\" t4 ON t4.id = t1.id",
|
||||
"WHERE",
|
||||
" (\"first_name\" = 'LookupFirst'",
|
||||
" AND \"last_name\" = 'LookupLast'",
|
||||
" AND \"date_of_birth\" = '{{timestamp}}'",
|
||||
" AND \"pronouns\" = 'they/them'))"
|
||||
" (t4.\"first_name\" = 'LookupFirst'",
|
||||
" AND t4.\"last_name\" = 'LookupLast'",
|
||||
" AND t4.\"date_of_birth\" = '{{timestamp}}'",
|
||||
" AND t4.\"pronouns\" = 'they/them'))"
|
||||
],
|
||||
[
|
||||
"INSERT INTO agreego.\"entity\" (",
|
||||
@ -1687,17 +1687,17 @@
|
||||
"LEFT JOIN agreego.\"user\" t3 ON t3.id = t1.id",
|
||||
"LEFT JOIN agreego.\"person\" t4 ON t4.id = t1.id",
|
||||
"WHERE",
|
||||
" (\"first_name\" = 'LookupFirst'",
|
||||
" AND \"last_name\" = 'LookupLast'",
|
||||
" AND \"date_of_birth\" = '{{timestamp}}'",
|
||||
" AND \"pronouns\" = 'they/them')",
|
||||
" (t4.\"first_name\" = 'LookupFirst'",
|
||||
" AND t4.\"last_name\" = 'LookupLast'",
|
||||
" AND t4.\"date_of_birth\" = '{{timestamp}}'",
|
||||
" AND t4.\"pronouns\" = 'they/them')",
|
||||
"UNION SELECT COALESCE(to_jsonb(t1.*), '{}') || COALESCE(to_jsonb(t2.*), '{}') || COALESCE(to_jsonb(t3.*), '{}') || COALESCE(to_jsonb(t4.*), '{}')",
|
||||
"FROM agreego.\"entity\" t1",
|
||||
"LEFT JOIN agreego.\"organization\" t2 ON t2.id = t1.id",
|
||||
"LEFT JOIN agreego.\"user\" t3 ON t3.id = t1.id",
|
||||
"LEFT JOIN agreego.\"person\" t4 ON t4.id = t1.id",
|
||||
"WHERE",
|
||||
" (\"name\" = 'LookupName'))"
|
||||
" (t3.\"name\" = 'LookupName'))"
|
||||
],
|
||||
[
|
||||
"INSERT INTO agreego.\"entity\" (",
|
||||
@ -1862,10 +1862,10 @@
|
||||
"LEFT JOIN agreego.\"user\" t3 ON t3.id = t1.id",
|
||||
"LEFT JOIN agreego.\"person\" t4 ON t4.id = t1.id",
|
||||
"WHERE",
|
||||
" (\"first_name\" = 'LookupFirst'",
|
||||
" AND \"last_name\" = 'LookupLast'",
|
||||
" AND \"date_of_birth\" = '{{timestamp}}'",
|
||||
" AND \"pronouns\" = 'they/them'))"
|
||||
" (t4.\"first_name\" = 'LookupFirst'",
|
||||
" AND t4.\"last_name\" = 'LookupLast'",
|
||||
" AND t4.\"date_of_birth\" = '{{timestamp}}'",
|
||||
" AND t4.\"pronouns\" = 'they/them'))"
|
||||
],
|
||||
[
|
||||
"INSERT INTO agreego.\"entity\" (",
|
||||
@ -2796,10 +2796,10 @@
|
||||
"LEFT JOIN agreego.\"relationship\" t2 ON t2.id = t1.id",
|
||||
"LEFT JOIN agreego.\"contact\" t3 ON t3.id = t1.id",
|
||||
"WHERE",
|
||||
" (t1.\"type\" = 'contact'",
|
||||
" AND \"source_id\" = '{{uuid:generated_0}}'",
|
||||
" AND \"target_id\" = '{{uuid:generated_1}}'",
|
||||
" AND \"start_date\" = '{{timestamp}}'))"
|
||||
" (t2.\"type\" = 'contact'",
|
||||
" AND t2.\"source_id\" = '{{uuid:generated_0}}'",
|
||||
" AND t2.\"target_id\" = '{{uuid:generated_1}}'",
|
||||
" AND t2.\"start_date\" = '{{timestamp}}'))"
|
||||
],
|
||||
[
|
||||
"INSERT INTO agreego.\"entity\" (",
|
||||
@ -2928,10 +2928,10 @@
|
||||
"LEFT JOIN agreego.\"relationship\" t2 ON t2.id = t1.id",
|
||||
"LEFT JOIN agreego.\"contact\" t3 ON t3.id = t1.id",
|
||||
"WHERE",
|
||||
" (t1.\"type\" = 'contact'",
|
||||
" AND \"source_id\" = '{{uuid:generated_0}}'",
|
||||
" AND \"target_id\" = '{{uuid:generated_5}}'",
|
||||
" AND \"start_date\" = '{{timestamp}}'))"
|
||||
" (t2.\"type\" = 'contact'",
|
||||
" AND t2.\"source_id\" = '{{uuid:generated_0}}'",
|
||||
" AND t2.\"target_id\" = '{{uuid:generated_5}}'",
|
||||
" AND t2.\"start_date\" = '{{timestamp}}'))"
|
||||
],
|
||||
[
|
||||
"INSERT INTO agreego.\"entity\" (",
|
||||
@ -3060,10 +3060,10 @@
|
||||
"LEFT JOIN agreego.\"relationship\" t2 ON t2.id = t1.id",
|
||||
"LEFT JOIN agreego.\"contact\" t3 ON t3.id = t1.id",
|
||||
"WHERE",
|
||||
" (t1.\"type\" = 'contact'",
|
||||
" AND \"source_id\" = '{{uuid:generated_0}}'",
|
||||
" AND \"target_id\" = '{{uuid:generated_9}}'",
|
||||
" AND \"start_date\" = '{{timestamp}}'))"
|
||||
" (t2.\"type\" = 'contact'",
|
||||
" AND t2.\"source_id\" = '{{uuid:generated_0}}'",
|
||||
" AND t2.\"target_id\" = '{{uuid:generated_9}}'",
|
||||
" AND t2.\"start_date\" = '{{timestamp}}'))"
|
||||
],
|
||||
[
|
||||
"INSERT INTO agreego.\"entity\" (",
|
||||
|
||||
@ -818,17 +818,20 @@ impl Merger {
|
||||
}
|
||||
|
||||
for (lookup_fields, parent_type) in lookup_satisfied_keys {
|
||||
let t_alias = entity_type
|
||||
.hierarchy
|
||||
.iter()
|
||||
.position(|name| name == &parent_type.name)
|
||||
.map(|idx| format!("t{}", idx + 1))
|
||||
.unwrap_or_else(|| "t1".to_string());
|
||||
|
||||
let mut lookup_predicates = Vec::new();
|
||||
for column in lookup_fields {
|
||||
let val = entity_fields
|
||||
.get(column)
|
||||
.or_else(|| parent_type.field_defaults.get(column))
|
||||
.unwrap_or(&Value::Null);
|
||||
if column == "type" {
|
||||
lookup_predicates.push(format!("t1.\"{}\" = {}", column, Self::quote_literal(val)));
|
||||
} else {
|
||||
lookup_predicates.push(format!("\"{}\" = {}", column, Self::quote_literal(val)));
|
||||
}
|
||||
lookup_predicates.push(format!("{}.\"{}\" = {}", t_alias, column, Self::quote_literal(val)));
|
||||
}
|
||||
where_parts.push(format!("({})", lookup_predicates.join(" AND ")));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user