You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spark.apache.org by gu...@apache.org on 2019/06/04 07:28:02 UTC
[spark] branch branch-2.4 updated: [SPARK-27873][SQL][BRANCH-2.4]
columnNameOfCorruptRecord should not be checked with column names in CSV
header when disabling enforceSchema
This is an automated email from the ASF dual-hosted git repository.
gurwls223 pushed a commit to branch branch-2.4
in repository https://gitbox.apache.org/repos/asf/spark.git
The following commit(s) were added to refs/heads/branch-2.4 by this push:
new 880cb7b [SPARK-27873][SQL][BRANCH-2.4] columnNameOfCorruptRecord should not be checked with column names in CSV header when disabling enforceSchema
880cb7b is described below
commit 880cb7bee08172e2b82ac6fe57e4b75f8f495c1b
Author: Liang-Chi Hsieh <vi...@gmail.com>
AuthorDate: Tue Jun 4 16:27:44 2019 +0900
[SPARK-27873][SQL][BRANCH-2.4] columnNameOfCorruptRecord should not be checked with column names in CSV header when disabling enforceSchema
## What changes were proposed in this pull request?
If we want to keep corrupt record when reading CSV, we provide a new column into the schema, that is `columnNameOfCorruptRecord`. But this new column isn't actually a column in CSV header. So if `enforceSchema` is disabled, `CSVHeaderChecker` throws a exception complaining that number of column in CSV header isn't equal to that in the schema.
This backports the fix into branch-2.4.
## How was this patch tested?
Added test.
Closes #24771 from viirya/SPARK-27873-2.4.
Authored-by: Liang-Chi Hsieh <vi...@gmail.com>
Signed-off-by: HyukjinKwon <gu...@apache.org>
---
.../execution/datasources/csv/CSVDataSource.scala | 12 +++++++++--
.../sql/execution/datasources/csv/CSVSuite.scala | 25 ++++++++++++++++++++++
2 files changed, 35 insertions(+), 2 deletions(-)
diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/csv/CSVDataSource.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/csv/CSVDataSource.scala
index e840ff1..62c3c16 100644
--- a/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/csv/CSVDataSource.scala
+++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/csv/CSVDataSource.scala
@@ -210,7 +210,11 @@ object TextInputCSVDataSource extends CSVDataSource {
// Note: if there are only comments in the first block, the header would probably
// be not extracted.
CSVUtils.extractHeader(lines, parser.options).foreach { header =>
- val schema = if (columnPruning) requiredSchema else dataSchema
+ val actualRequiredSchema =
+ StructType(requiredSchema.filterNot(_.name == parser.options.columnNameOfCorruptRecord))
+ val actualDataSchema =
+ StructType(dataSchema.filterNot(_.name == parser.options.columnNameOfCorruptRecord))
+ val schema = if (columnPruning) actualRequiredSchema else actualDataSchema
val columnNames = parser.tokenizer.parseLine(header)
CSVDataSource.checkHeaderColumnNames(
schema,
@@ -297,7 +301,11 @@ object MultiLineCSVDataSource extends CSVDataSource {
caseSensitive: Boolean,
columnPruning: Boolean): Iterator[InternalRow] = {
def checkHeader(header: Array[String]): Unit = {
- val schema = if (columnPruning) requiredSchema else dataSchema
+ val actualRequiredSchema =
+ StructType(requiredSchema.filterNot(_.name == parser.options.columnNameOfCorruptRecord))
+ val actualDataSchema =
+ StructType(dataSchema.filterNot(_.name == parser.options.columnNameOfCorruptRecord))
+ val schema = if (columnPruning) actualRequiredSchema else actualDataSchema
CSVDataSource.checkHeaderColumnNames(
schema,
header,
diff --git a/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/csv/CSVSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/csv/CSVSuite.scala
index d59035b..df9d154 100644
--- a/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/csv/CSVSuite.scala
+++ b/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/csv/CSVSuite.scala
@@ -1836,4 +1836,29 @@ class CSVSuite extends QueryTest with SharedSQLContext with SQLTestUtils with Te
val schema = new StructType().add("a", StringType).add("b", IntegerType)
checkAnswer(spark.read.schema(schema).option("delimiter", delimiter).csv(input), Row("abc", 1))
}
+
+ test("SPARK-27873: disabling enforceSchema should not fail columnNameOfCorruptRecord") {
+ Seq(false, true).foreach { multiLine =>
+ withTempPath { path =>
+ val df = Seq(("0", "2013-abc-11")).toDF("a", "b")
+ df.write
+ .option("header", "true")
+ .csv(path.getAbsolutePath)
+
+ val schema = StructType.fromDDL("a int, b date")
+ val columnNameOfCorruptRecord = "_unparsed"
+ val schemaWithCorrField = schema.add(columnNameOfCorruptRecord, StringType)
+ val readDF = spark
+ .read
+ .option("mode", "Permissive")
+ .option("header", "true")
+ .option("enforceSchema", false)
+ .option("multiLine", multiLine)
+ .option("columnNameOfCorruptRecord", columnNameOfCorruptRecord)
+ .schema(schemaWithCorrField)
+ .csv(path.getAbsoluteFile.toString)
+ checkAnswer(readDF, Row(null, null, "0,2013-abc-11") :: Nil)
+ }
+ }
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@spark.apache.org
For additional commands, e-mail: commits-help@spark.apache.org