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 2ee562add9..6312e74132 100644 --- ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java +++ ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java @@ -12980,10 +12980,10 @@ private void validate(Task task, boolean reworkMapredWork) * property map * @return Modified table property map */ - private Map addDefaultProperties( + private Map validateAndAddDefaultProperties( Map tblProp, boolean isExt, StorageFormat storageFormat, String qualifiedTableName, List sortCols, boolean isMaterialization, - boolean isTemporaryTable) { + boolean isTemporaryTable) throws SemanticException { Map retValue; if (tblProp == null) { retValue = new HashMap(); @@ -13002,6 +13002,12 @@ private void validate(Task task, boolean reworkMapredWork) } } } + if (!retValue.containsKey(hive_metastoreConstants.TABLE_IS_TRANSACTIONAL) + && retValue.containsKey(hive_metastoreConstants.TABLE_TRANSACTIONAL_PROPERTIES)) { + throw new SemanticException("Cannot specify " + + hive_metastoreConstants.TABLE_TRANSACTIONAL_PROPERTIES + + " without " + hive_metastoreConstants.TABLE_IS_TRANSACTIONAL); + } if (isExt && HiveConf.getBoolVar(conf, ConfVars.HIVE_EXTERNALTABLE_PURGE_DEFAULT)) { if (retValue.get(MetaStoreUtils.EXTERNAL_TABLE_PURGE) == null) { @@ -13009,7 +13015,8 @@ private void validate(Task task, boolean reworkMapredWork) } } - boolean makeInsertOnly = !isTemporaryTable && HiveConf.getBoolVar(conf, ConfVars.HIVE_CREATE_TABLES_AS_INSERT_ONLY); + boolean makeInsertOnly = !isTemporaryTable && HiveConf.getBoolVar( + conf, ConfVars.HIVE_CREATE_TABLES_AS_INSERT_ONLY); boolean makeAcid = !isTemporaryTable && MetastoreConf.getBoolVar(conf, MetastoreConf.ConfVars.CREATE_TABLES_AS_ACID) && HiveConf.getBoolVar(conf, ConfVars.HIVE_SUPPORT_CONCURRENCY) && @@ -13024,35 +13031,42 @@ private void validate(Task task, boolean reworkMapredWork) TransactionalValidationListener.INSERTONLY_TRANSACTIONAL_PROPERTY); } if (makeAcid) { - /*for CTAS, TransactionalValidationListener.makeAcid() runs to late to make table Acid - so the initial write ends up running as non-acid...*/ - try { - Class inputFormatClass = storageFormat.getInputFormat() == null ? null : - Class.forName(storageFormat.getInputFormat()); - Class outputFormatClass = storageFormat.getOutputFormat() == null ? null : - Class.forName(storageFormat.getOutputFormat()); - if (inputFormatClass == null || outputFormatClass == null || - !AcidInputFormat.class.isAssignableFrom(inputFormatClass) || - !AcidOutputFormat.class.isAssignableFrom(outputFormatClass)) { - return retValue; - } - } catch (ClassNotFoundException e) { - LOG.warn("Could not verify InputFormat=" + storageFormat.getInputFormat() + " or OutputFormat=" + - storageFormat.getOutputFormat() + " for " + qualifiedTableName); - return retValue; - } - if(sortCols != null && !sortCols.isEmpty()) { - return retValue; - } - retValue.put(hive_metastoreConstants.TABLE_IS_TRANSACTIONAL, "true"); - retValue.put(hive_metastoreConstants.TABLE_TRANSACTIONAL_PROPERTIES, - TransactionalValidationListener.DEFAULT_TRANSACTIONAL_PROPERTY); - LOG.info("Automatically chose to make " + qualifiedTableName + " acid."); + retValue = convertToAcidByDefault(storageFormat, qualifiedTableName, sortCols, retValue); } } return retValue; } + private Map convertToAcidByDefault( + StorageFormat storageFormat, String qualifiedTableName, List sortCols, + Map retValue) { + /*for CTAS, TransactionalValidationListener.makeAcid() runs to late to make table Acid + so the initial write ends up running as non-acid...*/ + try { + Class inputFormatClass = storageFormat.getInputFormat() == null ? null : + Class.forName(storageFormat.getInputFormat()); + Class outputFormatClass = storageFormat.getOutputFormat() == null ? null : + Class.forName(storageFormat.getOutputFormat()); + if (inputFormatClass == null || outputFormatClass == null || + !AcidInputFormat.class.isAssignableFrom(inputFormatClass) || + !AcidOutputFormat.class.isAssignableFrom(outputFormatClass)) { + return retValue; + } + } catch (ClassNotFoundException e) { + LOG.warn("Could not verify InputFormat=" + storageFormat.getInputFormat() + " or OutputFormat=" + + storageFormat.getOutputFormat() + " for " + qualifiedTableName); + return retValue; + } + if (sortCols != null && !sortCols.isEmpty()) { + return retValue; + } + retValue.put(hive_metastoreConstants.TABLE_IS_TRANSACTIONAL, "true"); + retValue.put(hive_metastoreConstants.TABLE_TRANSACTIONAL_PROPERTIES, + TransactionalValidationListener.DEFAULT_TRANSACTIONAL_PROPERTY); + LOG.info("Automatically chose to make " + qualifiedTableName + " acid."); + return retValue; + } + /** * Checks to see if given partition columns has DEFAULT or CHECK constraints (whether ENABLED or DISABLED) * Or has NOT NULL constraints (only ENABLED) @@ -13328,7 +13342,7 @@ ASTNode analyzeCreateTable( throw new SemanticException( "Partition columns can only declared using their name and types in regular CREATE TABLE statements"); } - tblProps = addDefaultProperties( + tblProps = validateAndAddDefaultProperties( tblProps, isExt, storageFormat, dbDotTab, sortCols, isMaterialization, isTemporary); addDbAndTabToOutputs(qualifiedTabName, TableType.MANAGED_TABLE, isTemporary, tblProps); @@ -13352,7 +13366,7 @@ ASTNode analyzeCreateTable( break; case CTLT: // create table like - tblProps = addDefaultProperties( + tblProps = validateAndAddDefaultProperties( tblProps, isExt, storageFormat, dbDotTab, sortCols, isMaterialization, isTemporary); addDbAndTabToOutputs(qualifiedTabName, TableType.MANAGED_TABLE, isTemporary, tblProps); @@ -13436,7 +13450,7 @@ ASTNode analyzeCreateTable( "Partition columns can only declared using their names in CTAS statements"); } - tblProps = addDefaultProperties( + tblProps = validateAndAddDefaultProperties( tblProps, isExt, storageFormat, dbDotTab, sortCols, isMaterialization, isTemporary); addDbAndTabToOutputs(qualifiedTabName, TableType.MANAGED_TABLE, isTemporary, tblProps); tableDesc = new CreateTableDesc(qualifiedTabName[0], dbDotTab, isExt, isTemporary, cols, diff --git ql/src/test/queries/clientnegative/txnprops.q ql/src/test/queries/clientnegative/txnprops.q new file mode 100644 index 0000000000..3c2dcfb88d --- /dev/null +++ ql/src/test/queries/clientnegative/txnprops.q @@ -0,0 +1,7 @@ +--! qt:dataset:src + +set hive.support.concurrency=true; +set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager; + +drop table test_props; +create table test_props TBLPROPERTIES ("transactional_properties"="insert_only") as select * from src limit 1; diff --git ql/src/test/results/clientnegative/txnprops.q.out ql/src/test/results/clientnegative/txnprops.q.out new file mode 100644 index 0000000000..24a59f3cf8 --- /dev/null +++ ql/src/test/results/clientnegative/txnprops.q.out @@ -0,0 +1,5 @@ +PREHOOK: query: drop table test_props +PREHOOK: type: DROPTABLE +POSTHOOK: query: drop table test_props +POSTHOOK: type: DROPTABLE +FAILED: SemanticException Cannot specify transactional_properties without transactional