diff --git ql/src/java/org/apache/hadoop/hive/ql/ErrorMsg.java ql/src/java/org/apache/hadoop/hive/ql/ErrorMsg.java index d58f62655d..83053d1c10 100644 --- ql/src/java/org/apache/hadoop/hive/ql/ErrorMsg.java +++ ql/src/java/org/apache/hadoop/hive/ql/ErrorMsg.java @@ -470,6 +470,7 @@ RESOURCE_PLAN_ALREADY_EXISTS(10417, "Resource plan {0} already exists", true), RESOURCE_PLAN_NOT_EXISTS(10418, "Resource plan {0} does not exist", true), INCOMPATIBLE_STRUCT(10419, "Incompatible structs.", true), + OBJECTNAME_CONTAINS_DOT(10420, "Table or database name may not contain dot(.) character", true), //========================== 20000 range starts here ========================// diff --git ql/src/java/org/apache/hadoop/hive/ql/parse/BaseSemanticAnalyzer.java ql/src/java/org/apache/hadoop/hive/ql/parse/BaseSemanticAnalyzer.java index 3a51d9795b..5d4ab3d131 100644 --- ql/src/java/org/apache/hadoop/hive/ql/parse/BaseSemanticAnalyzer.java +++ ql/src/java/org/apache/hadoop/hive/ql/parse/BaseSemanticAnalyzer.java @@ -363,24 +363,36 @@ public static String charSetString(String charSetName, String charSetString) * Get dequoted name from a table/column node. * @param tableOrColumnNode the table or column node * @return for table node, db.tab or tab. for column node column. + * @throws SemanticException */ - public static String getUnescapedName(ASTNode tableOrColumnNode) { + public static String getUnescapedName(ASTNode tableOrColumnNode) throws SemanticException { return getUnescapedName(tableOrColumnNode, null); } - public static Map.Entry getDbTableNamePair(ASTNode tableNameNode) { - assert(tableNameNode.getToken().getType() == HiveParser.TOK_TABNAME); + public static Map.Entry getDbTableNamePair(ASTNode tableNameNode) throws SemanticException { + + if (tableNameNode.getType() != HiveParser.TOK_TABNAME || + (tableNameNode.getChildCount() != 1 && tableNameNode.getChildCount() != 2)) { + throw new SemanticException(ErrorMsg.INVALID_TABLE_NAME.getMsg(tableNameNode)); + } + if (tableNameNode.getChildCount() == 2) { String dbName = unescapeIdentifier(tableNameNode.getChild(0).getText()); String tableName = unescapeIdentifier(tableNameNode.getChild(1).getText()); + if (dbName.contains(".") || tableName.contains(".")) { + throw new SemanticException(ErrorMsg.OBJECTNAME_CONTAINS_DOT.getMsg(tableNameNode)); + } return Pair.of(dbName, tableName); } else { String tableName = unescapeIdentifier(tableNameNode.getChild(0).getText()); + if (tableName.contains(".")) { + throw new SemanticException(ErrorMsg.OBJECTNAME_CONTAINS_DOT.getMsg(tableNameNode)); + } return Pair.of(null,tableName); } } - public static String getUnescapedName(ASTNode tableOrColumnNode, String currentDatabase) { + public static String getUnescapedName(ASTNode tableOrColumnNode, String currentDatabase) throws SemanticException { int tokenType = tableOrColumnNode.getToken().getType(); if (tokenType == HiveParser.TOK_TABNAME) { // table node @@ -409,9 +421,15 @@ public static String getUnescapedName(ASTNode tableOrColumnNode, String currentD if (tabNameNode.getChildCount() == 2) { String dbName = unescapeIdentifier(tabNameNode.getChild(0).getText()); String tableName = unescapeIdentifier(tabNameNode.getChild(1).getText()); + if (dbName.contains(".") || tableName.contains(".")) { + throw new SemanticException(ErrorMsg.OBJECTNAME_CONTAINS_DOT.getMsg(tabNameNode)); + } return new String[] {dbName, tableName}; } String tableName = unescapeIdentifier(tabNameNode.getChild(0).getText()); + if (tableName.contains(".")) { + throw new SemanticException(ErrorMsg.OBJECTNAME_CONTAINS_DOT.getMsg(tabNameNode)); + } return Utilities.getDbTableName(tableName); } @@ -433,8 +451,9 @@ public static String getDotName(String[] qname) throws SemanticException { * @param node the table node * @return the table name without schema qualification * (i.e., if name is "db.table" or "table", returns "table") + * @throws SemanticException */ - public static String getUnescapedUnqualifiedTableName(ASTNode node) { + public static String getUnescapedUnqualifiedTableName(ASTNode node) throws SemanticException { assert node.getChildCount() <= 2; if (node.getChildCount() == 2) { @@ -2287,12 +2306,13 @@ public void addPropertyReadEntry(Map tblProps, Set i Configuration conf = new Configuration(); conf.set(CredentialProviderFactory.CREDENTIAL_PROVIDER_PATH, keystore); boolean found = false; - for (CredentialProvider provider : CredentialProviderFactory.getProviders(conf)) + for (CredentialProvider provider : CredentialProviderFactory.getProviders(conf)) { if (provider instanceof AbstractJavaKeyStoreProvider) { Path path = ((AbstractJavaKeyStoreProvider) provider).getPath(); inputs.add(toReadEntity(path)); found = true; } + } if (!found) { throw new SemanticException("Cannot recognize keystore " + keystore + ", only JavaKeyStoreProvider is " + "supported"); diff --git ql/src/java/org/apache/hadoop/hive/ql/parse/DDLSemanticAnalyzer.java ql/src/java/org/apache/hadoop/hive/ql/parse/DDLSemanticAnalyzer.java index b477480e0a..2465fd7670 100644 --- ql/src/java/org/apache/hadoop/hive/ql/parse/DDLSemanticAnalyzer.java +++ ql/src/java/org/apache/hadoop/hive/ql/parse/DDLSemanticAnalyzer.java @@ -3599,7 +3599,9 @@ private void analyzeAlterTableAddParts(String[] qualified, CommonTree ast, boole // Compile internal query to capture underlying table partition dependencies StringBuilder cmd = new StringBuilder(); cmd.append("SELECT * FROM "); - cmd.append(HiveUtils.unparseIdentifier(getDotName(qualified))); + cmd.append(HiveUtils.unparseIdentifier(qualified[0])); + cmd.append("."); + cmd.append(HiveUtils.unparseIdentifier(qualified[1])); cmd.append(" WHERE "); boolean firstOr = true; for (int i = 0; i < addPartitionDesc.getPartitionCount(); ++i) { diff --git ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java index b330d710a1..2b2d4e50b0 100644 --- ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java +++ ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java @@ -994,7 +994,8 @@ protected void setAST(ASTNode newAST) { } return new int[] {aliasIndex, propsIndex, tsampleIndex, ssampleIndex}; } - String findSimpleTableName(ASTNode tabref, int aliasIndex) { + + String findSimpleTableName(ASTNode tabref, int aliasIndex) throws SemanticException { assert tabref.getType() == HiveParser.TOK_TABREF; ASTNode tableTree = (ASTNode) (tabref.getChild(0)); @@ -11826,7 +11827,8 @@ private Table getTableObjectByName(String tableName) throws HiveException { } private static void walkASTAndQualifyNames(ASTNode ast, - Set cteAlias, Context ctx, Hive db, Set ignoredTokens, UnparseTranslator unparseTranslator) { + Set cteAlias, Context ctx, Hive db, Set ignoredTokens, UnparseTranslator unparseTranslator) + throws SemanticException { Queue queue = new LinkedList<>(); queue.add(ast); while (!queue.isEmpty()) { diff --git ql/src/java/org/apache/hadoop/hive/ql/parse/SubQueryUtils.java ql/src/java/org/apache/hadoop/hive/ql/parse/SubQueryUtils.java index 3c4e3d5f75..099157f2c7 100644 --- ql/src/java/org/apache/hadoop/hive/ql/parse/SubQueryUtils.java +++ ql/src/java/org/apache/hadoop/hive/ql/parse/SubQueryUtils.java @@ -297,13 +297,13 @@ static int checkAggOrWindowing(ASTNode expressionTree) throws SemanticException return r; } - static List getTableAliasesInSubQuery(ASTNode fromClause) { + static List getTableAliasesInSubQuery(ASTNode fromClause) throws SemanticException { List aliases = new ArrayList(); getTableAliasesInSubQuery((ASTNode) fromClause.getChild(0), aliases); return aliases; } - private static void getTableAliasesInSubQuery(ASTNode joinNode, List aliases) { + private static void getTableAliasesInSubQuery(ASTNode joinNode, List aliases) throws SemanticException { if ((joinNode.getToken().getType() == HiveParser.TOK_TABREF) || (joinNode.getToken().getType() == HiveParser.TOK_SUBQUERY) @@ -324,7 +324,7 @@ private static void getTableAliasesInSubQuery(ASTNode joinNode, List ali getTableAliasesInSubQuery(right, aliases); } } - + static ASTNode hasUnQualifiedColumnReferences(ASTNode ast) { int type = ast.getType(); if ( type == HiveParser.DOT ) { @@ -333,7 +333,7 @@ static ASTNode hasUnQualifiedColumnReferences(ASTNode ast) { else if ( type == HiveParser.TOK_TABLE_OR_COL ) { return ast; } - + for(int i=0; i < ast.getChildCount(); i++ ) { ASTNode c = hasUnQualifiedColumnReferences((ASTNode) ast.getChild(i)); if ( c != null ) { @@ -368,7 +368,7 @@ static ASTNode setQualifiedColumnReferences(ASTNode ast, String tableAlias) { } return ast; } - + static ASTNode subQueryWhere(ASTNode insertClause) { if (insertClause.getChildCount() > 2 && insertClause.getChild(2).getType() == HiveParser.TOK_WHERE ) { @@ -502,15 +502,15 @@ static ASTNode buildPostJoinNullCheck(List subQueryJoinAliasExprs) { * This Subquery is joined with the Outer Query plan on the join condition 'c = 0'. * The join condition ensures that in case there are null values in the joining column * the Query returns no rows. - * + * * The AST tree for this is: - * + * * ^(TOK_QUERY * ^(TOK FROM * ^(TOK_SUBQUERY * {the input SubQuery, with correlation removed} - * subQueryAlias - * ) + * subQueryAlias + * ) * ) * ^(TOK_INSERT * ^(TOK_DESTINATION...) @@ -518,51 +518,51 @@ static ASTNode buildPostJoinNullCheck(List subQueryJoinAliasExprs) { * ^(TOK_SELECTEXPR {ast tree for count *} * ) * ^(TOK_WHERE - * {is null check for joining column} + * {is null check for joining column} * ) * ) * ) - */ - static ASTNode buildNotInNullCheckQuery(ASTNode subQueryAST, - String subQueryAlias, + */ + static ASTNode buildNotInNullCheckQuery(ASTNode subQueryAST, + String subQueryAlias, String cntAlias, List corrExprs, RowResolver sqRR) { - + subQueryAST = (ASTNode) ParseDriver.adaptor.dupTree(subQueryAST); - ASTNode qry = (ASTNode) + ASTNode qry = (ASTNode) ParseDriver.adaptor.create(HiveParser.TOK_QUERY, "TOK_QUERY"); - + qry.addChild(buildNotInNullCheckFrom(subQueryAST, subQueryAlias)); ASTNode insertAST = buildNotInNullCheckInsert(); qry.addChild(insertAST); insertAST.addChild(buildNotInNullCheckSelect(cntAlias)); - insertAST.addChild(buildNotInNullCheckWhere(subQueryAST, + insertAST.addChild(buildNotInNullCheckWhere(subQueryAST, subQueryAlias, corrExprs, sqRR)); - + return qry; } - + /* * build: * ^(TOK FROM * ^(TOK_SUBQUERY * {the input SubQuery, with correlation removed} - * subQueryAlias - * ) + * subQueryAlias + * ) * ) */ static ASTNode buildNotInNullCheckFrom(ASTNode subQueryAST, String subQueryAlias) { ASTNode from = (ASTNode) ParseDriver.adaptor.create(HiveParser.TOK_FROM, "TOK_FROM"); - ASTNode sqExpr = (ASTNode) + ASTNode sqExpr = (ASTNode) ParseDriver.adaptor.create(HiveParser.TOK_SUBQUERY, "TOK_SUBQUERY"); sqExpr.addChild(subQueryAST); sqExpr.addChild(createAliasAST(subQueryAlias)); from.addChild(sqExpr); return from; } - + /* * build * ^(TOK_INSERT @@ -570,21 +570,21 @@ static ASTNode buildNotInNullCheckFrom(ASTNode subQueryAST, String subQueryAlias * ) */ static ASTNode buildNotInNullCheckInsert() { - ASTNode insert = (ASTNode) + ASTNode insert = (ASTNode) ParseDriver.adaptor.create(HiveParser.TOK_INSERT, "TOK_INSERT"); - ASTNode dest = (ASTNode) + ASTNode dest = (ASTNode) ParseDriver.adaptor.create(HiveParser.TOK_DESTINATION, "TOK_DESTINATION"); - ASTNode dir = (ASTNode) + ASTNode dir = (ASTNode) ParseDriver.adaptor.create(HiveParser.TOK_DIR, "TOK_DIR"); - ASTNode tfile = (ASTNode) + ASTNode tfile = (ASTNode) ParseDriver.adaptor.create(HiveParser.TOK_TMP_FILE, "TOK_TMP_FILE"); insert.addChild(dest); dest.addChild(dir); dir.addChild(tfile); - + return insert; } - + /* * build: * ^(TOK_SELECT @@ -592,37 +592,37 @@ static ASTNode buildNotInNullCheckInsert() { * ) */ static ASTNode buildNotInNullCheckSelect(String cntAlias) { - ASTNode select = (ASTNode) + ASTNode select = (ASTNode) ParseDriver.adaptor.create(HiveParser.TOK_SELECT, "TOK_SELECT"); - ASTNode selectExpr = (ASTNode) + ASTNode selectExpr = (ASTNode) ParseDriver.adaptor.create(HiveParser.TOK_SELEXPR, "TOK_SELEXPR"); - ASTNode countStar = (ASTNode) + ASTNode countStar = (ASTNode) ParseDriver.adaptor.create(HiveParser.TOK_FUNCTIONSTAR, "TOK_FUNCTIONSTAR"); ASTNode alias = (createAliasAST(cntAlias)); - + countStar.addChild((ASTNode) ParseDriver.adaptor.create(HiveParser.Identifier, "count")); select.addChild(selectExpr); selectExpr.addChild(countStar); selectExpr.addChild(alias); - + return select; } - + /* * build: * ^(TOK_WHERE - * {is null check for joining column} + * {is null check for joining column} * ) */ - static ASTNode buildNotInNullCheckWhere(ASTNode subQueryAST, - String sqAlias, + static ASTNode buildNotInNullCheckWhere(ASTNode subQueryAST, + String sqAlias, List corrExprs, RowResolver sqRR) { - + ASTNode sqSelect = (ASTNode) subQueryAST.getChild(1).getChild(1); ASTNode selExpr = (ASTNode) sqSelect.getChild(0); String colAlias = null; - + if ( selExpr.getChildCount() == 2 ) { colAlias = selExpr.getChild(1).getText(); } else if (selExpr.getChild(0).getType() != HiveParser.TOK_ALLCOLREF) { @@ -634,29 +634,29 @@ static ASTNode buildNotInNullCheckWhere(ASTNode subQueryAST, String[] joinColName = sqRR.reverseLookup(joinColumn.getInternalName()); colAlias = joinColName[1]; } - + ASTNode searchCond = isNull(createColRefAST(sqAlias, colAlias)); - + for(ASTNode e : corrExprs ) { ASTNode p = (ASTNode) ParseDriver.adaptor.dupTree(e); - p = isNull(p); - searchCond = orAST(searchCond, p); + p = isNull(p); + searchCond = orAST(searchCond, p); } - + ASTNode where = (ASTNode) ParseDriver.adaptor.create(HiveParser.TOK_WHERE, "TOK_WHERE"); where.addChild(searchCond); return where; } - + static ASTNode buildNotInNullJoinCond(String subqueryAlias, String cntAlias) { - - ASTNode eq = (ASTNode) + + ASTNode eq = (ASTNode) ParseDriver.adaptor.create(HiveParser.EQUAL, "="); - + eq.addChild(createColRefAST(subqueryAlias, cntAlias)); - eq.addChild((ASTNode) + eq.addChild((ASTNode) ParseDriver.adaptor.create(HiveParser.Number, "0")); - + return eq; } @@ -716,7 +716,7 @@ public static void checkForTopLevelSubqueries(ASTNode selExprList) throws Semant } } } - + public static interface ISubQueryJoinInfo { public String getAlias(); public JoinType getJoinType(); @@ -726,7 +726,7 @@ public static void checkForTopLevelSubqueries(ASTNode selExprList) throws Semant public String getOuterQueryId(); }; - + /* * Using CommonTreeAdaptor because the Adaptor in ParseDriver doesn't carry * the token indexes when duplicating a Tree. diff --git ql/src/test/queries/clientnegative/create_table_failure2.q ql/src/test/queries/clientnegative/create_table_failure2.q index e873f3469f..48f834bca2 100644 --- ql/src/test/queries/clientnegative/create_table_failure2.q +++ ql/src/test/queries/clientnegative/create_table_failure2.q @@ -1,2 +1,2 @@ --! qt:dataset:src -create table `table_in_database_creation_not_exist.test` as select * from src limit 1; \ No newline at end of file +create table table_in_database_creation_not_exist.test as select * from src limit 1; diff --git ql/src/test/queries/clientnegative/create_table_failure4.q ql/src/test/queries/clientnegative/create_table_failure4.q index 67745e0111..6a548734c3 100644 --- ql/src/test/queries/clientnegative/create_table_failure4.q +++ ql/src/test/queries/clientnegative/create_table_failure4.q @@ -1 +1 @@ -create table `table_in_database_creation_not_exist.test` (a string); \ No newline at end of file +create table table_in_database_creation_not_exist.test (a string); diff --git ql/src/test/queries/clientnegative/incorrectly_quoted_insert.q ql/src/test/queries/clientnegative/incorrectly_quoted_insert.q new file mode 100644 index 0000000000..bfdf1b6b5c --- /dev/null +++ ql/src/test/queries/clientnegative/incorrectly_quoted_insert.q @@ -0,0 +1,5 @@ +create database tdb; +use tdb; +create table t1(id int); +create table t2(id int); +explain insert into `tdb.t1` select * from t2; diff --git ql/src/test/queries/clientnegative/table_create_with_dot.q ql/src/test/queries/clientnegative/table_create_with_dot.q new file mode 100644 index 0000000000..5b3a253083 --- /dev/null +++ ql/src/test/queries/clientnegative/table_create_with_dot.q @@ -0,0 +1,2 @@ +create database asd; +create table `asd.tbl` (a integer); diff --git ql/src/test/results/clientnegative/incorrectly_quoted_insert.q.out ql/src/test/results/clientnegative/incorrectly_quoted_insert.q.out new file mode 100644 index 0000000000..7b476d5130 --- /dev/null +++ ql/src/test/results/clientnegative/incorrectly_quoted_insert.q.out @@ -0,0 +1,29 @@ +PREHOOK: query: create database tdb +PREHOOK: type: CREATEDATABASE +PREHOOK: Output: database:tdb +POSTHOOK: query: create database tdb +POSTHOOK: type: CREATEDATABASE +POSTHOOK: Output: database:tdb +PREHOOK: query: use tdb +PREHOOK: type: SWITCHDATABASE +PREHOOK: Input: database:tdb +POSTHOOK: query: use tdb +POSTHOOK: type: SWITCHDATABASE +POSTHOOK: Input: database:tdb +PREHOOK: query: create table t1(id int) +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:tdb +PREHOOK: Output: tdb@t1 +POSTHOOK: query: create table t1(id int) +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:tdb +POSTHOOK: Output: tdb@t1 +PREHOOK: query: create table t2(id int) +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:tdb +PREHOOK: Output: tdb@t2 +POSTHOOK: query: create table t2(id int) +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:tdb +POSTHOOK: Output: tdb@t2 +FAILED: SemanticException Line 2:20 Table or database name may not contain dot(.) character 'tdb.t1' diff --git ql/src/test/results/clientnegative/table_create_with_dot.q.out ql/src/test/results/clientnegative/table_create_with_dot.q.out new file mode 100644 index 0000000000..99cdf0cf84 --- /dev/null +++ ql/src/test/results/clientnegative/table_create_with_dot.q.out @@ -0,0 +1,7 @@ +PREHOOK: query: create database asd +PREHOOK: type: CREATEDATABASE +PREHOOK: Output: database:asd +POSTHOOK: query: create database asd +POSTHOOK: type: CREATEDATABASE +POSTHOOK: Output: database:asd +FAILED: SemanticException Line 2:13 Table or database name may not contain dot(.) character 'asd.tbl'