Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 628471e5d5 | |||
| 0093aea790 | |||
| 45ebc57e0c | |||
| 00319b570b |
@ -172,53 +172,69 @@
|
|||||||
"schemas": {
|
"schemas": {
|
||||||
"person": {},
|
"person": {},
|
||||||
"person.filter": {
|
"person.filter": {
|
||||||
"type": "object",
|
|
||||||
"compiledPropertyNames": [
|
"compiledPropertyNames": [
|
||||||
"$and",
|
"$and",
|
||||||
"$or",
|
"$or",
|
||||||
|
"ad_hoc",
|
||||||
"age",
|
"age",
|
||||||
"billing_address",
|
"billing_address",
|
||||||
"birth_date",
|
"birth_date",
|
||||||
"first_name"
|
"first_name",
|
||||||
|
"tags"
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"$and": {
|
"$and": {
|
||||||
"type": [
|
|
||||||
"array",
|
|
||||||
"null"
|
|
||||||
],
|
|
||||||
"items": {
|
"items": {
|
||||||
"compiledPropertyNames": [
|
"compiledPropertyNames": [
|
||||||
"$and",
|
"$and",
|
||||||
"$or",
|
"$or",
|
||||||
|
"ad_hoc",
|
||||||
"age",
|
"age",
|
||||||
"billing_address",
|
"billing_address",
|
||||||
"birth_date",
|
"birth_date",
|
||||||
"first_name"
|
"first_name",
|
||||||
|
"tags"
|
||||||
],
|
],
|
||||||
"type": "person.filter"
|
"type": "person.filter"
|
||||||
}
|
},
|
||||||
|
"type": [
|
||||||
|
"array",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"$or": {
|
"$or": {
|
||||||
"type": [
|
|
||||||
"array",
|
|
||||||
"null"
|
|
||||||
],
|
|
||||||
"items": {
|
"items": {
|
||||||
"compiledPropertyNames": [
|
"compiledPropertyNames": [
|
||||||
"$and",
|
"$and",
|
||||||
"$or",
|
"$or",
|
||||||
|
"ad_hoc",
|
||||||
"age",
|
"age",
|
||||||
"billing_address",
|
"billing_address",
|
||||||
"birth_date",
|
"birth_date",
|
||||||
"first_name"
|
"first_name",
|
||||||
|
"tags"
|
||||||
],
|
],
|
||||||
"type": "person.filter"
|
"type": "person.filter"
|
||||||
}
|
},
|
||||||
},
|
|
||||||
"first_name": {
|
|
||||||
"type": [
|
"type": [
|
||||||
"string.condition",
|
"array",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ad_hoc": {
|
||||||
|
"compiledPropertyNames": [
|
||||||
|
"foo"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"foo": {
|
||||||
|
"type": [
|
||||||
|
"string.condition",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": [
|
||||||
|
"object",
|
||||||
"null"
|
"null"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -239,8 +255,21 @@
|
|||||||
"date.condition",
|
"date.condition",
|
||||||
"null"
|
"null"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"first_name": {
|
||||||
|
"type": [
|
||||||
|
"string.condition",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"tags": {
|
||||||
|
"type": [
|
||||||
|
"string.condition",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"type": "object"
|
||||||
},
|
},
|
||||||
"address": {},
|
"address": {},
|
||||||
"address.filter": {
|
"address.filter": {
|
||||||
|
|||||||
@ -12,11 +12,11 @@ impl Schema {
|
|||||||
) {
|
) {
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
for c in id.chars() {
|
for c in id.chars() {
|
||||||
if !c.is_ascii_lowercase() && !c.is_ascii_digit() && c != '_' && c != '.' {
|
if !c.is_ascii_lowercase() && !c.is_ascii_digit() && c != '_' && c != '.' && c != '$' {
|
||||||
errors.push(crate::drop::Error {
|
errors.push(crate::drop::Error {
|
||||||
code: "INVALID_IDENTIFIER".to_string(),
|
code: "INVALID_IDENTIFIER".to_string(),
|
||||||
message: format!(
|
message: format!(
|
||||||
"Invalid character '{}' in JSON Schema '{}' property: '{}'. Identifiers must exclusively contain [a-z0-9_.]",
|
"Invalid character '{}' in JSON Schema '{}' property: '{}'. Identifiers must exclusively contain [a-z0-9_.$]",
|
||||||
c, field_name, id
|
c, field_name, id
|
||||||
),
|
),
|
||||||
details: crate::drop::ErrorDetails {
|
details: crate::drop::ErrorDetails {
|
||||||
|
|||||||
@ -14,7 +14,35 @@ impl 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 = BTreeMap::new();
|
||||||
for (key, child) in props {
|
for (key, child) in props {
|
||||||
if let Some(mut filter_type) = Self::resolve_filter_type(child) {
|
let mut structural_filter = None;
|
||||||
|
|
||||||
|
let is_array = match &child.obj.type_ {
|
||||||
|
Some(SchemaTypeOrArray::Single(t)) => t == "array",
|
||||||
|
Some(SchemaTypeOrArray::Multiple(types)) => types.contains(&"array".to_string()),
|
||||||
|
None => false,
|
||||||
|
};
|
||||||
|
|
||||||
|
if is_array {
|
||||||
|
if let Some(items) = &child.obj.items {
|
||||||
|
if !items.is_proxy() {
|
||||||
|
structural_filter = items.compile_filter(_db, "", _errors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if !child.is_proxy() {
|
||||||
|
structural_filter = child.compile_filter(_db, "", _errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(mut inline_schema) = structural_filter {
|
||||||
|
inline_schema.obj.type_ = Some(SchemaTypeOrArray::Multiple(vec![
|
||||||
|
"object".to_string(),
|
||||||
|
"null".to_string(),
|
||||||
|
]));
|
||||||
|
|
||||||
|
filter_props.insert(
|
||||||
|
key.clone(),
|
||||||
|
Arc::new(inline_schema),
|
||||||
|
);
|
||||||
|
} else if let Some(mut filter_type) = Self::resolve_filter_type(child) {
|
||||||
filter_type.push("null".to_string());
|
filter_type.push("null".to_string());
|
||||||
|
|
||||||
let mut child_obj = SchemaObject::default();
|
let mut child_obj = SchemaObject::default();
|
||||||
@ -31,47 +59,49 @@ impl Schema {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !filter_props.is_empty() {
|
if !filter_props.is_empty() {
|
||||||
let root_filter_type = format!("{}.filter", root_id);
|
if !root_id.is_empty() {
|
||||||
|
let root_filter_type = format!("{}.filter", root_id);
|
||||||
|
|
||||||
let mut and_obj = SchemaObject::default();
|
let mut and_obj = SchemaObject::default();
|
||||||
and_obj.type_ = Some(SchemaTypeOrArray::Multiple(vec![
|
and_obj.type_ = Some(SchemaTypeOrArray::Multiple(vec![
|
||||||
"array".to_string(),
|
"array".to_string(),
|
||||||
"null".to_string(),
|
"null".to_string(),
|
||||||
]));
|
]));
|
||||||
and_obj.items = Some(Arc::new(Schema {
|
and_obj.items = Some(Arc::new(Schema {
|
||||||
obj: SchemaObject {
|
obj: SchemaObject {
|
||||||
type_: Some(SchemaTypeOrArray::Single(root_filter_type.clone())),
|
type_: Some(SchemaTypeOrArray::Single(root_filter_type.clone())),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
always_fail: false,
|
|
||||||
}));
|
|
||||||
filter_props.insert(
|
|
||||||
"$and".to_string(),
|
|
||||||
Arc::new(Schema {
|
|
||||||
obj: and_obj,
|
|
||||||
always_fail: false,
|
always_fail: false,
|
||||||
}),
|
}));
|
||||||
);
|
filter_props.insert(
|
||||||
|
"$and".to_string(),
|
||||||
|
Arc::new(Schema {
|
||||||
|
obj: and_obj,
|
||||||
|
always_fail: false,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
let mut or_obj = SchemaObject::default();
|
let mut or_obj = SchemaObject::default();
|
||||||
or_obj.type_ = Some(SchemaTypeOrArray::Multiple(vec![
|
or_obj.type_ = Some(SchemaTypeOrArray::Multiple(vec![
|
||||||
"array".to_string(),
|
"array".to_string(),
|
||||||
"null".to_string(),
|
"null".to_string(),
|
||||||
]));
|
]));
|
||||||
or_obj.items = Some(Arc::new(Schema {
|
or_obj.items = Some(Arc::new(Schema {
|
||||||
obj: SchemaObject {
|
obj: SchemaObject {
|
||||||
type_: Some(SchemaTypeOrArray::Single(root_filter_type.clone())),
|
type_: Some(SchemaTypeOrArray::Single(root_filter_type.clone())),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
always_fail: false,
|
|
||||||
}));
|
|
||||||
filter_props.insert(
|
|
||||||
"$or".to_string(),
|
|
||||||
Arc::new(Schema {
|
|
||||||
obj: or_obj,
|
|
||||||
always_fail: false,
|
always_fail: false,
|
||||||
}),
|
}));
|
||||||
);
|
filter_props.insert(
|
||||||
|
"$or".to_string(),
|
||||||
|
Arc::new(Schema {
|
||||||
|
obj: or_obj,
|
||||||
|
always_fail: false,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let mut wrapper_obj = SchemaObject::default();
|
let mut wrapper_obj = SchemaObject::default();
|
||||||
// Filters are just plain objects containing conditions, no inheritance required
|
// Filters are just plain objects containing conditions, no inheritance required
|
||||||
@ -119,7 +149,12 @@ impl Schema {
|
|||||||
"number" => Some(vec!["number.condition".to_string()]),
|
"number" => Some(vec!["number.condition".to_string()]),
|
||||||
"boolean" => Some(vec!["boolean.condition".to_string()]),
|
"boolean" => Some(vec!["boolean.condition".to_string()]),
|
||||||
"object" => None, // Inline structures are ignored in Composed References
|
"object" => None, // Inline structures are ignored in Composed References
|
||||||
"array" => None, // We don't filter primitive arrays or map complex arrays yet
|
"array" => {
|
||||||
|
if let Some(items) = &schema.obj.items {
|
||||||
|
return Self::resolve_filter_type(items);
|
||||||
|
}
|
||||||
|
None
|
||||||
|
},
|
||||||
"null" => None,
|
"null" => None,
|
||||||
custom => {
|
custom => {
|
||||||
// Assume anything else is a Relational cross-boundary that already has its own .filter dynamically built
|
// Assume anything else is a Relational cross-boundary that already has its own .filter dynamically built
|
||||||
|
|||||||
Reference in New Issue
Block a user