This is an automated email from the ASF dual-hosted git repository. michaelsmith pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/impala.git
commit f0ac9a4b7d3b7c1eb9e9b5cc36aae80031ce9340 Author: Balazs Hevele <[email protected]> AuthorDate: Mon Jan 26 14:50:14 2026 +0100 IMPALA-12844: Support setting DBPROPERTIES Added support for ALTER DATABASE <db> SET DBPROPERTIES(...) Added support for [WITH DBPROPERTIES(...)] for CREATE DATABASE queries Database properties can now be set by Impala through these queries either at database creation or for already existing databases. Testing: - Added frontend tests for parsing/analyzing/authorizing relevant queries - Added E2E tests to verify that altering properties does take effect Change-Id: I628c7bed4f0c39aed7f5f4ffea52421caf501933 Reviewed-on: http://gerrit.cloudera.org:8080/23905 Reviewed-by: Impala Public Jenkins <[email protected]> Tested-by: Impala Public Jenkins <[email protected]> --- common/thrift/JniCatalog.thrift | 12 +++++ fe/src/main/cup/sql-parser.cup | 22 ++++++++- .../analysis/AlterDbSetDbPropertiesStmt.java | 57 ++++++++++++++++++++++ .../org/apache/impala/analysis/CreateDbStmt.java | 10 +++- .../apache/impala/service/CatalogOpExecutor.java | 56 +++++++++++++++------ .../org/apache/impala/analysis/AnalyzeDDLTest.java | 9 ++++ .../org/apache/impala/analysis/ParserTest.java | 36 ++++++++++++++ .../authorization/AuthorizationStmtTest.java | 34 +++++++++++++ .../authorization/ranger/RangerAuditLogTest.java | 16 ++++++ .../queries/QueryTest/create-database.test | 24 +++++++++ tests/custom_cluster/test_events_custom_configs.py | 2 + tests/metadata/test_ddl.py | 6 +++ tests/metadata/test_ddl_base.py | 4 ++ 13 files changed, 268 insertions(+), 20 deletions(-) diff --git a/common/thrift/JniCatalog.thrift b/common/thrift/JniCatalog.thrift index b3c871fa7..ebd49dd38 100644 --- a/common/thrift/JniCatalog.thrift +++ b/common/thrift/JniCatalog.thrift @@ -67,6 +67,7 @@ enum TOwnerType { // Types of ALTER DATABASE commands supported. enum TAlterDbType { SET_OWNER = 0 + SET_DBPROPERTIES = 1 } // Parameters for ALTER DATABASE SET OWNER commands. @@ -82,6 +83,11 @@ struct TAlterDbSetOwnerParams { 3: optional string server_name } +// Parameters for ALTER DATABASE SET DBPROPERTIES commands. +struct TAlterDbSetDbPropertiesParams { + 1: map<string, string> properties +} + struct TAlterDbParams { // The type of ALTER DATABASE command. 1: required TAlterDbType alter_type @@ -91,6 +97,9 @@ struct TAlterDbParams { // Parameters for ALTER DATABASE SET OWNER commands. 3: optional TAlterDbSetOwnerParams set_owner_params + + // Parameters for ALTER DATABASE SET DBPROPERTIES commands. + 4: optional TAlterDbSetDbPropertiesParams set_dbproperties_params } // Types of ALTER TABLE commands supported. @@ -145,6 +154,9 @@ struct TCreateDbParams { // Optional HDFS path for the database. Overrides location as the default location for // all managed tables created in the database. 7: optional string managed_location + + // Optional dbparams to be set after creation + 8: optional map<string, string> properties } // Parameters of CREATE DATA SOURCE commands diff --git a/fe/src/main/cup/sql-parser.cup b/fe/src/main/cup/sql-parser.cup index cb4449230..d1772268c 100755 --- a/fe/src/main/cup/sql-parser.cup +++ b/fe/src/main/cup/sql-parser.cup @@ -527,6 +527,7 @@ nonterminal ComputeStatsStmt compute_stats_stmt; nonterminal DropDbStmt drop_db_stmt; nonterminal DropStatsStmt drop_stats_stmt; nonterminal DropTableOrViewStmt drop_tbl_or_view_stmt; +nonterminal HashMap opt_with_dbproperties; nonterminal CreateDbStmt create_db_stmt; nonterminal CreateTableAsSelectStmt create_tbl_as_select_stmt; nonterminal CreateTableAsSelectStmt.CtasParams create_tbl_as_select_params; @@ -1414,6 +1415,12 @@ alter_db_stmt ::= parser.checkIdentKeyword("OWNER", owner_id); RESULT = new AlterDbSetOwnerStmt(db, new Owner(TOwnerType.ROLE, role)); :} + | KW_ALTER KW_DATABASE ident_or_unreserved:db KW_SET IDENT:dbproperties_id + LPAREN properties_map:properties RPAREN + {: + parser.checkIdentKeyword("DBPROPERTIES", dbproperties_id); + RESULT = new AlterDbSetDbPropertiesStmt(db, properties); + :} ; // In some places, the opt_partition_set is used to avoid conflicts even though @@ -1581,11 +1588,22 @@ opt_kw_column ::= | /* empty */ ; +opt_with_dbproperties ::= + KW_WITH IDENT:dbproperties_id LPAREN properties_map:properties RPAREN + {: + parser.checkIdentKeyword("DBPROPERTIES", dbproperties_id); + RESULT = properties; + :} + | /* empty */ + {: RESULT = null; :} + ; + create_db_stmt ::= KW_CREATE db_or_schema_kw if_not_exists_val:if_not_exists ident_or_unreserved:db_name - opt_comment_val:comment location_val:location managed_location_val:managed_location + opt_comment_val:comment opt_with_dbproperties:dbproperties + location_val:location managed_location_val:managed_location {: RESULT = new CreateDbStmt(db_name, comment, location, - managed_location, if_not_exists); + managed_location, if_not_exists, dbproperties); :} ; diff --git a/fe/src/main/java/org/apache/impala/analysis/AlterDbSetDbPropertiesStmt.java b/fe/src/main/java/org/apache/impala/analysis/AlterDbSetDbPropertiesStmt.java new file mode 100644 index 000000000..b766c0e80 --- /dev/null +++ b/fe/src/main/java/org/apache/impala/analysis/AlterDbSetDbPropertiesStmt.java @@ -0,0 +1,57 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.impala.analysis; + +import java.util.Map; + +import org.apache.impala.authorization.Privilege; +import org.apache.impala.common.AnalysisException; +import org.apache.impala.thrift.TAlterDbParams; +import org.apache.impala.thrift.TAlterDbSetDbPropertiesParams; +import org.apache.impala.thrift.TAlterDbType; + +/** + * Represents an ALTER DATABASE db SET DBPROPERTIES ('key'='value', ...) statement. + */ +public class AlterDbSetDbPropertiesStmt extends AlterDbStmt { + private final Map<String, String> dbProperties_; + + public AlterDbSetDbPropertiesStmt(String dbName, Map<String, String> properties) { + super(dbName); + this.dbProperties_ = properties; + } + + @Override + public void analyze(Analyzer analyzer) throws AnalysisException { + analyzer.getDb(dbName_, Privilege.ALTER); + } + + @Override + public TAlterDbParams toThrift() { + TAlterDbParams params = super.toThrift(); + params.setAlter_type(TAlterDbType.SET_DBPROPERTIES); + + TAlterDbSetDbPropertiesParams setDbPropertiesParams + = new TAlterDbSetDbPropertiesParams(); + + setDbPropertiesParams.setProperties(dbProperties_); + params.setSet_dbproperties_params(setDbPropertiesParams); + + return params; + } +} \ No newline at end of file diff --git a/fe/src/main/java/org/apache/impala/analysis/CreateDbStmt.java b/fe/src/main/java/org/apache/impala/analysis/CreateDbStmt.java index 40c6e9417..974b31892 100644 --- a/fe/src/main/java/org/apache/impala/analysis/CreateDbStmt.java +++ b/fe/src/main/java/org/apache/impala/analysis/CreateDbStmt.java @@ -17,6 +17,8 @@ package org.apache.impala.analysis; +import java.util.Map; + import com.google.common.base.Preconditions; import org.apache.hadoop.fs.permission.FsAction; import org.apache.impala.authorization.Privilege; @@ -35,6 +37,7 @@ public class CreateDbStmt extends StatementBase { private final HdfsUri managedLocation_; private final String comment_; private final boolean ifNotExists_; + private final Map<String, String> dbProperties_; // Database owner. Set during analysis. private String owner_; @@ -45,7 +48,7 @@ public class CreateDbStmt extends StatementBase { * Creates a database with the given name. */ public CreateDbStmt(String dbName) { - this(dbName, null, null, null, false); + this(dbName, null, null, null, false, null); } /** @@ -55,12 +58,14 @@ public class CreateDbStmt extends StatementBase { * unless the ifNotExists is true. */ public CreateDbStmt(String dbName, String comment, HdfsUri location, - HdfsUri managedlocation, boolean ifNotExists) { + HdfsUri managedlocation, boolean ifNotExists, + Map<String, String> properties) { this.dbName_ = dbName; this.comment_ = comment; this.location_ = location; this.managedLocation_ = managedlocation; this.ifNotExists_ = ifNotExists; + this.dbProperties_ = properties; } public String getComment() { return comment_; } @@ -92,6 +97,7 @@ public class CreateDbStmt extends StatementBase { params.setIf_not_exists(getIfNotExists()); params.setOwner(getOwner()); params.setServer_name(serverName_); + params.setProperties(dbProperties_); return params; } diff --git a/fe/src/main/java/org/apache/impala/service/CatalogOpExecutor.java b/fe/src/main/java/org/apache/impala/service/CatalogOpExecutor.java index 79ca38519..3b3bbbf9c 100644 --- a/fe/src/main/java/org/apache/impala/service/CatalogOpExecutor.java +++ b/fe/src/main/java/org/apache/impala/service/CatalogOpExecutor.java @@ -177,7 +177,9 @@ import org.apache.impala.hive.executor.HiveJavaFunction; import org.apache.impala.hive.executor.HiveJavaFunctionFactory; import org.apache.impala.thrift.JniCatalogConstants; import org.apache.impala.thrift.TAlterDbParams; +import org.apache.impala.thrift.TAlterDbType; import org.apache.impala.thrift.TAlterDbSetOwnerParams; +import org.apache.impala.thrift.TAlterDbSetDbPropertiesParams; import org.apache.impala.thrift.TAlterTableAddColsParams; import org.apache.impala.thrift.TAlterTableAddDropRangePartitionParams; import org.apache.impala.thrift.TAlterTableAddPartitionParams; @@ -2341,6 +2343,11 @@ public class CatalogOpExecutor { if (params.getComment() != null) { db.setDescription(params.getComment()); } + if (params.getProperties() != null) { + for (Map.Entry<String, String> property : params.getProperties().entrySet()) { + db.putToParameters(property.getKey(), property.getValue()); + } + } if (params.getLocation() != null) { db.setLocationUri(params.getLocation()); } @@ -2724,7 +2731,7 @@ public class CatalogOpExecutor { // parameters. If the applyAlterDatabase method below throws an exception, // catalog might end up in a inconsistent state. Ideally, we should make a copy // of hms Database object and then update the Db once the HMS operation succeeds - // similar to what happens in alterDatabaseSetOwner method. + // similar to what happens in alterDatabase method. if (catalog_.addFunction(fn)) { addCatalogServiceIdentifiers(db.getMetaStoreDb(), catalog_.getCatalogServiceId(), newCatalogVersion); @@ -8454,23 +8461,29 @@ public class CatalogOpExecutor { if (db == null) { throw new CatalogException("Database: " + dbName + " does not exist."); } + TAlterDbSetOwnerParams setOwnerParams = null; + TAlterDbSetDbPropertiesParams setDbPropertiesParams = null; switch (params.getAlter_type()) { - case SET_OWNER: - alterDatabaseSetOwner(db, params.getSet_owner_params(), wantMinimalResult, - response, catalogTimeline); + case SET_OWNER: { + setOwnerParams = params.getSet_owner_params(); + Preconditions.checkNotNull(setOwnerParams); + Preconditions.checkNotNull(setOwnerParams.owner_name); + Preconditions.checkNotNull(setOwnerParams.owner_type); + tryLock(db, "altering the owner", catalogTimeline); + break; + } + case SET_DBPROPERTIES: { + setDbPropertiesParams = params.getSet_dbproperties_params(); + Preconditions.checkNotNull(setDbPropertiesParams); + Preconditions.checkNotNull(setDbPropertiesParams.properties); + tryLock(db, "altering dbproperties", catalogTimeline); break; + } default: throw new UnsupportedOperationException( "Unknown ALTER DATABASE operation type: " + params.getAlter_type()); } - } - private void alterDatabaseSetOwner(Db db, TAlterDbSetOwnerParams params, - boolean wantMinimalResult, TDdlExecResponse response, - EventSequence catalogTimeline) throws ImpalaException { - Preconditions.checkNotNull(params.owner_name); - Preconditions.checkNotNull(params.owner_type); - tryLock(db, "altering the owner", catalogTimeline); // Get a new catalog version to assign to the database being altered. long newCatalogVersion = catalog_.incrementAndGetCatalogVersion(); catalog_.getLock().writeLock().unlock(); @@ -8480,16 +8493,27 @@ public class CatalogOpExecutor { newCatalogVersion); String originalOwnerName = msDb.getOwnerName(); PrincipalType originalOwnerType = msDb.getOwnerType(); - msDb.setOwnerName(params.owner_name); - msDb.setOwnerType(PrincipalType.valueOf(params.owner_type.name())); + switch (params.getAlter_type()) { + case SET_OWNER: { + msDb.setOwnerName(setOwnerParams.owner_name); + msDb.setOwnerType(PrincipalType.valueOf(setOwnerParams.owner_type.name())); + break; + } + case SET_DBPROPERTIES: { + for (Map.Entry<String, String> property : + setDbPropertiesParams.properties.entrySet()) + msDb.putToParameters(property.getKey(), property.getValue()); + break; + } + } try { applyAlterDatabase(msDb, catalogTimeline); } catch (ImpalaRuntimeException e) { throw e; } - if (authzConfig_.isEnabled()) { - authzManager_.updateDatabaseOwnerPrivilege(params.server_name, db.getName(), - originalOwnerName, originalOwnerType, msDb.getOwnerName(), + if (params.getAlter_type() == TAlterDbType.SET_OWNER && authzConfig_.isEnabled()) { + authzManager_.updateDatabaseOwnerPrivilege(setOwnerParams.server_name, + db.getName(), originalOwnerName, originalOwnerType, msDb.getOwnerName(), msDb.getOwnerType(), response); } Db updatedDb = catalog_.updateDb(msDb); diff --git a/fe/src/test/java/org/apache/impala/analysis/AnalyzeDDLTest.java b/fe/src/test/java/org/apache/impala/analysis/AnalyzeDDLTest.java index 7369aff50..ae0529e4f 100644 --- a/fe/src/test/java/org/apache/impala/analysis/AnalyzeDDLTest.java +++ b/fe/src/test/java/org/apache/impala/analysis/AnalyzeDDLTest.java @@ -2421,6 +2421,8 @@ public class AnalyzeDDLTest extends FrontendTestBase { AnalysisError("create database new_db managedlocation " + "'blah://bucket/test-warehouse/new_db'", "No FileSystem for scheme: blah"); + + AnalyzesOk("create database new_db with dbproperties('a'='b')"); } @Test @@ -4843,6 +4845,13 @@ public class AnalyzeDDLTest extends FrontendTestBase { } } + @Test + public void TestAlterDatabaseSetDbProperties() { + AnalyzesOk("alter database functional set dbproperties('a'='b')"); + AnalysisError("alter database doesntexist set dbproperties('a'='b')", + "Database does not exist: doesntexist"); + } + @Test public void TestAlterTableSetOwner() { String[] ownerTypes = new String[]{"user", "role"}; diff --git a/fe/src/test/java/org/apache/impala/analysis/ParserTest.java b/fe/src/test/java/org/apache/impala/analysis/ParserTest.java index 4905851f5..b81a7bac8 100644 --- a/fe/src/test/java/org/apache/impala/analysis/ParserTest.java +++ b/fe/src/test/java/org/apache/impala/analysis/ParserTest.java @@ -2262,6 +2262,9 @@ public class ParserTest extends FrontendTestBase { ParsesOk(String.format("CREATE %s Foo LOCATION '/hdfs_location'", kw)); ParsesOk(String.format( "CREATE %s Foo COMMENT 'comment' LOCATION '/hdfs_location'", kw)); + ParsesOk(String.format("CREATE %s Foo WITH DBPROPERTIES('k'='v')", kw)); + ParsesOk(String.format( + "CREATE %s Foo WITH DBPROPERTIES('k1'='v1', 'k2'='v2')", kw)); // Only string literals are supported ParserError(String.format("CREATE %s Foo COMMENT mytable", kw)); @@ -2271,10 +2274,27 @@ public class ParserTest extends FrontendTestBase { ParserError(String.format( "CREATE %s Foo LOCATION '/hdfs/location' COMMENT 'comment'", kw)); + ParserError(String.format("CREATE %s Foo DBPROPERTIES('a'='b')", kw)); + ParserError(String.format("CREATE %s Foo WITH DBPROPERTIES()", kw)); + ParserError(String.format("CREATE %s Foo WITH DBPROPERTIES(a=)", kw)); + ParserError(String.format("CREATE %s Foo WITH DBPROPERTIES('a'=b)", kw)); + + // WITH DBPROPERTIES needs to be *before* LOCATION + ParserError(String.format( + "CREATE %s Foo LOCATION '/hdfs/location' WITH DBPROPERTIES('a'='b')", kw)); + ParsesOk(String.format( + "CREATE %s Foo WITH DBPROPERTIES('a'='b') LOCATION '/hdfs/location'", kw)); + ParserError(String.format("CREATE %s Foo COMMENT LOCATION '/hdfs_location'", kw)); ParserError(String.format("CREATE %s Foo LOCATION", kw)); ParserError(String.format("CREATE %s Foo LOCATION 'dfsd' 'dafdsf'", kw)); + ParsesOk(String.format( + "CREATE %s Foo COMMENT 'comment' WITH DBPROPERTIES('a'='b')", kw)); + ParsesOk(String.format( + "CREATE %s Foo COMMENT 'comment' WITH DBPROPERTIES('a'='b') " + + "LOCATION '/hdfs/location'", kw)); + ParserError(String.format("CREATE Foo")); ParserError(String.format("CREATE %s 'Foo'", kw)); ParserError(String.format("CREATE %s", kw)); @@ -4458,6 +4478,22 @@ public class ParserTest extends FrontendTestBase { ParserError("ALTER DATABASE SET OWNER"); } + @Test + public void TestAlterDatabaseSetDbProperties() { + ParsesOk("ALTER DATABASE db SET DBPROPERTIES('a'='b')"); + ParsesOk("ALTER DATABASE db SET DBPROPERTIES('a'='b', 'b'='c')"); + ParsesOk("ALTER DATABASE db SET DBPROPERTIES('a'='b', 'b'='c', 'c'='d')"); + + ParserError("ALTER DATABASE db SET DBPROPERTIESS('a'='b')"); + ParserError("ALTER DATABASE db SET DBPROPERTIES()"); + ParserError("ALTER DATABASE db SET DBPROPERTIES('a')"); + ParserError("ALTER DATABASE db SET DBPROPERTIES('a'=)"); + ParserError("ALTER DATABASE db SET DBPROPERTIES('a'=b)"); + ParserError("ALTER DATABASE db SET DBPROPERTIES(a='b')"); + ParserError("ALTER DATABASE db SET DBPROPERTIES('a'='b' 'c'='d')"); + ParserError("ALTER DATABASE db SET DBPROPERTIES('a'='b',)"); + } + @Test public void TestAlterTableOrViewSetOwner() { for (String type : new String[]{"TABLE", "VIEW"}) { diff --git a/fe/src/test/java/org/apache/impala/authorization/AuthorizationStmtTest.java b/fe/src/test/java/org/apache/impala/authorization/AuthorizationStmtTest.java index 70dc27ef7..977f32cc9 100644 --- a/fe/src/test/java/org/apache/impala/authorization/AuthorizationStmtTest.java +++ b/fe/src/test/java/org/apache/impala/authorization/AuthorizationStmtTest.java @@ -341,6 +341,11 @@ public class AuthorizationStmtTest extends AuthorizationTestBase { expectedAuthorizables); verifyPrivilegeReqs(createAnalysisCtx("functional"), "alter view alltypes_view as select 1", expectedAuthorizables); + + // Alter database set dbproperties. + expectedAuthorizables = Sets.newHashSet("functional"); + verifyPrivilegeReqs("alter database functional set dbproperties ('a'='b')", + expectedAuthorizables); } @Test @@ -2738,6 +2743,35 @@ public class AuthorizationStmtTest extends AuthorizationTestBase { assertTrue(exceptionThrown); } + @Test + public void testAlterDatabaseSetDbProperties() throws ImpalaException { + authorize("alter database functional set dbproperties('a'='b')") + .ok(onServer(TPrivilegeLevel.ALL)) + .ok(onServer(TPrivilegeLevel.OWNER)) + .ok(onServer(TPrivilegeLevel.ALTER)) + .ok(onDatabase("functional", TPrivilegeLevel.ALL)) + .ok(onDatabase("functional", TPrivilegeLevel.OWNER)) + .ok(onDatabase("functional", TPrivilegeLevel.ALTER)) + .error(alterError("functional")) + .error(alterError("functional"), onServer(allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, + TPrivilegeLevel.ALTER))) + .error(alterError("functional"), onDatabase("functional", + allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, + TPrivilegeLevel.ALTER))); + + authorize("alter database functional set dbproperties('a'='b')") + .ok(onServer(TPrivilegeLevel.values())) + .ok(onDatabase("functional", TPrivilegeLevel.values())); + + // Database does not exist. + authorize("alter database nodb set dbproperties('a'='b')") + .error(alterError("nodb")) + .error(alterError("nodb"), onServer(allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, + TPrivilegeLevel.ALTER))); + } + @Test public void testUpdate() throws ImpalaException { // Update is only supported on Kudu tables. diff --git a/fe/src/test/java/org/apache/impala/authorization/ranger/RangerAuditLogTest.java b/fe/src/test/java/org/apache/impala/authorization/ranger/RangerAuditLogTest.java index 0130f944c..f7bb3438e 100644 --- a/fe/src/test/java/org/apache/impala/authorization/ranger/RangerAuditLogTest.java +++ b/fe/src/test/java/org/apache/impala/authorization/ranger/RangerAuditLogTest.java @@ -76,6 +76,14 @@ public class RangerAuditLogTest extends AuthorizationTestBase { assertEquals("create database test_db", events.get(0).getRequestData()); }, "create database test_db", onServer(TPrivilegeLevel.CREATE)); + authzOk(events -> { + assertEquals(1, events.size()); + assertEventEquals("@database", "alter", "functional", 1, events.get(0)); + assertEquals("alter database functional set dbproperties ('a'='b')", + events.get(0).getRequestData()); + }, "alter database functional set dbproperties ('a'='b')", + onDatabase("functional", TPrivilegeLevel.ALTER)); + authzOk(events -> { assertEquals(1, events.size()); assertEventEquals("@table", "create", "functional/test_tbl", 1, events.get(0)); @@ -433,6 +441,14 @@ public class RangerAuditLogTest extends AuthorizationTestBase { assertEquals("create database test_db", events.get(0).getRequestData()); }, "create database test_db"); + authzError(events -> { + assertEquals(1, events.size()); + assertEventEquals("@database", "alter", "functional", 0, events.get(0)); + assertEquals("alter database functional set dbproperties ('a'='b')", + events.get(0).getRequestData()); + }, "alter database functional set dbproperties ('a'='b')", + onDatabase("functional", TPrivilegeLevel.SELECT)); + authzError(events -> { assertEquals(1, events.size()); assertEventEquals("@table", "create", "functional/test_tbl", 0, events.get(0)); diff --git a/testdata/workloads/functional-query/queries/QueryTest/create-database.test b/testdata/workloads/functional-query/queries/QueryTest/create-database.test index 650db4dab..2cc99803c 100644 --- a/testdata/workloads/functional-query/queries/QueryTest/create-database.test +++ b/testdata/workloads/functional-query/queries/QueryTest/create-database.test @@ -231,3 +231,27 @@ drop database $DATABASE_loc ---- RESULTS 'Database has been dropped.' ==== +---- QUERY +# Test CREATE DATABASE WITH DBPROPERTIES +create database $DATABASE_loc WITH DBPROPERTIES('key0'='value0', 'key1'='value1') +---- RESULTS +'Database has been created.' +==== +---- QUERY +# Test that DESCRIBE EXTENDED also has all properties. +describe database extended $DATABASE_loc +---- RESULTS +'$DATABASE_loc','$NAMENODE/$EXTERNAL_WAREHOUSE_DIR/$DATABASE_loc.db','' +'Owner: ','','' +'','$USER','USER' +'Parameter: ','','' +'','key0','value0' +'','key1','value1' +---- TYPES +string, string, string +==== +---- QUERY +drop database $DATABASE_loc +---- RESULTS +'Database has been dropped.' +==== diff --git a/tests/custom_cluster/test_events_custom_configs.py b/tests/custom_cluster/test_events_custom_configs.py index 1c2209209..93099e934 100644 --- a/tests/custom_cluster/test_events_custom_configs.py +++ b/tests/custom_cluster/test_events_custom_configs.py @@ -122,6 +122,8 @@ class TestEventProcessingCustomConfigsBase(CustomClusterTestSuite): # ALTER_DATABASE case "comment on database {0} is 'self-event test database'".format(db_name), "alter database {0} set owner user `test-user`".format(db_name), + "alter database {0} set dbproperties ('comment'='self-event test " + "database')".format(db_name), "create function {0}.f() returns int location '{1}/libTestUdfs.so' " "symbol='NoArgs'".format(db_name, WAREHOUSE), "drop function {0}.f()".format(db_name), diff --git a/tests/metadata/test_ddl.py b/tests/metadata/test_ddl.py index 54989b84a..0c56dd3f4 100644 --- a/tests/metadata/test_ddl.py +++ b/tests/metadata/test_ddl.py @@ -267,6 +267,12 @@ class TestDdlStatements(TestDdlBase): unique_database)).get_data() assert "INT\tf()\tNATIVE\ttrue" == func_names + def test_alter_database_set_db_properties(self, unique_database): + self.client.execute("alter database {0} set dbproperties('k'='v')".format( + unique_database)) + properties = self._get_db_properties(unique_database) + assert properties['k'] == 'v' + def test_alter_table_set_owner(self, unique_database): table_name = "{0}.test_owner_tbl".format(unique_database) self.client.execute("create table {0}(i int)".format(table_name)) diff --git a/tests/metadata/test_ddl_base.py b/tests/metadata/test_ddl_base.py index f35a7c7da..c37630761 100644 --- a/tests/metadata/test_ddl_base.py +++ b/tests/metadata/test_ddl_base.py @@ -74,6 +74,10 @@ class TestDdlBase(ImpalaTestSuite): """Extracts the DB properties mapping from the output of DESCRIBE FORMATTED""" return self._get_properties("Owner:", db_name, True) + def _get_db_properties(self, db_name): + """Extracts the DB properties mapping from the output of DESCRIBE FORMATTED""" + return self._get_properties("Parameter:", db_name, True) + def _get_property(self, property_name, name, is_db=False): """Extracts a db/table property value from the output of DESCRIBE FORMATTED.""" result = self.client.execute("describe {0} formatted {1}".format(
