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

diqiu50 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/main by this push:
     new 2937e7be21 [#10519] fix(postgresql): handle unconstrained NUMERIC type 
with precision=0 (#10534)
2937e7be21 is described below

commit 2937e7be214f810b3eb1d693694a2689563b0a57
Author: Qi Yu <[email protected]>
AuthorDate: Mon May 18 11:52:32 2026 +0800

    [#10519] fix(postgresql): handle unconstrained NUMERIC type with 
precision=0 (#10534)
    
    ### What changes were proposed in this pull request?
    
    In `PostgreSqlTypeConverter.toGravitino()`, when a PostgreSQL column is
    defined as `NUMERIC` without explicit precision/scale, the JDBC driver
    returns `columnSize=0`. This was passed directly to
    `Types.DecimalType.of(0, ...)` which rejects precision=0 with an
    `IllegalArgumentException`.
    
    Fix: map `columnSize=null` or `columnSize=0` to `DECIMAL(38, 18)` — the
    maximum supported precision with a sensible default scale.
    
    ### Why are the changes needed?
    
    Fix: #10519
    
    Unconstrained `NUMERIC` columns are valid in PostgreSQL and commonly
    used. Loading any table containing such a column was completely broken.
    
    ### Does this PR introduce _any_ user-facing change?
    
    Yes — loading tables with unconstrained `NUMERIC` columns now succeeds,
    returning `DECIMAL(38, 18)` instead of throwing an error.
    
    ### How was this patch tested?
    
    Added unit tests in `TestPostgreSqlTypeConverter` for both
    `columnSize=0` and `columnSize=null` cases.
    
    ---------
    
    Co-authored-by: Claude Sonnet 4.6 <[email protected]>
---
 .../postgresql/converter/PostgreSqlTypeConverter.java     | 12 +++++++++++-
 .../postgresql/converter/TestPostgreSqlTypeConverter.java | 15 +++++++++++++++
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git 
a/catalogs/catalog-jdbc-postgresql/src/main/java/org/apache/gravitino/catalog/postgresql/converter/PostgreSqlTypeConverter.java
 
b/catalogs/catalog-jdbc-postgresql/src/main/java/org/apache/gravitino/catalog/postgresql/converter/PostgreSqlTypeConverter.java
index a50e12baf0..09613ecac5 100644
--- 
a/catalogs/catalog-jdbc-postgresql/src/main/java/org/apache/gravitino/catalog/postgresql/converter/PostgreSqlTypeConverter.java
+++ 
b/catalogs/catalog-jdbc-postgresql/src/main/java/org/apache/gravitino/catalog/postgresql/converter/PostgreSqlTypeConverter.java
@@ -41,6 +41,8 @@ public class PostgreSqlTypeConverter extends 
JdbcTypeConverter {
   static final String BYTEA = "bytea";
   @VisibleForTesting static final String JDBC_ARRAY_PREFIX = "_";
   @VisibleForTesting static final String ARRAY_TOKEN = "[]";
+  @VisibleForTesting static final int DEFAULT_NUMERIC_PRECISION = 38;
+  @VisibleForTesting static final int DEFAULT_NUMERIC_SCALE = 18;
 
   @Override
   public Type toGravitino(JdbcTypeBean typeBean) {
@@ -76,7 +78,15 @@ public class PostgreSqlTypeConverter extends 
JdbcTypeConverter {
             .map(Types.TimestampType::withTimeZone)
             .orElseGet(Types.TimestampType::withTimeZone);
       case NUMERIC:
-        return Types.DecimalType.of(typeBean.getColumnSize(), 
typeBean.getScale());
+        Integer columnSize = typeBean.getColumnSize();
+        Integer scale = typeBean.getScale();
+        if (columnSize == null || columnSize == 0) {
+          // PostgreSQL unconstrained NUMERIC has no fixed precision/scale. 
Gravitino DecimalType
+          // cannot represent that exactly, so use the maximum supported 
decimal as a compatibility
+          // tradeoff for engines and clients that cannot consume ExternalType.
+          return Types.DecimalType.of(DEFAULT_NUMERIC_PRECISION, 
DEFAULT_NUMERIC_SCALE);
+        }
+        return Types.DecimalType.of(columnSize, scale == null ? 0 : scale);
       case VARCHAR:
         return typeBean.getColumnSize() == null
             ? Types.StringType.get()
diff --git 
a/catalogs/catalog-jdbc-postgresql/src/test/java/org/apache/gravitino/catalog/postgresql/converter/TestPostgreSqlTypeConverter.java
 
b/catalogs/catalog-jdbc-postgresql/src/test/java/org/apache/gravitino/catalog/postgresql/converter/TestPostgreSqlTypeConverter.java
index d976336fb1..b868ab1f18 100644
--- 
a/catalogs/catalog-jdbc-postgresql/src/test/java/org/apache/gravitino/catalog/postgresql/converter/TestPostgreSqlTypeConverter.java
+++ 
b/catalogs/catalog-jdbc-postgresql/src/test/java/org/apache/gravitino/catalog/postgresql/converter/TestPostgreSqlTypeConverter.java
@@ -27,6 +27,8 @@ import static 
org.apache.gravitino.catalog.postgresql.converter.PostgreSqlTypeCo
 import static 
org.apache.gravitino.catalog.postgresql.converter.PostgreSqlTypeConverter.BOOL;
 import static 
org.apache.gravitino.catalog.postgresql.converter.PostgreSqlTypeConverter.BPCHAR;
 import static 
org.apache.gravitino.catalog.postgresql.converter.PostgreSqlTypeConverter.BYTEA;
+import static 
org.apache.gravitino.catalog.postgresql.converter.PostgreSqlTypeConverter.DEFAULT_NUMERIC_PRECISION;
+import static 
org.apache.gravitino.catalog.postgresql.converter.PostgreSqlTypeConverter.DEFAULT_NUMERIC_SCALE;
 import static 
org.apache.gravitino.catalog.postgresql.converter.PostgreSqlTypeConverter.FLOAT_4;
 import static 
org.apache.gravitino.catalog.postgresql.converter.PostgreSqlTypeConverter.FLOAT_8;
 import static 
org.apache.gravitino.catalog.postgresql.converter.PostgreSqlTypeConverter.INT_2;
@@ -68,6 +70,19 @@ public class TestPostgreSqlTypeConverter {
     checkJdbcTypeToGravitinoType(Types.TimestampType.withoutTimeZone(3), 
TIMESTAMP, 23, null, 3);
     checkJdbcTypeToGravitinoType(Types.TimestampType.withoutTimeZone(6), 
TIMESTAMP, 26, null, 6);
     checkJdbcTypeToGravitinoType(Types.DecimalType.of(10, 2), NUMERIC, 10, 2, 
0);
+    // Unconstrained NUMERIC (no precision) returns columnSize=0 from JDBC 
metadata;
+    // mapped to Gravitino's maximum supported decimal as a compatibility 
tradeoff.
+    checkJdbcTypeToGravitinoType(
+        Types.DecimalType.of(DEFAULT_NUMERIC_PRECISION, 
DEFAULT_NUMERIC_SCALE), NUMERIC, 0, 0, 0);
+    checkJdbcTypeToGravitinoType(
+        Types.DecimalType.of(DEFAULT_NUMERIC_PRECISION, DEFAULT_NUMERIC_SCALE),
+        NUMERIC,
+        null,
+        null,
+        0);
+    checkJdbcTypeToGravitinoType(Types.DecimalType.of(9, 0), NUMERIC, 9, 0, 0);
+    checkJdbcTypeToGravitinoType(Types.DecimalType.of(18, 0), NUMERIC, 18, 0, 
0);
+    checkJdbcTypeToGravitinoType(Types.DecimalType.of(20, 0), NUMERIC, 20, 0, 
0);
     checkJdbcTypeToGravitinoType(Types.VarCharType.of(20), VARCHAR, 20, null, 
0);
     checkJdbcTypeToGravitinoType(Types.FixedCharType.of(20), BPCHAR, 20, null, 
0);
     checkJdbcTypeToGravitinoType(Types.StringType.get(), TEXT, null, null, 0);

Reply via email to