more filter fixes

This commit is contained in:
2026-04-17 07:43:19 -04:00
parent c2267b68d8
commit 69bd726b25
10 changed files with 75 additions and 26 deletions

View File

@ -94,19 +94,30 @@
{ {
"id": "type3", "id": "type3",
"type": "type", "type": "type",
"name": "filter", "name": "search",
"module": "core", "module": "core",
"source": "filter", "source": "search",
"hierarchy": [ "hierarchy": [
"filter" "search"
], ],
"variations": [ "variations": [
"filter", "search"
"string.condition",
"integer.condition",
"date.condition"
], ],
"schemas": { "schemas": {
"search": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"filter": {
"type": "filter"
}
}
},
"filter": {
"type": "object"
},
"condition": { "condition": {
"type": "object", "type": "object",
"properties": { "properties": {
@ -161,7 +172,7 @@
"schemas": { "schemas": {
"person": {}, "person": {},
"person.filter": { "person.filter": {
"type": "object", "type": "filter",
"compiledPropertyNames": [ "compiledPropertyNames": [
"age", "age",
"billing_address", "billing_address",
@ -197,7 +208,7 @@
}, },
"address": {}, "address": {},
"address.filter": { "address.filter": {
"type": "object", "type": "filter",
"compiledPropertyNames": [ "compiledPropertyNames": [
"city" "city"
], ],
@ -210,10 +221,33 @@
} }
} }
}, },
"filter": {},
"condition": {}, "condition": {},
"string.condition": {}, "string.condition": {},
"integer.condition": {}, "integer.condition": {},
"date.condition": {} "date.condition": {},
"search": {},
"search.filter": {
"type": "filter",
"compiledPropertyNames": [
"filter",
"name"
],
"properties": {
"filter": {
"type": [
"filter.filter",
"null"
]
},
"name": {
"type": [
"string.condition",
"null"
]
}
}
}
} }
} }
} }

View File

@ -1195,7 +1195,7 @@
"description": "Simple entity select with multiple filters", "description": "Simple entity select with multiple filters",
"action": "query", "action": "query",
"schema_id": "entity", "schema_id": "entity",
"filters": { "filter": {
"id": { "id": {
"$eq": "123e4567-e89b-12d3-a456-426614174000", "$eq": "123e4567-e89b-12d3-a456-426614174000",
"$ne": "123e4567-e89b-12d3-a456-426614174001", "$ne": "123e4567-e89b-12d3-a456-426614174001",
@ -1443,7 +1443,7 @@
"description": "Person select on full schema with filters", "description": "Person select on full schema with filters",
"action": "query", "action": "query",
"schema_id": "full.person", "schema_id": "full.person",
"filters": { "filter": {
"age": { "age": {
"$eq": 30, "$eq": 30,
"$gt": 20, "$gt": 20,

View File

@ -1,6 +1,6 @@
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 crate::database::Database;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::sync::Arc; use std::sync::Arc;
@ -20,16 +20,26 @@ impl Schema {
let mut child_obj = SchemaObject::default(); let mut child_obj = SchemaObject::default();
child_obj.type_ = Some(SchemaTypeOrArray::Multiple(filter_type)); child_obj.type_ = Some(SchemaTypeOrArray::Multiple(filter_type));
filter_props.insert(key.clone(), Arc::new(Schema { obj: child_obj, always_fail: false })); filter_props.insert(
key.clone(),
Arc::new(Schema {
obj: child_obj,
always_fail: false,
}),
);
} }
} }
if !filter_props.is_empty() { if !filter_props.is_empty() {
let mut wrapper_obj = SchemaObject::default(); let mut wrapper_obj = SchemaObject::default();
wrapper_obj.type_ = Some(SchemaTypeOrArray::Single("object".to_string())); // Conceptually link this directly into the STI lineage of the base `filter` object
wrapper_obj.type_ = Some(SchemaTypeOrArray::Single("filter".to_string()));
wrapper_obj.properties = Some(filter_props); wrapper_obj.properties = Some(filter_props);
return Some(Schema { obj: wrapper_obj, always_fail: false }); return Some(Schema {
obj: wrapper_obj,
always_fail: false,
});
} }
} }
None None

View File

@ -1,6 +1,6 @@
pub mod collection; pub mod collection;
pub mod edges; pub mod edges;
pub mod filters; pub mod filter;
pub mod polymorphism; pub mod polymorphism;
use crate::database::schema::Schema; use crate::database::schema::Schema;

View File

@ -15,6 +15,7 @@ pub struct Punc {
pub public: bool, pub public: bool,
pub form: bool, pub form: bool,
pub get: Option<String>, pub get: Option<String>,
pub save: Option<String>,
pub page: Option<Page>, pub page: Option<Page>,
#[serde(default)] #[serde(default)]
pub schemas: std::collections::BTreeMap<String, Arc<Schema>>, pub schemas: std::collections::BTreeMap<String, Arc<Schema>>,

View File

@ -3,6 +3,8 @@ use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, Default)] #[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(default)] #[serde(default)]
pub struct Relation { pub struct Relation {
pub id: String,
pub r#type: String,
pub constraint: String, pub constraint: String,
pub source_type: String, pub source_type: String,
pub source_columns: Vec<String>, pub source_columns: Vec<String>,

View File

@ -72,7 +72,7 @@ pub fn jspg_merge(schema_id: &str, data: JsonB) -> JsonB {
} }
#[cfg_attr(not(test), pg_extern)] #[cfg_attr(not(test), pg_extern)]
pub fn jspg_query(schema_id: &str, filters: Option<JsonB>) -> JsonB { pub fn jspg_query(schema_id: &str, filter: Option<JsonB>) -> JsonB {
let engine_opt = { let engine_opt = {
let lock = GLOBAL_JSPG.read().unwrap(); let lock = GLOBAL_JSPG.read().unwrap();
lock.clone() lock.clone()
@ -82,7 +82,7 @@ pub fn jspg_query(schema_id: &str, filters: Option<JsonB>) -> JsonB {
Some(engine) => { Some(engine) => {
let drop = engine let drop = engine
.queryer .queryer
.query(schema_id, filters.as_ref().map(|f| &f.0)); .query(schema_id, filter.as_ref().map(|f| &f.0));
JsonB(serde_json::to_value(drop).unwrap()) JsonB(serde_json::to_value(drop).unwrap())
} }
None => jspg_failure(), None => jspg_failure(),

View File

@ -21,9 +21,9 @@ impl Queryer {
pub fn query( pub fn query(
&self, &self,
schema_id: &str, schema_id: &str,
filters: Option<&serde_json::Value>, filter: Option<&serde_json::Value>,
) -> crate::drop::Drop { ) -> crate::drop::Drop {
let filters_map = filters.and_then(|f| f.as_object()); let filters_map = filter.and_then(|f| f.as_object());
// 1. Process filters into structured $op keys and linear values // 1. Process filters into structured $op keys and linear values
let (filter_keys, args) = match self.parse_filter_entries(filters_map) { let (filter_keys, args) = match self.parse_filter_entries(filters_map) {
@ -35,7 +35,7 @@ impl Queryer {
details: crate::drop::ErrorDetails { details: crate::drop::ErrorDetails {
path: None, // filters apply to the root query path: None, // filters apply to the root query
cause: Some(msg), cause: Some(msg),
context: filters.cloned(), context: filter.cloned(),
schema: Some(schema_id.to_string()), schema: Some(schema_id.to_string()),
}, },
}]); }]);

View File

@ -92,6 +92,8 @@ fn test_library_api() {
"puncs": {}, "puncs": {},
"relations": { "relations": {
"fk_test_target": { "fk_test_target": {
"id": "11111111-1111-1111-1111-111111111111",
"type": "relation",
"constraint": "fk_test_target", "constraint": "fk_test_target",
"destination_columns": ["id"], "destination_columns": ["id"],
"destination_type": "target_schema", "destination_type": "target_schema",
@ -144,7 +146,7 @@ fn test_library_api() {
"target": { "type": ["target_schema.filter", "null"] }, "target": { "type": ["target_schema.filter", "null"] },
"type": { "type": ["string.condition", "null"] } "type": { "type": ["string.condition", "null"] }
}, },
"type": "object" "type": "filter"
} }
}, },
"sensitive": false, "sensitive": false,
@ -181,7 +183,7 @@ fn test_library_api() {
"properties": { "properties": {
"value": { "type": ["number.condition", "null"] } "value": { "type": ["number.condition", "null"] }
}, },
"type": "object" "type": "filter"
} }
}, },
"sensitive": false, "sensitive": false,

View File

@ -17,7 +17,7 @@ pub struct Case {
// For Query // For Query
#[serde(default)] #[serde(default)]
pub filters: Option<serde_json::Value>, pub filter: Option<serde_json::Value>,
// For Merge & Validate // For Merge & Validate
#[serde(default)] #[serde(default)]
@ -122,7 +122,7 @@ impl Case {
use crate::queryer::Queryer; use crate::queryer::Queryer;
let queryer = Queryer::new(db.clone()); let queryer = Queryer::new(db.clone());
let result = queryer.query(&self.schema_id, self.filters.as_ref()); let result = queryer.query(&self.schema_id, self.filter.as_ref());
let return_val = if let Some(expect) = &self.expect { let return_val = if let Some(expect) = &self.expect {
if let Err(e) = expect.assert_drop(&result) { if let Err(e) = expect.assert_drop(&result) {