Uh oh!
There was an error while loading. Please reload this page.
[SPARK-19667][SQL]create table with hiveenabled in default database use warehouse path instead of the location of default database - #17001
Conversation
…se warehouse path instead of the location of default database
SparkQA
commented
Feb 20, 2017
Test build #73171 has finished for PR 17001 at commit
|
SparkQA
commented
Feb 21, 2017
Test build #73201 has finished for PR 17001 at commit
|
windpiger
commented
Feb 21, 2017
cloud-fan
commented
Feb 22, 2017
I'd like to treat this as a workaround, the location of default database is still invalid in cluster- We can make this logic more clear and consistent: the default database should not have a location, when we try to get the location of default DB, we should use the warehouse path. |
windpiger
commented
Feb 22, 2017
Agreed, I process the logic in create/get database in HiveClientImpl |
SparkQA
commented
Feb 22, 2017
Test build #73260 has finished for PR 17001 at commit
|
SparkQA
commented
Feb 22, 2017
Test build #73261 has finished for PR 17001 at commit
|
| database.name, | ||
| database.description, | ||
| database.locationUri, | ||
| if (database.name == SessionCatalog.DEFAULT_DATABASE) "" else database.locationUri, |
There was a problem hiding this comment.
If it is empty, metastore will set it for us, right?
There was a problem hiding this comment.
sorry, actually it will throw an exception, my local default has created, so it does not hit the exception, I will just replace the default database location when reload from metastore, drop the logic when create database set location to empty string.
gatorsmile
commented
Feb 22, 2017
Are you able to find the specific Hive JIRA for this? |
windpiger
commented
Feb 22, 2017
Personally, I think we should improve the test case. Instead of doing it in HiveDDLSuite, we can do it in HiveSparkSubmitSuite.scala. Basically, when using the same metastore, you just need to verify whether the table location is dependent on |
windpiger
commented
Feb 22, 2017
great, I will take a look at it~ |
SparkQA
commented
Feb 22, 2017
Test build #73263 has finished for PR 17001 at commit
|
SparkQA
commented
Feb 22, 2017
Test build #73270 has finished for PR 17001 at commit
|
locally test BucketedWriteWithoutHiveSupportSuite is ok, let me find out why failed in jenkins |
SparkQA
commented
Feb 22, 2017
Test build #73273 has finished for PR 17001 at commit
|
SparkQA
commented
Feb 22, 2017
Test build #73274 has finished for PR 17001 at commit
|
| * Implementations should throw [[NoSuchDatabaseException]] when databases don't exist. | ||
| */ | ||
| abstract class ExternalCatalog { | ||
| abstract class ExternalCatalog(conf: SparkConf, hadoopConf: Configuration) { |
There was a problem hiding this comment.
how about we just pass in a defaultDB: CatalogDatabase? then we don't need to add the protected def warehousePath: String
There was a problem hiding this comment.
I think conf/hadoopConf is more useful, later logic can use it. and it's subclass also has these two conf
There was a problem hiding this comment.
we still have conf/hadoopConf in InMemoryCatalog and HiveExternalCatalog, we can just add one more parameter.
There was a problem hiding this comment.
if we pass a defaultDB, it seems like we introduce an instance of defaultDB as we discussed above
There was a problem hiding this comment.
but it will be only used in getDatabase, and we can save a metastore call to get the default database.
There was a problem hiding this comment.
@cloud-fan I found it that if we add a parameter defaultDB for ExternalCatalog and its subclass InMemoryCatalog and HiveExternalCatalog, this change will cause a lot of related code to be modified, such as test cases ,and other logic where create InMemoryCatalog and HiveExternalCatalog
For example:
currently all the parameters of InMemoryCatalog have its own default value
class InMemoryCatalog(conf: SparkConf = new SparkConf,hadoopConfig: Configuration = new Configuration)
we can create it without an parameters, but if we add a defaultDB, we should new a defaultDB in the parameter, while we can not create a legal deafultDB because we can not get the warehouse path for the defaultDB like this:
class InMemoryCatalog(conf: SparkConf = new SparkConf,hadoopConfig: Configuration = new Configuration, defaultDB: CatalogDatabase = CatalogDatabase("default","","${can not get the warehouse path}",Map.empty))
if we don't provide a default value for defautDB in the parameter, this will cause more code change which I think it is not proper.
what about we keep the provided def warehousePath in ExternalCatalog, and add alazy val defaultDB = { val qualifiedWarehousePath = SessionCatalog .makeQualifiedPath(warehousePath, hadoopConf).toString CatalogDatabase("default","", qualifiedWarehousePath, Map.empty) }
this can also avoid call getDatabase
There was a problem hiding this comment.
I have modify the code by adding
lazy val defaultDB = { val qualifiedWarehousePath = SessionCatalog .makeQualifiedPath(warehousePath, hadoopConf).toString CatalogDatabase("default","", qualifiedWarehousePath, Map.empty) }
in ExternalCatalog
if it is not ok ,I will revert it, thanks~
SparkQA
commented
Mar 2, 2017
Test build #73755 has finished for PR 17001 at commit
|
SparkQA
commented
Mar 2, 2017
Test build #73761 has finished for PR 17001 at commit
|
| def main(args: Array[String]): Unit = { | ||
| val spark = SparkSession.builder().enableHiveSupport().getOrCreate() | ||
| try { | ||
| val warehousePath = s"file:${spark.sharedState.warehousePath.stripSuffix("/")}" |
SparkQA
commented
Mar 3, 2017
Test build #73827 has started for PR 17001 at commit |
| def getDatabase(db: String): CatalogDatabase | ||
| final def getDatabase(db: String): CatalogDatabase = { | ||
| val database = getDatabaseInternal(db) |
SparkQA
commented
Mar 3, 2017
Test build #73834 has finished for PR 17001 at commit
|
SparkQA
commented
Mar 3, 2017
Test build #73838 has finished for PR 17001 at commit
|
windpiger
commented
Mar 8, 2017
retest this please |
SparkQA
commented
Mar 8, 2017
Test build #74170 has finished for PR 17001 at commit
|
| spark.sql("CREATE TABLE t4(e string)") | ||
| val table4 = spark.sessionState.catalog.getTableMetadata(TableIdentifier("t4")) | ||
| // the table created in the database which created in this job, it will use the location | ||
| // of the database. |
There was a problem hiding this comment.
->
The table created in the non-default database (created in this job) is under the database location.
| assert(new Path(table2.location) != fs.makeQualified( | ||
| new Path(warehousePath, "not_default.db/t2"))) | ||
| spark.sql("CREATE DATABASE not_default_1") |
| spark.sql("CREATE TABLE t2(c string)") | ||
| val table2 = spark.sessionState.catalog.getTableMetadata(TableIdentifier("t2")) | ||
| // the table in not default database created here in this job, it will use the location | ||
| // of the database as its location, not the warehouse path in this job |
There was a problem hiding this comment.
->
The table created in the non-default database (created in another job) is under the database location.
| // the location when it's created. | ||
| assert(new Path(table1.location) != fs.makeQualified( | ||
| new Path(warehousePath, "not_default.db/t1"))) | ||
| assert(!new File(warehousePath.toString, "not_default.db/t1").exists()) |
There was a problem hiding this comment.
This scenario (line 993-1000) is not needed to test, IMO. Most of the test cases already cover it.
| spark.sql("CREATE TABLE t3(d string)") | ||
| val table3 = spark.sessionState.catalog.getTableMetadata(TableIdentifier("t3")) | ||
| // the table in default database created here in this job, it will use the warehouse path | ||
| // of this job as its location |
There was a problem hiding this comment.
->
When a job creates a table in the default database, the table location is under the warehouse path
that is configured for the local job.
| val table = spark.sessionState.catalog.getTableMetadata(TableIdentifier("t")) | ||
| // the table in default database created in job(SPARK_19667_CREATE_TABLE) above, | ||
| // which has different warehouse path from this job, its location still equals to | ||
| // the location when it's created. |
There was a problem hiding this comment.
How about?
For the table created by another job in the default database, the location of this table is not changed, even if the current job has a different warehouse path.
| val warehousePath = new Path(spark.sharedState.warehousePath) | ||
| val fs = warehousePath.getFileSystem(spark.sessionState.newHadoopConf()) | ||
| val defaultDB = spark.sessionState.catalog.getDatabaseMetadata("default") | ||
| // default database use warehouse path as its location |
There was a problem hiding this comment.
default -> The defaultuse warehouse path -> uses the warehouse path
gatorsmile
commented
Mar 12, 2017
A general suggestion in the table names of the test case. We can name the database based on the database type. (e.g., |
windpiger
commented
Mar 13, 2017
@gatorsmile thanks for your suggestion~ |
gatorsmile
commented
Mar 21, 2017
any update? ping @windpiger |
1 similar comment
HyukjinKwon
commented
May 11, 2017
any update? ping @windpiger |
## What changes were proposed in this pull request? This PR proposes to close PRs ... - inactive to the review comments more than a month - WIP and inactive more than a month - with Jenkins build failure but inactive more than a month - suggested to be closed and no comment against that - obviously looking inappropriate (e.g., Branch 0.5) To make sure, I left a comment for each PR about a week ago and I could not have a response back from the author in these PRs below: Closesapache#11129Closesapache#12085Closesapache#12162Closesapache#12419Closesapache#12420Closesapache#12491Closesapache#13762Closesapache#13837Closesapache#13851Closesapache#13881Closesapache#13891Closesapache#13959Closesapache#14091Closesapache#14481Closesapache#14547Closesapache#14557Closesapache#14686Closesapache#15594Closesapache#15652Closesapache#15850Closesapache#15914Closesapache#15918Closesapache#16285Closesapache#16389Closesapache#16652Closesapache#16743Closesapache#16893Closesapache#16975Closesapache#17001Closesapache#17088Closesapache#17119Closesapache#17272Closesapache#17971 Added: Closesapache#17778Closesapache#17303Closesapache#17872 ## How was this patch tested? N/A Author: hyukjinkwon <gurwls223@gmail.com> Closesapache#18017 from HyukjinKwon/close-inactive-prs.
What changes were proposed in this pull request?
Currently, when we create a managed table with HiveEnabled in default database, Spark will use the location of default database as the table's location, this is ok in non-shared metastore.
While if we use a shared metastore between different clusters, for example,
there is a hive metastore in Cluster-A, and the metastore use a remote mysql as its db, and create a default database in metastore, then the location of the default database is the path in Cluster-A
then we create another Cluster-B, and Cluster-B also use the same remote mysql as its metastore's db, so the default database conf in Cluster-B download from mysql, which location is the path of Cluster-A
then we create a table in Cluster-B in default database, it will throw an exception, that UnknowHost Cluster-A
In Hive2.0.0, it is allowed to create a table in default database which shared between clusters , and this action is not allowed in other database, just for default.
As a spark User, we will want to have the same action as Hive, thus we can create table in default database using a shared mysql in metastore.
How was this patch tested?
unit test added