Skip to content

Commit 47aa6b2

Browse files
GrandChamanJulius de Bruijn
authored and
Julius de Bruijn
committed
Added support for 'ROW_TO_JSON' function for postgresql
1 parent da00612 commit 47aa6b2

File tree

5 files changed

+104
-0
lines changed

5 files changed

+104
-0
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
# Changelog
2+
## Unreleased
3+
4+
- Added support for `ROW_TO_JSON` function in postgresql
25

36
## v0.2.0-alpha.13
47

src/ast/function.rs

+8
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ mod lower;
55
mod maximum;
66
mod minimum;
77
mod row_number;
8+
mod row_to_json;
89
mod sum;
910
mod upper;
1011

@@ -15,6 +16,8 @@ pub use lower::*;
1516
pub use maximum::*;
1617
pub use minimum::*;
1718
pub use row_number::*;
19+
#[cfg(all(feature = "json", feature = "postgresql"))]
20+
pub use row_to_json::*;
1821
pub use sum::*;
1922
pub use upper::*;
2023

@@ -31,6 +34,8 @@ pub struct Function<'a> {
3134
/// A database function type
3235
#[derive(Debug, Clone, PartialEq)]
3336
pub(crate) enum FunctionType<'a> {
37+
#[cfg(all(feature = "json", feature = "postgresql"))]
38+
RowToJson(RowToJson<'a>),
3439
RowNumber(RowNumber<'a>),
3540
Count(Count<'a>),
3641
AggregateToString(AggregateToString<'a>),
@@ -54,6 +59,9 @@ impl<'a> Aliasable<'a> for Function<'a> {
5459
}
5560
}
5661

62+
#[cfg(all(feature = "json", feature = "postgresql"))]
63+
function!(RowToJson);
64+
5765
function!(
5866
RowNumber,
5967
Count,

src/ast/function/row_to_json.rs

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
use super::Function;
2+
use crate::ast::Table;
3+
4+
#[derive(Debug, Clone, PartialEq)]
5+
#[cfg_attr(feature = "docs", doc(cfg(feature = "postgresql")))]
6+
#[cfg(all(feature = "json", feature = "postgresql"))]
7+
/// A representation of the `ROW_TO_JSON` function in the database.
8+
/// Only for `Postgresql`
9+
pub struct RowToJson<'a> {
10+
pub(crate) expr: Table<'a>,
11+
pub(crate) pretty_print: bool,
12+
}
13+
14+
/// Return the given table in `JSON` format.
15+
///
16+
/// Only available for `Postgresql`
17+
///
18+
/// ```no_run
19+
/// # use quaint::{ast::*, visitor::{Visitor, Postgres}};
20+
/// # fn main() -> Result<(), quaint::error::Error> {
21+
/// let cte = Select::default()
22+
/// .value(val!("hello_world").alias("toto"))
23+
/// .into_cte("one");
24+
/// let select = Select::from_table("one")
25+
/// .value(row_to_json("one", false))
26+
/// .with(cte);
27+
/// let result = api.conn().select(select).await?;
28+
///
29+
/// assert_eq!(
30+
/// Value::Json(Some(serde_json::json!({
31+
/// "toto": "hello_world"
32+
/// }))),
33+
/// result.into_single().unwrap()[0]
34+
/// );
35+
/// # Ok(())
36+
/// # }
37+
/// ```
38+
#[cfg_attr(feature = "docs", doc(cfg(feature = "postgresql")))]
39+
#[cfg(all(feature = "json", feature = "postgresql"))]
40+
pub fn row_to_json<'a, T>(expr: T, pretty_print: bool) -> Function<'a>
41+
where
42+
T: Into<Table<'a>>,
43+
{
44+
let fun = RowToJson {
45+
expr: expr.into(),
46+
pretty_print,
47+
};
48+
49+
fun.into()
50+
}

src/tests/query.rs

+38
Original file line numberDiff line numberDiff line change
@@ -1457,6 +1457,44 @@ async fn enum_values(api: &mut dyn TestApi) -> crate::Result<()> {
14571457
Ok(())
14581458
}
14591459

1460+
#[test_each_connector(tags("postgresql"))]
1461+
#[cfg(all(feature = "json", feature = "postgresql"))]
1462+
async fn row_to_json_normal(api: &mut dyn TestApi) -> crate::Result<()> {
1463+
let cte = Select::default()
1464+
.value(val!("hello_world").alias("toto"))
1465+
.into_cte("one");
1466+
let select = Select::from_table("one").value(row_to_json("one", false)).with(cte);
1467+
let result = api.conn().select(select).await?;
1468+
1469+
assert_eq!(
1470+
Value::Json(Some(serde_json::json!({
1471+
"toto": "hello_world"
1472+
}))),
1473+
result.into_single().unwrap()[0]
1474+
);
1475+
1476+
Ok(())
1477+
}
1478+
1479+
#[test_each_connector(tags("postgresql"))]
1480+
#[cfg(all(feature = "json", feature = "postgresql"))]
1481+
async fn row_to_json_pretty(api: &mut dyn TestApi) -> crate::Result<()> {
1482+
let cte = Select::default()
1483+
.value(val!("hello_world").alias("toto"))
1484+
.into_cte("one");
1485+
let select = Select::from_table("one").value(row_to_json("one", true)).with(cte);
1486+
let result = api.conn().select(select).await?;
1487+
1488+
assert_eq!(
1489+
Value::Json(Some(serde_json::json!({
1490+
"toto": "hello_world"
1491+
}))),
1492+
result.into_single().unwrap()[0]
1493+
);
1494+
1495+
Ok(())
1496+
}
1497+
14601498
#[test_each_connector(ignore("mysql"))]
14611499
async fn single_common_table_expression(api: &mut dyn TestApi) -> crate::Result<()> {
14621500
let cte = Select::default()

src/visitor.rs

+5
Original file line numberDiff line numberDiff line change
@@ -921,6 +921,11 @@ pub trait Visitor<'a> {
921921
FunctionType::AggregateToString(agg) => {
922922
self.visit_aggregate_to_string(agg.value.as_ref().clone())?;
923923
}
924+
#[cfg(all(feature = "json", feature = "postgresql"))]
925+
FunctionType::RowToJson(row_to_json) => {
926+
self.write("ROW_TO_JSON")?;
927+
self.surround_with("(", ")", |ref mut s| s.visit_table(row_to_json.expr, false))?
928+
}
924929
FunctionType::Average(avg) => {
925930
self.visit_average(avg)?;
926931
}

0 commit comments

Comments
 (0)