fixed proxy references without null option not being treated as proxies
This commit is contained in:
@ -351,6 +351,7 @@ The Queryer transforms Postgres into a pre-compiled Semantic Query Engine, desig
|
|||||||
* **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.
|
* **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.
|
* **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.
|
||||||
* **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.
|
* **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.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@ -211,6 +211,13 @@
|
|||||||
"gender": {},
|
"gender": {},
|
||||||
"gender.condition": {
|
"gender.condition": {
|
||||||
"type": "condition",
|
"type": "condition",
|
||||||
|
"compiledPropertyNames": [
|
||||||
|
"kind",
|
||||||
|
"$eq",
|
||||||
|
"$ne",
|
||||||
|
"$of",
|
||||||
|
"$nof"
|
||||||
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"$eq": {
|
"$eq": {
|
||||||
"type": [
|
"type": [
|
||||||
@ -224,15 +231,6 @@
|
|||||||
"null"
|
"null"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"$of": {
|
|
||||||
"type": [
|
|
||||||
"array",
|
|
||||||
"null"
|
|
||||||
],
|
|
||||||
"items": {
|
|
||||||
"type": "gender"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"$nof": {
|
"$nof": {
|
||||||
"type": [
|
"type": [
|
||||||
"array",
|
"array",
|
||||||
@ -241,158 +239,20 @@
|
|||||||
"items": {
|
"items": {
|
||||||
"type": "gender"
|
"type": "gender"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"$of": {
|
||||||
|
"type": [
|
||||||
|
"array",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"items": {
|
||||||
|
"type": "gender"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"compiledPropertyNames": [
|
|
||||||
"kind",
|
|
||||||
"$eq",
|
|
||||||
"$ne",
|
|
||||||
"$of",
|
|
||||||
"$nof"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"person": {},
|
"person": {},
|
||||||
"person.filter": {
|
"person.filter": {
|
||||||
"type": "filter",
|
|
||||||
"properties": {
|
|
||||||
"first_name": {
|
|
||||||
"type": [
|
|
||||||
"string.condition",
|
|
||||||
"null"
|
|
||||||
],
|
|
||||||
"compiledPropertyNames": [
|
|
||||||
"kind",
|
|
||||||
"$eq"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"age": {
|
|
||||||
"type": [
|
|
||||||
"integer.condition",
|
|
||||||
"null"
|
|
||||||
],
|
|
||||||
"compiledPropertyNames": [
|
|
||||||
"kind",
|
|
||||||
"$eq"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"billing_address": {
|
|
||||||
"type": [
|
|
||||||
"address.filter",
|
|
||||||
"null"
|
|
||||||
],
|
|
||||||
"compiledPropertyNames": [
|
|
||||||
"city",
|
|
||||||
"$and",
|
|
||||||
"$or"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"gender": {
|
|
||||||
"type": [
|
|
||||||
"gender.condition",
|
|
||||||
"null"
|
|
||||||
],
|
|
||||||
"compiledPropertyNames": [
|
|
||||||
"kind",
|
|
||||||
"$eq",
|
|
||||||
"$ne",
|
|
||||||
"$of",
|
|
||||||
"$nof"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"birth_date": {
|
|
||||||
"type": [
|
|
||||||
"date.condition",
|
|
||||||
"null"
|
|
||||||
],
|
|
||||||
"compiledPropertyNames": [
|
|
||||||
"kind",
|
|
||||||
"$eq"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"uuid_field": {
|
|
||||||
"type": [
|
|
||||||
"uuid.condition",
|
|
||||||
"null"
|
|
||||||
],
|
|
||||||
"compiledPropertyNames": [
|
|
||||||
"kind",
|
|
||||||
"$eq"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"tags": {
|
|
||||||
"type": [
|
|
||||||
"string.condition",
|
|
||||||
"null"
|
|
||||||
],
|
|
||||||
"compiledPropertyNames": [
|
|
||||||
"kind",
|
|
||||||
"$eq"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"ad_hoc": {
|
|
||||||
"type": [
|
|
||||||
"filter",
|
|
||||||
"null"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"foo": {
|
|
||||||
"type": [
|
|
||||||
"string.condition",
|
|
||||||
"null"
|
|
||||||
],
|
|
||||||
"compiledPropertyNames": [
|
|
||||||
"kind",
|
|
||||||
"$eq"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compiledPropertyNames": [
|
|
||||||
"foo"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"$and": {
|
|
||||||
"type": [
|
|
||||||
"array",
|
|
||||||
"null"
|
|
||||||
],
|
|
||||||
"items": {
|
|
||||||
"type": "person.filter",
|
|
||||||
"compiledPropertyNames": [
|
|
||||||
"first_name",
|
|
||||||
"age",
|
|
||||||
"billing_address",
|
|
||||||
"gender",
|
|
||||||
"birth_date",
|
|
||||||
"uuid_field",
|
|
||||||
"tags",
|
|
||||||
"ad_hoc",
|
|
||||||
"$and",
|
|
||||||
"$or"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"$or": {
|
|
||||||
"type": [
|
|
||||||
"array",
|
|
||||||
"null"
|
|
||||||
],
|
|
||||||
"items": {
|
|
||||||
"type": "person.filter",
|
|
||||||
"compiledPropertyNames": [
|
|
||||||
"first_name",
|
|
||||||
"age",
|
|
||||||
"billing_address",
|
|
||||||
"gender",
|
|
||||||
"birth_date",
|
|
||||||
"uuid_field",
|
|
||||||
"tags",
|
|
||||||
"ad_hoc",
|
|
||||||
"$and",
|
|
||||||
"$or"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compiledPropertyNames": [
|
"compiledPropertyNames": [
|
||||||
"first_name",
|
"first_name",
|
||||||
"age",
|
"age",
|
||||||
@ -404,34 +264,133 @@
|
|||||||
"ad_hoc",
|
"ad_hoc",
|
||||||
"$and",
|
"$and",
|
||||||
"$or"
|
"$or"
|
||||||
]
|
],
|
||||||
|
"properties": {
|
||||||
|
"$and": {
|
||||||
|
"items": {
|
||||||
|
"compiledPropertyNames": [
|
||||||
|
"first_name",
|
||||||
|
"age",
|
||||||
|
"billing_address",
|
||||||
|
"gender",
|
||||||
|
"birth_date",
|
||||||
|
"uuid_field",
|
||||||
|
"tags",
|
||||||
|
"ad_hoc",
|
||||||
|
"$and",
|
||||||
|
"$or"
|
||||||
|
],
|
||||||
|
"type": "person.filter"
|
||||||
|
},
|
||||||
|
"type": [
|
||||||
|
"array",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"$or": {
|
||||||
|
"items": {
|
||||||
|
"compiledPropertyNames": [
|
||||||
|
"first_name",
|
||||||
|
"age",
|
||||||
|
"billing_address",
|
||||||
|
"gender",
|
||||||
|
"birth_date",
|
||||||
|
"uuid_field",
|
||||||
|
"tags",
|
||||||
|
"ad_hoc",
|
||||||
|
"$and",
|
||||||
|
"$or"
|
||||||
|
],
|
||||||
|
"type": "person.filter"
|
||||||
|
},
|
||||||
|
"type": [
|
||||||
|
"array",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ad_hoc": {
|
||||||
|
"compiledPropertyNames": [
|
||||||
|
"foo"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"foo": {
|
||||||
|
"type": [
|
||||||
|
"string.condition",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": [
|
||||||
|
"filter",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"age": {
|
||||||
|
"type": [
|
||||||
|
"integer.condition",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"billing_address": {
|
||||||
|
"type": [
|
||||||
|
"address.filter",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"birth_date": {
|
||||||
|
"type": [
|
||||||
|
"date.condition",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"uuid_field": {
|
||||||
|
"type": [
|
||||||
|
"uuid.condition",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"first_name": {
|
||||||
|
"type": [
|
||||||
|
"string.condition",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"gender": {
|
||||||
|
"type": [
|
||||||
|
"gender.condition",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"tags": {
|
||||||
|
"type": [
|
||||||
|
"string.condition",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "filter"
|
||||||
},
|
},
|
||||||
"address": {},
|
"address": {},
|
||||||
"address.filter": {
|
"address.filter": {
|
||||||
"type": "filter",
|
"type": "filter",
|
||||||
|
"compiledPropertyNames": [
|
||||||
|
"city",
|
||||||
|
"$and",
|
||||||
|
"$or"
|
||||||
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"city": {
|
|
||||||
"type": [
|
|
||||||
"string.condition",
|
|
||||||
"null"
|
|
||||||
],
|
|
||||||
"compiledPropertyNames": [
|
|
||||||
"kind",
|
|
||||||
"$eq"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"$and": {
|
"$and": {
|
||||||
"type": [
|
"type": [
|
||||||
"array",
|
"array",
|
||||||
"null"
|
"null"
|
||||||
],
|
],
|
||||||
"items": {
|
"items": {
|
||||||
"type": "address.filter",
|
|
||||||
"compiledPropertyNames": [
|
"compiledPropertyNames": [
|
||||||
"city",
|
"city",
|
||||||
"$and",
|
"$and",
|
||||||
"$or"
|
"$or"
|
||||||
]
|
],
|
||||||
|
"type": "address.filter"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"$or": {
|
"$or": {
|
||||||
@ -440,20 +399,21 @@
|
|||||||
"null"
|
"null"
|
||||||
],
|
],
|
||||||
"items": {
|
"items": {
|
||||||
"type": "address.filter",
|
|
||||||
"compiledPropertyNames": [
|
"compiledPropertyNames": [
|
||||||
"city",
|
"city",
|
||||||
"$and",
|
"$and",
|
||||||
"$or"
|
"$or"
|
||||||
]
|
],
|
||||||
|
"type": "address.filter"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"city": {
|
||||||
|
"type": [
|
||||||
|
"string.condition",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"compiledPropertyNames": [
|
|
||||||
"city",
|
|
||||||
"$and",
|
|
||||||
"$or"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"condition": {},
|
"condition": {},
|
||||||
"filter": {},
|
"filter": {},
|
||||||
@ -464,47 +424,28 @@
|
|||||||
"search": {},
|
"search": {},
|
||||||
"search.filter": {
|
"search.filter": {
|
||||||
"type": "filter",
|
"type": "filter",
|
||||||
|
"compiledPropertyNames": [
|
||||||
|
"kind",
|
||||||
|
"name",
|
||||||
|
"filter",
|
||||||
|
"$and",
|
||||||
|
"$or"
|
||||||
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"kind": {
|
|
||||||
"type": [
|
|
||||||
"string.condition",
|
|
||||||
"null"
|
|
||||||
],
|
|
||||||
"compiledPropertyNames": [
|
|
||||||
"kind",
|
|
||||||
"$eq"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"type": [
|
|
||||||
"string.condition",
|
|
||||||
"null"
|
|
||||||
],
|
|
||||||
"compiledPropertyNames": [
|
|
||||||
"kind",
|
|
||||||
"$eq"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"filter": {
|
|
||||||
"type": [
|
|
||||||
"$kind.filter",
|
|
||||||
"null"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"$and": {
|
"$and": {
|
||||||
"type": [
|
"type": [
|
||||||
"array",
|
"array",
|
||||||
"null"
|
"null"
|
||||||
],
|
],
|
||||||
"items": {
|
"items": {
|
||||||
"type": "search.filter",
|
|
||||||
"compiledPropertyNames": [
|
"compiledPropertyNames": [
|
||||||
"kind",
|
"kind",
|
||||||
"name",
|
"name",
|
||||||
"filter",
|
"filter",
|
||||||
"$and",
|
"$and",
|
||||||
"$or"
|
"$or"
|
||||||
]
|
],
|
||||||
|
"type": "search.filter"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"$or": {
|
"$or": {
|
||||||
@ -513,24 +454,35 @@
|
|||||||
"null"
|
"null"
|
||||||
],
|
],
|
||||||
"items": {
|
"items": {
|
||||||
"type": "search.filter",
|
|
||||||
"compiledPropertyNames": [
|
"compiledPropertyNames": [
|
||||||
"kind",
|
"kind",
|
||||||
"name",
|
"name",
|
||||||
"filter",
|
"filter",
|
||||||
"$and",
|
"$and",
|
||||||
"$or"
|
"$or"
|
||||||
]
|
],
|
||||||
|
"type": "search.filter"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"filter": {
|
||||||
|
"type": [
|
||||||
|
"$kind.filter",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"kind": {
|
||||||
|
"type": [
|
||||||
|
"string.condition",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": [
|
||||||
|
"string.condition",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"compiledPropertyNames": [
|
|
||||||
"kind",
|
|
||||||
"name",
|
|
||||||
"filter",
|
|
||||||
"$and",
|
|
||||||
"$or"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2547,10 +2547,7 @@
|
|||||||
"type": "pet",
|
"type": "pet",
|
||||||
"properties": {
|
"properties": {
|
||||||
"cover_attachment": {
|
"cover_attachment": {
|
||||||
"type": [
|
"type": "attachment",
|
||||||
"attachment",
|
|
||||||
"null"
|
|
||||||
],
|
|
||||||
"properties": {
|
"properties": {
|
||||||
"kind": {
|
"kind": {
|
||||||
"const": "cover"
|
"const": "cover"
|
||||||
|
|||||||
@ -29,21 +29,10 @@ impl Schema {
|
|||||||
if db.types.contains_key(&base_type_name) {
|
if db.types.contains_key(&base_type_name) {
|
||||||
parent_type_name = Some(base_type_name);
|
parent_type_name = Some(base_type_name);
|
||||||
}
|
}
|
||||||
} else if let Some(t_or_arr) = &self.obj.type_ {
|
} else if let Some(crate::database::object::SchemaTypeOrArray::Single(t)) = &self.obj.type_ {
|
||||||
match t_or_arr {
|
// 3. Nested graphs trust their explicit struct pointer reference
|
||||||
crate::database::object::SchemaTypeOrArray::Single(t) => {
|
if !crate::database::object::is_primitive_type(t) {
|
||||||
if !crate::database::object::is_primitive_type(t) {
|
parent_type_name = Some(t.split('.').next_back().unwrap_or(t).to_string());
|
||||||
parent_type_name = Some(t.split('.').next_back().unwrap_or(t).to_string());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
crate::database::object::SchemaTypeOrArray::Multiple(types) => {
|
|
||||||
for t in types {
|
|
||||||
if !crate::database::object::is_primitive_type(t) {
|
|
||||||
parent_type_name = Some(t.split('.').next_back().unwrap_or(t).to_string());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,23 +46,13 @@ impl Schema {
|
|||||||
let mut is_array = false;
|
let mut is_array = false;
|
||||||
|
|
||||||
// Structurally unpack the inner target entity if the object maps to an array list
|
// Structurally unpack the inner target entity if the object maps to an array list
|
||||||
if let Some(t_or_arr) = &prop_schema.obj.type_ {
|
if let Some(crate::database::object::SchemaTypeOrArray::Single(t)) =
|
||||||
match t_or_arr {
|
&prop_schema.obj.type_
|
||||||
crate::database::object::SchemaTypeOrArray::Single(t) => {
|
{
|
||||||
if t == "array" {
|
if t == "array" {
|
||||||
is_array = true;
|
is_array = true;
|
||||||
if let Some(items) = &prop_schema.obj.items {
|
if let Some(items) = &prop_schema.obj.items {
|
||||||
target_schema = items.clone();
|
target_schema = items.clone();
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
crate::database::object::SchemaTypeOrArray::Multiple(types) => {
|
|
||||||
if types.contains(&"array".to_string()) {
|
|
||||||
is_array = true;
|
|
||||||
if let Some(items) = &prop_schema.obj.items {
|
|
||||||
target_schema = items.clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -81,21 +60,11 @@ impl Schema {
|
|||||||
// Determine the physical Postgres table backing the nested child schema recursively
|
// Determine the physical Postgres table backing the nested child schema recursively
|
||||||
if let Some(family) = &target_schema.obj.family {
|
if let Some(family) = &target_schema.obj.family {
|
||||||
child_type_name = Some(family.split('.').next_back().unwrap_or(family).to_string());
|
child_type_name = Some(family.split('.').next_back().unwrap_or(family).to_string());
|
||||||
} else if let Some(t_or_arr) = &target_schema.obj.type_ {
|
} else if let Some(crate::database::object::SchemaTypeOrArray::Single(t)) =
|
||||||
match t_or_arr {
|
&target_schema.obj.type_
|
||||||
crate::database::object::SchemaTypeOrArray::Single(t) => {
|
{
|
||||||
if !crate::database::object::is_primitive_type(t) {
|
if !crate::database::object::is_primitive_type(t) {
|
||||||
child_type_name = Some(t.split('.').next_back().unwrap_or(t).to_string());
|
child_type_name = Some(t.split('.').next_back().unwrap_or(t).to_string());
|
||||||
}
|
|
||||||
}
|
|
||||||
crate::database::object::SchemaTypeOrArray::Multiple(types) => {
|
|
||||||
for t in types {
|
|
||||||
if !crate::database::object::is_primitive_type(t) {
|
|
||||||
child_type_name = Some(t.split('.').next_back().unwrap_or(t).to_string());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if let Some(arr) = &target_schema.obj.one_of {
|
} else if let Some(arr) = &target_schema.obj.one_of {
|
||||||
if let Some(first) = arr.first() {
|
if let Some(first) = arr.first() {
|
||||||
|
|||||||
@ -40,7 +40,6 @@ impl Schema {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut props = IndexMap::new();
|
let mut props = IndexMap::new();
|
||||||
let mut inherited_edges = IndexMap::new();
|
|
||||||
|
|
||||||
// 1. Resolve INHERITANCE dependencies first
|
// 1. Resolve INHERITANCE dependencies first
|
||||||
if let Some(crate::database::object::SchemaTypeOrArray::Single(t)) = &self.obj.type_ {
|
if let Some(crate::database::object::SchemaTypeOrArray::Single(t)) = &self.obj.type_ {
|
||||||
@ -50,9 +49,6 @@ impl Schema {
|
|||||||
if let Some(p_props) = parent.obj.compiled_properties.get() {
|
if let Some(p_props) = parent.obj.compiled_properties.get() {
|
||||||
props.extend(p_props.clone());
|
props.extend(p_props.clone());
|
||||||
}
|
}
|
||||||
if let Some(p_edges) = parent.obj.compiled_edges.get() {
|
|
||||||
inherited_edges.extend(p_edges.clone());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -81,12 +77,6 @@ impl Schema {
|
|||||||
if !crate::database::object::is_primitive_type(t) && !t.starts_with('$') {
|
if !crate::database::object::is_primitive_type(t) && !t.starts_with('$') {
|
||||||
if let Some(parent) = db.schemas.get(t).cloned() {
|
if let Some(parent) = db.schemas.get(t).cloned() {
|
||||||
parent.as_ref().compile(db, t, t.clone(), errors);
|
parent.as_ref().compile(db, t, t.clone(), errors);
|
||||||
if let Some(p_props) = parent.obj.compiled_properties.get() {
|
|
||||||
props.extend(p_props.clone());
|
|
||||||
}
|
|
||||||
if let Some(p_edges) = parent.obj.compiled_edges.get() {
|
|
||||||
inherited_edges.extend(p_edges.clone());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -126,10 +116,7 @@ impl Schema {
|
|||||||
let _ = self.obj.compiled_property_names.set(names);
|
let _ = self.obj.compiled_property_names.set(names);
|
||||||
|
|
||||||
// 5. Compute Edges natively
|
// 5. Compute Edges natively
|
||||||
let mut schema_edges = self.compile_edges(db, root_id, &path, &props, errors);
|
let schema_edges = self.compile_edges(db, root_id, &path, &props, errors);
|
||||||
for (k, v) in inherited_edges {
|
|
||||||
schema_edges.entry(k).or_insert(v);
|
|
||||||
}
|
|
||||||
let _ = self.obj.compiled_edges.set(schema_edges);
|
let _ = self.obj.compiled_edges.set(schema_edges);
|
||||||
|
|
||||||
// 5. Build our inline children properties recursively NOW! (Depth-first search)
|
// 5. Build our inline children properties recursively NOW! (Depth-first search)
|
||||||
|
|||||||
@ -87,29 +87,13 @@ impl<'a> Compiler<'a> {
|
|||||||
.next_back()
|
.next_back()
|
||||||
.unwrap_or(family_target);
|
.unwrap_or(family_target);
|
||||||
resolved_type = self.db.types.get(base_type_name);
|
resolved_type = self.db.types.get(base_type_name);
|
||||||
} else if let Some(t_or_arr) = &items.obj.type_ {
|
} else if let Some(crate::database::object::SchemaTypeOrArray::Single(t)) = &items.obj.type_
|
||||||
match t_or_arr {
|
{
|
||||||
crate::database::object::SchemaTypeOrArray::Single(t) => {
|
if !crate::database::object::is_primitive_type(t) {
|
||||||
if !crate::database::object::is_primitive_type(t) {
|
resolved_type = self
|
||||||
resolved_type = self
|
.db
|
||||||
.db
|
.types
|
||||||
.types
|
.get(&t.split('.').next_back().unwrap_or(t).to_string());
|
||||||
.get(&t.split('.').next_back().unwrap_or(t).to_string());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
crate::database::object::SchemaTypeOrArray::Multiple(types) => {
|
|
||||||
for t in types {
|
|
||||||
if !crate::database::object::is_primitive_type(t) {
|
|
||||||
resolved_type = self
|
|
||||||
.db
|
|
||||||
.types
|
|
||||||
.get(&t.split('.').next_back().unwrap_or(t).to_string());
|
|
||||||
if resolved_type.is_some() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -137,6 +121,21 @@ impl<'a> Compiler<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn compile_reference(&mut self, node: Node<'a>) -> Result<(String, String), String> {
|
fn compile_reference(&mut self, node: Node<'a>) -> Result<(String, String), String> {
|
||||||
|
// Handle Direct Refs via type pointer first
|
||||||
|
if let Some(crate::database::object::SchemaTypeOrArray::Single(t)) = &node.schema.obj.type_ {
|
||||||
|
if !crate::database::object::is_primitive_type(t) {
|
||||||
|
if !self.db.types.contains_key(t) {
|
||||||
|
// If it's just an ad-hoc struct ref, we should resolve it
|
||||||
|
if let Some(target_schema) = self.db.schemas.get(t).cloned() {
|
||||||
|
let mut ref_node = node.clone();
|
||||||
|
ref_node.schema = target_schema.clone();
|
||||||
|
ref_node.schema_id = Some(t.clone());
|
||||||
|
return self.compile_node(ref_node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Determine if this schema represents a Database Entity
|
// Determine if this schema represents a Database Entity
|
||||||
let mut resolved_type = None;
|
let mut resolved_type = None;
|
||||||
|
|
||||||
@ -152,25 +151,12 @@ impl<'a> Compiler<'a> {
|
|||||||
.next_back()
|
.next_back()
|
||||||
.unwrap_or(family_target);
|
.unwrap_or(family_target);
|
||||||
resolved_type = self.db.types.get(base_type_name);
|
resolved_type = self.db.types.get(base_type_name);
|
||||||
} else if let Some(t_or_arr) = &node.schema.obj.type_ {
|
} else if let Some(crate::database::object::SchemaTypeOrArray::Single(t)) =
|
||||||
match t_or_arr {
|
&node.schema.obj.type_
|
||||||
crate::database::object::SchemaTypeOrArray::Single(t) => {
|
{
|
||||||
if !crate::database::object::is_primitive_type(t) {
|
if !crate::database::object::is_primitive_type(t) {
|
||||||
let base_type_name = t.split('.').next_back().unwrap_or(t).to_string();
|
let base_type_name = t.split('.').next_back().unwrap_or(t).to_string();
|
||||||
resolved_type = self.db.types.get(&base_type_name);
|
resolved_type = self.db.types.get(&base_type_name);
|
||||||
}
|
|
||||||
}
|
|
||||||
crate::database::object::SchemaTypeOrArray::Multiple(types) => {
|
|
||||||
for t in types {
|
|
||||||
if !crate::database::object::is_primitive_type(t) {
|
|
||||||
let base_type_name = t.split('.').next_back().unwrap_or(t).to_string();
|
|
||||||
resolved_type = self.db.types.get(&base_type_name);
|
|
||||||
if resolved_type.is_some() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -179,16 +165,9 @@ impl<'a> Compiler<'a> {
|
|||||||
return self.compile_entity(type_def, node.clone(), false);
|
return self.compile_entity(type_def, node.clone(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle Direct Refs via type pointer
|
// Fallback error if the schema pointer was unresolved
|
||||||
if let Some(crate::database::object::SchemaTypeOrArray::Single(t)) = &node.schema.obj.type_ {
|
if let Some(crate::database::object::SchemaTypeOrArray::Single(t)) = &node.schema.obj.type_ {
|
||||||
if !crate::database::object::is_primitive_type(t) {
|
if !crate::database::object::is_primitive_type(t) {
|
||||||
// If it's just an ad-hoc struct ref, we should resolve it
|
|
||||||
if let Some(target_schema) = self.db.schemas.get(t).cloned() {
|
|
||||||
let mut ref_node = node.clone();
|
|
||||||
ref_node.schema = target_schema.clone();
|
|
||||||
ref_node.schema_id = Some(t.clone());
|
|
||||||
return self.compile_node(ref_node);
|
|
||||||
}
|
|
||||||
return Err(format!("Unresolved schema type pointer: {}", t));
|
return Err(format!("Unresolved schema type pointer: {}", t));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -469,9 +448,6 @@ impl<'a> Compiler<'a> {
|
|||||||
Some(crate::database::object::SchemaTypeOrArray::Single(s)) => {
|
Some(crate::database::object::SchemaTypeOrArray::Single(s)) => {
|
||||||
!crate::database::object::is_primitive_type(s)
|
!crate::database::object::is_primitive_type(s)
|
||||||
}
|
}
|
||||||
Some(crate::database::object::SchemaTypeOrArray::Multiple(v)) => {
|
|
||||||
v.iter().any(|s| !crate::database::object::is_primitive_type(s))
|
|
||||||
}
|
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -157,10 +157,7 @@ fn test_library_api() {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"name": { "type": ["string.condition", "null"] },
|
"name": { "type": ["string.condition", "null"] },
|
||||||
"target": {
|
"target": { "type": ["target_schema.filter", "null"] },
|
||||||
"type": ["target_schema.filter", "null"],
|
|
||||||
"compiledPropertyNames": ["value", "$and", "$or"]
|
|
||||||
},
|
|
||||||
"type": { "type": ["string.condition", "null"] }
|
"type": { "type": ["string.condition", "null"] }
|
||||||
},
|
},
|
||||||
"type": "filter"
|
"type": "filter"
|
||||||
|
|||||||
Reference in New Issue
Block a user