@@ -34,6 +34,7 @@ import org.apache.spark.sql.connector.catalog.CatalogManager.SESSION_CATALOG_NAM
3434import org .apache .spark .sql .connector .catalog .SupportsNamespaces .PROP_OWNER
3535import org .apache .spark .sql .internal .{SQLConf , StaticSQLConf }
3636import org .apache .spark .sql .types ._
37+ import org .apache .spark .util .Utils
3738
3839class InMemorySessionCatalogSuite extends SessionCatalogSuite {
3940 protected val utils = new CatalogTestUtils {
@@ -2091,4 +2092,179 @@ abstract class SessionCatalogSuite extends AnalysisTest with Eventually {
20912092 assert(exception.getMessage.matches(expectedPattern))
20922093 }
20932094 }
2095+
2096+ test(" UnresolvedCatalogRelation requires database in identifier" ) {
2097+ val catalog = new SessionCatalog (newBasicCatalog())
2098+ val db = " test_db"
2099+ catalog.createDatabase(newDb(db), ignoreIfExists = false )
2100+
2101+ // Create a table with database
2102+ val validTable = CatalogTable (
2103+ identifier = TableIdentifier (" test_table" , Some (db)),
2104+ tableType = CatalogTableType .MANAGED ,
2105+ storage = CatalogStorageFormat .empty,
2106+ schema = new StructType ().add(" id" , IntegerType )
2107+ )
2108+ catalog.createTable(validTable, ignoreIfExists = false )
2109+
2110+ // Try to create UnresolvedCatalogRelation without database - should fail
2111+ val tableMetaWithoutDb = validTable.copy(
2112+ identifier = TableIdentifier (" test_table" , None )
2113+ )
2114+
2115+ val exception = intercept[AssertionError ] {
2116+ UnresolvedCatalogRelation (tableMetaWithoutDb)
2117+ }
2118+
2119+ val expectedMessage =
2120+ " assertion failed: Table identifier `test_table` is missing database name. " +
2121+ " UnresolvedCatalogRelation requires a fully qualified table identifier with database."
2122+ assert(exception.getMessage === expectedMessage)
2123+ }
2124+
2125+ test(" HiveTableRelation requires database in identifier" ) {
2126+ val catalog = new SessionCatalog (newBasicCatalog())
2127+ val db = " test_db"
2128+ catalog.createDatabase(newDb(db), ignoreIfExists = false )
2129+
2130+ // Create a table with database
2131+ val validTable = CatalogTable (
2132+ identifier = TableIdentifier (" test_table" , Some (db)),
2133+ tableType = CatalogTableType .MANAGED ,
2134+ storage = CatalogStorageFormat .empty,
2135+ schema = new StructType ()
2136+ .add(" id" , IntegerType )
2137+ .add(" name" , StringType )
2138+ )
2139+
2140+ // Try to create HiveTableRelation without database - should fail
2141+ val tableMetaWithoutDb = validTable.copy(
2142+ identifier = TableIdentifier (" test_table" , None )
2143+ )
2144+
2145+ val exception = intercept[AssertionError ] {
2146+ HiveTableRelation (
2147+ tableMetaWithoutDb,
2148+ Seq (AttributeReference (" id" , IntegerType )()),
2149+ Seq .empty
2150+ )
2151+ }
2152+
2153+ val expectedMessage =
2154+ " assertion failed: Table identifier `test_table` is missing database name. " +
2155+ " HiveTableRelation requires a fully qualified table identifier with database."
2156+ assert(exception.getMessage === expectedMessage)
2157+ }
2158+
2159+ test(" SQLFunction requires either exprText or queryText" ) {
2160+ // Test case 1: Neither exprText nor queryText provided
2161+ val exception1 = intercept[AssertionError ] {
2162+ SQLFunction (
2163+ name = FunctionIdentifier (" test_func" ),
2164+ inputParam = None ,
2165+ returnType = scala.util.Left (IntegerType ),
2166+ exprText = None ,
2167+ queryText = None ,
2168+ comment = None ,
2169+ deterministic = Some (true ),
2170+ containsSQL = Some (false ),
2171+ isTableFunc = false ,
2172+ properties = Map .empty
2173+ )
2174+ }
2175+
2176+ val expectedMessage = " assertion failed: SQL function 'test_func' is missing function body. " +
2177+ " Either exprText or queryText must be defined. " +
2178+ " Found: exprText=None, queryText=None."
2179+ assert(exception1.getMessage === expectedMessage)
2180+ }
2181+
2182+ test(" SQLFunction return type must match function type" ) {
2183+ // Test case: isTableFunc=true but returnType is Left (scalar type)
2184+ val exception = intercept[AssertionError ] {
2185+ SQLFunction (
2186+ name = FunctionIdentifier (" test_func" ),
2187+ inputParam = None ,
2188+ returnType = scala.util.Left (IntegerType ), // Scalar return type
2189+ exprText = Some (" SELECT 1" ),
2190+ queryText = None ,
2191+ comment = None ,
2192+ deterministic = Some (true ),
2193+ containsSQL = Some (true ),
2194+ isTableFunc = true , // But marked as table function
2195+ properties = Map .empty
2196+ )
2197+ }
2198+
2199+ val expectedMessage =
2200+ " assertion failed: SQL function 'test_func' has mismatched function type " +
2201+ " and return type. " +
2202+ " isTableFunc=true, returnType.isRight=false, returnType.isLeft=true. " +
2203+ " Table functions require Right[StructType] and scalar functions require Left[DataType]."
2204+ assert(exception.getMessage === expectedMessage)
2205+ }
2206+
2207+ test(" InMemoryCatalog.createTable requires database in identifier" ) {
2208+ val catalog = new InMemoryCatalog ()
2209+ val db = " test_db"
2210+ val dbDefinition = CatalogDatabase (
2211+ name = db,
2212+ description = " test database" ,
2213+ locationUri = Utils .createTempDir().toURI,
2214+ properties = Map .empty
2215+ )
2216+ catalog.createDatabase(dbDefinition, ignoreIfExists = false )
2217+
2218+ // Try to create table without database - should fail
2219+ val tableWithoutDb = CatalogTable (
2220+ identifier = TableIdentifier (" test_table" , None ),
2221+ tableType = CatalogTableType .MANAGED ,
2222+ storage = CatalogStorageFormat .empty,
2223+ schema = new StructType ().add(" id" , IntegerType )
2224+ )
2225+
2226+ val exception = intercept[AssertionError ] {
2227+ catalog.createTable(tableWithoutDb, ignoreIfExists = false )
2228+ }
2229+
2230+ val expectedMessage =
2231+ " assertion failed: Table identifier `test_table` is missing database name. " +
2232+ " Cannot create table without a database specified."
2233+ assert(exception.getMessage === expectedMessage)
2234+ }
2235+
2236+ test(" InMemoryCatalog.alterTable requires database in identifier" ) {
2237+ val catalog = new InMemoryCatalog ()
2238+ val db = " test_db"
2239+ val dbDefinition = CatalogDatabase (
2240+ name = db,
2241+ description = " test database" ,
2242+ locationUri = Utils .createTempDir().toURI,
2243+ properties = Map .empty
2244+ )
2245+ catalog.createDatabase(dbDefinition, ignoreIfExists = false )
2246+
2247+ // First create a valid table
2248+ val validTable = CatalogTable (
2249+ identifier = TableIdentifier (" test_table" , Some (db)),
2250+ tableType = CatalogTableType .MANAGED ,
2251+ storage = CatalogStorageFormat .empty,
2252+ schema = new StructType ().add(" id" , IntegerType )
2253+ )
2254+ catalog.createTable(validTable, ignoreIfExists = false )
2255+
2256+ // Try to alter table with identifier without database - should fail
2257+ val tableWithoutDb = validTable.copy(
2258+ identifier = TableIdentifier (" test_table" , None )
2259+ )
2260+
2261+ val exception = intercept[AssertionError ] {
2262+ catalog.alterTable(tableWithoutDb)
2263+ }
2264+
2265+ val expectedMessage =
2266+ " assertion failed: Table identifier `test_table` is missing database name. " +
2267+ " Cannot alter table without a database specified."
2268+ assert(exception.getMessage === expectedMessage)
2269+ }
20942270}
0 commit comments