use super::*; use pretty_assertions::assert_eq; use sea_query::extension::postgres::{PgFunc, json_table as pg_json_table}; #[test] fn json_table_basic_columns() { let query = Query::select() .from_function( PgFunc::json_table( Expr::val(r#"[{"name": "John", "age": 30}, {"name": "Jane", "age": 25}]"#), "$[*]", ) .for_ordinality("row_number") .column(pg_json_table::Column::new("name", "text").path("$.name")) .column(pg_json_table::Column::new("age", "int").path("$.age")) .build(), "people", ) .column("*") .to_owned(); assert_eq!( query.to_string(PostgresQueryBuilder), r#"SELECT "*" FROM JSON_TABLE('[{"name": "John", "age": 30}, {"name": "Jane", "age": 25}]', '$[*]' COLUMNS (row_number FOR ORDINALITY, name "text" PATH '$.name', age "int" PATH '$.age')) AS "people""# ); } #[test] fn json_table_passing_and_error_handling() { let query = Query::select() .from_function( PgFunc::json_table( Expr::val(r#"{"users": [{"id": 1, "name": "John"}, {"id": 2, "name": "Jane"}]}"#), "$.users[*] ? (@.id > $min_id)", ) .passing(0, "min_id") .column( pg_json_table::Column::new("user_id", "int") .path("$.id") .null_on_error(), ) .column( pg_json_table::Column::new("user_name", "text") .path("$.name") .default_on_empty(Expr::val("Unknown")), ) .error_on_error() .build(), "filtered_users", ) .column("*") .to_owned(); assert_eq!( query.to_string(PostgresQueryBuilder), r#"SELECT "*" FROM JSON_TABLE('{"users": [{"id": 1, "name": "John"}, {"id": 2, "name": "Jane"}]}', '$.users[*] ? (@.id > $min_id)' PASSING 0 AS min_id COLUMNS (user_id "int" PATH '$.id' NULL ON ERROR, user_name "text" PATH '$.name' DEFAULT 'Unknown' ON EMPTY) ERROR ON ERROR) AS "filtered_users""# ); } #[test] fn json_table_nested_path() { let query = Query::select() .from_function( PgFunc::json_table( Expr::val( r#"{"users": [{"name": "John", "phones": ["123", "456"]}, {"name": "Jane", "phones": ["789"]}]}"#, ), "$.users[*]", ) .column(pg_json_table::Column::new("user_name", "text").path("$.name")) .nested( pg_json_table::NestedPath::new("$.phones[*]") .column(pg_json_table::Column::new("phone", "text").path("$")), ) .build(), "user_phones", ) .column("*") .to_owned(); assert_eq!( query.to_string(PostgresQueryBuilder), r#"SELECT "*" FROM JSON_TABLE('{"users": [{"name": "John", "phones": ["123", "456"]}, {"name": "Jane", "phones": ["789"]}]}', '$.users[*]' COLUMNS (user_name "text" PATH '$.name', NESTED PATH '$.phones[*]' COLUMNS (phone "text" PATH '$'))) AS "user_phones""# ); } #[test] fn json_table_nested_path_recursion_and_siblings() { let query = Query::select() .from_function( PgFunc::json_table( Expr::cust( r#"'{"favorites":[{"movies":[{"name":"One","director":"John Doe"}],"books":[{"name":"Mystery","authors":[{"name":"Brown Dan"}]}]}]}'::json"#, ), "$.favorites[*]", ) .for_ordinality("user_id") .nested( pg_json_table::NestedPath::new("$.movies[*]") .for_ordinality("movie_id") .column(pg_json_table::Column::new("mname", "text").path("$.name")) .column(pg_json_table::Column::new("director", "text")), ) .nested( pg_json_table::NestedPath::new("$.books[*]") .for_ordinality("book_id") .column(pg_json_table::Column::new("bname", "text").path("$.name")) .nested( pg_json_table::NestedPath::new("$.authors[*]") .for_ordinality("author_id") .column( pg_json_table::Column::new("author_name", "text").path("$.name"), ), ), ) .build(), "jt", ) .column("*") .to_owned(); assert_eq!( query.to_string(PostgresQueryBuilder), r#"SELECT "*" FROM JSON_TABLE('{"favorites":[{"movies":[{"name":"One","director":"John Doe"}],"books":[{"name":"Mystery","authors":[{"name":"Brown Dan"}]}]}]}'::json, '$.favorites[*]' COLUMNS (user_id FOR ORDINALITY, NESTED PATH '$.movies[*]' COLUMNS (movie_id FOR ORDINALITY, mname "text" PATH '$.name', director "text"), NESTED PATH '$.books[*]' COLUMNS (book_id FOR ORDINALITY, bname "text" PATH '$.name', NESTED PATH '$.authors[*]' COLUMNS (author_id FOR ORDINALITY, author_name "text" PATH '$.name')))) AS "jt""# ); }