This is an automated email from the ASF dual-hosted git repository.

lidavidm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-adbc.git


The following commit(s) were added to refs/heads/main by this push:
     new 6abfb8513 test(c/driver/postgresql): add Materialize to test matrix 
(#4794)
6abfb8513 is described below

commit 6abfb851369a179bbc56ad72469a5b2ed1a200ae
Author: David Li <[email protected]>
AuthorDate: Sat Sep 19 18:34:20 2026 +0900

    test(c/driver/postgresql): add Materialize to test matrix (#4794)
    
    Closes #3690.
    
    Assisted-by: GPT-6 Astra <[email protected]>
---
 .github/workflows/integration.yml                  |  7 ++++-
 .../queries-materialize/type/bind/decimal.txtcase  | 24 +++++++++++++++
 .../queries-materialize/type/bind/time_us.txtcase  | 23 +++++++++++++++
 .../type/bind/timestamp_ns.txtcase                 | 23 +++++++++++++++
 .../type/bind/timestamptz_ns.txtcase               | 24 +++++++++++++++
 .../type/select/decimal.txtcase                    | 24 +++++++++++++++
 .../type/select/float32.txtcase                    | 30 +++++++++++++++++++
 .../type/select/float64.txtcase                    | 30 +++++++++++++++++++
 .../queries-materialize/type/select/json.txtcase   | 33 +++++++++++++++++++++
 .../queries-materialize/type/select/jsonb.txtcase  | 28 ++++++++++++++++++
 c/driver/postgresql/validation/tests/postgresql.py | 34 ++++++++++++++++++----
 .../postgresql/validation/tests/test_connection.py |  9 ++++++
 compose.yaml                                       | 12 ++++++++
 docs/source/driver/postgresql.rst                  |  3 +-
 14 files changed, 297 insertions(+), 7 deletions(-)

diff --git a/.github/workflows/integration.yml 
b/.github/workflows/integration.yml
index d1c9db29f..43fcb7fd9 100644
--- a/.github/workflows/integration.yml
+++ b/.github/workflows/integration.yml
@@ -337,6 +337,11 @@ jobs:
             vendor: cratedb
             uri: postgresql://crate@localhost:5436/doc?sslmode=disable
             experimental: true
+          - name: Materialize
+            service: materialize-test
+            vendor: materialize
+            uri: 
postgresql://materialize@localhost:5441/materialize?sslmode=disable
+            experimental: false
           - name: ParadeDB
             service: paradedb-test
             vendor: paradedb
@@ -356,7 +361,7 @@ jobs:
             service: cedardb-test
             vendor: cedardb
             uri: 
postgresql://localhost:5433/postgres?user=postgres&password=CedarDB2026%21
-            experimental: true
+            experimental: false
     steps:
       - name: Free up disk space
         run: |
diff --git 
a/c/driver/postgresql/validation/queries-materialize/type/bind/decimal.txtcase 
b/c/driver/postgresql/validation/queries-materialize/type/bind/decimal.txtcase
new file mode 100644
index 000000000..53180edff
--- /dev/null
+++ 
b/c/driver/postgresql/validation/queries-materialize/type/bind/decimal.txtcase
@@ -0,0 +1,24 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+// part: expected
+
+{"res": null}
+{"res": "-999.99"}
+{"res": "0"}
+{"res": "123.45"}
+{"res": "9999999.99"}
diff --git 
a/c/driver/postgresql/validation/queries-materialize/type/bind/time_us.txtcase 
b/c/driver/postgresql/validation/queries-materialize/type/bind/time_us.txtcase
new file mode 100644
index 000000000..dcb6e22da
--- /dev/null
+++ 
b/c/driver/postgresql/validation/queries-materialize/type/bind/time_us.txtcase
@@ -0,0 +1,23 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+// part: setup_query
+
+CREATE TABLE test_time (
+    idx INT,
+    res TIME
+);
diff --git 
a/c/driver/postgresql/validation/queries-materialize/type/bind/timestamp_ns.txtcase
 
b/c/driver/postgresql/validation/queries-materialize/type/bind/timestamp_ns.txtcase
new file mode 100644
index 000000000..56e335653
--- /dev/null
+++ 
b/c/driver/postgresql/validation/queries-materialize/type/bind/timestamp_ns.txtcase
@@ -0,0 +1,23 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+// part: setup_query
+
+CREATE TABLE test_timestamp (
+    idx INT,
+    res TIMESTAMP(6)
+);
diff --git 
a/c/driver/postgresql/validation/queries-materialize/type/bind/timestamptz_ns.txtcase
 
b/c/driver/postgresql/validation/queries-materialize/type/bind/timestamptz_ns.txtcase
new file mode 100644
index 000000000..8db0d3b99
--- /dev/null
+++ 
b/c/driver/postgresql/validation/queries-materialize/type/bind/timestamptz_ns.txtcase
@@ -0,0 +1,24 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+// part: setup_query
+
+CREATE TABLE test_timestamptz (
+    idx INT,
+    res TIMESTAMP(6) WITH TIME ZONE,
+    res2 TIMESTAMP(6) WITH TIME ZONE
+);
diff --git 
a/c/driver/postgresql/validation/queries-materialize/type/select/decimal.txtcase
 
b/c/driver/postgresql/validation/queries-materialize/type/select/decimal.txtcase
new file mode 100644
index 000000000..29fdc061c
--- /dev/null
+++ 
b/c/driver/postgresql/validation/queries-materialize/type/select/decimal.txtcase
@@ -0,0 +1,24 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+// part: expected
+
+{"res": "123.45"}
+{"res": "0"}
+{"res": "-999.99"}
+{"res": "9999999.99"}
+{"res": null}
diff --git 
a/c/driver/postgresql/validation/queries-materialize/type/select/float32.txtcase
 
b/c/driver/postgresql/validation/queries-materialize/type/select/float32.txtcase
new file mode 100644
index 000000000..b6e9ad856
--- /dev/null
+++ 
b/c/driver/postgresql/validation/queries-materialize/type/select/float32.txtcase
@@ -0,0 +1,30 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+// part: setup_query
+
+CREATE TABLE test_float32 (
+    idx INTEGER,
+    res REAL
+);
+
+INSERT INTO test_float32 (idx, res) VALUES (1, CAST('3.14' AS REAL));
+INSERT INTO test_float32 (idx, res) VALUES (2, CAST('0.0' AS REAL));
+INSERT INTO test_float32 (idx, res) VALUES (3, CAST('-3.4e38' AS REAL));
+INSERT INTO test_float32 (idx, res) VALUES (4, CAST('3.4e38' AS REAL));
+INSERT INTO test_float32 (idx, res) VALUES (5, CAST('1.175494351e-38' AS 
REAL));
+INSERT INTO test_float32 (idx, res) VALUES (6, NULL);
diff --git 
a/c/driver/postgresql/validation/queries-materialize/type/select/float64.txtcase
 
b/c/driver/postgresql/validation/queries-materialize/type/select/float64.txtcase
new file mode 100644
index 000000000..4db8390f9
--- /dev/null
+++ 
b/c/driver/postgresql/validation/queries-materialize/type/select/float64.txtcase
@@ -0,0 +1,30 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+// part: setup_query
+
+CREATE TABLE test_float64 (
+    idx INTEGER,
+    res DOUBLE PRECISION
+);
+
+INSERT INTO test_float64 (idx, res) VALUES (1, CAST('3.14159265358979' AS 
DOUBLE PRECISION));
+INSERT INTO test_float64 (idx, res) VALUES (2, CAST('0.0' AS DOUBLE 
PRECISION));
+INSERT INTO test_float64 (idx, res) VALUES (3, CAST('-1.7976931348623157e308' 
AS DOUBLE PRECISION));
+INSERT INTO test_float64 (idx, res) VALUES (4, CAST('1.7976931348623157e308' 
AS DOUBLE PRECISION));
+INSERT INTO test_float64 (idx, res) VALUES (5, CAST('2.2250738585072014e-308' 
AS DOUBLE PRECISION));
+INSERT INTO test_float64 (idx, res) VALUES (6, NULL);
diff --git 
a/c/driver/postgresql/validation/queries-materialize/type/select/json.txtcase 
b/c/driver/postgresql/validation/queries-materialize/type/select/json.txtcase
new file mode 100644
index 000000000..e61171d1b
--- /dev/null
+++ 
b/c/driver/postgresql/validation/queries-materialize/type/select/json.txtcase
@@ -0,0 +1,33 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+// part: metadata
+
+[tags]
+sql-type-name = "jsonb"
+
+// part: expected
+
+{"res": null}
+{"res": "null"}
+{"res": "\"foobar\""}
+{"res": "1"}
+{"res": "true"}
+{"res": "[]"}
+{"res": "[\"spam\",\"eggs\",2.5,false]"}
+{"res": "{\"a\":12345,\"b\":\"hello\",\"c\":[1,2,3],\"d\":{\"e\":\"nested\"}}"}
+{"res": "[{\"id\":1,\"name\":\"Alice\"},{\"id\":2,\"name\":\"Bob\"}]"}
diff --git 
a/c/driver/postgresql/validation/queries-materialize/type/select/jsonb.txtcase 
b/c/driver/postgresql/validation/queries-materialize/type/select/jsonb.txtcase
new file mode 100644
index 000000000..a301f733a
--- /dev/null
+++ 
b/c/driver/postgresql/validation/queries-materialize/type/select/jsonb.txtcase
@@ -0,0 +1,28 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+// part: expected
+
+{"res": null}
+{"res": "null"}
+{"res": "\"foobar\""}
+{"res": "1"}
+{"res": "true"}
+{"res": "[]"}
+{"res": "[\"spam\",\"eggs\",2.5,false]"}
+{"res": "{\"a\":12345,\"b\":\"hello\",\"c\":[1,2,3],\"d\":{\"e\":\"nested\"}}"}
+{"res": "[{\"id\":1,\"name\":\"Alice\"},{\"id\":2,\"name\":\"Bob\"}]"}
diff --git a/c/driver/postgresql/validation/tests/postgresql.py 
b/c/driver/postgresql/validation/tests/postgresql.py
index 0dee33afc..85f99c1f7 100644
--- a/c/driver/postgresql/validation/tests/postgresql.py
+++ b/c/driver/postgresql/validation/tests/postgresql.py
@@ -69,7 +69,7 @@ class PostgreSQLQuirks(model.DriverQuirks):
     )
 
     @property
-    def queries_paths(self) -> tuple[Path]:
+    def queries_paths(self) -> tuple[Path, ...]:
         return (Path(__file__).parent.parent / "queries",)
 
     def bind_parameter(self, index: int) -> str:
@@ -113,7 +113,7 @@ class CedarDBQuirks(PostgreSQLQuirks):
     )
 
     @property
-    def queries_paths(self) -> tuple[Path]:
+    def queries_paths(self) -> tuple[Path, ...]:
         return (
             *super().queries_paths,
             Path(__file__).parent.parent / "queries-cedardb",
@@ -139,7 +139,7 @@ class CockroachDBQuirks(PostgreSQLQuirks):
     )
 
     @property
-    def queries_paths(self) -> tuple[Path]:
+    def queries_paths(self) -> tuple[Path, ...]:
         return (
             *super().queries_paths,
             Path(__file__).parent.parent / "queries-cockroachdb",
@@ -164,8 +164,8 @@ class CrateDBQuirks(PostgreSQLQuirks):
     )
 
     @property
-    def queries_paths(self) -> tuple[Path]:
-        extra_paths: tuple[str] = ()
+    def queries_paths(self) -> tuple[Path, ...]:
+        extra_paths: tuple[Path, ...] = ()
         if os.environ.get("POSTGRES_TYPE_RESOLVER_MODE") != "builtin":
             extra_paths = (
                 Path(__file__).parent.parent / "queries-cratedb-typeresolver",
@@ -192,6 +192,28 @@ class CrateDBQuirks(PostgreSQLQuirks):
             yield
 
 
+class MaterializeQuirks(PostgreSQLQuirks):
+    vendor_version = re.compile(r"905[0-9]{2}")
+    short_version = "9.5"
+    features = PostgreSQLQuirks.features.with_values(
+        # Materialize cannot decode the driver's text parameter as regclass.
+        connection_get_table_schema=False,
+        current_catalog="materialize",
+        # The table metadata query fails with "function unnest(text) does not 
exist".
+        get_objects=False,
+        # COPY FROM only supports TEXT and CSV, while ingestion uses binary 
COPY.
+        # https://materialize.com/docs/sql/copy-from/
+        statement_bulk_ingest=False,
+    )
+
+    @property
+    def queries_paths(self) -> tuple[Path, ...]:
+        return (
+            *super().queries_paths,
+            Path(__file__).parent.parent / "queries-materialize",
+        )
+
+
 class ParadeDBQuirks(PostgreSQLQuirks):
     pass
 
@@ -218,6 +240,7 @@ VENDORS = (
     "citus",
     "cockroachdb",
     "cratedb",
+    "materialize",
     "paradedb",
     "timescaledb",
     "yugabytedb",
@@ -230,6 +253,7 @@ _QUIRKS = {
     "citus": CitusQuirks,
     "cockroachdb": CockroachDBQuirks,
     "cratedb": CrateDBQuirks,
+    "materialize": MaterializeQuirks,
     "paradedb": ParadeDBQuirks,
     "timescaledb": TimescaleDBQuirks,
     "yugabytedb": YugabyteDBQuirks,
diff --git a/c/driver/postgresql/validation/tests/test_connection.py 
b/c/driver/postgresql/validation/tests/test_connection.py
index e29253e20..5fb9cb649 100644
--- a/c/driver/postgresql/validation/tests/test_connection.py
+++ b/c/driver/postgresql/validation/tests/test_connection.py
@@ -33,11 +33,20 @@ class TestConnection(test_connection.TestConnection):
     def test_get_objects_catalog(self, conn, driver) -> None:
         if isinstance(driver, postgresql.CrateDBQuirks):
             pytest.skip("GetObjects is marked unsupported for CrateDB")
+        if isinstance(driver, postgresql.MaterializeQuirks):
+            pytest.skip("GetObjects is marked unsupported for Materialize")
         super().test_get_objects_catalog(conn, driver)
 
+    def test_get_objects_schema(self, conn, driver) -> None:
+        if isinstance(driver, postgresql.MaterializeQuirks):
+            pytest.skip("GetObjects is marked unsupported for Materialize")
+        super().test_get_objects_schema(conn, driver)
+
     def test_get_objects_table_not_exist(self, conn, driver) -> None:
         if isinstance(driver, postgresql.CrateDBQuirks):
             pytest.skip("GetObjects is marked unsupported for CrateDB")
+        if isinstance(driver, postgresql.MaterializeQuirks):
+            pytest.skip("GetObjects is marked unsupported for Materialize")
         super().test_get_objects_table_not_exist(conn, driver)
 
     def test_get_objects_column_filter_table(
diff --git a/compose.yaml b/compose.yaml
index 2d02cb5a8..28d356b8d 100644
--- a/compose.yaml
+++ b/compose.yaml
@@ -479,6 +479,18 @@ services:
     ports:
       - "5440:5432"
 
+  materialize-test:
+    container_name: adbc_materialize_test
+    image: materialize/materialized:v26.41.1
+    healthcheck:
+      test: ["CMD", "curl", "--fail", "http://localhost:6878/api/readyz";]
+      interval: 10s
+      timeout: 5s
+      retries: 20
+      start_period: 60s
+    ports:
+      - "5441:6875"
+
   spiceai-test:
     container_name: adbc-spiceai
     build:
diff --git a/docs/source/driver/postgresql.rst 
b/docs/source/driver/postgresql.rst
index 002bfa223..0fb23cea5 100644
--- a/docs/source/driver/postgresql.rst
+++ b/docs/source/driver/postgresql.rst
@@ -359,6 +359,7 @@ the PostgreSQL wire protocol:
 - CockroachDB
 - CrateDB
 - Google AlloyDB Omni
+- Materialize
 - ParadeDB
 - TimescaleDB
 - YugabyteDB
@@ -372,7 +373,7 @@ vendors:
 
 - CedarDB v2026-8-13 (unless the "builtin" type resolver is used, see above)
 
-The driver is not and will not support the following vendors:
+The driver does not and will not support the following vendors:
 
 - Amazon Redshift (note that a dedicated driver is available for Redshift from
   a third party, see :ref:`driver-table`)

Reply via email to