Skip to content

Commit 2fa7ee4

Browse files
committed
Support show create table from non-default catalog
1 parent 61a3001 commit 2fa7ee4

File tree

7 files changed

+149
-34
lines changed

7 files changed

+149
-34
lines changed

ql/src/java/org/apache/hadoop/hive/ql/ddl/table/create/show/ShowCreateTableAnalyzer.java

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818

1919
package org.apache.hadoop.hive.ql.ddl.table.create.show;
2020

21-
import java.util.Map.Entry;
22-
2321
import org.apache.commons.lang3.StringUtils;
22+
import org.apache.commons.lang3.tuple.Triple;
23+
import org.apache.hadoop.hive.common.TableName;
2424
import org.apache.hadoop.hive.ql.QueryState;
2525
import org.apache.hadoop.hive.ql.ddl.DDLWork;
2626
import org.apache.hadoop.hive.ql.ddl.DDLSemanticAnalyzerFactory.DDLType;
@@ -46,17 +46,21 @@ public ShowCreateTableAnalyzer(QueryState queryState) throws SemanticException {
4646
public void analyzeInternal(ASTNode root) throws SemanticException {
4747
ctx.setResFile(ctx.getLocalTmpPath());
4848

49-
Entry<String, String> tableIdentifier = getDbTableNamePair((ASTNode) root.getChild(0));
50-
if (tableIdentifier.getValue().contains(".")) {
49+
Triple<String, String, String> tableIdentifier = getCatDbTableNameTriple((ASTNode) root.getChild(0));
50+
if (tableIdentifier.toString().contains(".")) {
5151
throw new SemanticException("The SHOW CREATE TABLE command is not supported for metadata tables.");
5252
}
53-
Table table = getTable(tableIdentifier.getKey(), tableIdentifier.getValue(), true);
53+
String catName = tableIdentifier.getLeft();
54+
String dbName = tableIdentifier.getMiddle();
55+
String tblName = tableIdentifier.getRight();
56+
TableName tableName = new TableName(catName, dbName, tblName);
57+
Table table = getTable(tableName, true);
5458

5559
inputs.add(new ReadEntity(table));
5660

5761
// If no DB was specified in statement, do not include it in the final output
58-
ShowCreateTableDesc desc = new ShowCreateTableDesc(table.getDbName(), table.getTableName(),
59-
ctx.getResFile().toString(), StringUtils.isBlank(tableIdentifier.getKey()));
62+
ShowCreateTableDesc desc = new ShowCreateTableDesc(table.getCatName(), table.getDbName(), table.getTableName(),
63+
ctx.getResFile().toString(), StringUtils.isBlank(tableIdentifier.getMiddle()));
6064
Task<DDLWork> task = TaskFactory.get(new DDLWork(getInputs(), getOutputs(), desc));
6165
rootTasks.add(task);
6266

ql/src/java/org/apache/hadoop/hive/ql/ddl/table/create/show/ShowCreateTableDesc.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,14 @@ public class ShowCreateTableDesc implements DDLDesc, Serializable {
3333

3434
public static final String SCHEMA = "createtab_stmt#string";
3535

36+
private final String catalogName;
3637
private final String databaseName;
3738
private final String tableName;
3839
private final String resFile;
3940
private final boolean isRelative;
4041

41-
public ShowCreateTableDesc(String databaseName, String tableName, String resFile, boolean isRelative) {
42+
public ShowCreateTableDesc(String catalogName, String databaseName, String tableName, String resFile, boolean isRelative) {
43+
this.catalogName = catalogName;
4244
this.databaseName = databaseName;
4345
this.tableName = tableName;
4446
this.resFile = resFile;
@@ -60,6 +62,11 @@ public String getDatabaseName() {
6062
return databaseName;
6163
}
6264

65+
@Explain(displayName = "catalog name", explainLevels = { Level.USER, Level.DEFAULT, Level.EXTENDED })
66+
public String getCatalogName() {
67+
return catalogName;
68+
}
69+
6370
@Explain(displayName = "relative table location", explainLevels = { Level.EXTENDED })
6471
public boolean isRelative() {
6572
return isRelative;

ql/src/java/org/apache/hadoop/hive/ql/ddl/table/create/show/ShowCreateTableOperation.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,10 @@
2323
import java.io.IOException;
2424
import java.nio.charset.StandardCharsets;
2525
import java.util.ArrayList;
26-
import java.util.Arrays;
27-
import java.util.Collections;
28-
import java.util.HashSet;
2926
import java.util.List;
30-
import java.util.Set;
3127

3228
import org.apache.hadoop.fs.Path;
29+
import org.apache.hadoop.hive.common.TableName;
3330
import org.apache.hadoop.hive.ql.ddl.DDLOperation;
3431
import org.apache.hadoop.hive.ql.ddl.DDLOperationContext;
3532
import org.apache.hadoop.hive.ql.ddl.ShowUtils;
@@ -50,7 +47,8 @@ public ShowCreateTableOperation(DDLOperationContext context, ShowCreateTableDesc
5047
public int execute() throws HiveException {
5148
// get the create table statement for the table and populate the output
5249
try (DataOutputStream outStream = ShowUtils.getOutputStream(new Path(desc.getResFile()), context)) {
53-
Table table = context.getDb().getTable(desc.getDatabaseName(), desc.getTableName());
50+
TableName tn = new TableName(desc.getCatalogName(), desc.getDatabaseName(), desc.getTableName());
51+
Table table = context.getDb().getTable(tn, true);
5452
DDLPlanUtils ddlObj = new DDLPlanUtils();
5553
String command;
5654
if (table.isView()) {

ql/src/java/org/apache/hadoop/hive/ql/metadata/Hive.java

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1668,8 +1668,20 @@ public Table getTable(final String dbName, final String tableName) throws HiveEx
16681668
* if there's an internal error or if the table doesn't exist
16691669
*/
16701670
public Table getTable(TableName tableName) throws HiveException {
1671-
return this.getTable(ObjectUtils.firstNonNull(tableName.getDb(), SessionState.get().getCurrentDatabase()),
1672-
tableName.getTable(), tableName.getTableMetaRef(), true);
1671+
return getTable(tableName, true);
1672+
}
1673+
1674+
/**
1675+
* Returns metadata of the table. We should prioritize this method and phase out other getTable calls.
1676+
*
1677+
* @param tableName the tableName object
1678+
* @param throwException
1679+
* controls whether an exception is thrown or a returns a null
1680+
* @exception HiveException
1681+
* if there's an internal error or if the table doesn't exist
1682+
*/
1683+
public Table getTable(TableName tableName, boolean throwException) throws HiveException {
1684+
return this.getTable(tableName, throwException, false, false);
16731685
}
16741686

16751687
/**
@@ -1767,10 +1779,23 @@ public Table getTable(final String dbName, final String tableName, String tableM
17671779
* get column statistics if available
17681780
* @return the table or if throwException is false a null value.
17691781
* @throws HiveException
1782+
*
1783+
* @deprecated use {@link #getTable(TableName, boolean, boolean, boolean)}
17701784
*/
17711785
public Table getTable(final String dbName, final String tableName, String tableMetaRef, boolean throwException,
17721786
boolean checkTransactional, boolean getColumnStats) throws HiveException {
17731787

1788+
TableName table = new TableName(getDefaultCatalog(conf), dbName, tableName, tableMetaRef);
1789+
return getTable(table, throwException, checkTransactional, getColumnStats);
1790+
}
1791+
1792+
public Table getTable(final TableName table, boolean throwException,
1793+
boolean checkTransactional, boolean getColumnStats) throws HiveException {
1794+
1795+
String catName = table.getCat() != null ? table.getCat() : HiveUtils.getCurrentCatalogOrDefault(conf);
1796+
String dbName = table.getDb() != null ? table.getDb() : SessionState.get().getCurrentDatabase();
1797+
String tableName = table.getTable();
1798+
String tableMetaRef = table.getTableMetaRef();
17741799
if (tableName == null || tableName.equals("")) {
17751800
throw new HiveException("empty table creation??");
17761801
}
@@ -1780,7 +1805,7 @@ public Table getTable(final String dbName, final String tableName, String tableM
17801805
try {
17811806
// Note: this is currently called w/true from StatsOptimizer only.
17821807
GetTableRequest request = new GetTableRequest(dbName, tableName);
1783-
request.setCatName(getDefaultCatalog(conf));
1808+
request.setCatName(catName);
17841809
request.setGetColumnStats(getColumnStats);
17851810
request.setEngine(Constants.HIVE_ENGINE);
17861811
if (checkTransactional) {

ql/src/java/org/apache/hadoop/hive/ql/parse/BaseSemanticAnalyzer.java

Lines changed: 55 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import org.antlr.runtime.tree.Tree;
4141
import org.apache.calcite.sql.SqlKind;
4242
import org.apache.commons.lang3.tuple.Pair;
43+
import org.apache.commons.lang3.tuple.Triple;
4344
import org.apache.hadoop.conf.Configuration;
4445
import org.apache.hadoop.fs.Path;
4546
import org.apache.hadoop.hive.common.FileUtils;
@@ -124,6 +125,7 @@
124125
import com.google.common.collect.ImmutableList;
125126

126127
import static org.apache.hadoop.hive.conf.HiveConf.ConfVars.HIVE_LOAD_DATA_USE_NATIVE_API;
128+
import static org.apache.hadoop.hive.metastore.utils.MetaStoreUtils.getDefaultCatalog;
127129
import static org.apache.hadoop.hive.ql.parse.PTFInvocationSpec.NullOrder.NULLS_FIRST;
128130
import static org.apache.hadoop.hive.ql.parse.PTFInvocationSpec.NullOrder.NULLS_LAST;
129131
import static org.apache.hadoop.hive.ql.parse.PTFInvocationSpec.Order.ASC;
@@ -431,6 +433,9 @@ public static String getUnescapedName(ASTNode tableOrColumnNode) throws Semantic
431433
return getUnescapedName(tableOrColumnNode, null);
432434
}
433435

436+
/**
437+
* * @deprecated use {@link #getCatDbTableNameTriple(ASTNode)} instead.
438+
*/
434439
public static Map.Entry<String, String> getDbTableNamePair(ASTNode tableNameNode) throws SemanticException {
435440

436441
if (tableNameNode.getType() != HiveParser.TOK_TABNAME ||
@@ -459,6 +464,29 @@ public static Map.Entry<String, String> getDbTableNamePair(ASTNode tableNameNode
459464
}
460465
}
461466

467+
public static Triple<String, String, String> getCatDbTableNameTriple(ASTNode tableNameNode) throws SemanticException {
468+
if (tableNameNode.getType() != HiveParser.TOK_TABNAME || tableNameNode.getChildCount() < 1 || tableNameNode.getChildCount() > 4) {
469+
throw new SemanticException(ASTErrorUtils.getMsg(ErrorMsg.INVALID_TABLE_NAME.getMsg(), tableNameNode));
470+
}
471+
472+
List<String> parts = new ArrayList<>();
473+
for (int i = 0; i < tableNameNode.getChildCount(); i++) {
474+
String part = unescapeIdentifier(tableNameNode.getChild(i).getText());
475+
if (part != null && part.contains(".")) {
476+
throw new SemanticException(ASTErrorUtils.getMsg(ErrorMsg.OBJECTNAME_CONTAINS_DOT.getMsg(), tableNameNode));
477+
}
478+
parts.add(part);
479+
}
480+
481+
return switch (parts.size()) {
482+
case 1 -> Triple.of(null, null, parts.get(0));
483+
case 2 -> Triple.of(null, parts.get(0), parts.get(1));
484+
case 3 -> Triple.of(parts.get(0), parts.get(1), parts.get(2));
485+
case 4 -> Triple.of(parts.get(0), parts.get(1), parts.get(2) + "." + parts.get(3));
486+
default -> throw new SemanticException(ASTErrorUtils.getMsg(ErrorMsg.INVALID_TABLE_NAME.getMsg(), tableNameNode));
487+
};
488+
}
489+
462490
public static String getUnescapedName(ASTNode tableOrColumnNode, String currentDatabase) throws SemanticException {
463491
int tokenType = tableOrColumnNode.getToken().getType();
464492
if (tokenType == HiveParser.TOK_TABNAME) {
@@ -1967,7 +1995,27 @@ protected Table getTable(TableName tn) throws SemanticException {
19671995
}
19681996

19691997
protected Table getTable(TableName tn, boolean throwException) throws SemanticException {
1970-
return getTable(tn.getDb(), tn.getTable(), tn.getTableMetaRef(), throwException);
1998+
String catName = tn.getCat();
1999+
String dbName = tn.getDb();
2000+
String tblName = tn.getTable();
2001+
2002+
Table tab;
2003+
try {
2004+
tab = db.getTable(tn, false);
2005+
}
2006+
catch (InvalidTableException e) {
2007+
throw new SemanticException(ErrorMsg.INVALID_TABLE.getMsg(TableName.fromString(tblName,
2008+
catName, dbName).getNotEmptyDbTable()), e);
2009+
}
2010+
catch (Exception e) {
2011+
throw new SemanticException(e.getMessage(), e);
2012+
}
2013+
if (tab == null && throwException) {
2014+
// getTable needs a refactor with all ~50 occurences
2015+
throw new SemanticException(ErrorMsg.INVALID_TABLE.getMsg(TableName.fromString(tblName,
2016+
catName, dbName).getNotEmptyDbTable()));
2017+
}
2018+
return tab;
19712019
}
19722020

19732021
protected Table getTable(String tblName) throws SemanticException {
@@ -1982,25 +2030,14 @@ protected Table getTable(String database, String tblName, boolean throwException
19822030
return getTable(database, tblName, null, throwException);
19832031
}
19842032

2033+
/**
2034+
* @deprecated use {@link #getTable(TableName, boolean)} instead
2035+
* Since this is a protected method, can we directly remove it?
2036+
*/
19852037
protected Table getTable(String database, String tblName, String tableMetaRef, boolean throwException)
19862038
throws SemanticException {
1987-
Table tab;
1988-
try {
1989-
String tableName = tableMetaRef == null ? tblName : tblName + "." + tableMetaRef;
1990-
tab = database == null ? db.getTable(tableName, false)
1991-
: db.getTable(database, tblName, tableMetaRef, false);
1992-
}
1993-
catch (InvalidTableException e) {
1994-
throw new SemanticException(ErrorMsg.INVALID_TABLE.getMsg(TableName.fromString(tblName, null, database).getNotEmptyDbTable()), e);
1995-
}
1996-
catch (Exception e) {
1997-
throw new SemanticException(e.getMessage(), e);
1998-
}
1999-
if (tab == null && throwException) {
2000-
// getTable needs a refactor with all ~50 occurences
2001-
throw new SemanticException(ErrorMsg.INVALID_TABLE.getMsg(TableName.fromString(tblName, null, database).getNotEmptyDbTable()));
2002-
}
2003-
return tab;
2039+
TableName table = new TableName(getDefaultCatalog(conf), database, tblName, tableMetaRef);
2040+
return getTable(table, throwException);
20042041
}
20052042

20062043
public List<Task<?>> getAllRootTasks() {

ql/src/test/queries/clientpositive/catalog_database_table.q

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,9 @@ create table testcat.testdb1.test2(id int);
1616

1717
-- show tables in current db testcat.testdb1
1818
show tables;
19+
20+
-- show create table in current db testcat.testdb1
21+
show create table test1;
22+
23+
-- show create table use cat.db.tbl syntax
24+
show create table testcat.testdb1.test2;

ql/src/test/results/clientpositive/llap/catalog_database_table.q.out

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,41 @@ POSTHOOK: type: SHOWTABLES
4141
POSTHOOK: Input: database:testdb1
4242
test1
4343
test2
44+
PREHOOK: query: show create table test1
45+
PREHOOK: type: SHOW_CREATETABLE
46+
PREHOOK: Input: testdb1@test1
47+
POSTHOOK: query: show create table test1
48+
POSTHOOK: type: SHOW_CREATETABLE
49+
POSTHOOK: Input: testdb1@test1
50+
CREATE TABLE `test1`(
51+
`id` int)
52+
ROW FORMAT SERDE
53+
'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'
54+
STORED AS INPUTFORMAT
55+
'org.apache.hadoop.mapred.TextInputFormat'
56+
OUTPUTFORMAT
57+
'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
58+
LOCATION
59+
#### A masked pattern was here ####
60+
TBLPROPERTIES (
61+
'bucketing_version'='2',
62+
#### A masked pattern was here ####
63+
PREHOOK: query: show create table testcat.testdb1.test2
64+
PREHOOK: type: SHOW_CREATETABLE
65+
PREHOOK: Input: testdb1@test2
66+
POSTHOOK: query: show create table testcat.testdb1.test2
67+
POSTHOOK: type: SHOW_CREATETABLE
68+
POSTHOOK: Input: testdb1@test2
69+
CREATE TABLE `testdb1`.`test2`(
70+
`id` int)
71+
ROW FORMAT SERDE
72+
'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'
73+
STORED AS INPUTFORMAT
74+
'org.apache.hadoop.mapred.TextInputFormat'
75+
OUTPUTFORMAT
76+
'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
77+
LOCATION
78+
#### A masked pattern was here ####
79+
TBLPROPERTIES (
80+
'bucketing_version'='2',
81+
#### A masked pattern was here ####

0 commit comments

Comments
 (0)