Skip to content

Commit e5d2c37

Browse files
yanboliangliancheng
authored andcommitted
[SPARK-5821] [SQL] JSON CTAS command should throw error message when delete path failure
When using "CREATE TEMPORARY TABLE AS SELECT" to create JSON table, we first delete the path file or directory and then generate a new directory with the same name. But if only read permission was granted, the delete failed. Here we just throwing an error message to let users know what happened. ParquetRelation2 may also hit this problem. I think to restrict JSONRelation and ParquetRelation2 must base on directory is more reasonable for access control. Maybe I can do it in follow up works. Author: Yanbo Liang <[email protected]> Author: Yanbo Liang <[email protected]> Closes #4610 from yanboliang/jsonInsertImprovements and squashes the following commits: c387fce [Yanbo Liang] fix typos 42d7fb6 [Yanbo Liang] add unittest & fix output format 46f0d9d [Yanbo Liang] Update JSONRelation.scala e2df8d5 [Yanbo Liang] check path exisit when write 79f7040 [Yanbo Liang] Update JSONRelation.scala e4bc229 [Yanbo Liang] Update JSONRelation.scala 5a42d83 [Yanbo Liang] JSONRelation CTAS should check if delete is successful
1 parent 937c1e5 commit e5d2c37

File tree

2 files changed

+53
-8
lines changed

2 files changed

+53
-8
lines changed

sql/core/src/main/scala/org/apache/spark/sql/json/JSONRelation.scala

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,23 @@ private[sql] class DefaultSource
6868
mode match {
6969
case SaveMode.Append =>
7070
sys.error(s"Append mode is not supported by ${this.getClass.getCanonicalName}")
71-
case SaveMode.Overwrite =>
72-
fs.delete(filesystemPath, true)
71+
case SaveMode.Overwrite => {
72+
var success: Boolean = false
73+
try {
74+
success = fs.delete(filesystemPath, true)
75+
} catch {
76+
case e: IOException =>
77+
throw new IOException(
78+
s"Unable to clear output directory ${filesystemPath.toString} prior"
79+
+ s" to writing to JSON table:\n${e.toString}")
80+
}
81+
if (!success) {
82+
throw new IOException(
83+
s"Unable to clear output directory ${filesystemPath.toString} prior"
84+
+ s" to writing to JSON table.")
85+
}
7386
true
87+
}
7488
case SaveMode.ErrorIfExists =>
7589
sys.error(s"path $path already exists.")
7690
case SaveMode.Ignore => false
@@ -114,13 +128,21 @@ private[sql] case class JSONRelation(
114128
val fs = filesystemPath.getFileSystem(sqlContext.sparkContext.hadoopConfiguration)
115129

116130
if (overwrite) {
117-
try {
118-
fs.delete(filesystemPath, true)
119-
} catch {
120-
case e: IOException =>
131+
if (fs.exists(filesystemPath)) {
132+
var success: Boolean = false
133+
try {
134+
success = fs.delete(filesystemPath, true)
135+
} catch {
136+
case e: IOException =>
137+
throw new IOException(
138+
s"Unable to clear output directory ${filesystemPath.toString} prior"
139+
+ s" to writing to JSON table:\n${e.toString}")
140+
}
141+
if (!success) {
121142
throw new IOException(
122143
s"Unable to clear output directory ${filesystemPath.toString} prior"
123-
+ s" to INSERT OVERWRITE a JSON table:\n${e.toString}")
144+
+ s" to writing to JSON table.")
145+
}
124146
}
125147
// Write the data.
126148
data.toJSON.saveAsTextFile(path)

sql/core/src/test/scala/org/apache/spark/sql/sources/CreateTableAsSelectSuite.scala

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
package org.apache.spark.sql.sources
1919

20-
import java.io.File
20+
import java.io.{IOException, File}
2121

2222
import org.apache.spark.sql.AnalysisException
2323
import org.scalatest.BeforeAndAfterAll
@@ -62,6 +62,29 @@ class CreateTableAsSelectSuite extends DataSourceTest with BeforeAndAfterAll {
6262
dropTempTable("jsonTable")
6363
}
6464

65+
test("CREATE TEMPORARY TABLE AS SELECT based on the file without write permission") {
66+
val childPath = new File(path.toString, "child")
67+
path.mkdir()
68+
childPath.createNewFile()
69+
path.setWritable(false)
70+
71+
val e = intercept[IOException] {
72+
sql(
73+
s"""
74+
|CREATE TEMPORARY TABLE jsonTable
75+
|USING org.apache.spark.sql.json.DefaultSource
76+
|OPTIONS (
77+
| path '${path.toString}'
78+
|) AS
79+
|SELECT a, b FROM jt
80+
""".stripMargin)
81+
sql("SELECT a, b FROM jsonTable").collect()
82+
}
83+
assert(e.getMessage().contains("Unable to clear output directory"))
84+
85+
path.setWritable(true)
86+
}
87+
6588
test("create a table, drop it and create another one with the same name") {
6689
sql(
6790
s"""

0 commit comments

Comments
 (0)