You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hive.apache.org by ay...@apache.org on 2024/06/26 10:45:34 UTC
(hive) branch master updated: HIVE-28275: Iceberg: Add support for 'If Not Exists' and 'or Replace' for Create Tag. (#5317). (Ayush Saxena, reviewed by Simhadri Govindappa)
This is an automated email from the ASF dual-hosted git repository.
ayushsaxena pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hive.git
The following commit(s) were added to refs/heads/master by this push:
new 74b9c88aced HIVE-28275: Iceberg: Add support for 'If Not Exists' and 'or Replace' for Create Tag. (#5317). (Ayush Saxena, reviewed by Simhadri Govindappa)
74b9c88aced is described below
commit 74b9c88aced9407351f6635769a4bd48214fca1e
Author: Ayush Saxena <ay...@apache.org>
AuthorDate: Wed Jun 26 16:15:29 2024 +0530
HIVE-28275: Iceberg: Add support for 'If Not Exists' and 'or Replace' for Create Tag. (#5317). (Ayush Saxena, reviewed by Simhadri Govindappa)
---
.../iceberg/mr/hive/IcebergSnapshotRefExec.java | 27 ++++++++++-
.../test/queries/positive/alter_table_create_tag.q | 9 ++++
.../results/positive/alter_table_create_tag.q.out | 52 ++++++++++++++++++++++
.../hadoop/hive/ql/parse/AlterClauseParser.g | 12 ++++-
4 files changed, 96 insertions(+), 4 deletions(-)
diff --git a/iceberg/iceberg-handler/src/main/java/org/apache/iceberg/mr/hive/IcebergSnapshotRefExec.java b/iceberg/iceberg-handler/src/main/java/org/apache/iceberg/mr/hive/IcebergSnapshotRefExec.java
index 3e251913801..9d3af3b45c5 100644
--- a/iceberg/iceberg-handler/src/main/java/org/apache/iceberg/mr/hive/IcebergSnapshotRefExec.java
+++ b/iceberg/iceberg-handler/src/main/java/org/apache/iceberg/mr/hive/IcebergSnapshotRefExec.java
@@ -103,6 +103,19 @@ public class IcebergSnapshotRefExec {
}
}
+ private static boolean refExistsAsTag(Table table, String tagName) {
+ SnapshotRef tagRef = table.refs().get(tagName);
+ if (tagRef != null) {
+ if (tagRef.isTag()) {
+ return true;
+ } else {
+ throw new IllegalArgumentException(
+ "Cannot complete create tag operation on " + tagName + ", as it exists as Branch");
+ }
+ }
+ return false;
+ }
+
private static boolean refExistsAsBranch(Table table, String branchName) {
SnapshotRef branchRef = table.refs().get(branchName);
if (branchRef != null) {
@@ -154,6 +167,11 @@ public class IcebergSnapshotRefExec {
public static void createTag(Table table, AlterTableSnapshotRefSpec.CreateSnapshotRefSpec createTagSpec) {
String tagName = createTagSpec.getRefName();
+ boolean refExistsAsTag = refExistsAsTag(table, tagName);
+ if (createTagSpec.isIfNotExists() && refExistsAsTag) {
+ return;
+ }
+ boolean isReplace = createTagSpec.isReplace() && refExistsAsTag;
Long snapshotId = null;
if (createTagSpec.getSnapshotId() != null) {
snapshotId = createTagSpec.getSnapshotId();
@@ -162,9 +180,14 @@ public class IcebergSnapshotRefExec {
} else {
snapshotId = table.currentSnapshot().snapshotId();
}
- LOG.info("Creating tag {} on iceberg table {} with snapshotId {}", tagName, table.name(), snapshotId);
ManageSnapshots manageSnapshots = table.manageSnapshots();
- manageSnapshots.createTag(tagName, snapshotId);
+ if (isReplace) {
+ LOG.info("Replacing tag {} on iceberg table {} with snapshotId {}", tagName, table.name(), snapshotId);
+ manageSnapshots.replaceTag(tagName, snapshotId);
+ } else {
+ LOG.info("Creating tag {} on iceberg table {} with snapshotId {}", tagName, table.name(), snapshotId);
+ manageSnapshots.createTag(tagName, snapshotId);
+ }
if (createTagSpec.getMaxRefAgeMs() != null) {
manageSnapshots.setMaxRefAgeMs(tagName, createTagSpec.getMaxRefAgeMs());
}
diff --git a/iceberg/iceberg-handler/src/test/queries/positive/alter_table_create_tag.q b/iceberg/iceberg-handler/src/test/queries/positive/alter_table_create_tag.q
index ad5eabb3e8b..2ef424aeeb1 100644
--- a/iceberg/iceberg-handler/src/test/queries/positive/alter_table_create_tag.q
+++ b/iceberg/iceberg-handler/src/test/queries/positive/alter_table_create_tag.q
@@ -17,6 +17,15 @@ explain alter table iceTbl create tag test_tag_2 retain 5 days;
alter table iceTbl create tag test_tag_2 retain 5 days;
select name, max_reference_age_in_ms from default.iceTbl.refs where type='TAG';
+-- create a tag which already exists
+explain alter table iceTbl create tag if not exists test_tag_2;
+alter table iceTbl create tag if not exists test_tag_2;
+
+-- create or replace
+explain alter table iceTbl create or replace tag test_tag_1;
+alter table iceTbl create or replace tag test_tag_1;
+select * from default.iceTbl.tag_test_tag_1;
+
-- drop a tag
explain alter table iceTbl drop tag test_tag_2;
alter table iceTbl drop tag test_tag_2;
diff --git a/iceberg/iceberg-handler/src/test/results/positive/alter_table_create_tag.q.out b/iceberg/iceberg-handler/src/test/results/positive/alter_table_create_tag.q.out
index 803891e4b28..38a4e3dd45c 100644
--- a/iceberg/iceberg-handler/src/test/results/positive/alter_table_create_tag.q.out
+++ b/iceberg/iceberg-handler/src/test/results/positive/alter_table_create_tag.q.out
@@ -83,6 +83,58 @@ POSTHOOK: Input: default@icetbl
POSTHOOK: Output: hdfs://### HDFS PATH ###
test_tag_1 NULL
test_tag_2 432000000
+PREHOOK: query: explain alter table iceTbl create tag if not exists test_tag_2
+PREHOOK: type: ALTERTABLE_CREATETAG
+PREHOOK: Input: default@icetbl
+POSTHOOK: query: explain alter table iceTbl create tag if not exists test_tag_2
+POSTHOOK: type: ALTERTABLE_CREATETAG
+POSTHOOK: Input: default@icetbl
+STAGE DEPENDENCIES:
+ Stage-0 is a root stage
+
+STAGE PLANS:
+ Stage: Stage-0
+ SnapshotRef Operation
+ table name: default.iceTbl
+ spec: AlterTableSnapshotRefSpec{operationType=CREATE_TAG, operationParams=CreateSnapshotRefSpec{refName=test_tag_2, isReplace=false, ifNotExists=true}}
+
+PREHOOK: query: alter table iceTbl create tag if not exists test_tag_2
+PREHOOK: type: ALTERTABLE_CREATETAG
+PREHOOK: Input: default@icetbl
+POSTHOOK: query: alter table iceTbl create tag if not exists test_tag_2
+POSTHOOK: type: ALTERTABLE_CREATETAG
+POSTHOOK: Input: default@icetbl
+PREHOOK: query: explain alter table iceTbl create or replace tag test_tag_1
+PREHOOK: type: ALTERTABLE_CREATETAG
+PREHOOK: Input: default@icetbl
+POSTHOOK: query: explain alter table iceTbl create or replace tag test_tag_1
+POSTHOOK: type: ALTERTABLE_CREATETAG
+POSTHOOK: Input: default@icetbl
+STAGE DEPENDENCIES:
+ Stage-0 is a root stage
+
+STAGE PLANS:
+ Stage: Stage-0
+ SnapshotRef Operation
+ table name: default.iceTbl
+ spec: AlterTableSnapshotRefSpec{operationType=CREATE_TAG, operationParams=CreateSnapshotRefSpec{refName=test_tag_1, isReplace=true, ifNotExists=false}}
+
+PREHOOK: query: alter table iceTbl create or replace tag test_tag_1
+PREHOOK: type: ALTERTABLE_CREATETAG
+PREHOOK: Input: default@icetbl
+POSTHOOK: query: alter table iceTbl create or replace tag test_tag_1
+POSTHOOK: type: ALTERTABLE_CREATETAG
+POSTHOOK: Input: default@icetbl
+PREHOOK: query: select * from default.iceTbl.tag_test_tag_1
+PREHOOK: type: QUERY
+PREHOOK: Input: default@icetbl
+PREHOOK: Output: hdfs://### HDFS PATH ###
+POSTHOOK: query: select * from default.iceTbl.tag_test_tag_1
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@icetbl
+POSTHOOK: Output: hdfs://### HDFS PATH ###
+1 jack
+2 bob
PREHOOK: query: explain alter table iceTbl drop tag test_tag_2
PREHOOK: type: ALTERTABLE_DROPTAG
PREHOOK: Input: default@icetbl
diff --git a/parser/src/java/org/apache/hadoop/hive/ql/parse/AlterClauseParser.g b/parser/src/java/org/apache/hadoop/hive/ql/parse/AlterClauseParser.g
index 2f136a5d998..65a35c2e0b7 100644
--- a/parser/src/java/org/apache/hadoop/hive/ql/parse/AlterClauseParser.g
+++ b/parser/src/java/org/apache/hadoop/hive/ql/parse/AlterClauseParser.g
@@ -75,6 +75,7 @@ alterTableStatementSuffix
| alterStatementSuffixSetOwner
| alterStatementSuffixSetPartSpec
| alterStatementSuffixExecute
+ | (KW_CREATE KW_OR KW_REPLACE KW_TAG) => alterStatementSuffixCreateOrReplaceTag
| alterStatementSuffixCreateBranch
| alterStatementSuffixDropBranch
| alterStatementSuffixCreateTag
@@ -582,10 +583,17 @@ alterStatementSuffixDropTag
alterStatementSuffixCreateTag
@init { gParent.pushMsg("alter table create tag", state); }
@after { gParent.popMsg(state); }
- : KW_CREATE KW_TAG tagName=identifier snapshotIdOfRef? refRetain?
- -> ^(TOK_ALTERTABLE_CREATE_TAG $tagName snapshotIdOfRef? refRetain?)
+ : KW_CREATE KW_TAG ifNotExists? tagName=identifier snapshotIdOfRef? refRetain?
+ -> ^(TOK_ALTERTABLE_CREATE_TAG $tagName ifNotExists? snapshotIdOfRef? refRetain?)
;
+alterStatementSuffixCreateOrReplaceTag
+@init { gParent.pushMsg("alter table create tag", state); }
+@after { gParent.popMsg(state); }
+ : KW_CREATE KW_OR KW_REPLACE KW_TAG tagName=identifier snapshotIdOfRef? refRetain?
+ -> ^(TOK_ALTERTABLE_CREATE_TAG $tagName KW_REPLACE snapshotIdOfRef? refRetain?)
+ ;
+
fileFormat
@init { gParent.pushMsg("file format specification", state); }
@after { gParent.popMsg(state); }