use scythe_codegen::{GeneratedCode, generate_with_backend, get_backend};
use scythe_core::analyzer::analyze;
use scythe_core::catalog::Catalog;
use scythe_core::dialect::SqlDialect;
use scythe_core::errors::ScytheError;
use scythe_core::parser::parse_query_with_dialect;
const NESTED_ARRAY_SCHEMA: &str = "\
CREATE TYPE order_status AS ENUM ('pending', 'shipped'); \
CREATE TABLE users (id SERIAL PRIMARY KEY, name TEXT NOT NULL); \
CREATE TABLE orders (id SERIAL PRIMARY KEY, user_id INTEGER NOT NULL, status order_status NOT NULL);";
const NESTED_ARRAY_QUERY: &str = "-- @name GetUserOrders\n-- @returns :many\n\
SELECT u.id, json_agg(o.*) AS orders FROM users u JOIN orders o ON o.user_id = u.id GROUP BY u.id;";
fn generate(backend_name: &str) -> Result<GeneratedCode, ScytheError> {
let backend = get_backend(backend_name, "postgresql").expect("backend must support postgresql");
let catalog =
Catalog::from_ddl_with_dialect(&[NESTED_ARRAY_SCHEMA], &SqlDialect::PostgreSQL).expect("schema must parse");
let parsed = parse_query_with_dialect(NESTED_ARRAY_QUERY, &SqlDialect::PostgreSQL).expect("query must parse");
let analyzed = analyze(&catalog, &parsed).expect("query must analyze");
generate_with_backend(&analyzed, &*backend)
}
#[test]
fn unsupported_backend_reports_the_degraded_column_struct_and_backend() {
let code = generate("java-jdbc").expect("degradation is not a hard error by default");
assert_eq!(
code.degraded_nested_structs.len(),
1,
"exactly one column (orders) referenced the unsupported struct: {:?}",
code.degraded_nested_structs
);
let degradation = &code.degraded_nested_structs[0];
assert_eq!(degradation.column, "orders");
assert_eq!(degradation.struct_name, "GetUserOrdersRowOrders");
assert_eq!(degradation.fallback_type, "json");
assert_eq!(degradation.backend, "java-jdbc");
assert!(code.row_struct.is_some(), "codegen must still produce a row struct");
}
#[test]
fn backend_with_json_array_marker_reports_that_fallback_not_plain_json() {
let code = generate("typescript-pg").expect("degradation is not a hard error by default");
assert_eq!(code.degraded_nested_structs.len(), 1);
assert_eq!(code.degraded_nested_structs[0].fallback_type, "json_array");
assert_eq!(code.degraded_nested_structs[0].backend, "typescript-pg");
}
#[test]
fn supporting_backend_reports_no_degradation() {
let code = generate("rust-sqlx").expect("codegen must succeed");
assert!(
code.degraded_nested_structs.is_empty(),
"rust-sqlx supports the nested struct and must not report a degradation: {:?}",
code.degraded_nested_structs
);
assert_eq!(
code.nested_struct_defs.len(),
1,
"the struct definition must still be emitted"
);
}