Skip to content

Commit

Permalink
* add test
Browse files Browse the repository at this point in the history
* support array type

Signed-off-by: Zejiong Dong <[email protected]>
  • Loading branch information
ZENOTME committed Oct 25, 2022
1 parent 39fd793 commit c67bd5e
Show file tree
Hide file tree
Showing 2 changed files with 259 additions and 67 deletions.
219 changes: 152 additions & 67 deletions sqllogictest-bin/src/engines/postgres_extended.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::sync::Arc;

use anyhow::Context;
use async_trait::async_trait;
use chrono::{NaiveDate, NaiveDateTime, NaiveTime, DateTime};
use chrono::{DateTime, NaiveDate, NaiveDateTime, NaiveTime};
use pg_interval::Interval;
use postgres_types::Type;
use rust_decimal::Decimal;
Expand Down Expand Up @@ -74,6 +74,60 @@ macro_rules! array_process {
}
}
};
($row:ident, $output:ident, $idx:ident, $t:ty, $convert:ident) => {
let value: Option<Vec<Option<$t>>> = $row.get($idx);
match value {
Some(value) => {
write!($output, "{{").unwrap();
for (i, v) in value.iter().enumerate() {
match v {
Some(v) => {
write!($output, "{}", $convert(v)).unwrap();
}
None => {
write!($output, "NULL").unwrap();
}
}
if i < value.len() - 1 {
write!($output, ",").unwrap();
}
}
write!($output, "}}").unwrap();
}
None => {
write!($output, "NULL").unwrap();
}
}
};
($self:ident, $row:ident, $output:ident, $idx:ident, $t:ty, $ty_name:expr) => {
let value: Option<Vec<Option<$t>>> = $row.get($idx);
match value {
Some(value) => {
write!($output, "{{").unwrap();
for (i, v) in value.iter().enumerate() {
match v {
Some(v) => {
let sql = format!("select ($1::{})::varchar", stringify!($ty_name));
let tmp_rows = $self.client.query(&sql, &[&v]).await.unwrap();
let value: &str = tmp_rows.get(0).unwrap().get(0);
assert!(value.len() > 0);
write!($output, "{}", value).unwrap();
}
None => {
write!($output, "NULL").unwrap();
}
}
if i < value.len() - 1 {
write!($output, ",").unwrap();
}
}
write!($output, "}}").unwrap();
}
None => {
write!($output, "NULL").unwrap();
}
}
};
}

macro_rules! single_process {
Expand All @@ -88,17 +142,25 @@ macro_rules! single_process {
}
}
};
}

macro_rules! str_process {
($row:ident, $output:ident, $idx:ident, $t:ty, $convert:ident) => {
let value: Option<$t> = $row.get($idx);
match value {
Some(value) => {
write!($output, "{}", $convert(&value)).unwrap();
}
None => {
write!($output, "NULL").unwrap();
}
}
};
($self:ident, $row:ident, $output:ident, $idx:ident, $t:ty, $ty_name:expr) => {
let value: Option<$t> = $row.get($idx);
match value {
Some(value) => {
let sql = format!("select ($1::{})::varchar", stringify!($ty_name));
let tmp_rows = $self.client.query(&sql, &[&value]).await.unwrap();
let value: &str = tmp_rows.get(0).unwrap().get(0);
assert!(value.len()>0);
assert!(value.len() > 0);
write!($output, "{}", value).unwrap();
}
None => {
Expand All @@ -108,6 +170,46 @@ macro_rules! str_process {
};
}

fn bool_to_str(value: &bool) -> &'static str {
if *value {
"t"
} else {
"f"
}
}

fn varchar_to_str(value: &str) -> String {
if value.is_empty() {
"(empty)".to_string()
} else {
value.to_string()
}
}

fn float4_to_str(value: &f32) -> String {
if value.is_nan() {
"NaN".to_string()
} else if *value == f32::INFINITY {
"Infinity".to_string()
} else if *value == f32::NEG_INFINITY {
"-Infinity".to_string()
} else {
value.to_string()
}
}

fn float8_to_str(value: &f64) -> String {
if value.is_nan() {
"NaN".to_string()
} else if *value == f64::INFINITY {
"Infinity".to_string()
} else if *value == f64::NEG_INFINITY {
"-Infinity".to_string()
} else {
value.to_string()
}
}

#[async_trait]
impl sqllogictest::AsyncDB for PostgresExtended {
type Error = tokio_postgres::error::Error;
Expand Down Expand Up @@ -154,6 +256,9 @@ impl sqllogictest::AsyncDB for PostgresExtended {
Type::TIMESTAMP => {
single_process!(row, output, idx, NaiveDateTime);
}
Type::BOOL => {
single_process!(row, output, idx, bool, bool_to_str);
}
Type::INT2_ARRAY => {
array_process!(row, output, idx, i16);
}
Expand All @@ -163,84 +268,64 @@ impl sqllogictest::AsyncDB for PostgresExtended {
Type::INT8_ARRAY => {
array_process!(row, output, idx, i64);
}
Type::BOOL_ARRAY => {
array_process!(row, output, idx, bool, bool_to_str);
}
Type::FLOAT4_ARRAY => {
array_process!(row, output, idx, f32);
array_process!(row, output, idx, f32, float4_to_str);
}
Type::FLOAT8_ARRAY => {
array_process!(row, output, idx, f64);
array_process!(row, output, idx, f64, float8_to_str);
}
Type::NUMERIC_ARRAY => {
array_process!(row, output, idx, Decimal);
}
Type::VARCHAR | Type::TEXT => {
let value: Option<&str> = row.get(idx);
match value {
Some(value) => {
if value.is_empty() {
write!(output, "(empty)").unwrap();
} else {
write!(output, "{}", value).unwrap();
}
}
None => {
write!(output, "NULL").unwrap();
}
}
Type::DATE_ARRAY => {
array_process!(row, output, idx, NaiveDate);
}
Type::BOOL => {
let value: Option<bool> = row.get(idx);
match value {
Some(value) => {
if value {
write!(output, "t").unwrap();
} else {
write!(output, "f").unwrap();
}
}
None => {
write!(output, "NULL").unwrap();
}
}
Type::TIME_ARRAY => {
array_process!(row, output, idx, NaiveTime);
}
Type::TIMESTAMP_ARRAY => {
array_process!(row, output, idx, NaiveDateTime);
}
Type::VARCHAR_ARRAY | Type::TEXT_ARRAY => {
array_process!(row, output, idx, String, varchar_to_str);
}
Type::VARCHAR | Type::TEXT => {
single_process!(row, output, idx, String, varchar_to_str);
}
Type::FLOAT4 => {
let value: Option<f32> = row.get(idx);
match value {
Some(value) => {
if value == f32::INFINITY {
write!(output, "Infinity").unwrap();
} else if value == f32::NEG_INFINITY {
write!(output, "-Infinity").unwrap();
} else {
write!(output, "{}", value).unwrap();
}
}
None => {
write!(output, "NULL").unwrap();
}
}
single_process!(row, output, idx, f32, float4_to_str);
}
Type::FLOAT8 => {
let value: Option<f64> = row.get(idx);
match value {
Some(value) => {
if value == f64::INFINITY {
write!(output, "Infinity").unwrap();
} else if value == f64::NEG_INFINITY {
write!(output, "-Infinity").unwrap();
} else {
write!(output, "{}", value).unwrap();
}
}
None => {
write!(output, "NULL").unwrap();
}
}
single_process!(row, output, idx, f64, float8_to_str);
}
Type::INTERVAL => {
str_process!(self,row, output, idx, Interval,INTERVAL);
single_process!(self, row, output, idx, Interval, INTERVAL);
}
Type::TIMESTAMPTZ => {
str_process!(self,row, output, idx, DateTime<chrono::Utc> ,TIMESTAMPTZ);
single_process!(
self,
row,
output,
idx,
DateTime<chrono::Utc>,
TIMESTAMPTZ
);
}
Type::INTERVAL_ARRAY => {
array_process!(self, row, output, idx, Interval, INTERVAL);
}
Type::TIMESTAMPTZ_ARRAY => {
array_process!(
self,
row,
output,
idx,
DateTime<chrono::Utc>,
TIMESTAMPTZ
);
}
_ => {
todo!("Don't support {} type now.", column.type_().name())
Expand Down
107 changes: 107 additions & 0 deletions sqllogictest-bin/src/engines/postgres_extended_test.slt
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# postgres_extended engine support following type:
# NOTE: array only support one dimension
# int2
# int2 array
# int4
# int4 array
# int8
# int8 array
# float4
# float4 array
# float8
# float8 array
# numeric (not include: NaN,+Inf,-Inf)
# numeric array
# varchar
# varchar array
# date
# date array
# time
# time array
# timestamp
# timestamp array
# timestamptz
# timestamptz array
# interval
# interval array
# bool
# bool array

# int2 && int2 array
query I
select 1::int2, '{1,2,3}'::int2[]
----
1 {1,2,3}

# int4 && int4 array
query I
select 1::int4, '{1,2,3}'::int4[]
----
1 {1,2,3}

# int8 && int8 array
query I
select 1::int8, '{1,2,3}'::int8[]
----
1 {1,2,3}

# float4 && float4 array
query I
select 1.0::float4, '{NaN,+Inf,-Inf}'::float4[]
----
1 {NaN,Infinity,-Infinity}

# float8 && float8 array
query I
select 1.0::float8, '{NaN,+Inf,-Inf}'::float8[]
----
1 {NaN,Infinity,-Infinity}

# numeric && numeric array
query I
select 1.0::numeric, '{2.0,3.0123,4.0123}'::numeric[]
----
1.0 {2.0,3.0123,4.0123}

# varchar && varchar array
query I
select 'a'::varchar, '{a,b,""}'::varchar[]
----
a {a,b,(empty)}

# date && date array
query I
select '2018-01-01'::date, '{2018-01-01,2018-01-02,2018-01-03}'::date[]
----
2018-01-01 {2018-01-01,2018-01-02,2018-01-03}

# time && time array
query I
select '12:00:00'::time, '{12:00:00,12:00:01,12:00:02}'::time[]
----
12:00:00 {12:00:00,12:00:01,12:00:02}

# timestamp && timestamp array
query I
select '2018-01-01 12:00:00'::timestamp, '{2018-01-01 12:00:00,2018-01-01 12:00:01,2018-01-01 12:00:02}'::timestamp[]
----
2018-01-01 12:00:00 {2018-01-01 12:00:00,2018-01-01 12:00:01,2018-01-01 12:00:02}

# timestamptz && timestamptz array
query I
select '2018-01-01 12:00:00+08'::timestamptz, '{2018-01-01 12:00:00+08,2018-01-01 12:00:01+08,2018-01-01 12:00:02+08}'::timestamptz[]
----
2018-01-01 12:00:00+08 {2018-01-01 12:00:00+08,2018-01-01 12:00:01+08,2018-01-01 12:00:02+08}

# interval && interval array
query I
select '1 day'::interval, '{1 day,2 mon,30 day}'::interval[]
----
1 day {1 day,2 mons,30 days}

# bool && bool array
query I
select true::bool, '{true,false}'::bool[]
----
t {t,f}

0 comments on commit c67bd5e

Please sign in to comment.