-
Notifications
You must be signed in to change notification settings - Fork 29k
[SPARK-19211][SQL] Explicitly prevent Insert into View or Create View As Insert #17125
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
d1484f9
ae28e4b
792cca9
57b64ad
68cee40
9af2d7e
8d4be05
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1329,6 +1329,16 @@ class SparkSqlAstBuilder(conf: SQLConf) extends AstBuilder { | |
| if (ctx.identifierList != null) { | ||
| operationNotAllowed("CREATE VIEW ... PARTITIONED ON", ctx) | ||
| } else { | ||
| // CREATE VIEW ... AS INSERT INTO is not allowed. | ||
| val query = ctx.query.queryNoWith | ||
| query match { | ||
|
||
| case s: SingleInsertQueryContext if s.insertInto != null => | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. when
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For example,
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmm, a select query is
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah... You can see that in: |
||
| operationNotAllowed("CREATE VIEW ... AS INSERT INTO", ctx) | ||
| case m: MultiInsertQueryContext => | ||
|
||
| operationNotAllowed("CREATE VIEW ... AS FROM ... [INSERT INTO ...]+", ctx) | ||
| case _ => // OK | ||
| } | ||
|
|
||
| val userSpecifiedColumns = Option(ctx.identifierCommentList).toSeq.flatMap { icl => | ||
| icl.identifierComment.asScala.map { ic => | ||
| ic.identifier.getText -> Option(ic.STRING).map(string) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,6 +20,7 @@ package org.apache.spark.sql.execution | |
| import org.apache.spark.sql._ | ||
| import org.apache.spark.sql.catalyst.TableIdentifier | ||
| import org.apache.spark.sql.catalyst.analysis.NoSuchTableException | ||
| import org.apache.spark.sql.catalyst.parser.ParseException | ||
| import org.apache.spark.sql.test.{SharedSQLContext, SQLTestUtils} | ||
|
|
||
| class SimpleSQLViewSuite extends SQLViewSuite with SharedSQLContext | ||
|
|
@@ -172,7 +173,7 @@ abstract class SQLViewSuite extends QueryTest with SQLTestUtils { | |
| var e = intercept[AnalysisException] { | ||
| sql(s"INSERT INTO TABLE $viewName SELECT 1") | ||
| }.getMessage | ||
| assert(e.contains("Inserting into an RDD-based table is not allowed")) | ||
| assert(e.contains("inserting into a view is not allowed")) | ||
|
|
||
| val dataFilePath = | ||
| Thread.currentThread().getContextClassLoader.getResource("data/files/employee.dat") | ||
|
|
@@ -484,6 +485,23 @@ abstract class SQLViewSuite extends QueryTest with SQLTestUtils { | |
| } | ||
| } | ||
|
|
||
| test("create view as insert into table") { | ||
|
||
| withView("testView") { | ||
| // Single insert query | ||
| val e1 = intercept[ParseException] { | ||
| sql(s"CREATE VIEW testView AS INSERT INTO jt VALUES(1, 1)") | ||
|
||
| }.getMessage | ||
| assert(e1.contains("Operation not allowed: CREATE VIEW ... AS INSERT INTO")) | ||
|
|
||
| // Multi insert query | ||
| val e2 = intercept[ParseException] { | ||
| sql(s"CREATE VIEW testView AS FROM jt INSERT INTO tbl1 SELECT * WHERE jt.id < 5 " + | ||
| s"INSERT INTO tbl2 SELECT * WHERE jt.id > 4") | ||
|
||
| }.getMessage | ||
| assert(e2.contains("Operation not allowed: CREATE VIEW ... AS FROM ... [INSERT INTO ...]+")) | ||
| } | ||
| } | ||
|
|
||
| test("CTE within view") { | ||
| withView("cte_view") { | ||
| sql("CREATE VIEW cte_view AS WITH w AS (SELECT 1 AS n) SELECT n FROM w") | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why this change?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When we try to insert into a view, the logical plan that
lookupTableFromCatalog()returns is not resolved, so we have to performresolveRelation()over the node.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so we will resolve something to
Viewby doing this?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We will resolve the child of the view by doing this I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we need to resolve the child of view? Once we see the pattern
Insert(View, ...)we will throw exception, we don't care about whether the child of view is resolved or not.