This is an automated email from the ASF dual-hosted git repository.
mihaibudiu pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/main by this push:
new 5b2a14494d [CALCITE-7524] JdbcSchema throws exception for DECIMAL
columns with precision 0 in JDBC metadata
5b2a14494d is described below
commit 5b2a14494dc370ac7692f57319f9748c31999418
Author: AlexisCubilla <[email protected]>
AuthorDate: Tue May 12 15:47:04 2026 -0300
[CALCITE-7524] JdbcSchema throws exception for DECIMAL columns with
precision 0 in JDBC metadata
Problem:
JdbcSchema builds RelDataType from DatabaseMetaData (COLUMN_SIZE,
DECIMAL_DIGITS).
Some JDBC drivers (notably PostgreSQL) return COLUMN_SIZE 0 for
NUMERIC/DECIMAL
columns declared without explicit precision. That led to
createSqlType(DECIMAL, 0, scale), which SqlTypeFactoryImpl rejects
("DECIMAL precision 0 must be between 1 and ...").
Root cause:
sqlType() treated any non-negative precision as literal. Zero is used by
drivers
as "unspecified" / unknown width, not as a valid SQL DECIMAL precision.
Fix:
When sqlTypeName is DECIMAL and reported precision is 0, replace it with
typeFactory.getTypeSystem().getDefaultPrecision(DECIMAL) before
createSqlType.
---
.../apache/calcite/adapter/jdbc/JdbcSchema.java | 9 ++-
.../apache/calcite/test/JdbcSchemaSqlTypeTest.java | 74 ++++++++++++++++++++++
2 files changed, 82 insertions(+), 1 deletion(-)
diff --git a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcSchema.java
b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcSchema.java
index eb1f11b74d..7d1cb8864a 100644
--- a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcSchema.java
+++ b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcSchema.java
@@ -448,7 +448,14 @@ private static RelDataType sqlType(RelDataTypeFactory
typeFactory, int dataType,
if (precision >= 0
&& scale >= 0
&& sqlTypeName.allowsPrecScale(true, true)) {
- return typeFactory.createSqlType(sqlTypeName, precision, scale);
+ int p = precision;
+ // Some JDBC drivers (e.g. PostgreSQL) report column size 0 for NUMERIC /
+ // DECIMAL columns without explicit precision in DDL. Calcite rejects
+ // DECIMAL(0, scale) (see SqlTypeFactoryImpl#createSqlType).
+ if (p == 0 && sqlTypeName == SqlTypeName.DECIMAL) {
+ p = typeFactory.getTypeSystem().getDefaultPrecision(sqlTypeName);
+ }
+ return typeFactory.createSqlType(sqlTypeName, p, scale);
} else if (precision >= 0 && sqlTypeName.allowsPrecNoScale()) {
return typeFactory.createSqlType(sqlTypeName, precision);
} else {
diff --git
a/core/src/test/java/org/apache/calcite/test/JdbcSchemaSqlTypeTest.java
b/core/src/test/java/org/apache/calcite/test/JdbcSchemaSqlTypeTest.java
new file mode 100644
index 0000000000..33a74c9416
--- /dev/null
+++ b/core/src/test/java/org/apache/calcite/test/JdbcSchemaSqlTypeTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+package org.apache.calcite.test;
+
+import org.apache.calcite.adapter.jdbc.JdbcSchema;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.rel.type.RelDataTypeSystem;
+import org.apache.calcite.sql.type.SqlTypeFactoryImpl;
+import org.apache.calcite.sql.type.SqlTypeName;
+
+import org.junit.jupiter.api.Test;
+
+import java.lang.reflect.Method;
+import java.sql.Types;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/** Tests JDBC metadata type mapping in {@link JdbcSchema}. */
+class JdbcSchemaSqlTypeTest {
+
+ @Test void jdbcSchemaSqlTypeMapsNumericZeroPrecision() throws Exception {
+ final RelDataTypeFactory factory =
+ new SqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT);
+ final Method sqlType =
+ JdbcSchema.class.getDeclaredMethod(
+ "sqlType",
+ RelDataTypeFactory.class,
+ int.class,
+ int.class,
+ int.class,
+ String.class);
+ sqlType.setAccessible(true);
+ final RelDataType t =
+ (RelDataType) sqlType.invoke(null, factory, Types.NUMERIC, 0, 6, null);
+ assertThat(t.getSqlTypeName(), is(SqlTypeName.DECIMAL));
+ assertThat(t.getPrecision(), is(19));
+ assertThat(t.getScale(), is(6));
+ }
+
+ @Test void jdbcSchemaSqlTypeMapsDecimalZeroPrecision() throws Exception {
+ final RelDataTypeFactory factory =
+ new SqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT);
+ final Method sqlType =
+ JdbcSchema.class.getDeclaredMethod(
+ "sqlType",
+ RelDataTypeFactory.class,
+ int.class,
+ int.class,
+ int.class,
+ String.class);
+ sqlType.setAccessible(true);
+ final RelDataType t =
+ (RelDataType) sqlType.invoke(null, factory, Types.DECIMAL, 0, 2, null);
+ assertThat(t.getSqlTypeName(), is(SqlTypeName.DECIMAL));
+ assertThat(t.getPrecision(), is(19));
+ assertThat(t.getScale(), is(2));
+ }
+}