Skip to content

Commit b5678be

Browse files
mariosmeim-dbHyukjinKwon
authored andcommitted
[SPARK-35446] Override getJDBCType in MySQLDialect to map FloatType to FLOAT
### What changes were proposed in this pull request? Override `getJDBCType` method in `MySQLDialect` so that `FloatType` is mapped to `FLOAT` instead of `REAL` ### Why are the changes needed? MySQL treats `REAL` as a synonym to `DOUBLE` by default (see https://dev.mysql.com/doc/refman/8.0/en/numeric-types.html). Therefore, when creating a table with a column of `REAL` type, it will be created as `DOUBLE`. However, currently, `MySQLDialect` does not provide an implementation for `getJDBCType`, and will thus ultimately fall back to `JdbcUtils.getCommonJDBCType`, which maps `FloatType` to `REAL`. This change is needed so that we can properly map the `FloatType` to `FLOAT` for MySQL. ### Does this PR introduce _any_ user-facing change? Prior to this PR, when writing a dataframe with a `FloatType` column to a MySQL table, it will create a `DOUBLE` column. After the PR, it will create a `FLOAT` column. ### How was this patch tested? Added a test case in `JDBCSuite` that verifies the mapping. Closes #32605 from mariosmeim-db/SPARK-35446. Authored-by: Marios Meimaris <[email protected]> Signed-off-by: Hyukjin Kwon <[email protected]>
1 parent f2c0a04 commit b5678be

File tree

3 files changed

+16
-1
lines changed

3 files changed

+16
-1
lines changed

docs/sql-migration-guide.md

+2
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ license: |
9292
- In Spark 3.2, `CREATE TABLE AS SELECT` with non-empty `LOCATION` will throw `AnalysisException`. To restore the behavior before Spark 3.2, you can set `spark.sql.legacy.allowNonEmptyLocationInCTAS` to `true`.
9393

9494
- In Spark 3.2, special datetime values such as `epoch`, `today`, `yesterday`, `tomorrow`, and `now` are supported in typed literals only, for instance, `select timestamp'now'`. In Spark 3.1 and 3.0, such special values are supported in any casts of strings to dates/timestamps. To keep these special values as dates/timestamps in Spark 3.1 and 3.0, you should replace them manually, e.g. `if (c in ('now', 'today'), current_date(), cast(c as date))`.
95+
96+
- In Spark 3.2, `FloatType` is mapped to `FLOAT` in MySQL. Prior to this, it used to be mapped to `REAL`, which is by default a synonym to `DOUBLE PRECISION` in MySQL.
9597

9698
## Upgrading from Spark SQL 3.0 to 3.1
9799

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

+9-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ package org.apache.spark.sql.jdbc
2020
import java.sql.{SQLFeatureNotSupportedException, Types}
2121
import java.util.Locale
2222

23-
import org.apache.spark.sql.types.{BooleanType, DataType, LongType, MetadataBuilder}
23+
import org.apache.spark.sql.execution.datasources.jdbc.JdbcUtils
24+
import org.apache.spark.sql.types.{BooleanType, DataType, FloatType, LongType, MetadataBuilder}
2425

2526
private case object MySQLDialect extends JdbcDialect {
2627

@@ -94,4 +95,11 @@ private case object MySQLDialect extends JdbcDialect {
9495
override def getTableCommentQuery(table: String, comment: String): String = {
9596
s"ALTER TABLE $table COMMENT = '$comment'"
9697
}
98+
99+
override def getJDBCType(dt: DataType): Option[JdbcType] = dt match {
100+
// See SPARK-35446: MySQL treats REAL as a synonym to DOUBLE by default
101+
// We override getJDBCType so that FloatType is mapped to FLOAT instead
102+
case FloatType => Option(JdbcType("FLOAT", java.sql.Types.FLOAT))
103+
case _ => JdbcUtils.getCommonJDBCType(dt)
104+
}
97105
}

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

+5
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,11 @@ class JDBCSuite extends QueryTest
899899
Option(TimestampType))
900900
}
901901

902+
test("SPARK-35446: MySQLDialect type mapping of float") {
903+
val mySqlDialect = JdbcDialects.get("jdbc:mysql://127.0.0.1/db")
904+
assert(mySqlDialect.getJDBCType(FloatType).map(_.databaseTypeDefinition).get == "FLOAT")
905+
}
906+
902907
test("PostgresDialect type mapping") {
903908
val Postgres = JdbcDialects.get("jdbc:postgresql://127.0.0.1/db")
904909
val md = new MetadataBuilder().putLong("scale", 0)

0 commit comments

Comments
 (0)