From 39e8604b23850a81d72a3a7546e145a246e6fac1 Mon Sep 17 00:00:00 2001
From: Japin Li <japinli@hotmail.com>
Date: Mon, 8 Jul 2024 16:51:12 +0800
Subject: [PATCH] Add vectorization for timestamp[tz] data types (#266)

---
 .../columnar/sql/columnar--11.1-3--11.1-4.sql | 18 ++++++++++++++
 .../columnar/vectorization/types/date.c       |  8 ++++++-
 columnar/src/test/regress/columnar_schedule   |  1 +
 .../expected/columnar_vectorization.out       | 24 +++++++++++++++++++
 .../regress/sql/columnar_vectorization.sql    |  9 +++++++
 5 files changed, 59 insertions(+), 1 deletion(-)
 create mode 100644 columnar/src/test/regress/expected/columnar_vectorization.out
 create mode 100644 columnar/src/test/regress/sql/columnar_vectorization.sql

diff --git a/columnar/src/backend/columnar/sql/columnar--11.1-3--11.1-4.sql b/columnar/src/backend/columnar/sql/columnar--11.1-3--11.1-4.sql
index 2255b7f0..b88c769f 100644
--- a/columnar/src/backend/columnar/sql/columnar--11.1-3--11.1-4.sql
+++ b/columnar/src/backend/columnar/sql/columnar--11.1-3--11.1-4.sql
@@ -100,3 +100,21 @@ CREATE FUNCTION vtime_gt(time, time) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE
 CREATE FUNCTION vtime_lt(time, time) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT;
 CREATE FUNCTION vtime_le(time, time) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT;
 CREATE FUNCTION vtime_ge(time, time) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT;
+
+-- timestamp
+
+CREATE FUNCTION vtimestamp_eq(timestamp, timestamp) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT;
+CREATE FUNCTION vtimestamp_ne(timestamp, timestamp) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT;
+CREATE FUNCTION vtimestamp_gt(timestamp, timestamp) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT;
+CREATE FUNCTION vtimestamp_lt(timestamp, timestamp) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT;
+CREATE FUNCTION vtimestamp_le(timestamp, timestamp) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT;
+CREATE FUNCTION vtimestamp_ge(timestamp, timestamp) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT;
+
+-- timestamptz
+
+CREATE FUNCTION vtimestamptz_eq(timestamptz, timestamptz) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT;
+CREATE FUNCTION vtimestamptz_ne(timestamptz, timestamptz) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT;
+CREATE FUNCTION vtimestamptz_gt(timestamptz, timestamptz) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT;
+CREATE FUNCTION vtimestamptz_lt(timestamptz, timestamptz) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT;
+CREATE FUNCTION vtimestamptz_le(timestamptz, timestamptz) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT;
+CREATE FUNCTION vtimestamptz_ge(timestamptz, timestamptz) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT;
diff --git a/columnar/src/backend/columnar/vectorization/types/date.c b/columnar/src/backend/columnar/vectorization/types/date.c
index 1936cb1a..5119b532 100644
--- a/columnar/src/backend/columnar/vectorization/types/date.c
+++ b/columnar/src/backend/columnar/vectorization/types/date.c
@@ -10,4 +10,10 @@
 BUILD_CMP_OPERATOR_INT(date_, DateADT, DateADT)
 
 // time (int64)
-BUILD_CMP_OPERATOR_INT(time_, TimeADT, TimeADT)
\ No newline at end of file
+BUILD_CMP_OPERATOR_INT(time_, TimeADT, TimeADT)
+
+// timestamp (int64)
+BUILD_CMP_OPERATOR_INT(timestamp_, Timestamp, Timestamp)
+
+// timestamptz (int64)
+BUILD_CMP_OPERATOR_INT(timestamptz_, TimestampTz, TimestampTz)
diff --git a/columnar/src/test/regress/columnar_schedule b/columnar/src/test/regress/columnar_schedule
index 277d4db7..a5a426e5 100644
--- a/columnar/src/test/regress/columnar_schedule
+++ b/columnar/src/test/regress/columnar_schedule
@@ -37,3 +37,4 @@ test: columnar_cache
 test: columnar_aggregates
 test: columnar_upsert
 test: columnar_customindex
+test: columnar_vectorization
diff --git a/columnar/src/test/regress/expected/columnar_vectorization.out b/columnar/src/test/regress/expected/columnar_vectorization.out
new file mode 100644
index 00000000..85873fb0
--- /dev/null
+++ b/columnar/src/test/regress/expected/columnar_vectorization.out
@@ -0,0 +1,24 @@
+CREATE TABLE t (id int, ts timestamp) USING columnar;
+INSERT INTO t SELECT id, now() + id * '1 day'::interval FROM generate_series(1, 100000) id;
+EXPLAIN (costs off) SELECT * FROM t WHERE ts between '2026-01-01'::timestamp and '2026-02-01'::timestamp;
+                                                                              QUERY PLAN                                                                               
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ Custom Scan (ColumnarScan) on t
+   Columnar Projected Columns: id, ts
+   Columnar Chunk Group Filters: ((ts >= 'Thu Jan 01 00:00:00 2026'::timestamp without time zone) AND (ts <= 'Sun Feb 01 00:00:00 2026'::timestamp without time zone))
+   Columnar Vectorized Filter: ((ts >= 'Thu Jan 01 00:00:00 2026'::timestamp without time zone) AND (ts <= 'Sun Feb 01 00:00:00 2026'::timestamp without time zone))
+(4 rows)
+
+DROP TABLE t;
+CREATE TABLE t (id int, ts timestamptz) USING columnar;
+INSERT INTO t SELECT id, now() + id * '1 day'::interval FROM generate_series(1, 100000) id;
+EXPLAIN (costs off) SELECT * FROM t WHERE ts between '2026-01-01'::timestamptz and '2026-02-01'::timestamptz;
+                                                                               QUERY PLAN                                                                                
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ Custom Scan (ColumnarScan) on t
+   Columnar Projected Columns: id, ts
+   Columnar Chunk Group Filters: ((ts >= 'Thu Jan 01 00:00:00 2026 PST'::timestamp with time zone) AND (ts <= 'Sun Feb 01 00:00:00 2026 PST'::timestamp with time zone))
+   Columnar Vectorized Filter: ((ts >= 'Thu Jan 01 00:00:00 2026 PST'::timestamp with time zone) AND (ts <= 'Sun Feb 01 00:00:00 2026 PST'::timestamp with time zone))
+(4 rows)
+
+DROP TABLE t;
diff --git a/columnar/src/test/regress/sql/columnar_vectorization.sql b/columnar/src/test/regress/sql/columnar_vectorization.sql
new file mode 100644
index 00000000..ae0d9206
--- /dev/null
+++ b/columnar/src/test/regress/sql/columnar_vectorization.sql
@@ -0,0 +1,9 @@
+CREATE TABLE t (id int, ts timestamp) USING columnar;
+INSERT INTO t SELECT id, now() + id * '1 day'::interval FROM generate_series(1, 100000) id;
+EXPLAIN (costs off) SELECT * FROM t WHERE ts between '2026-01-01'::timestamp and '2026-02-01'::timestamp;
+DROP TABLE t;
+
+CREATE TABLE t (id int, ts timestamptz) USING columnar;
+INSERT INTO t SELECT id, now() + id * '1 day'::interval FROM generate_series(1, 100000) id;
+EXPLAIN (costs off) SELECT * FROM t WHERE ts between '2026-01-01'::timestamptz and '2026-02-01'::timestamptz;
+DROP TABLE t;