-
Notifications
You must be signed in to change notification settings - Fork 29k
[SPARK-4943][SQL] Allow table name having dot for db/catalog #3941
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 3 commits
3652997
6ae77ce
29e5e55
343ae27
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 |
|---|---|---|
|
|
@@ -28,77 +28,63 @@ trait Catalog { | |
|
|
||
| def caseSensitive: Boolean | ||
|
|
||
| def tableExists(db: Option[String], tableName: String): Boolean | ||
| def tableExists(tableIdentifier: Seq[String]): Boolean | ||
|
|
||
| def lookupRelation( | ||
| databaseName: Option[String], | ||
| tableName: String, | ||
| alias: Option[String] = None): LogicalPlan | ||
| tableIdentifier: Seq[String], | ||
| alias: Option[String] = None): LogicalPlan | ||
|
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. Indent wrapped arguments 4 spaces.
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. agreed |
||
|
|
||
| def registerTable(databaseName: Option[String], tableName: String, plan: LogicalPlan): Unit | ||
| def registerTable(tableIdentifier: Seq[String], plan: LogicalPlan): Unit | ||
|
|
||
| def unregisterTable(databaseName: Option[String], tableName: String): Unit | ||
| def unregisterTable(tableIdentifier: Seq[String]): Unit | ||
|
|
||
| def unregisterAllTables(): Unit | ||
|
|
||
| protected def processDatabaseAndTableName( | ||
| databaseName: Option[String], | ||
| tableName: String): (Option[String], String) = { | ||
| protected def processTableIdentifier(tableIdentifier: Seq[String]): | ||
| Seq[String] = { | ||
|
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. I don't think this needs to be wrapped, does it?
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. agreed |
||
| if (!caseSensitive) { | ||
| (databaseName.map(_.toLowerCase), tableName.toLowerCase) | ||
| tableIdentifier.map(_.toLowerCase) | ||
| } else { | ||
| (databaseName, tableName) | ||
| tableIdentifier | ||
| } | ||
| } | ||
|
|
||
| protected def processDatabaseAndTableName( | ||
| databaseName: String, | ||
| tableName: String): (String, String) = { | ||
| if (!caseSensitive) { | ||
| (databaseName.toLowerCase, tableName.toLowerCase) | ||
| } else { | ||
| (databaseName, tableName) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| class SimpleCatalog(val caseSensitive: Boolean) extends Catalog { | ||
| val tables = new mutable.HashMap[String, LogicalPlan]() | ||
|
|
||
| override def registerTable( | ||
| databaseName: Option[String], | ||
| tableName: String, | ||
| tableIdentifier: Seq[String], | ||
| plan: LogicalPlan): Unit = { | ||
| val (dbName, tblName) = processDatabaseAndTableName(databaseName, tableName) | ||
| tables += ((tblName, plan)) | ||
| val tableIdent = processTableIdentifier(tableIdentifier) | ||
| tables += ((tableIdent.mkString("."), plan)) | ||
| } | ||
|
|
||
| override def unregisterTable( | ||
| databaseName: Option[String], | ||
| tableName: String) = { | ||
| val (dbName, tblName) = processDatabaseAndTableName(databaseName, tableName) | ||
| tables -= tblName | ||
| override def unregisterTable(tableIdentifier: Seq[String]) = { | ||
| val tableIdent = processTableIdentifier(tableIdentifier) | ||
| tables -= tableIdent.mkString(".") | ||
| } | ||
|
|
||
| override def unregisterAllTables() = { | ||
| tables.clear() | ||
| } | ||
|
|
||
| override def tableExists(db: Option[String], tableName: String): Boolean = { | ||
| val (dbName, tblName) = processDatabaseAndTableName(db, tableName) | ||
| tables.get(tblName) match { | ||
| override def tableExists(tableIdentifier: Seq[String]): Boolean = { | ||
| val tableIdent = processTableIdentifier(tableIdentifier) | ||
| tables.get(tableIdent.mkString(".")) match { | ||
| case Some(_) => true | ||
| case None => false | ||
| } | ||
| } | ||
|
|
||
| override def lookupRelation( | ||
| databaseName: Option[String], | ||
| tableName: String, | ||
| tableIdentifier: Seq[String], | ||
| alias: Option[String] = None): LogicalPlan = { | ||
| val (dbName, tblName) = processDatabaseAndTableName(databaseName, tableName) | ||
| val table = tables.getOrElse(tblName, sys.error(s"Table Not Found: $tableName")) | ||
| val tableWithQualifiers = Subquery(tblName, table) | ||
| val tableIdent = processTableIdentifier(tableIdentifier) | ||
| val tableFullName = tableIdent.mkString(".") | ||
| val table = tables.getOrElse(tableFullName, sys.error(s"Table Not Found: $tableFullName")) | ||
| val tableWithQualifiers = Subquery(tableIdent.head, table) | ||
|
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.
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. I store the seq in reversed order, so table name is at head.
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. Oh, sorry that was not obvious to me, and seems pretty confusing. Why not store it in the order the user gave it to you?
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. By reversed order, we know database name will be at 2nd, so it's easy to access it by using lift(1)
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. That does not seem worth the confusion of having it in reverse order. Also looking at that code more closely, we would silently discard extra part of the table identifier right? Seems like we should explicitly handle the cases where there are 1, 2, and more elements of the table identifier.
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. agreed |
||
|
|
||
| // If an alias was specified by the lookup, wrap the plan in a subquery so that attributes are | ||
| // properly qualified with this alias. | ||
|
|
@@ -115,43 +101,41 @@ class SimpleCatalog(val caseSensitive: Boolean) extends Catalog { | |
| trait OverrideCatalog extends Catalog { | ||
|
|
||
| // TODO: This doesn't work when the database changes... | ||
| val overrides = new mutable.HashMap[(Option[String],String), LogicalPlan]() | ||
| val overrides = new mutable.HashMap[String, LogicalPlan]() | ||
|
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. Why collapse this to a
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. restore it to (Option[String],String) |
||
|
|
||
| abstract override def tableExists(db: Option[String], tableName: String): Boolean = { | ||
| val (dbName, tblName) = processDatabaseAndTableName(db, tableName) | ||
| overrides.get((dbName, tblName)) match { | ||
| abstract override def tableExists(tableIdentifier: Seq[String]): Boolean = { | ||
| val tableIdent = processTableIdentifier(tableIdentifier).mkString(".") | ||
| overrides.get(tableIdent) match { | ||
| case Some(_) => true | ||
| case None => super.tableExists(db, tableName) | ||
| case None => super.tableExists(tableIdentifier) | ||
| } | ||
| } | ||
|
|
||
| abstract override def lookupRelation( | ||
| databaseName: Option[String], | ||
| tableName: String, | ||
| tableIdentifier: Seq[String], | ||
| alias: Option[String] = None): LogicalPlan = { | ||
| val (dbName, tblName) = processDatabaseAndTableName(databaseName, tableName) | ||
| val overriddenTable = overrides.get((dbName, tblName)) | ||
| val tableWithQualifers = overriddenTable.map(r => Subquery(tblName, r)) | ||
| val tableIdent = processTableIdentifier(tableIdentifier) | ||
| val overriddenTable = overrides.get(tableIdent.mkString(".")) | ||
| val tableWithQualifers = overriddenTable.map(r => Subquery(tableIdent.head, r)) | ||
|
|
||
| // If an alias was specified by the lookup, wrap the plan in a subquery so that attributes are | ||
| // properly qualified with this alias. | ||
| val withAlias = | ||
| tableWithQualifers.map(r => alias.map(a => Subquery(a, r)).getOrElse(r)) | ||
|
|
||
| withAlias.getOrElse(super.lookupRelation(dbName, tblName, alias)) | ||
| withAlias.getOrElse(super.lookupRelation(tableIdentifier, alias)) | ||
| } | ||
|
|
||
| override def registerTable( | ||
| databaseName: Option[String], | ||
| tableName: String, | ||
| tableIdentifier: Seq[String], | ||
| plan: LogicalPlan): Unit = { | ||
| val (dbName, tblName) = processDatabaseAndTableName(databaseName, tableName) | ||
| overrides.put((dbName, tblName), plan) | ||
| val tableIdent = processTableIdentifier(tableIdentifier).mkString(".") | ||
| overrides.put(tableIdent, plan) | ||
| } | ||
|
|
||
| override def unregisterTable(databaseName: Option[String], tableName: String): Unit = { | ||
| val (dbName, tblName) = processDatabaseAndTableName(databaseName, tableName) | ||
| overrides.remove((dbName, tblName)) | ||
| override def unregisterTable(tableIdentifier: Seq[String]): Unit = { | ||
| val tableIdent = processTableIdentifier(tableIdentifier).mkString(".") | ||
| overrides.remove(tableIdent) | ||
| } | ||
|
|
||
| override def unregisterAllTables(): Unit = { | ||
|
|
@@ -167,22 +151,21 @@ object EmptyCatalog extends Catalog { | |
|
|
||
| val caseSensitive: Boolean = true | ||
|
|
||
| def tableExists(db: Option[String], tableName: String): Boolean = { | ||
| def tableExists(tableIdentifier: Seq[String]): Boolean = { | ||
| throw new UnsupportedOperationException | ||
| } | ||
|
|
||
| def lookupRelation( | ||
| databaseName: Option[String], | ||
| tableName: String, | ||
| tableIdentifier: Seq[String], | ||
| alias: Option[String] = None) = { | ||
| throw new UnsupportedOperationException | ||
| } | ||
|
|
||
| def registerTable(databaseName: Option[String], tableName: String, plan: LogicalPlan): Unit = { | ||
| def registerTable(tableIdentifier: Seq[String], plan: LogicalPlan): Unit = { | ||
| throw new UnsupportedOperationException | ||
| } | ||
|
|
||
| def unregisterTable(databaseName: Option[String], tableName: String): Unit = { | ||
| def unregisterTable(tableIdentifier: Seq[String]): Unit = { | ||
| throw new UnsupportedOperationException | ||
| } | ||
|
|
||
|
|
||
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.
I think this should probably just be a single rule. With something like:
repsep(ident, ",")for the table identifier.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.
I change it to rep1sep(ident, ".")