fixing ordering checkpoint

This commit is contained in:
2026-05-14 03:21:12 -04:00
parent 3d918a1acc
commit 3034406706
14 changed files with 89 additions and 85 deletions

1
Cargo.lock generated
View File

@ -1663,6 +1663,7 @@ version = "1.0.149"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
dependencies = [ dependencies = [
"indexmap",
"itoa", "itoa",
"memchr", "memchr",
"serde", "serde",

View File

@ -6,7 +6,7 @@ edition = "2024"
[dependencies] [dependencies]
pgrx = "0.16.1" pgrx = "0.16.1"
serde = { version = "1.0.228", features = ["derive", "rc"] } serde = { version = "1.0.228", features = ["derive", "rc"] }
serde_json = "1.0.149" serde_json = { version = "1.0.149", features = ["preserve_order"] }
lazy_static = "1.5.0" lazy_static = "1.5.0"
once_cell = "1.21.3" once_cell = "1.21.3"
ahash = "0.8.12" ahash = "0.8.12"
@ -30,7 +30,7 @@ pgrx-tests = "0.16.1"
[build-dependencies] [build-dependencies]
serde = { version = "1.0.228", features = ["derive"] } serde = { version = "1.0.228", features = ["derive"] }
serde_json = "1.0.149" serde_json = { version = "1.0.149", features = ["preserve_order"] }
[lib] [lib]
crate-type = ["cdylib", "lib"] crate-type = ["cdylib", "lib"]

View File

@ -197,11 +197,11 @@
"gender.condition": { "gender.condition": {
"type": "condition", "type": "condition",
"compiledPropertyNames": [ "compiledPropertyNames": [
"kind",
"$eq", "$eq",
"$ne", "$ne",
"$nof",
"$of", "$of",
"kind" "$nof"
], ],
"properties": { "properties": {
"$eq": { "$eq": {
@ -239,29 +239,29 @@
"person": {}, "person": {},
"person.filter": { "person.filter": {
"compiledPropertyNames": [ "compiledPropertyNames": [
"$and", "first_name",
"$or",
"ad_hoc",
"age", "age",
"billing_address", "billing_address",
"birth_date",
"first_name",
"gender", "gender",
"tags" "birth_date",
"tags",
"ad_hoc",
"$and",
"$or"
], ],
"properties": { "properties": {
"$and": { "$and": {
"items": { "items": {
"compiledPropertyNames": [ "compiledPropertyNames": [
"$and", "first_name",
"$or",
"ad_hoc",
"age", "age",
"billing_address", "billing_address",
"birth_date",
"first_name",
"gender", "gender",
"tags" "birth_date",
"tags",
"ad_hoc",
"$and",
"$or"
], ],
"type": "person.filter" "type": "person.filter"
}, },
@ -273,15 +273,15 @@
"$or": { "$or": {
"items": { "items": {
"compiledPropertyNames": [ "compiledPropertyNames": [
"$and", "first_name",
"$or",
"ad_hoc",
"age", "age",
"billing_address", "billing_address",
"birth_date",
"first_name",
"gender", "gender",
"tags" "birth_date",
"tags",
"ad_hoc",
"$and",
"$or"
], ],
"type": "person.filter" "type": "person.filter"
}, },
@ -350,9 +350,9 @@
"address.filter": { "address.filter": {
"type": "filter", "type": "filter",
"compiledPropertyNames": [ "compiledPropertyNames": [
"city",
"$and", "$and",
"$or", "$or"
"city"
], ],
"properties": { "properties": {
"$and": { "$and": {
@ -362,9 +362,9 @@
], ],
"items": { "items": {
"compiledPropertyNames": [ "compiledPropertyNames": [
"city",
"$and", "$and",
"$or", "$or"
"city"
], ],
"type": "address.filter" "type": "address.filter"
} }
@ -376,9 +376,9 @@
], ],
"items": { "items": {
"compiledPropertyNames": [ "compiledPropertyNames": [
"city",
"$and", "$and",
"$or", "$or"
"city"
], ],
"type": "address.filter" "type": "address.filter"
} }
@ -400,11 +400,11 @@
"search.filter": { "search.filter": {
"type": "filter", "type": "filter",
"compiledPropertyNames": [ "compiledPropertyNames": [
"$and",
"$or",
"filter",
"kind", "kind",
"name" "name",
"filter",
"$and",
"$or"
], ],
"properties": { "properties": {
"$and": { "$and": {
@ -414,11 +414,11 @@
], ],
"items": { "items": {
"compiledPropertyNames": [ "compiledPropertyNames": [
"$and",
"$or",
"filter",
"kind", "kind",
"name" "name",
"filter",
"$and",
"$or"
], ],
"type": "search.filter" "type": "search.filter"
} }
@ -430,11 +430,11 @@
], ],
"items": { "items": {
"compiledPropertyNames": [ "compiledPropertyNames": [
"$and",
"$or",
"filter",
"kind", "kind",
"name" "name",
"filter",
"$and",
"$or"
], ],
"type": "search.filter" "type": "search.filter"
} }

View File

@ -1258,14 +1258,14 @@
"sql": [ "sql": [
[ [
"(SELECT jsonb_strip_nulls((SELECT jsonb_build_object(", "(SELECT jsonb_strip_nulls((SELECT jsonb_build_object(",
" 'age', person_1.age,",
" 'archived', entity_3.archived,", " 'archived', entity_3.archived,",
" 'created_at', entity_3.created_at,", " 'created_at', entity_3.created_at,",
" 'first_name', person_1.first_name,",
" 'id', entity_3.id,", " 'id', entity_3.id,",
" 'last_name', person_1.last_name,", " 'type', entity_3.type,",
" 'name', organization_2.name,", " 'name', organization_2.name,",
" 'type', entity_3.type)", " 'age', person_1.age,",
" 'first_name', person_1.first_name,",
" 'last_name', person_1.last_name)",
"FROM agreego.person person_1", "FROM agreego.person person_1",
"JOIN agreego.organization organization_2 ON organization_2.id = person_1.id", "JOIN agreego.organization organization_2 ON organization_2.id = person_1.id",
"JOIN agreego.entity entity_3 ON entity_3.id = organization_2.id", "JOIN agreego.entity entity_3 ON entity_3.id = organization_2.id",

View File

@ -1,12 +1,12 @@
use crate::database::object::{SchemaObject, SchemaTypeOrArray}; use crate::database::object::{SchemaObject, SchemaTypeOrArray};
use crate::database::schema::Schema; use crate::database::schema::Schema;
use crate::database::r#enum::Enum; use crate::database::r#enum::Enum;
use std::collections::BTreeMap; use indexmap::IndexMap;
use std::sync::Arc; use std::sync::Arc;
impl Enum { impl Enum {
pub fn compile_condition(&self) -> Schema { pub fn compile_condition(&self) -> Schema {
let mut props = BTreeMap::new(); let mut props = IndexMap::new();
let enum_name = &self.name; let enum_name = &self.name;
let mut eq_obj = SchemaObject::default(); let mut eq_obj = SchemaObject::default();

View File

@ -1,4 +1,5 @@
use crate::database::schema::Schema; use crate::database::schema::Schema;
use indexmap::IndexMap;
impl Schema { impl Schema {
/// Dynamically infers and compiles all structural database relationships between this Schema /// Dynamically infers and compiles all structural database relationships between this Schema
@ -10,10 +11,10 @@ impl Schema {
db: &crate::database::Database, db: &crate::database::Database,
root_id: &str, root_id: &str,
path: &str, path: &str,
props: &std::collections::BTreeMap<String, std::sync::Arc<Schema>>, props: &IndexMap<String, std::sync::Arc<Schema>>,
errors: &mut Vec<crate::drop::Error>, errors: &mut Vec<crate::drop::Error>,
) -> std::collections::BTreeMap<String, crate::database::edge::Edge> { ) -> IndexMap<String, crate::database::edge::Edge> {
let mut schema_edges = std::collections::BTreeMap::new(); let mut schema_edges = IndexMap::new();
// Determine the physical Database Table Name this schema structurally represents // Determine the physical Database Table Name this schema structurally represents
// Plucks the polymorphic discriminator via dot-notation (e.g. extracting "person" from "full.person") // Plucks the polymorphic discriminator via dot-notation (e.g. extracting "person" from "full.person")

View File

@ -1,7 +1,7 @@
use crate::database::Database; use crate::database::Database;
use crate::database::object::{SchemaObject, SchemaTypeOrArray}; use crate::database::object::{SchemaObject, SchemaTypeOrArray};
use crate::database::schema::Schema; use crate::database::schema::Schema;
use std::collections::BTreeMap; use indexmap::IndexMap;
use std::sync::Arc; use std::sync::Arc;
impl Schema { impl Schema {
@ -12,7 +12,7 @@ impl Schema {
_errors: &mut Vec<crate::drop::Error>, _errors: &mut Vec<crate::drop::Error>,
) -> Option<Schema> { ) -> Option<Schema> {
if let Some(props) = self.obj.compiled_properties.get() { if let Some(props) = self.obj.compiled_properties.get() {
let mut filter_props = BTreeMap::new(); let mut filter_props = IndexMap::new();
for (key, child) in props { for (key, child) in props {
let mut structural_filter = None; let mut structural_filter = None;

View File

@ -5,6 +5,7 @@ pub mod filter;
pub mod polymorphism; pub mod polymorphism;
use crate::database::schema::Schema; use crate::database::schema::Schema;
use indexmap::IndexMap;
impl Schema { impl Schema {
pub fn compile( pub fn compile(
@ -48,7 +49,7 @@ impl Schema {
} }
} }
let mut props = std::collections::BTreeMap::new(); let mut props = 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_ {
@ -124,8 +125,7 @@ impl Schema {
// 4. Set the OnceLock! // 4. Set the OnceLock!
let _ = self.obj.compiled_properties.set(props.clone()); let _ = self.obj.compiled_properties.set(props.clone());
let mut names: Vec<String> = props.keys().cloned().collect(); let names: Vec<String> = props.keys().cloned().collect();
names.sort();
let _ = self.obj.compiled_property_names.set(names); let _ = self.obj.compiled_property_names.set(names);
// 5. Compute Edges natively // 5. Compute Edges natively

View File

@ -8,7 +8,7 @@ impl Schema {
path: &str, path: &str,
errors: &mut Vec<crate::drop::Error>, errors: &mut Vec<crate::drop::Error>,
) { ) {
let mut options = std::collections::BTreeMap::new(); let mut options = indexmap::IndexMap::new();
let strategy: &str; let strategy: &str;
if let Some(family) = &self.obj.family { if let Some(family) = &self.obj.family {

View File

@ -23,18 +23,18 @@ use punc::Punc;
use relation::Relation; use relation::Relation;
use schema::Schema; use schema::Schema;
use serde_json::Value; use serde_json::Value;
use std::collections::HashMap; use indexmap::IndexMap;
use std::sync::Arc; use std::sync::Arc;
use r#type::Type; use r#type::Type;
#[derive(serde::Serialize)] #[derive(serde::Serialize)]
pub struct Database { pub struct Database {
pub enums: HashMap<String, Enum>, pub enums: IndexMap<String, Enum>,
pub types: HashMap<String, Type>, pub types: IndexMap<String, Type>,
pub puncs: HashMap<String, Punc>, pub puncs: IndexMap<String, Punc>,
pub relations: HashMap<String, Relation>, pub relations: IndexMap<String, Relation>,
#[serde(skip)] #[serde(skip)]
pub schemas: HashMap<String, Arc<Schema>>, pub schemas: IndexMap<String, Arc<Schema>>,
#[serde(skip)] #[serde(skip)]
pub executor: Box<dyn DatabaseExecutor + Send + Sync>, pub executor: Box<dyn DatabaseExecutor + Send + Sync>,
} }
@ -42,11 +42,11 @@ pub struct Database {
impl Database { impl Database {
pub fn new(val: &serde_json::Value) -> (Self, crate::drop::Drop) { pub fn new(val: &serde_json::Value) -> (Self, crate::drop::Drop) {
let mut db = Self { let mut db = Self {
enums: HashMap::new(), enums: IndexMap::new(),
types: HashMap::new(), types: IndexMap::new(),
relations: HashMap::new(), relations: IndexMap::new(),
puncs: HashMap::new(), puncs: IndexMap::new(),
schemas: HashMap::new(), schemas: IndexMap::new(),
#[cfg(not(test))] #[cfg(not(test))]
executor: Box::new(SpiExecutor::new()), executor: Box::new(SpiExecutor::new()),
#[cfg(test)] #[cfg(test)]

View File

@ -1,7 +1,7 @@
use crate::database::schema::Schema; use crate::database::schema::Schema;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_json::Value; use serde_json::Value;
use std::collections::BTreeMap; use indexmap::IndexMap;
use std::sync::Arc; use std::sync::Arc;
use std::sync::OnceLock; use std::sync::OnceLock;
@ -30,10 +30,10 @@ pub struct SchemaObject {
// Object Keywords // Object Keywords
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub properties: Option<BTreeMap<String, Arc<Schema>>>, pub properties: Option<IndexMap<String, Arc<Schema>>>,
#[serde(rename = "patternProperties")] #[serde(rename = "patternProperties")]
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub pattern_properties: Option<BTreeMap<String, Arc<Schema>>>, pub pattern_properties: Option<IndexMap<String, Arc<Schema>>>,
#[serde(rename = "additionalProperties")] #[serde(rename = "additionalProperties")]
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub additional_properties: Option<Arc<Schema>>, pub additional_properties: Option<Arc<Schema>>,
@ -46,7 +46,7 @@ pub struct SchemaObject {
// dependencies can be schema dependencies or property dependencies // dependencies can be schema dependencies or property dependencies
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub dependencies: Option<BTreeMap<String, Dependency>>, pub dependencies: Option<IndexMap<String, Dependency>>,
// Array Keywords // Array Keywords
#[serde(rename = "items")] #[serde(rename = "items")]
@ -147,7 +147,7 @@ pub struct SchemaObject {
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub control: Option<String>, pub control: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub actions: Option<BTreeMap<String, Action>>, pub actions: Option<IndexMap<String, Action>>,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub computer: Option<String>, pub computer: Option<String>,
#[serde(default)] #[serde(default)]
@ -164,7 +164,7 @@ pub struct SchemaObject {
// Internal structural representation caching active AST Node maps. Unlike the Go framework counterpart, the JSPG implementation DOES natively include ALL ancestral inheritance boundary schemas because it compiles locally against the raw database graph. // Internal structural representation caching active AST Node maps. Unlike the Go framework counterpart, the JSPG implementation DOES natively include ALL ancestral inheritance boundary schemas because it compiles locally against the raw database graph.
#[serde(skip)] #[serde(skip)]
pub compiled_properties: OnceLock<BTreeMap<String, Arc<Schema>>>, pub compiled_properties: OnceLock<IndexMap<String, Arc<Schema>>>,
#[serde(rename = "compiledDiscriminator")] #[serde(rename = "compiledDiscriminator")]
#[serde(skip_deserializing)] #[serde(skip_deserializing)]
@ -176,13 +176,13 @@ pub struct SchemaObject {
#[serde(skip_deserializing)] #[serde(skip_deserializing)]
#[serde(skip_serializing_if = "crate::database::object::is_once_lock_map_empty")] #[serde(skip_serializing_if = "crate::database::object::is_once_lock_map_empty")]
#[serde(serialize_with = "crate::database::object::serialize_once_lock")] #[serde(serialize_with = "crate::database::object::serialize_once_lock")]
pub compiled_options: OnceLock<BTreeMap<String, (Option<usize>, Option<String>)>>, pub compiled_options: OnceLock<IndexMap<String, (Option<usize>, Option<String>)>>,
#[serde(rename = "compiledEdges")] #[serde(rename = "compiledEdges")]
#[serde(skip_deserializing)] #[serde(skip_deserializing)]
#[serde(skip_serializing_if = "crate::database::object::is_once_lock_map_empty")] #[serde(skip_serializing_if = "crate::database::object::is_once_lock_map_empty")]
#[serde(serialize_with = "crate::database::object::serialize_once_lock")] #[serde(serialize_with = "crate::database::object::serialize_once_lock")]
pub compiled_edges: OnceLock<BTreeMap<String, crate::database::edge::Edge>>, pub compiled_edges: OnceLock<IndexMap<String, crate::database::edge::Edge>>,
#[serde(skip)] #[serde(skip)]
pub compiled_format: OnceLock<CompiledFormat>, pub compiled_format: OnceLock<CompiledFormat>,
@ -245,7 +245,7 @@ pub fn serialize_once_lock<T: serde::Serialize, S: serde::Serializer>(
} }
} }
pub fn is_once_lock_map_empty<K, V>(lock: &OnceLock<std::collections::BTreeMap<K, V>>) -> bool { pub fn is_once_lock_map_empty<K, V>(lock: &OnceLock<indexmap::IndexMap<K, V>>) -> bool {
lock.get().map_or(true, |m| m.is_empty()) lock.get().map_or(true, |m| m.is_empty())
} }

View File

@ -1,5 +1,6 @@
use crate::database::Database; use crate::database::Database;
use std::sync::Arc; use std::sync::Arc;
use indexmap::IndexMap;
pub struct Compiler<'a> { pub struct Compiler<'a> {
pub db: &'a Database, pub db: &'a Database,
@ -256,7 +257,7 @@ impl<'a> Compiler<'a> {
fn compile_object( fn compile_object(
&mut self, &mut self,
props: &std::collections::BTreeMap<String, std::sync::Arc<crate::database::schema::Schema>>, props: &IndexMap<String, std::sync::Arc<crate::database::schema::Schema>>,
node: Node<'a>, node: Node<'a>,
) -> Result<(String, String), String> { ) -> Result<(String, String), String> {
let mut build_args = Vec::new(); let mut build_args = Vec::new();
@ -417,7 +418,7 @@ impl<'a> Compiler<'a> {
) -> Result<Vec<String>, String> { ) -> Result<Vec<String>, String> {
let mut select_args = Vec::new(); let mut select_args = Vec::new();
let grouped_fields = r#type.grouped_fields.as_ref().and_then(|v| v.as_object()); let grouped_fields = r#type.grouped_fields.as_ref().and_then(|v| v.as_object());
let default_props = std::collections::BTreeMap::new(); let default_props = IndexMap::new();
let merged_props = node let merged_props = node
.schema .schema
.obj .obj

View File

@ -127,7 +127,7 @@ fn test_library_api() {
"forward": true "forward": true
} }
}, },
"compiledPropertyNames": ["name", "target", "type"], "compiledPropertyNames": ["type", "name", "target"],
"properties": { "properties": {
"name": { "type": "string" }, "name": { "type": "string" },
"target": { "target": {
@ -140,19 +140,19 @@ fn test_library_api() {
"type": "object" "type": "object"
}, },
"source_schema.filter": { "source_schema.filter": {
"compiledPropertyNames": ["$and", "$or", "name", "target", "type"], "compiledPropertyNames": ["type", "name", "target", "$and", "$or"],
"properties": { "properties": {
"$and": { "$and": {
"type": ["array", "null"], "type": ["array", "null"],
"items": { "items": {
"compiledPropertyNames": ["$and", "$or", "name", "target", "type"], "compiledPropertyNames": ["type", "name", "target", "$and", "$or"],
"type": "source_schema.filter" "type": "source_schema.filter"
} }
}, },
"$or": { "$or": {
"type": ["array", "null"], "type": ["array", "null"],
"items": { "items": {
"compiledPropertyNames": ["$and", "$or", "name", "target", "type"], "compiledPropertyNames": ["type", "name", "target", "$and", "$or"],
"type": "source_schema.filter" "type": "source_schema.filter"
} }
}, },
@ -193,19 +193,19 @@ fn test_library_api() {
"type": "object" "type": "object"
}, },
"target_schema.filter": { "target_schema.filter": {
"compiledPropertyNames": ["$and", "$or", "value"], "compiledPropertyNames": ["value", "$and", "$or"],
"properties": { "properties": {
"$and": { "$and": {
"type": ["array", "null"], "type": ["array", "null"],
"items": { "items": {
"compiledPropertyNames": ["$and", "$or", "value"], "compiledPropertyNames": ["value", "$and", "$or"],
"type": "target_schema.filter" "type": "target_schema.filter"
} }
}, },
"$or": { "$or": {
"type": ["array", "null"], "type": ["array", "null"],
"items": { "items": {
"compiledPropertyNames": ["$and", "$or", "value"], "compiledPropertyNames": ["value", "$and", "$or"],
"type": "target_schema.filter" "type": "target_schema.filter"
} }
}, },

View File

@ -1,6 +1,7 @@
use crate::validator::context::ValidationContext; use crate::validator::context::ValidationContext;
use crate::validator::error::ValidationError; use crate::validator::error::ValidationError;
use crate::validator::result::ValidationResult; use crate::validator::result::ValidationResult;
use indexmap::IndexMap;
impl<'a> ValidationContext<'a> { impl<'a> ValidationContext<'a> {
pub(crate) fn validate_family( pub(crate) fn validate_family(
@ -65,7 +66,7 @@ impl<'a> ValidationContext<'a> {
pub(crate) fn execute_polymorph( pub(crate) fn execute_polymorph(
&self, &self,
options: &std::collections::BTreeMap<String, (Option<usize>, Option<String>)>, options: &IndexMap<String, (Option<usize>, Option<String>)>,
result: &mut ValidationResult, result: &mut ValidationResult,
) -> Result<bool, ValidationError> { ) -> Result<bool, ValidationError> {
// 1. O(1) Fast-Path Router & Extractor // 1. O(1) Fast-Path Router & Extractor