diff --git ql/src/java/org/apache/hadoop/hive/ql/ErrorMsg.java ql/src/java/org/apache/hadoop/hive/ql/ErrorMsg.java index 463e8fb..87af882 100644 --- ql/src/java/org/apache/hadoop/hive/ql/ErrorMsg.java +++ ql/src/java/org/apache/hadoop/hive/ql/ErrorMsg.java @@ -417,6 +417,8 @@ "that implements AcidOutputFormat while transaction manager that supports ACID is in use"), VALUES_TABLE_CONSTRUCTOR_NOT_SUPPORTED(10296, "Values clause with table constructor not yet supported"), + ACID_OP_ON_NONACID_TABLE(10297, "Attempt to do update or delete on a table that does not use an" + + " AcidOutputFormat, table: "), //========================== 20000 range starts here ========================// SCRIPT_INIT_ERROR(20000, "Unable to initialize custom script."), 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 db2ad3f..2908237 100644 --- ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java +++ ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java @@ -1418,11 +1418,20 @@ public void getMetaData(QB qb, ReadEntity parentInput) throws SemanticException } // Disallow INSERT INTO on bucketized tables + boolean isAcid = isAcidTable(tab); if (qb.getParseInfo().isInsertIntoTable(tab.getDbName(), tab.getTableName()) && - tab.getNumBuckets() > 0 && !isAcidTable(tab)) { + tab.getNumBuckets() > 0 && !isAcid) { throw new SemanticException(ErrorMsg.INSERT_INTO_BUCKETIZED_TABLE. getMsg("Table: " + tab_name)); } + // Disallow update and delete on non-acid tables + if ((updating() || deleting()) && !isAcid) { + // isAcidTable above also checks for whether we are using an acid compliant + // transaction manager. But that has already been caught in + // UpdateDeleteSemanticAnalyzer, so if we are updating or deleting and getting nonAcid + // here, it means the table itself doesn't support it. + throw new SemanticException(ErrorMsg.ACID_OP_ON_NONACID_TABLE.getMsg(tab_name)); + } // We check offline of the table, as if people only select from an // non-existing partition of an offline table, the partition won't diff --git ql/src/test/queries/clientnegative/delete_non_acid_table.q ql/src/test/queries/clientnegative/delete_non_acid_table.q new file mode 100644 index 0000000..6ae82ff --- /dev/null +++ ql/src/test/queries/clientnegative/delete_non_acid_table.q @@ -0,0 +1,12 @@ +set hive.support.concurrency=true; +set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager; +set hive.input.format=org.apache.hadoop.hive.ql.io.HiveInputFormat; +set hive.enforce.bucketing=true; + +create table not_an_acid_table2(a int, b varchar(128)); + +insert into table not_an_acid_table2 select cint, cast(cstring1 as varchar(128)) from alltypesorc where cint is not null order by cint limit 10; + +select a,b from not_an_acid_table2 order by a; + +delete from not_an_acid_table2 where b = '0ruyd6Y50JpdGRf6HqD'; diff --git ql/src/test/queries/clientnegative/update_non_acid_table.q ql/src/test/queries/clientnegative/update_non_acid_table.q new file mode 100644 index 0000000..dd0b01e --- /dev/null +++ ql/src/test/queries/clientnegative/update_non_acid_table.q @@ -0,0 +1,12 @@ +set hive.support.concurrency=true; +set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager; +set hive.input.format=org.apache.hadoop.hive.ql.io.HiveInputFormat; +set hive.enforce.bucketing=true; + +create table not_an_acid_table(a int, b varchar(128)); + +insert into table not_an_acid_table select cint, cast(cstring1 as varchar(128)) from alltypesorc where cint is not null order by cint limit 10; + +select a,b from not_an_acid_table order by a; + +update not_an_acid_table set b = 'fred' where b = '0ruyd6Y50JpdGRf6HqD'; diff --git ql/src/test/results/clientnegative/delete_non_acid_table.q.out ql/src/test/results/clientnegative/delete_non_acid_table.q.out new file mode 100644 index 0000000..acf9eed --- /dev/null +++ ql/src/test/results/clientnegative/delete_non_acid_table.q.out @@ -0,0 +1,37 @@ +PREHOOK: query: create table not_an_acid_table2(a int, b varchar(128)) +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +PREHOOK: Output: default@not_an_acid_table2 +POSTHOOK: query: create table not_an_acid_table2(a int, b varchar(128)) +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@not_an_acid_table2 +PREHOOK: query: insert into table not_an_acid_table2 select cint, cast(cstring1 as varchar(128)) from alltypesorc where cint is not null order by cint limit 10 +PREHOOK: type: QUERY +PREHOOK: Input: default@alltypesorc +PREHOOK: Output: default@not_an_acid_table2 +POSTHOOK: query: insert into table not_an_acid_table2 select cint, cast(cstring1 as varchar(128)) from alltypesorc where cint is not null order by cint limit 10 +POSTHOOK: type: QUERY +POSTHOOK: Input: default@alltypesorc +POSTHOOK: Output: default@not_an_acid_table2 +POSTHOOK: Lineage: not_an_acid_table2.a SIMPLE [(alltypesorc)alltypesorc.FieldSchema(name:cint, type:int, comment:null), ] +POSTHOOK: Lineage: not_an_acid_table2.b EXPRESSION [(alltypesorc)alltypesorc.FieldSchema(name:cstring1, type:string, comment:null), ] +PREHOOK: query: select a,b from not_an_acid_table2 order by a +PREHOOK: type: QUERY +PREHOOK: Input: default@not_an_acid_table2 +#### A masked pattern was here #### +POSTHOOK: query: select a,b from not_an_acid_table2 order by a +POSTHOOK: type: QUERY +POSTHOOK: Input: default@not_an_acid_table2 +#### A masked pattern was here #### +-1073279343 oj1YrV5Wa +-1073051226 A34p7oRr2WvUJNf +-1072910839 0iqrc5 +-1072081801 dPkN74F7 +-1072076362 2uLyD28144vklju213J1mr +-1071480828 aw724t8c5558x2xneC624 +-1071363017 Anj0oF +-1070883071 0ruyd6Y50JpdGRf6HqD +-1070551679 iUR3Q +-1069736047 k17Am8uPHWk02cEf1jet +FAILED: SemanticException [Error 10297]: Attempt to do update or delete on a table that does not use an AcidOutputFormat, table: default.not_an_acid_table2 diff --git ql/src/test/results/clientnegative/update_non_acid_table.q.out ql/src/test/results/clientnegative/update_non_acid_table.q.out new file mode 100644 index 0000000..30127df --- /dev/null +++ ql/src/test/results/clientnegative/update_non_acid_table.q.out @@ -0,0 +1,37 @@ +PREHOOK: query: create table not_an_acid_table(a int, b varchar(128)) +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +PREHOOK: Output: default@not_an_acid_table +POSTHOOK: query: create table not_an_acid_table(a int, b varchar(128)) +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@not_an_acid_table +PREHOOK: query: insert into table not_an_acid_table select cint, cast(cstring1 as varchar(128)) from alltypesorc where cint is not null order by cint limit 10 +PREHOOK: type: QUERY +PREHOOK: Input: default@alltypesorc +PREHOOK: Output: default@not_an_acid_table +POSTHOOK: query: insert into table not_an_acid_table select cint, cast(cstring1 as varchar(128)) from alltypesorc where cint is not null order by cint limit 10 +POSTHOOK: type: QUERY +POSTHOOK: Input: default@alltypesorc +POSTHOOK: Output: default@not_an_acid_table +POSTHOOK: Lineage: not_an_acid_table.a SIMPLE [(alltypesorc)alltypesorc.FieldSchema(name:cint, type:int, comment:null), ] +POSTHOOK: Lineage: not_an_acid_table.b EXPRESSION [(alltypesorc)alltypesorc.FieldSchema(name:cstring1, type:string, comment:null), ] +PREHOOK: query: select a,b from not_an_acid_table order by a +PREHOOK: type: QUERY +PREHOOK: Input: default@not_an_acid_table +#### A masked pattern was here #### +POSTHOOK: query: select a,b from not_an_acid_table order by a +POSTHOOK: type: QUERY +POSTHOOK: Input: default@not_an_acid_table +#### A masked pattern was here #### +-1073279343 oj1YrV5Wa +-1073051226 A34p7oRr2WvUJNf +-1072910839 0iqrc5 +-1072081801 dPkN74F7 +-1072076362 2uLyD28144vklju213J1mr +-1071480828 aw724t8c5558x2xneC624 +-1071363017 Anj0oF +-1070883071 0ruyd6Y50JpdGRf6HqD +-1070551679 iUR3Q +-1069736047 k17Am8uPHWk02cEf1jet +FAILED: SemanticException [Error 10297]: Attempt to do update or delete on a table that does not use an AcidOutputFormat, table: default.not_an_acid_table