sea_query/extension/postgres/func/json_table/
mod.rs

1use crate::*;
2use std::borrow::Cow;
3
4mod builder;
5pub use builder::Builder;
6mod column;
7pub use column::ColumnBuilder;
8mod exists_column;
9pub use exists_column::ExistsColumnBuilder;
10mod nested;
11pub use nested::NestedPathBuilder;
12pub(super) mod types;
13pub use types::*;
14
15impl PgFunc {
16    /// Create a `JSON_TABLE` function builder. Postgres only.
17    ///
18    /// # Examples
19    ///
20    /// Basic usage with simple columns:
21    /// ```
22    /// use sea_query::extension::postgres::*;
23    /// use sea_query::{tests_cfg::*, *};
24    ///
25    /// let query = Query::select()
26    ///     .from_function(
27    ///         PgFunc::json_table(
28    ///             Expr::val(r#"[{"name": "John", "age": 30}, {"name": "Jane", "age": 25}]"#),
29    ///             "$[*]"
30    ///         )
31    ///         .ordinality_column("row_number")
32    ///         .column("name", "text").path("$.name").build_column()
33    ///         .column("age", "int").path("$.age").build_column()
34    ///         .build(),
35    ///         "people"
36    ///     )
37    ///     .column("*")
38    ///     .to_owned();
39    ///
40    /// assert_eq!(
41    ///     query.to_string(PostgresQueryBuilder),
42    ///     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""#
43    /// );
44    /// ```
45    ///
46    /// With PASSING parameters and error handling:
47    /// ```
48    /// use sea_query::extension::postgres::*;
49    /// use sea_query::{tests_cfg::*, *};
50    ///
51    /// let query = Query::select()
52    ///     .from_function(
53    ///         PgFunc::json_table(
54    ///             Expr::val(r#"{"users": [{"id": 1, "name": "John"}, {"id": 2, "name": "Jane"}]}"#),
55    ///             "$.users[*] ? (@.id > $min_id)"
56    ///         )
57    ///         .passing(0, "min_id")
58    ///         .column("user_id", "int").path("$.id").null_on_error().build_column()
59    ///         .column("user_name", "text").path("$.name").default_on_empty(Expr::val("Unknown")).build_column()
60    ///         .error_on_error()
61    ///         .build(),
62    ///         "filtered_users"
63    ///     )
64    ///     .column("*")
65    ///     .to_owned();
66    ///
67    /// assert_eq!(
68    ///     query.to_string(PostgresQueryBuilder),
69    ///     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""#
70    /// );
71    /// ```
72    ///
73    /// With NESTED PATH:
74    /// ```
75    /// use sea_query::extension::postgres::*;
76    /// use sea_query::{tests_cfg::*, *};
77    ///
78    /// let query = Query::select()
79    ///     .from_function(
80    ///         PgFunc::json_table(
81    ///             Expr::val(r#"{"users": [{"name": "John", "phones": ["123", "456"]}, {"name": "Jane", "phones": ["789"]}]}"#),
82    ///             "$.users[*]"
83    ///         )
84    ///         .column("user_name", "text").path("$.name").build_column()
85    ///         .nested("$.phones[*]")
86    ///             .column("phone", "text").path("$").build_column()
87    ///             .build_nested()
88    ///         .build(),
89    ///         "user_phones"
90    ///     )
91    ///     .column("*")
92    ///     .to_owned();
93    ///
94    /// assert_eq!(
95    ///     query.to_string(PostgresQueryBuilder),
96    ///     r#"SELECT "*" FROM JSON_TABLE('{"users": [{"name": "John", "phones": ["123", "456"]}, {"name": "Jane", "phones": ["789"]}]}', '$.users[*]' COLUMNS (user_name "text" PATH '$.name', NESTED '$.phones[*]' COLUMNS (phone "text" PATH '$'))) AS "user_phones""#
97    /// );
98    /// ```
99    pub fn json_table<T, P>(context_item: T, path_expression: P) -> Builder
100    where
101        T: Into<Expr>,
102        P: Into<Cow<'static, str>>,
103    {
104        Builder {
105            context_item: context_item.into(),
106            path_expression: path_expression.into(),
107            as_json_path_name: None,
108            passing: Vec::new(),
109            columns: Vec::new(),
110            on_error: None,
111        }
112    }
113}