Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 26 additions & 74 deletions src/extension/postgres/func/json_table/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ use std::fmt::Write;
use crate::extension::postgres::json_fn::{
write_as_json_path_name, write_json_path_expr, write_passing,
};
use crate::extension::postgres::json_table::ExistsColumnBuilder;
use crate::*;

use super::column::ColumnBuilder;
use super::nested::NestedPathBuilder;
use super::column::Column;
use super::exists_column::ExistsColumn;
use super::nested::NestedPath;
use super::types::*;

/// Builder for JSON_TABLE function
Expand All @@ -36,95 +36,49 @@ impl From<Builder> for Expr {
}

impl Builder {
/// Set the JSON path name (AS clause)
pub fn json_path_name<T>(mut self, name: T) -> Self
where
T: Into<Cow<'static, str>>,
{
/// Set the JSON path name (AS clause).
pub fn path_name(mut self, name: impl Into<Cow<'static, str>>) -> Self {
self.as_json_path_name = Some(name.into());
self
}

/// Add PASSING parameters
pub fn passing<V, A>(mut self, value: V, alias: A) -> Self
where
V: Into<Value>,
A: Into<Cow<'static, str>>,
{
pub fn passing(mut self, value: impl Into<Value>, alias: impl Into<Cow<'static, str>>) -> Self {
self.passing.push((value.into(), alias.into()));
self
}

/// Add multiple PASSING parameters at once
pub fn passing_many<V, A, I>(mut self, passing: I) -> Self
where
V: Into<Value>,
A: Into<Cow<'static, str>>,
I: IntoIterator<Item = (V, A)>,
{
pub fn passing_many(
mut self,
passing: impl IntoIterator<Item = (impl Into<Value>, impl Into<Cow<'static, str>>)>,
) -> Self {
for (value, alias) in passing {
self.passing.push((value.into(), alias.into()));
}
self
}

/// Add a FOR ORDINALITY column
pub fn ordinality_column<N>(mut self, name: N) -> Self
where
N: Into<Cow<'static, str>>,
{
/// Add a `FOR ORDINALITY` column.
pub fn for_ordinality(mut self, name: impl Into<Cow<'static, str>>) -> Self {
self.columns
.push(JsonTableColumn::Ordinality { name: name.into() });
self
}

/// Add a regular column
pub fn column<N, T>(self, name: N, column_type: T) -> ColumnBuilder<Self>
where
N: Into<Cow<'static, str>>,
T: Into<TypeRef>,
{
ColumnBuilder {
builder: self,
name: name.into(),
column_type: column_type.into(),
format_json: false,
encoding_utf8: false,
path: None,
wrapper: None,
quotes: None,
on_empty: None,
on_error: None,
}
pub fn column(mut self, column: Column) -> Self {
self.columns.push(column.into_column());
self
}

/// Add an EXISTS column
pub fn exists_column<N, T>(self, name: N, column_type: T) -> ExistsColumnBuilder<Self>
where
N: Into<Cow<'static, str>>,
T: Into<TypeRef>,
{
ExistsColumnBuilder {
builder: self,
name: name.into(),
column_type: column_type.into(),
path: None,
on_error: None,
}
pub fn exists(mut self, column: ExistsColumn) -> Self {
self.columns.push(column.into_column());
self
}

/// Add a NESTED PATH column
pub fn nested<P>(self, path: P) -> NestedPathBuilder
where
P: Into<Cow<'static, str>>,
{
NestedPathBuilder {
builder: self,
path: path.into(),
explicit: false,
json_path_name: None,
columns: Vec::new(),
}
pub fn nested(mut self, nested: NestedPath) -> Self {
self.columns.push(nested.into_column());
self
}

/// Convenience method for `ERROR ON ERROR`
Expand Down Expand Up @@ -156,8 +110,9 @@ impl Builder {
buf.write_str(", ")?;
write_json_path_expr(&mut buf, &self.path_expression)?;

self.as_json_path_name
.map(|x| write_as_json_path_name(&mut buf, &x));
if let Some(name) = &self.as_json_path_name {
write_as_json_path_name(&mut buf, name)?;
}

write_passing(&mut buf, self.passing)?;

Expand Down Expand Up @@ -272,12 +227,9 @@ impl Builder {
path,
as_json_path_name: json_path_name,
columns,
explicit_path,
// explicit_path,
} => {
buf.write_str("NESTED")?;
if *explicit_path {
buf.write_str(" PATH")?;
}
buf.write_str("NESTED PATH")?;
buf.write_str(" ")?;
write_json_path_expr(buf, path)?;

Expand Down
98 changes: 41 additions & 57 deletions src/extension/postgres/func/json_table/column.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,135 +3,120 @@ use std::borrow::Cow;
use crate::extension::postgres::json_fn::{QuotesClause, WrapperClause};
use crate::*;

use super::builder::Builder;
use super::types::*;
use super::types::{JsonTableColumn, OnClause};

/// Builder for regular columns in JSON_TABLE
/// Column definition in a `JSON_TABLE` `COLUMNS` clause.
#[derive(Debug, Clone)]
pub struct ColumnBuilder<T> {
pub(super) builder: T,
pub(super) name: Cow<'static, str>,
pub(super) column_type: TypeRef,
pub(super) format_json: bool,
pub(super) encoding_utf8: bool,
pub(super) path: Option<Cow<'static, str>>,
pub(super) wrapper: Option<WrapperClause>,
pub(super) quotes: Option<QuotesClause>,
pub(super) on_empty: Option<OnClause>,
pub(super) on_error: Option<OnClause>,
pub struct Column {
name: Cow<'static, str>,
column_type: TypeRef,
format_json: bool,
encoding_utf8: bool,
path: Option<Cow<'static, str>>,
wrapper: Option<WrapperClause>,
quotes: Option<QuotesClause>,
on_empty: Option<OnClause>,
on_error: Option<OnClause>,
}

impl<T> ColumnBuilder<T> {
/// Set FORMAT JSON
impl Column {
pub fn new(name: impl Into<Cow<'static, str>>, column_type: impl Into<TypeRef>) -> Self {
Self {
name: name.into(),
column_type: column_type.into(),
format_json: false,
encoding_utf8: false,
path: None,
wrapper: None,
quotes: None,
on_empty: None,
on_error: None,
}
}

/// Set `FORMAT JSON`.
pub fn format_json(mut self) -> Self {
self.format_json = true;
self
}

/// Set ENCODING UTF8 (requires FORMAT JSON)
/// Set `ENCODING UTF8`.
pub fn encoding_utf8(mut self) -> Self {
self.format_json = true;
self.encoding_utf8 = true;
self
}

/// Set PATH clause
pub fn path<P>(mut self, path: P) -> Self
where
P: Into<Cow<'static, str>>,
{
/// Set `PATH`.
pub fn path(mut self, path: impl Into<Cow<'static, str>>) -> Self {
self.path = Some(path.into());
self
}

/// Set WRAPPER clause
pub fn wrapper<W>(mut self, wrapper: W) -> Self
where
W: Into<WrapperClause>,
{
/// Set `WRAPPER`.
pub fn wrapper(mut self, wrapper: impl Into<WrapperClause>) -> Self {
self.wrapper = Some(wrapper.into());
self
}

/// Set QUOTES clause
pub fn quotes<Q>(mut self, quotes: Q) -> Self
where
Q: Into<QuotesClause>,
{
/// Set `QUOTES`.
pub fn quotes(mut self, quotes: impl Into<QuotesClause>) -> Self {
self.quotes = Some(quotes.into());
self
}

/// Convenience method for `ERROR ON EMPTY`
pub fn error_on_empty(mut self) -> Self {
self.on_empty = Some(OnClause::Error);
self
}

/// Convenience method for `NULL ON EMPTY`
pub fn null_on_empty(mut self) -> Self {
self.on_empty = Some(OnClause::Null);
self
}

/// Convenience method for `EMPTY ARRAY ON EMPTY`
pub fn empty_array_on_empty(mut self) -> Self {
self.on_empty = Some(OnClause::EmptyArray);
self
}

/// Convenience method for `EMPTY OBJECT ON EMPTY`
pub fn empty_object_on_empty(mut self) -> Self {
self.on_empty = Some(OnClause::EmptyObject);
self
}

/// Convenience method for `DEFAULT <expr> ON EMPTY`
pub fn default_on_empty<E>(mut self, expr: E) -> Self
where
E: Into<Expr>,
{
pub fn default_on_empty(mut self, expr: impl Into<Expr>) -> Self {
self.on_empty = Some(OnClause::Default(expr.into()));
self
}

/// Convenience method for `ERROR ON ERROR`
pub fn error_on_error(mut self) -> Self {
self.on_error = Some(OnClause::Error);
self
}

/// Convenience method for `NULL ON ERROR`
pub fn null_on_error(mut self) -> Self {
self.on_error = Some(OnClause::Null);
self
}

/// Convenience method for `EMPTY ARRAY ON ERROR`
pub fn empty_array_on_error(mut self) -> Self {
self.on_error = Some(OnClause::EmptyArray);
self
}

/// Convenience method for `EMPTY OBJECT ON ERROR`
pub fn empty_object_on_error(mut self) -> Self {
self.on_error = Some(OnClause::EmptyObject);
self
}

/// Convenience method for `DEFAULT <expr> ON ERROR`
pub fn default_on_error<E>(mut self, expr: E) -> Self
where
E: Into<Expr>,
{
pub fn default_on_error(mut self, expr: impl Into<Expr>) -> Self {
self.on_error = Some(OnClause::Default(expr.into()));
self
}
}

impl ColumnBuilder<Builder> {
/// Finish building this column and return to the main builder
pub fn build_column(mut self) -> Builder {
self.builder.columns.push(JsonTableColumn::Regular {
pub(super) fn into_column(self) -> JsonTableColumn {
JsonTableColumn::Regular {
name: self.name,
column_type: self.column_type,
format_json: self.format_json,
Expand All @@ -141,7 +126,6 @@ impl ColumnBuilder<Builder> {
quotes: self.quotes,
on_empty: self.on_empty,
on_error: self.on_error,
});
self.builder
}
}
}
Loading
Loading