generator checkpoint

This commit is contained in:
2026-07-09 14:26:45 -04:00
parent cef65958cb
commit 3bb7eb312a
9 changed files with 529 additions and 116 deletions

View File

@ -1,5 +1,6 @@
use crate::database::Database;
use indexmap::IndexMap;
use serde_json::Value;
use std::sync::Arc;
pub struct Compiler<'a> {
@ -86,13 +87,29 @@ impl<'a> Compiler<'a> {
.next_back()
.unwrap_or(family_target);
resolved_type = self.db.types.get(base_type_name);
} else if let Some(crate::database::object::SchemaTypeOrArray::Single(t)) = &items.obj.type_
{
if !crate::database::object::is_primitive_type(t) {
resolved_type = self
.db
.types
.get(&t.split('.').next_back().unwrap_or(t).to_string());
} else if let Some(t_or_arr) = &items.obj.type_ {
match t_or_arr {
crate::database::object::SchemaTypeOrArray::Single(t) => {
if !crate::database::object::is_primitive_type(t) {
resolved_type = self
.db
.types
.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;
}
}
}
}
}
}
}
@ -135,12 +152,25 @@ impl<'a> Compiler<'a> {
.next_back()
.unwrap_or(family_target);
resolved_type = self.db.types.get(base_type_name);
} else if let Some(crate::database::object::SchemaTypeOrArray::Single(t)) =
&node.schema.obj.type_
{
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);
} else if let Some(t_or_arr) = &node.schema.obj.type_ {
match t_or_arr {
crate::database::object::SchemaTypeOrArray::Single(t) => {
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);
}
}
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;
}
}
}
}
}
}
}
@ -439,6 +469,9 @@ impl<'a> Compiler<'a> {
Some(crate::database::object::SchemaTypeOrArray::Single(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,
};
@ -551,6 +584,7 @@ impl<'a> Compiler<'a> {
self.compile_filter_conditions(r#type, type_aliases, &node, &base_alias, &mut where_clauses);
self.compile_polymorphic_bounds(r#type, type_aliases, &node, &mut where_clauses);
self.compile_static_property_conditions(r#type, type_aliases, &node, &base_alias, &mut where_clauses);
let start_len = where_clauses.len();
self.compile_relation_conditions(
@ -865,4 +899,69 @@ impl<'a> Compiler<'a> {
}
Ok(())
}
fn compile_static_property_conditions(
&self,
r#type: &crate::database::r#type::Type,
type_aliases: &std::collections::HashMap<String, String>,
node: &Node,
base_alias: &str,
where_clauses: &mut Vec<String>,
) {
if let Some(props) = node.schema.obj.properties.as_ref() {
for (prop_name, prop_schema) in props {
let filter_alias = Self::resolve_filter_alias(r#type, type_aliases, base_alias, prop_name);
if let Some(const_val) = prop_schema.obj.const_.as_ref() {
let sql_val = Self::quote_literal(const_val);
where_clauses.push(format!("{}.{} = {}", filter_alias, prop_name, sql_val));
}
if let Some(enum_vals) = prop_schema.obj.enum_.as_ref() {
if !enum_vals.is_empty() {
let sql_vals: Vec<String> = enum_vals
.iter()
.map(|v| Self::quote_literal(v))
.collect();
where_clauses.push(format!(
"{}.{} IN ({})",
filter_alias,
prop_name,
sql_vals.join(", ")
));
}
}
}
}
}
fn quote_literal(val: &Value) -> String {
match val {
Value::Null => "NULL".to_string(),
Value::Bool(b) => {
if *b {
"true".to_string()
} else {
"false".to_string()
}
}
Value::Number(n) => {
if let Some(f) = n.as_f64() {
if f.fract() == 0.0 {
return f.trunc().to_string();
}
}
n.to_string()
}
Value::String(s) => {
if s.is_empty() {
"NULL".to_string()
} else {
format!("'{}'", s.replace('\'', "''"))
}
}
_ => format!(
"'{}'",
serde_json::to_string(val).unwrap().replace('\'', "''")
),
}
}
}