Skip to content

Commit

Permalink
feat(expr): add missing basic exprs for timestamptz and bytea (#1…
Browse files Browse the repository at this point in the history
  • Loading branch information
xiangjinwu committed Jul 3, 2023
1 parent 5e0386f commit f310e46
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 8 deletions.
17 changes: 16 additions & 1 deletion e2e_test/batch/functions/session_timezone.slt
Original file line number Diff line number Diff line change
Expand Up @@ -85,5 +85,20 @@ select '2016-10-31 11:00:00+00:00'::timestamptz - (interval '24 hours' + interva
----
2016-10-29 12:00:00+01:00

# Test case from https://github.com/postgres/postgres/blob/REL_15_3/src/backend/utils/adt/timestamp.c#L2697

statement ok
SET timezone = 'EST5EDT';

query T
SELECT ('2005-10-30 13:22:00-05:00'::timestamptz - '2005-10-29 13:22:00-04:00'::timestamptz);
----
1 day 01:00:00

query T
SELECT ('2005-10-29 13:22:00-04:00'::timestamptz + ('2005-10-30 13:22:00-05:00'::timestamptz - '2005-10-29 13:22:00-04:00'::timestamptz)) at time zone 'EST';
----
2005-10-30 14:22:00

statement ok
set timezone = 'UTC';
set timezone = 'UTC';
30 changes: 30 additions & 0 deletions e2e_test/batch/types/bytea.slt.part
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,33 @@ query T
SELECT 'De\\678dBeEf'::bytea;
----
\x44655c3637386442654566

query T
select 'a'::bytea = '\x61';
----
t

query T
select '\x31'::bytea > '1'::bytea;
----
f

query TI
select 'a'::varchar::bytea, octet_length('a'::varchar::bytea);
----
\x61 1

query TI
select 'a'::bytea::varchar, octet_length('a'::bytea::varchar);
----
\x61 4

query II
select bit_length('😇'), bit_length('😇'::bytea);
----
32 32

query II
select length('😇'), length('😇'::bytea);
----
1 4
7 changes: 5 additions & 2 deletions e2e_test/batch/types/timestamptz_utc.slt.part
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,6 @@ select extract(epoch from to_timestamp(1262349296.7890115));
----
1262349296.789012

# Arithmetic are currently done in UTC rather than session TimeZone

# If this was done in PostgreSQL under 'US/Pacific', it will return 1 hour
# earlier because there are only 23 hours in this day due to Daylight Saving.
query T
Expand All @@ -134,6 +132,11 @@ select TIMESTAMP WITH TIME ZONE '2022-08-09 00:00:00' - (INTERVAL '-2147483648 d
statement error out of range
select TIMESTAMP WITH TIME ZONE '2022-08-09 00:00:00' + (INTERVAL '-2147483648 days');

query T
select to_timestamp(1672535000) - to_timestamp(1672530000);
----
01:23:20

# timestamptz agg
query T
select max('2022-10-01 12:00:00-08:00'::timestamp with time zone);
Expand Down
16 changes: 16 additions & 0 deletions src/common/src/types/interval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,22 @@ impl Interval {
usecs: 0,
}
}

// Assuming 1 day = 24 hours, adjust `abs(usecs)` to be less than 24 hours, and has the same
// sign with `days`.
pub fn justify_hour(self) -> Option<Self> {
let whole_day = (self.usecs / USECS_PER_DAY) as i32;
let mut usecs = self.usecs % USECS_PER_DAY;
let mut days = self.days.checked_add(whole_day)?;
if days > 0 && usecs < 0 {
usecs += USECS_PER_DAY;
days -= 1;
} else if days < 0 && usecs > 0 {
usecs -= USECS_PER_DAY;
days += 1;
}
Some(Self::from_month_day_usec(self.months, days, usecs))
}
}

/// A separate mod so that `use types::*` or `use interval::*` does not `use IntervalTestExt` by
Expand Down
1 change: 1 addition & 0 deletions src/expr/src/vector_op/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ pub fn int32_to_bool(input: i32) -> Result<bool> {
#[function("cast(interval) -> varchar")]
#[function("cast(timestamp) -> varchar")]
#[function("cast(jsonb) -> varchar")]
#[function("cast(bytea) -> varchar")]
#[function("cast(list) -> varchar")]
pub fn general_to_text(elem: impl ToText, mut writer: &mut dyn Write) -> Result<()> {
elem.write(&mut writer).unwrap();
Expand Down
8 changes: 8 additions & 0 deletions src/expr/src/vector_op/cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ use risingwave_expr_macro::function;
#[function("equal(time, interval) -> boolean")]
#[function("equal(interval, time) -> boolean")]
#[function("equal(varchar, varchar) -> boolean")]
#[function("equal(bytea, bytea) -> boolean")]
#[function("equal(list, list) -> boolean")]
#[function("equal(struct, struct) -> boolean")]
pub fn general_eq<T1, T2, T3>(l: T1, r: T2) -> bool
Expand All @@ -59,6 +60,7 @@ where
#[function("not_equal(time, interval) -> boolean")]
#[function("not_equal(interval, time) -> boolean")]
#[function("not_equal(varchar, varchar) -> boolean")]
#[function("not_equal(bytea, bytea) -> boolean")]
#[function("not_equal(list, list) -> boolean")]
#[function("not_equal(struct, struct) -> boolean")]
pub fn general_ne<T1, T2, T3>(l: T1, r: T2) -> bool
Expand All @@ -85,6 +87,7 @@ where
#[function("greater_than_or_equal(time, interval) -> boolean")]
#[function("greater_than_or_equal(interval, time) -> boolean")]
#[function("greater_than_or_equal(varchar, varchar) -> boolean")]
#[function("greater_than_or_equal(bytea, bytea) -> boolean")]
#[function("greater_than_or_equal(list, list) -> boolean")]
#[function("greater_than_or_equal(struct, struct) -> boolean")]
pub fn general_ge<T1, T2, T3>(l: T1, r: T2) -> bool
Expand All @@ -111,6 +114,7 @@ where
#[function("greater_than(time, interval) -> boolean")]
#[function("greater_than(interval, time) -> boolean")]
#[function("greater_than(varchar, varchar) -> boolean")]
#[function("greater_than(bytea, bytea) -> boolean")]
#[function("greater_than(list, list) -> boolean")]
#[function("greater_than(struct, struct) -> boolean")]
pub fn general_gt<T1, T2, T3>(l: T1, r: T2) -> bool
Expand All @@ -137,6 +141,7 @@ where
#[function("less_than_or_equal(time, interval) -> boolean")]
#[function("less_than_or_equal(interval, time) -> boolean")]
#[function("less_than_or_equal(varchar, varchar) -> boolean")]
#[function("less_than_or_equal(bytea, bytea) -> boolean")]
#[function("less_than_or_equal(list, list) -> boolean")]
#[function("less_than_or_equal(struct, struct) -> boolean")]
pub fn general_le<T1, T2, T3>(l: T1, r: T2) -> bool
Expand All @@ -163,6 +168,7 @@ where
#[function("less_than(time, interval) -> boolean")]
#[function("less_than(interval, time) -> boolean")]
#[function("less_than(varchar, varchar) -> boolean")]
#[function("less_than(bytea, bytea) -> boolean")]
#[function("less_than(list, list) -> boolean")]
#[function("less_than(struct, struct) -> boolean")]
pub fn general_lt<T1, T2, T3>(l: T1, r: T2) -> bool
Expand All @@ -189,6 +195,7 @@ where
#[function("is_distinct_from(time, interval) -> boolean")]
#[function("is_distinct_from(interval, time) -> boolean")]
#[function("is_distinct_from(varchar, varchar) -> boolean")]
#[function("is_distinct_from(bytea, bytea) -> boolean")]
#[function("is_distinct_from(list, list) -> boolean")]
#[function("is_distinct_from(struct, struct) -> boolean")]
pub fn general_is_distinct_from<T1, T2, T3>(l: Option<T1>, r: Option<T2>) -> bool
Expand All @@ -215,6 +222,7 @@ where
#[function("is_not_distinct_from(time, interval) -> boolean")]
#[function("is_not_distinct_from(interval, time) -> boolean")]
#[function("is_not_distinct_from(varchar, varchar) -> boolean")]
#[function("is_not_distinct_from(bytea, bytea) -> boolean")]
#[function("is_not_distinct_from(list, list) -> boolean")]
#[function("is_not_distinct_from(struct, struct) -> boolean")]
pub fn general_is_not_distinct_from<T1, T2, T3>(l: Option<T1>, r: Option<T2>) -> bool
Expand Down
21 changes: 16 additions & 5 deletions src/expr/src/vector_op/length.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,24 @@ pub fn length(s: &str) -> i32 {
}

#[function("octet_length(varchar) -> int32")]
pub fn octet_length(s: &str) -> i32 {
pub fn octet_length_str(s: &str) -> i32 {
s.as_bytes().len() as i32
}

#[function("length(bytea) -> int32")]
#[function("octet_length(bytea) -> int32")]
pub fn octet_length_bytea(s: &[u8]) -> i32 {
s.len() as i32
}

#[function("bit_length(varchar) -> int32")]
pub fn bit_length(s: &str) -> i32 {
octet_length(s) * 8
pub fn bit_length_str(s: &str) -> i32 {
octet_length_str(s) * 8
}

#[function("bit_length(bytea) -> int32")]
pub fn bit_length_bytea(s: &[u8]) -> i32 {
octet_length_bytea(s) * 8
}

#[cfg(test)]
Expand All @@ -49,7 +60,7 @@ mod tests {
let cases = [("hello world", 11), ("你好", 6), ("😇哈哈hhh", 13)];

for (s, expected) in cases {
assert_eq!(octet_length(s), expected);
assert_eq!(octet_length_str(s), expected);
}
}

Expand All @@ -62,7 +73,7 @@ mod tests {
];

for (s, expected) in cases {
assert_eq!(bit_length(s), expected);
assert_eq!(bit_length_str(s), expected);
}
}
}
10 changes: 10 additions & 0 deletions src/expr/src/vector_op/timestamptz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,16 @@ pub fn timestamptz_at_time_zone(input: i64, time_zone: &str) -> Result<Timestamp
Ok(Timestamp(naive))
}

/// This operation is zone agnostic.
#[function("subtract(timestamptz, timestamptz) -> interval")]
pub fn timestamptz_timestamptz_sub(l: i64, r: i64) -> Result<Interval> {
let usecs = l.checked_sub(r).ok_or(ExprError::NumericOverflow)?;
let interval = Interval::from_month_day_usec(0, 0, usecs);
// https://github.com/postgres/postgres/blob/REL_15_3/src/backend/utils/adt/timestamp.c#L2697
let interval = interval.justify_hour().ok_or(ExprError::NumericOverflow)?;
Ok(interval)
}

#[function("subtract_with_time_zone(timestamptz, interval, varchar) -> timestamptz")]
pub fn timestamptz_interval_sub(input: i64, interval: Interval, time_zone: &str) -> Result<i64> {
timestamptz_interval_add(
Expand Down

0 comments on commit f310e46

Please sign in to comment.