Skip to content

Commit d2ab1db

Browse files
a-shkarupindongjoon-hyun
authored andcommitted
[SPARK-26538][SQL] Set default precision and scale for elements of postgres numeric array
## What changes were proposed in this pull request? When determining CatalystType for postgres columns with type `numeric[]` set the type of array element to `DecimalType(38, 18)` instead of `DecimalType(0,0)`. ## How was this patch tested? Tested with modified `org.apache.spark.sql.jdbc.JDBCSuite`. Ran the `PostgresIntegrationSuite` manually. Closes apache#23456 from a-shkarupin/postgres_numeric_array. Lead-authored-by: Oleksii Shkarupin <[email protected]> Co-authored-by: Dongjoon Hyun <[email protected]> Signed-off-by: Dongjoon Hyun <[email protected]> (cherry picked from commit 5b37092) Signed-off-by: Dongjoon Hyun <[email protected]>
1 parent 9c0e2f4 commit d2ab1db

File tree

3 files changed

+15
-5
lines changed

3 files changed

+15
-5
lines changed

external/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/PostgresIntegrationSuite.scala

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,15 @@ class PostgresIntegrationSuite extends DockerJDBCIntegrationSuite {
4646
conn.prepareStatement("CREATE TABLE bar (c0 text, c1 integer, c2 double precision, c3 bigint, "
4747
+ "c4 bit(1), c5 bit(10), c6 bytea, c7 boolean, c8 inet, c9 cidr, "
4848
+ "c10 integer[], c11 text[], c12 real[], c13 numeric(2,2)[], c14 enum_type, "
49-
+ "c15 float4, c16 smallint)").executeUpdate()
49+
+ "c15 float4, c16 smallint, c17 numeric[])").executeUpdate()
5050
conn.prepareStatement("INSERT INTO bar VALUES ('hello', 42, 1.25, 123456789012345, B'0', "
5151
+ "B'1000100101', E'\\\\xDEADBEEF', true, '172.16.0.42', '192.168.0.0/16', "
52-
+ """'{1, 2}', '{"a", null, "b"}', '{0.11, 0.22}', '{0.11, 0.22}', 'd1', 1.01, 1)"""
52+
+ """'{1, 2}', '{"a", null, "b"}', '{0.11, 0.22}', '{0.11, 0.22}', 'd1', 1.01, 1, """
53+
+ "'{111.2222, 333.4444}')"
5354
).executeUpdate()
5455
conn.prepareStatement("INSERT INTO bar VALUES (null, null, null, null, null, "
5556
+ "null, null, null, null, null, "
56-
+ "null, null, null, null, null, null, null)"
57+
+ "null, null, null, null, null, null, null, null)"
5758
).executeUpdate()
5859

5960
conn.prepareStatement("CREATE TABLE ts_with_timezone " +
@@ -85,7 +86,7 @@ class PostgresIntegrationSuite extends DockerJDBCIntegrationSuite {
8586
assert(rows.length == 2)
8687
// Test the types, and values using the first row.
8788
val types = rows(0).toSeq.map(x => x.getClass)
88-
assert(types.length == 17)
89+
assert(types.length == 18)
8990
assert(classOf[String].isAssignableFrom(types(0)))
9091
assert(classOf[java.lang.Integer].isAssignableFrom(types(1)))
9192
assert(classOf[java.lang.Double].isAssignableFrom(types(2)))
@@ -103,6 +104,7 @@ class PostgresIntegrationSuite extends DockerJDBCIntegrationSuite {
103104
assert(classOf[String].isAssignableFrom(types(14)))
104105
assert(classOf[java.lang.Float].isAssignableFrom(types(15)))
105106
assert(classOf[java.lang.Short].isAssignableFrom(types(16)))
107+
assert(classOf[Seq[BigDecimal]].isAssignableFrom(types(17)))
106108
assert(rows(0).getString(0).equals("hello"))
107109
assert(rows(0).getInt(1) == 42)
108110
assert(rows(0).getDouble(2) == 1.25)
@@ -123,6 +125,8 @@ class PostgresIntegrationSuite extends DockerJDBCIntegrationSuite {
123125
assert(rows(0).getString(14) == "d1")
124126
assert(rows(0).getFloat(15) == 1.01f)
125127
assert(rows(0).getShort(16) == 1)
128+
assert(rows(0).getSeq(17) ==
129+
Seq("111.222200000000000000", "333.444400000000000000").map(BigDecimal(_).bigDecimal))
126130

127131
// Test reading null values using the second row.
128132
assert(0.until(16).forall(rows(1).isNullAt(_)))

sql/core/src/main/scala/org/apache/spark/sql/jdbc/PostgresDialect.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,10 @@ private object PostgresDialect extends JdbcDialect {
6060
case "bytea" => Some(BinaryType)
6161
case "timestamp" | "timestamptz" | "time" | "timetz" => Some(TimestampType)
6262
case "date" => Some(DateType)
63-
case "numeric" | "decimal" => Some(DecimalType.bounded(precision, scale))
63+
case "numeric" | "decimal" if precision > 0 => Some(DecimalType.bounded(precision, scale))
64+
case "numeric" | "decimal" =>
65+
// SPARK-26538: handle numeric without explicit precision and scale.
66+
Some(DecimalType. SYSTEM_DEFAULT)
6467
case _ => None
6568
}
6669

sql/core/src/test/scala/org/apache/spark/sql/jdbc/JDBCSuite.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -825,8 +825,11 @@ class JDBCSuite extends QueryTest
825825

826826
test("PostgresDialect type mapping") {
827827
val Postgres = JdbcDialects.get("jdbc:postgresql://127.0.0.1/db")
828+
val md = new MetadataBuilder().putLong("scale", 0)
828829
assert(Postgres.getCatalystType(java.sql.Types.OTHER, "json", 1, null) === Some(StringType))
829830
assert(Postgres.getCatalystType(java.sql.Types.OTHER, "jsonb", 1, null) === Some(StringType))
831+
assert(Postgres.getCatalystType(java.sql.Types.ARRAY, "_numeric", 0, md) ==
832+
Some(ArrayType(DecimalType.SYSTEM_DEFAULT)))
830833
assert(Postgres.getJDBCType(FloatType).map(_.databaseTypeDefinition).get == "FLOAT4")
831834
assert(Postgres.getJDBCType(DoubleType).map(_.databaseTypeDefinition).get == "FLOAT8")
832835
val errMsg = intercept[IllegalArgumentException] {

0 commit comments

Comments
 (0)