Skip to content

Commit 30f2dac

Browse files
[SPARK-57778][SQL][TESTS] Use namedGridTest for the non-selectable object cases
1 parent c262c7a commit 30f2dac

1 file changed

Lines changed: 50 additions & 52 deletions

File tree

connector/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/v2/OracleIntegrationSuite.scala

Lines changed: 50 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -206,58 +206,56 @@ class OracleIntegrationSuite extends DockerJDBCIntegrationV2Suite with V2JDBCTes
206206
}
207207
}
208208

209-
test("SPARK-57778: objects that are not selectable as tables are handled gracefully") {
210-
// Each case: (description, setup DDL, object name in SYSTEM, teardown DDL). Oracle's table
211-
// listing surfaces these objects, but they cannot be read as tables.
212-
val cases = Seq(
213-
(
214-
"synonym to a procedure (ORA-04044)",
215-
Seq(
216-
"CREATE PROCEDURE test_proc AS BEGIN NULL; END;",
217-
"CREATE SYNONYM proc_synonym FOR test_proc"),
218-
"PROC_SYNONYM",
219-
Seq("DROP SYNONYM proc_synonym", "DROP PROCEDURE test_proc")),
220-
(
221-
"synonym to a broken function (ORA-04044)",
222-
Seq(
223-
"""CREATE FUNCTION broken_func RETURN NUMBER AS
224-
| x NUMBER;
225-
|BEGIN
226-
| SELECT col INTO x FROM non_existent_table_xyz;
227-
| RETURN x;
228-
|END;""".stripMargin,
229-
"CREATE SYNONYM func_synonym FOR broken_func"),
230-
"FUNC_SYNONYM",
231-
Seq("DROP SYNONYM func_synonym", "DROP FUNCTION broken_func")),
232-
(
233-
"invalid view (ORA-04063)",
234-
Seq("CREATE FORCE VIEW invalid_view AS SELECT * FROM non_existent_table_xyz"),
235-
"INVALID_VIEW",
236-
Seq("DROP VIEW invalid_view")))
237-
238-
val tableCatalog =
239-
spark.sessionState.catalogManager.catalog(catalogName).asInstanceOf[TableCatalog]
240-
241-
cases.foreach { case (desc, setup, objectName, teardown) =>
242-
withClue(s"[$desc] ") {
243-
Using.resource(getConnection()) { conn =>
244-
setup.foreach(conn.prepareStatement(_).executeUpdate())
245-
}
246-
try {
247-
// tableExists treats a non-selectable object as non-existent instead of throwing.
248-
assert(!tableCatalog.tableExists(Identifier.of(Array("SYSTEM"), objectName)))
249-
250-
// Reading it surfaces a dedicated, clear error instead of a raw JDBC failure.
251-
val e = intercept[AnalysisException] {
252-
sql(s"SELECT * FROM $catalogName.SYSTEM.$objectName").collect()
253-
}
254-
assert(e.getCondition == "JDBC_OBJECT_NOT_SELECTABLE")
255-
assert(e.getMessageParameters.get("objectName").contains(objectName))
256-
} finally {
257-
Using.resource(getConnection()) { conn =>
258-
teardown.foreach(conn.prepareStatement(_).executeUpdate())
259-
}
260-
}
209+
// An object that Oracle's table listing surfaces but that cannot be read as a table.
210+
// `setup`/`teardown` are the DDL to create/drop it; `objectName` is its name in SYSTEM.
211+
case class NonSelectableObjectCase(setup: Seq[String], objectName: String, teardown: Seq[String])
212+
213+
private val nonSelectableObjectCases = Map(
214+
"synonym to a procedure (ORA-04044)" -> NonSelectableObjectCase(
215+
setup = Seq(
216+
"CREATE PROCEDURE test_proc AS BEGIN NULL; END;",
217+
"CREATE SYNONYM proc_synonym FOR test_proc"),
218+
objectName = "PROC_SYNONYM",
219+
teardown = Seq("DROP SYNONYM proc_synonym", "DROP PROCEDURE test_proc")),
220+
"synonym to a broken function (ORA-04044)" -> NonSelectableObjectCase(
221+
// Function referencing a missing object -> created INVALID.
222+
setup = Seq(
223+
"""CREATE FUNCTION broken_func RETURN NUMBER AS
224+
| x NUMBER;
225+
|BEGIN
226+
| SELECT col INTO x FROM non_existent_table_xyz;
227+
| RETURN x;
228+
|END;""".stripMargin,
229+
"CREATE SYNONYM func_synonym FOR broken_func"),
230+
objectName = "FUNC_SYNONYM",
231+
teardown = Seq("DROP SYNONYM func_synonym", "DROP FUNCTION broken_func")),
232+
"invalid view (ORA-04063)" -> NonSelectableObjectCase(
233+
// FORCE-create a view over a missing table -> view is INVALID; SELECT raises ORA-04063.
234+
setup = Seq("CREATE FORCE VIEW invalid_view AS SELECT * FROM non_existent_table_xyz"),
235+
objectName = "INVALID_VIEW",
236+
teardown = Seq("DROP VIEW invalid_view")))
237+
238+
namedGridTest("SPARK-57778: non-selectable object is handled gracefully")(
239+
nonSelectableObjectCases) { testCase =>
240+
Using.resource(getConnection()) { conn =>
241+
testCase.setup.foreach(conn.prepareStatement(_).executeUpdate())
242+
}
243+
try {
244+
val tableCatalog =
245+
spark.sessionState.catalogManager.catalog(catalogName).asInstanceOf[TableCatalog]
246+
247+
// tableExists treats a non-selectable object as non-existent instead of throwing.
248+
assert(!tableCatalog.tableExists(Identifier.of(Array("SYSTEM"), testCase.objectName)))
249+
250+
// Reading it surfaces a dedicated, clear error instead of a raw JDBC failure.
251+
val e = intercept[AnalysisException] {
252+
sql(s"SELECT * FROM $catalogName.SYSTEM.${testCase.objectName}").collect()
253+
}
254+
assert(e.getCondition == "JDBC_OBJECT_NOT_SELECTABLE")
255+
assert(e.getMessageParameters.get("objectName").contains(testCase.objectName))
256+
} finally {
257+
Using.resource(getConnection()) { conn =>
258+
testCase.teardown.foreach(conn.prepareStatement(_).executeUpdate())
261259
}
262260
}
263261
}

0 commit comments

Comments
 (0)