+ * 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.
+ */
+
+import org.apache.hadoop.hive.metastore.api.FileMetadataExprType;
+import org.apache.hadoop.hive.metastore.api.MetaException;
+import org.apache.hadoop.hive.ql.io.sarg.SearchArgument;
+import org.apache.hadoop.hive.serde2.typeinfo.PrimitiveTypeInfo;
+
+import java.util.List;
+
+/**
+ * Default implementation of PartitionExpressionProxy. Eventually this should use the SARGs in
+ * Hive's storage-api. For now it just throws UnsupportedOperationException.
+ */
+public class DefaultPartitionExpressionProxy implements PartitionExpressionProxy {
+ @Override
+ public String convertExprToFilter(byte[] expr) throws MetaException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean filterPartitionsByExpr(List partColumnNames, List partColumnTypeInfos, byte[] expr, String defaultPartitionName, List partitionNames) throws MetaException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public FileMetadataExprType getMetadataType(String inputFormat) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public FileFormatProxy getFileFormatProxy(FileMetadataExprType type) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public SearchArgument createSarg(byte[] expr) {
+ throw new UnsupportedOperationException();
+ }
+}
\ No newline at end of file
diff --git a/metastore/src/java/org/apache/hadoop/hive/metastore/HiveAlterHandler.java b/metastore/src/java/org/apache/hadoop/hive/metastore/HiveAlterHandler.java
index 3d7df221fee4..03c970161b60 100644
--- a/metastore/src/java/org/apache/hadoop/hive/metastore/HiveAlterHandler.java
+++ b/metastore/src/java/org/apache/hadoop/hive/metastore/HiveAlterHandler.java
@@ -51,6 +51,7 @@
import org.apache.hadoop.ipc.RemoteException;
import org.apache.hive.common.util.HiveStringUtils;
+import javax.jdo.Constants;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
@@ -149,13 +150,29 @@ public void alterTable(RawStore msdb, Warehouse wh, String dbname,
rename = true;
}
- msdb.openTransaction();
+ String expectedKey = environmentContext != null && environmentContext.getProperties() != null ?
+ environmentContext.getProperties().get(hive_metastoreConstants.EXPECTED_PARAMETER_KEY) : null;
+ String expectedValue = environmentContext != null && environmentContext.getProperties() != null ?
+ environmentContext.getProperties().get(hive_metastoreConstants.EXPECTED_PARAMETER_VALUE) : null;
+
+ if (expectedKey != null) {
+ // If we have to check the expected state of the table we have to prevent nonrepeatable reads.
+ msdb.openTransaction(Constants.TX_REPEATABLE_READ);
+ } else {
+ msdb.openTransaction();
+ }
// get old table
oldt = msdb.getTable(dbname, name);
if (oldt == null) {
throw new InvalidOperationException("table " + dbname + "." + name + " doesn't exist");
}
+ if (expectedKey != null && expectedValue != null
+ && !expectedValue.equals(oldt.getParameters().get(expectedKey))) {
+ throw new MetaException("The table has been modified. The parameter value for key '" + expectedKey + "' is '"
+ + oldt.getParameters().get(expectedKey) + "'. The expected was value was '" + expectedValue + "'");
+ }
+
if (oldt.getPartitionKeysSize() != 0) {
isPartitionedTable = true;
}
diff --git a/metastore/src/java/org/apache/hadoop/hive/metastore/ObjectStore.java b/metastore/src/java/org/apache/hadoop/hive/metastore/ObjectStore.java
index ba46e63839e4..30c6874d91d6 100644
--- a/metastore/src/java/org/apache/hadoop/hive/metastore/ObjectStore.java
+++ b/metastore/src/java/org/apache/hadoop/hive/metastore/ObjectStore.java
@@ -561,17 +561,31 @@ public void shutdown() {
}
/**
- * Opens a new one or the one already created Every call of this function must
- * have corresponding commit or rollback function call
+ * Opens a new one or the one already created. Every call of this function must
+ * have corresponding commit or rollback function call.
*
* @return an active transaction
*/
-
@Override
public boolean openTransaction() {
+ return openTransaction(null);
+ }
+
+ /**
+ * Opens a new one or the one already created. Every call of this function must
+ * have corresponding commit or rollback function call.
+ *
+ * @param isolationLevel The transaction isolation level. Only possible to set on the first call.
+ * @return an active transaction
+ */
+ @Override
+ public boolean openTransaction(String isolationLevel) {
openTrasactionCalls++;
if (openTrasactionCalls == 1) {
currentTransaction = pm.currentTransaction();
+ if (isolationLevel != null) {
+ currentTransaction.setIsolationLevel(isolationLevel);
+ }
currentTransaction.begin();
transactionStatus = TXN_STATUS.OPEN;
} else {
@@ -581,10 +595,16 @@ public boolean openTransaction() {
throw new RuntimeException("openTransaction called in an interior"
+ " transaction scope, but currentTransaction is not active.");
}
+
+ // Can not change the isolation level on an already open transaction
+ if (isolationLevel != null && !isolationLevel.equals(currentTransaction.getIsolationLevel())) {
+ throw new RuntimeException("Can not set isolation level on an open transaction");
+ }
}
boolean result = currentTransaction.isActive();
- debugLog("Open transaction: count = " + openTrasactionCalls + ", isActive = " + result);
+ debugLog("Open transaction: count = " + openTrasactionCalls + ", isActive = " + result + ", isolationLevel = "
+ + currentTransaction.getIsolationLevel());
return result;
}
diff --git a/metastore/src/java/org/apache/hadoop/hive/metastore/RawStore.java b/metastore/src/java/org/apache/hadoop/hive/metastore/RawStore.java
index 639a1d8d60cc..8396c55f6b1f 100644
--- a/metastore/src/java/org/apache/hadoop/hive/metastore/RawStore.java
+++ b/metastore/src/java/org/apache/hadoop/hive/metastore/RawStore.java
@@ -77,13 +77,23 @@ public interface RawStore extends Configurable {
public abstract void shutdown();
/**
- * Opens a new one or the one already created Every call of this function must
- * have corresponding commit or rollback function call
+ * Opens a new one or the one already created. Every call of this function must
+ * have corresponding commit or rollback function call.
*
* @return an active transaction
*/
+ boolean openTransaction();
- public abstract boolean openTransaction();
+ /**
+ * Opens a new one or the one already created. Every call of this function must
+ * have corresponding commit or rollback function call.
+ *
+ * @param isolationLevel The transaction isolation level. Only possible to set on the first call.
+ * @return an active transaction
+ */
+ default boolean openTransaction(String isolationLevel) {
+ throw new UnsupportedOperationException("Setting isolation level for this Store is not supported");
+ }
/**
* if this is the commit of the first open call then an actual commit is
diff --git a/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/ConstraintBuilder.java b/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/ConstraintBuilder.java
new file mode 100644
index 000000000000..50e779a22bf2
--- /dev/null
+++ b/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/ConstraintBuilder.java
@@ -0,0 +1,98 @@
+/*
+ * 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
+ *
+ * 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.hadoop.hive.metastore.client.builder;
+
+import org.apache.hadoop.hive.metastore.api.MetaException;
+import org.apache.hadoop.hive.metastore.api.Table;
+
+/**
+ * Base builder for all types of constraints. Database name, table name, and column name
+ * must be provided.
+ * @param Type of builder extending this.
+ */
+abstract class ConstraintBuilder {
+ protected String dbName, tableName, columnName, constraintName;
+ protected int keySeq;
+ protected boolean enable, validate, rely;
+ private T child;
+
+ protected ConstraintBuilder() {
+ keySeq = 1;
+ enable = true;
+ validate = rely = false;
+ }
+
+ protected void setChild(T child) {
+ this.child = child;
+ }
+
+ protected void checkBuildable(String defaultConstraintName) throws MetaException {
+ if (dbName == null || tableName == null || columnName == null) {
+ throw new MetaException("You must provide database name, table name, and column name");
+ }
+ if (constraintName == null) {
+ constraintName = dbName + "_" + tableName + "_" + columnName + "_" + defaultConstraintName;
+ }
+ }
+
+ public T setDbName(String dbName) {
+ this.dbName = dbName;
+ return child;
+ }
+
+ public T setTableName(String tableName) {
+ this.tableName = tableName;
+ return child;
+ }
+
+ public T setDbAndTableName(Table table) {
+ this.dbName = table.getDbName();
+ this.tableName = table.getTableName();
+ return child;
+ }
+
+ public T setColumnName(String columnName) {
+ this.columnName = columnName;
+ return child;
+ }
+
+ public T setConstraintName(String constraintName) {
+ this.constraintName = constraintName;
+ return child;
+ }
+
+ public T setKeySeq(int keySeq) {
+ this.keySeq = keySeq;
+ return child;
+ }
+
+ public T setEnable(boolean enable) {
+ this.enable = enable;
+ return child;
+ }
+
+ public T setValidate(boolean validate) {
+ this.validate = validate;
+ return child;
+ }
+
+ public T setRely(boolean rely) {
+ this.rely = rely;
+ return child;
+ }
+}
diff --git a/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/DatabaseBuilder.java b/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/DatabaseBuilder.java
new file mode 100644
index 000000000000..99addedc1620
--- /dev/null
+++ b/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/DatabaseBuilder.java
@@ -0,0 +1,88 @@
+/*
+ * 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
+ *
+ * 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.hadoop.hive.metastore.client.builder;
+
+import org.apache.hadoop.hive.metastore.api.Database;
+import org.apache.hadoop.hive.metastore.api.MetaException;
+import org.apache.hadoop.hive.metastore.api.PrincipalType;
+import org.apache.hadoop.hive.metastore.utils.SecurityUtils;
+import org.apache.thrift.TException;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A builder for {@link Database}. The name of the new database is required. Everything else
+ * selects reasonable defaults.
+ */
+public class DatabaseBuilder {
+ private String name, description, location;
+ private Map params = new HashMap<>();
+ private String ownerName;
+ private PrincipalType ownerType;
+
+ public DatabaseBuilder setName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public DatabaseBuilder setDescription(String description) {
+ this.description = description;
+ return this;
+ }
+
+ public DatabaseBuilder setLocation(String location) {
+ this.location = location;
+ return this;
+ }
+
+ public DatabaseBuilder setParams(Map params) {
+ this.params = params;
+ return this;
+ }
+
+ public DatabaseBuilder addParam(String key, String value) {
+ params.put(key, value);
+ return this;
+ }
+
+ public DatabaseBuilder setOwnerName(String ownerName) {
+ this.ownerName = ownerName;
+ return this;
+ }
+
+ public DatabaseBuilder setOwnerType(PrincipalType ownerType) {
+ this.ownerType = ownerType;
+ return this;
+ }
+
+ public Database build() throws TException {
+ if (name == null) throw new MetaException("You must name the database");
+ Database db = new Database(name, description, location, params);
+ try {
+ if (ownerName != null) ownerName = SecurityUtils.getUser();
+ db.setOwnerName(ownerName);
+ if (ownerType == null) ownerType = PrincipalType.USER;
+ db.setOwnerType(ownerType);
+ return db;
+ } catch (IOException e) {
+ throw new MetaException(e.getMessage());
+ }
+ }
+}
diff --git a/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/FunctionBuilder.java b/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/FunctionBuilder.java
new file mode 100644
index 000000000000..378b56b3792e
--- /dev/null
+++ b/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/FunctionBuilder.java
@@ -0,0 +1,115 @@
+/*
+ * 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.hadoop.hive.metastore.client.builder;
+
+import org.apache.hadoop.hive.metastore.api.Database;
+import org.apache.hadoop.hive.metastore.api.Function;
+import org.apache.hadoop.hive.metastore.api.FunctionType;
+import org.apache.hadoop.hive.metastore.api.MetaException;
+import org.apache.hadoop.hive.metastore.api.PrincipalType;
+import org.apache.hadoop.hive.metastore.api.ResourceUri;
+import org.apache.hadoop.hive.metastore.utils.SecurityUtils;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Class for creating Thrift Function objects for tests, and API usage.
+ */
+public class FunctionBuilder {
+ private String dbName = "default";
+ private String funcName = null;
+ private String className = null;
+ private String owner = null;
+ private PrincipalType ownerType;
+ private int createTime;
+ private FunctionType funcType;
+ private List resourceUris;
+
+ public FunctionBuilder() {
+ // Set some reasonable defaults
+ ownerType = PrincipalType.USER;
+ createTime = (int) (System.currentTimeMillis() / 1000);
+ funcType = FunctionType.JAVA;
+ resourceUris = new ArrayList();
+ }
+
+ public FunctionBuilder setDbName(String dbName) {
+ this.dbName = dbName;
+ return this;
+ }
+
+ public FunctionBuilder setDbName(Database db) {
+ this.dbName = db.getName();
+ return this;
+ }
+
+ public FunctionBuilder setName(String funcName) {
+ this.funcName = funcName;
+ return this;
+ }
+
+ public FunctionBuilder setClass(String className) {
+ this.className = className;
+ return this;
+ }
+
+ public FunctionBuilder setOwner(String owner) {
+ this.owner = owner;
+ return this;
+ }
+
+ public FunctionBuilder setOwnerType(PrincipalType ownerType) {
+ this.ownerType = ownerType;
+ return this;
+ }
+
+ public FunctionBuilder setCreateTime(int createTime) {
+ this.createTime = createTime;
+ return this;
+ }
+
+ public FunctionBuilder setFunctionType(FunctionType funcType) {
+ this.funcType = funcType;
+ return this;
+ }
+
+ public FunctionBuilder setResourceUris(List resourceUris) {
+ this.resourceUris = resourceUris;
+ return this;
+ }
+
+ public FunctionBuilder addResourceUri(ResourceUri resourceUri) {
+ this.resourceUris.add(resourceUri);
+ return this;
+ }
+
+ public Function build() throws MetaException {
+ try {
+ if (owner != null) {
+ owner = SecurityUtils.getUser();
+ }
+ } catch (IOException e) {
+ throw new MetaException(e.getMessage());
+ }
+ return new Function(funcName, dbName, className, owner, ownerType, createTime, funcType,
+ resourceUris);
+ }
+}
diff --git a/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/GrantRevokePrivilegeRequestBuilder.java b/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/GrantRevokePrivilegeRequestBuilder.java
new file mode 100644
index 000000000000..26cea191e165
--- /dev/null
+++ b/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/GrantRevokePrivilegeRequestBuilder.java
@@ -0,0 +1,63 @@
+/*
+ * 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
+ *
+ * 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.hadoop.hive.metastore.client.builder;
+
+import org.apache.hadoop.hive.metastore.api.GrantRevokePrivilegeRequest;
+import org.apache.hadoop.hive.metastore.api.GrantRevokeType;
+import org.apache.hadoop.hive.metastore.api.HiveObjectPrivilege;
+import org.apache.hadoop.hive.metastore.api.MetaException;
+import org.apache.hadoop.hive.metastore.api.PrivilegeBag;
+
+/**
+ * A builder for {@link GrantRevokePrivilegeRequest}. The revoke of grant option defaults to
+ * false. The request Type and the privileges must be provided.
+ */
+public class GrantRevokePrivilegeRequestBuilder {
+ private GrantRevokeType requestType;
+ private PrivilegeBag privileges;
+ private boolean revokeGrantOption;
+
+ public GrantRevokePrivilegeRequestBuilder() {
+ privileges = new PrivilegeBag();
+ revokeGrantOption = false;
+ }
+
+ public GrantRevokePrivilegeRequestBuilder setRequestType(GrantRevokeType requestType) {
+ this.requestType = requestType;
+ return this;
+ }
+
+ public GrantRevokePrivilegeRequestBuilder setRevokeGrantOption(boolean revokeGrantOption) {
+ this.revokeGrantOption = revokeGrantOption;
+ return this;
+ }
+
+ public GrantRevokePrivilegeRequestBuilder addPrivilege(HiveObjectPrivilege privilege) {
+ privileges.addToPrivileges(privilege);
+ return this;
+ }
+
+ public GrantRevokePrivilegeRequest build() throws MetaException {
+ if (requestType == null || privileges.getPrivilegesSize() == 0) {
+ throw new MetaException("The request type and at least one privilege must be provided.");
+ }
+ GrantRevokePrivilegeRequest rqst = new GrantRevokePrivilegeRequest(requestType, privileges);
+ if (revokeGrantOption) rqst.setRevokeGrantOption(revokeGrantOption);
+ return rqst;
+ }
+}
diff --git a/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/HiveObjectPrivilegeBuilder.java b/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/HiveObjectPrivilegeBuilder.java
new file mode 100644
index 000000000000..d802e1a971ac
--- /dev/null
+++ b/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/HiveObjectPrivilegeBuilder.java
@@ -0,0 +1,63 @@
+/*
+ * 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
+ *
+ * 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.hadoop.hive.metastore.client.builder;
+
+import org.apache.hadoop.hive.metastore.api.HiveObjectPrivilege;
+import org.apache.hadoop.hive.metastore.api.HiveObjectRef;
+import org.apache.hadoop.hive.metastore.api.MetaException;
+import org.apache.hadoop.hive.metastore.api.PrincipalType;
+import org.apache.hadoop.hive.metastore.api.PrivilegeGrantInfo;
+
+/**
+ * Builder for {@link HiveObjectPrivilege}. All values must be set.
+ */
+public class HiveObjectPrivilegeBuilder {
+ private HiveObjectRef hiveObjectRef;
+ private String principleName;
+ private PrincipalType principalType;
+ private PrivilegeGrantInfo grantInfo;
+
+ public HiveObjectPrivilegeBuilder setHiveObjectRef(HiveObjectRef hiveObjectRef) {
+ this.hiveObjectRef = hiveObjectRef;
+ return this;
+ }
+
+ public HiveObjectPrivilegeBuilder setPrincipleName(String principleName) {
+ this.principleName = principleName;
+ return this;
+ }
+
+ public HiveObjectPrivilegeBuilder setPrincipalType(PrincipalType principalType) {
+ this.principalType = principalType;
+ return this;
+ }
+
+ public HiveObjectPrivilegeBuilder setGrantInfo(PrivilegeGrantInfo grantInfo) {
+ this.grantInfo = grantInfo;
+ return this;
+ }
+
+ public HiveObjectPrivilege build() throws MetaException {
+ if (hiveObjectRef == null || principleName == null || principalType == null ||
+ grantInfo == null) {
+ throw new MetaException("hive object reference, principle name and type, and grant info " +
+ "must all be provided");
+ }
+ return new HiveObjectPrivilege(hiveObjectRef, principleName, principalType, grantInfo);
+ }
+}
diff --git a/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/HiveObjectRefBuilder.java b/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/HiveObjectRefBuilder.java
new file mode 100644
index 000000000000..62a227adf89d
--- /dev/null
+++ b/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/HiveObjectRefBuilder.java
@@ -0,0 +1,63 @@
+/*
+ * 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
+ *
+ * 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.hadoop.hive.metastore.client.builder;
+
+import org.apache.hadoop.hive.metastore.api.Database;
+import org.apache.hadoop.hive.metastore.api.HiveObjectRef;
+import org.apache.hadoop.hive.metastore.api.HiveObjectType;
+import org.apache.hadoop.hive.metastore.api.Partition;
+import org.apache.hadoop.hive.metastore.api.Table;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A builder for {@link HiveObjectRef}. Unlike most builders (which allow a gradual building up
+ * of the values) this gives a number of methods that take the object to be referenced and then
+ * build the appropriate reference. This is intended primarily for use with
+ * {@link HiveObjectPrivilegeBuilder}
+ */
+public class HiveObjectRefBuilder {
+ private HiveObjectType objectType;
+ private String dbName, objectName, columnName;
+ private List partValues;
+
+ public HiveObjectRef buildGlobalReference() {
+ return new HiveObjectRef(HiveObjectType.GLOBAL, null, null, Collections.emptyList(), null);
+ }
+
+ public HiveObjectRef buildDatabaseReference(Database db) {
+ return new
+ HiveObjectRef(HiveObjectType.DATABASE, db.getName(), null, Collections.emptyList(), null);
+ }
+
+ public HiveObjectRef buildTableReference(Table table) {
+ return new HiveObjectRef(HiveObjectType.TABLE, table.getDbName(), table.getTableName(),
+ Collections.emptyList(), null);
+ }
+
+ public HiveObjectRef buildPartitionReference(Partition part) {
+ return new HiveObjectRef(HiveObjectType.PARTITION, part.getDbName(), part.getTableName(),
+ part.getValues(), null);
+ }
+
+ public HiveObjectRef buildColumnReference(Table table, String columnName) {
+ return new HiveObjectRef(HiveObjectType.TABLE, table.getDbName(), table.getTableName(),
+ Collections.emptyList(), columnName);
+ }
+}
diff --git a/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/IndexBuilder.java b/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/IndexBuilder.java
new file mode 100644
index 000000000000..6c8b1d80a90e
--- /dev/null
+++ b/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/IndexBuilder.java
@@ -0,0 +1,104 @@
+/*
+ * 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
+ *
+ * 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.hadoop.hive.metastore.client.builder;
+
+import org.apache.hadoop.hive.metastore.api.Index;
+import org.apache.hadoop.hive.metastore.api.MetaException;
+import org.apache.hadoop.hive.metastore.api.Table;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Builder for indices. You must supply the database name and table name (or table reference), a
+ * name for the index, and whatever StorageDescriptorBuilder requires. All other fields will be
+ * given reasonable defaults.
+ */
+public class IndexBuilder extends StorageDescriptorBuilder {
+ private String dbName, tableName, indexName, indexTableName, handlerClass;
+ private int createTime, lastAccessTime;
+ private Map indexParams;
+ private boolean deferredRebuild;
+
+ public IndexBuilder() {
+ // Set some reasonable defaults
+ indexParams = new HashMap<>();
+ createTime = lastAccessTime = (int)(System.currentTimeMillis() / 1000);
+ super.setChild(this);
+ }
+
+ public IndexBuilder setDbName(String dbName) {
+ this.dbName = dbName;
+ return this;
+ }
+
+ public IndexBuilder setTableName(String tableName) {
+ this.tableName = tableName;
+ return this;
+ }
+
+ public IndexBuilder setDbAndTableName(Table table) {
+ this.dbName = table.getDbName();
+ this.tableName = table.getTableName();
+ return this;
+ }
+
+ public IndexBuilder setCreateTime(int createTime) {
+ this.createTime = createTime;
+ return this;
+ }
+
+ public IndexBuilder setLastAccessTime(int lastAccessTime) {
+ this.lastAccessTime = lastAccessTime;
+ return this;
+ }
+
+ public IndexBuilder setIndexParams(Map indexParams) {
+ this.indexParams = indexParams;
+ return this;
+ }
+
+ public IndexBuilder setIndexName(String indexName) {
+ this.indexName = indexName;
+ return this;
+ }
+
+ public IndexBuilder setIndexTableName(String indexTableName) {
+ this.indexTableName = indexTableName;
+ return this;
+ }
+
+ public IndexBuilder setHandlerClass(String handlerClass) {
+ this.handlerClass = handlerClass;
+ return this;
+ }
+
+ public IndexBuilder setDeferredRebuild(boolean deferredRebuild) {
+ this.deferredRebuild = deferredRebuild;
+ return this;
+ }
+
+ public Index build() throws MetaException {
+ if (dbName == null || tableName == null || indexName == null) {
+ throw new MetaException("You must provide database name, table name, and index name");
+ }
+ if (indexTableName == null) indexTableName = tableName + "_" + indexName + "_table";
+ return new Index(indexName, handlerClass, dbName, tableName, createTime, lastAccessTime,
+ indexTableName, buildSd(), indexParams, deferredRebuild);
+ }
+}
diff --git a/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/PartitionBuilder.java b/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/PartitionBuilder.java
new file mode 100644
index 000000000000..265625f95ca6
--- /dev/null
+++ b/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/PartitionBuilder.java
@@ -0,0 +1,102 @@
+/*
+ * 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
+ *
+ * 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.hadoop.hive.metastore.client.builder;
+
+import org.apache.hadoop.hive.metastore.api.MetaException;
+import org.apache.hadoop.hive.metastore.api.Partition;
+import org.apache.hadoop.hive.metastore.api.Table;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Builder for {@link Partition}. The only requirements are 1. (database name and table name) or table
+ * reference; 2. partition values; 3. whatever {@link StorageDescriptorBuilder} requires.
+ */
+public class PartitionBuilder extends StorageDescriptorBuilder {
+ private String dbName, tableName;
+ private int createTime, lastAccessTime;
+ private Map partParams;
+ private List values;
+
+ public PartitionBuilder() {
+ // Set some reasonable defaults
+ partParams = new HashMap<>();
+ createTime = lastAccessTime = (int)(System.currentTimeMillis() / 1000);
+ super.setChild(this);
+ }
+
+ public PartitionBuilder setDbName(String dbName) {
+ this.dbName = dbName;
+ return this;
+ }
+
+ public PartitionBuilder setTableName(String tableName) {
+ this.tableName = tableName;
+ return this;
+ }
+
+ public PartitionBuilder setDbAndTableName(Table table) {
+ this.dbName = table.getDbName();
+ this.tableName = table.getTableName();
+ return this;
+ }
+
+ public PartitionBuilder setValues(List values) {
+ this.values = values;
+ return this;
+ }
+
+ public PartitionBuilder addValue(String value) {
+ if (values == null) values = new ArrayList<>();
+ values.add(value);
+ return this;
+ }
+
+ public PartitionBuilder setCreateTime(int createTime) {
+ this.createTime = createTime;
+ return this;
+ }
+
+ public PartitionBuilder setLastAccessTime(int lastAccessTime) {
+ this.lastAccessTime = lastAccessTime;
+ return this;
+ }
+
+ public PartitionBuilder setPartParams(Map partParams) {
+ this.partParams = partParams;
+ return this;
+ }
+
+ public PartitionBuilder addPartParam(String key, String value) {
+ if (partParams == null) partParams = new HashMap<>();
+ partParams.put(key, value);
+ return this;
+ }
+
+ public Partition build() throws MetaException {
+ if (dbName == null || tableName == null) {
+ throw new MetaException("database name and table name must be provided");
+ }
+ if (values == null) throw new MetaException("You must provide partition values");
+ return new Partition(values, dbName, tableName, createTime, lastAccessTime, buildSd(),
+ partParams);
+ }
+}
diff --git a/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/PrivilegeGrantInfoBuilder.java b/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/PrivilegeGrantInfoBuilder.java
new file mode 100644
index 000000000000..213798e262db
--- /dev/null
+++ b/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/PrivilegeGrantInfoBuilder.java
@@ -0,0 +1,83 @@
+/*
+ * 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
+ *
+ * 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.hadoop.hive.metastore.client.builder;
+
+import org.apache.hadoop.hive.metastore.api.MetaException;
+import org.apache.hadoop.hive.metastore.api.PrincipalType;
+import org.apache.hadoop.hive.metastore.api.PrivilegeGrantInfo;
+import org.apache.hadoop.hive.metastore.utils.SecurityUtils;
+
+import java.io.IOException;
+
+/**
+ * Builder for {@link PrivilegeGrantInfo}. The privilege is required. If not provided the grantor
+ * is
+ * assumed to be the current user. This is really intended for use by the
+ * {@link HiveObjectPrivilegeBuilder}.
+ */
+public class PrivilegeGrantInfoBuilder {
+ private String privilege, grantor;
+ private int createTime;
+ private PrincipalType grantorType;
+ private boolean grantOption;
+
+ public PrivilegeGrantInfoBuilder() {
+ createTime = (int)(System.currentTimeMillis() / 1000);
+ grantOption = false;
+ }
+
+ public PrivilegeGrantInfoBuilder setPrivilege(String privilege) {
+ this.privilege = privilege;
+ return this;
+ }
+
+ public PrivilegeGrantInfoBuilder setGrantor(String grantor) {
+ this.grantor = grantor;
+ return this;
+ }
+
+ public PrivilegeGrantInfoBuilder setCreateTime(int createTime) {
+ this.createTime = createTime;
+ return this;
+ }
+
+ public PrivilegeGrantInfoBuilder setGrantorType(PrincipalType grantorType) {
+ this.grantorType = grantorType;
+ return this;
+ }
+
+ public PrivilegeGrantInfoBuilder setGrantOption(boolean grantOption) {
+ this.grantOption = grantOption;
+ return this;
+ }
+
+ public PrivilegeGrantInfo build() throws MetaException {
+ if (privilege == null) {
+ throw new MetaException("Privilege must be provided.");
+ }
+ if (grantor == null) {
+ try {
+ grantor = SecurityUtils.getUser();
+ grantorType = PrincipalType.USER;
+ } catch (IOException e) {
+ throw new MetaException(e.getMessage());
+ }
+ }
+ return new PrivilegeGrantInfo(privilege, createTime, grantor, grantorType, grantOption);
+ }
+}
diff --git a/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/RoleBuilder.java b/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/RoleBuilder.java
new file mode 100644
index 000000000000..0b8d189f31a8
--- /dev/null
+++ b/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/RoleBuilder.java
@@ -0,0 +1,55 @@
+/*
+ * 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
+ *
+ * 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.hadoop.hive.metastore.client.builder;
+
+import org.apache.hadoop.hive.metastore.api.MetaException;
+import org.apache.hadoop.hive.metastore.api.Role;
+
+/**
+ * A builder for {@link Role}. The roleName and the ownerName must be provided.
+ */
+public class RoleBuilder {
+ private String roleName, ownerName;
+ private int createTime;
+
+ public RoleBuilder() {
+ createTime = (int)(System.currentTimeMillis() / 1000);
+ }
+
+ public RoleBuilder setRoleName(String roleName) {
+ this.roleName = roleName;
+ return this;
+ }
+
+ public RoleBuilder setOwnerName(String ownerName) {
+ this.ownerName = ownerName;
+ return this;
+ }
+
+ public RoleBuilder setCreateTime(int createTime) {
+ this.createTime = createTime;
+ return this;
+ }
+
+ public Role build() throws MetaException {
+ if (roleName == null || ownerName == null) {
+ throw new MetaException("role name and owner name must be provided.");
+ }
+ return new Role(roleName, createTime, ownerName);
+ }
+}
diff --git a/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/SQLForeignKeyBuilder.java b/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/SQLForeignKeyBuilder.java
new file mode 100644
index 000000000000..a39319a1e4da
--- /dev/null
+++ b/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/SQLForeignKeyBuilder.java
@@ -0,0 +1,83 @@
+/*
+ * 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
+ *
+ * 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.hadoop.hive.metastore.client.builder;
+
+import org.apache.hadoop.hive.metastore.api.MetaException;
+import org.apache.hadoop.hive.metastore.api.SQLForeignKey;
+import org.apache.hadoop.hive.metastore.api.SQLPrimaryKey;
+
+/**
+ * Builder for {@link SQLForeignKey}. Requires what {@link ConstraintBuilder} requires, plus
+ * primary key
+ * database, table, column and name.
+ */
+public class SQLForeignKeyBuilder extends ConstraintBuilder {
+ private String pkDb, pkTable, pkColumn, pkName;
+ private int updateRule, deleteRule;
+
+ public SQLForeignKeyBuilder() {
+ updateRule = deleteRule = 0;
+ }
+
+ public SQLForeignKeyBuilder setPkDb(String pkDb) {
+ this.pkDb = pkDb;
+ return this;
+ }
+
+ public SQLForeignKeyBuilder setPkTable(String pkTable) {
+ this.pkTable = pkTable;
+ return this;
+ }
+
+ public SQLForeignKeyBuilder setPkColumn(String pkColumn) {
+ this.pkColumn = pkColumn;
+ return this;
+ }
+
+ public SQLForeignKeyBuilder setPkName(String pkName) {
+ this.pkName = pkName;
+ return this;
+ }
+
+ public SQLForeignKeyBuilder setPrimaryKey(SQLPrimaryKey pk) {
+ pkDb = pk.getTable_db();
+ pkTable = pk.getTable_name();
+ pkColumn = pk.getColumn_name();
+ pkName = pk.getPk_name();
+ return this;
+ }
+
+ public SQLForeignKeyBuilder setUpdateRule(int updateRule) {
+ this.updateRule = updateRule;
+ return this;
+ }
+
+ public SQLForeignKeyBuilder setDeleteRule(int deleteRule) {
+ this.deleteRule = deleteRule;
+ return this;
+ }
+
+ public SQLForeignKey build() throws MetaException {
+ checkBuildable("foreign_key");
+ if (pkDb == null || pkTable == null || pkColumn == null || pkName == null) {
+ throw new MetaException("You must provide the primary key database, table, column, and name");
+ }
+ return new SQLForeignKey(pkDb, pkTable, pkColumn, dbName, tableName, columnName, keySeq,
+ updateRule, deleteRule, constraintName, pkName, enable, validate, rely);
+ }
+}
diff --git a/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/SQLPrimaryKeyBuilder.java b/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/SQLPrimaryKeyBuilder.java
new file mode 100644
index 000000000000..9000f861676a
--- /dev/null
+++ b/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/SQLPrimaryKeyBuilder.java
@@ -0,0 +1,42 @@
+/*
+ * 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
+ *
+ * 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.hadoop.hive.metastore.client.builder;
+
+import org.apache.hadoop.hive.metastore.api.MetaException;
+import org.apache.hadoop.hive.metastore.api.SQLPrimaryKey;
+
+/**
+ * Builder for {@link SQLPrimaryKey}. Only requires what {@link ConstraintBuilder} requires.
+ */
+public class SQLPrimaryKeyBuilder extends ConstraintBuilder {
+
+ public SQLPrimaryKeyBuilder() {
+ super.setChild(this);
+ }
+
+ // Just to translate
+ public SQLPrimaryKeyBuilder setPrimaryKeyName(String name) {
+ return setConstraintName(name);
+ }
+
+ public SQLPrimaryKey build() throws MetaException {
+ checkBuildable("primary_key");
+ return new SQLPrimaryKey(dbName, tableName, columnName, keySeq, constraintName, enable,
+ validate, rely);
+ }
+}
diff --git a/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/StorageDescriptorBuilder.java b/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/StorageDescriptorBuilder.java
new file mode 100644
index 000000000000..39d1fa210ce3
--- /dev/null
+++ b/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/StorageDescriptorBuilder.java
@@ -0,0 +1,210 @@
+/*
+ * 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
+ *
+ * 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.hadoop.hive.metastore.client.builder;
+
+import org.apache.hadoop.hive.metastore.api.FieldSchema;
+import org.apache.hadoop.hive.metastore.api.MetaException;
+import org.apache.hadoop.hive.metastore.api.Order;
+import org.apache.hadoop.hive.metastore.api.SerDeInfo;
+import org.apache.hadoop.hive.metastore.api.SkewedInfo;
+import org.apache.hadoop.hive.metastore.api.StorageDescriptor;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Builds a {@link StorageDescriptor}. Only requires that columns be set. It picks reasonable
+ * defaults for everything else. This is intended for use just by objects that have a StorageDescriptor,
+ * not direct use.
+ */
+abstract class StorageDescriptorBuilder {
+ private static final String SERDE_LIB = "org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe";
+ private static final String INPUT_FORMAT = "org.apache.hadoop.hive.ql.io.HiveInputFormat";
+ private static final String OUTPUT_FORMAT = "org.apache.hadoop.hive.ql.io.HiveOutputFormat";
+
+ private String location, inputFormat, outputFormat, serdeName, serdeLib;
+ private List cols;
+ private int numBuckets;
+ private Map storageDescriptorParams, serdeParams;
+ private boolean compressed, storedAsSubDirectories;
+ private List bucketCols, skewedColNames;
+ private List sortCols;
+ private List> skewedColValues;
+ private Map, String> skewedColValueLocationMaps;
+ // This enables us to return the correct type from the builder
+ private T child;
+
+ protected StorageDescriptorBuilder() {
+ // Set some reasonable defaults
+ storageDescriptorParams = new HashMap<>();
+ serdeParams = new HashMap<>();
+ bucketCols = new ArrayList<>();
+ sortCols = new ArrayList<>();
+ numBuckets = 0;
+ compressed = false;
+ inputFormat = INPUT_FORMAT;
+ outputFormat = OUTPUT_FORMAT;
+ serdeLib = SERDE_LIB;
+ skewedColNames = new ArrayList<>();
+ skewedColValues = new ArrayList<>();
+ skewedColValueLocationMaps = new HashMap<>();
+ }
+
+ protected StorageDescriptor buildSd() throws MetaException {
+ if (cols == null) throw new MetaException("You must provide the columns");
+ SerDeInfo serdeInfo = new SerDeInfo(serdeName, serdeLib, serdeParams);
+ StorageDescriptor sd = new StorageDescriptor(cols, location, inputFormat, outputFormat,
+ compressed, numBuckets, serdeInfo, bucketCols, sortCols, storageDescriptorParams);
+ sd.setStoredAsSubDirectories(storedAsSubDirectories);
+ if (skewedColNames != null) {
+ SkewedInfo skewed = new SkewedInfo(skewedColNames, skewedColValues,
+ skewedColValueLocationMaps);
+ sd.setSkewedInfo(skewed);
+ }
+ return sd;
+ }
+
+ protected void setChild(T child) {
+ this.child = child;
+ }
+
+ public T setLocation(String location) {
+ this.location = location;
+ return child;
+ }
+
+ public T setInputFormat(String inputFormat) {
+ this.inputFormat = inputFormat;
+ return child;
+ }
+
+ public T setOutputFormat(String outputFormat) {
+ this.outputFormat = outputFormat;
+ return child;
+ }
+
+ public T setSerdeName(String serdeName) {
+ this.serdeName = serdeName;
+ return child;
+ }
+
+ public T setSerdeLib(String serdeLib) {
+ this.serdeLib = serdeLib;
+ return child;
+ }
+ public T setCols(List cols) {
+ this.cols = cols;
+ return child;
+ }
+
+ public T addCol(String name, String type, String comment) {
+ if (cols == null) cols = new ArrayList<>();
+ cols.add(new FieldSchema(name, type, comment));
+ return child;
+ }
+
+ public T addCol(String name, String type) {
+ return addCol(name, type, "");
+ }
+
+ public T setNumBuckets(int numBuckets) {
+ this.numBuckets = numBuckets;
+ return child;
+ }
+
+ public T setStorageDescriptorParams(
+ Map storageDescriptorParams) {
+ this.storageDescriptorParams = storageDescriptorParams;
+ return child;
+ }
+
+ public T addStorageDescriptorParam(String key, String value) {
+ if (storageDescriptorParams == null) storageDescriptorParams = new HashMap<>();
+ storageDescriptorParams.put(key, value);
+ return child;
+ }
+
+ public T setSerdeParams(Map serdeParams) {
+ this.serdeParams = serdeParams;
+ return child;
+ }
+
+ public T addSerdeParam(String key, String value) {
+ if (serdeParams == null) serdeParams = new HashMap<>();
+ serdeParams.put(key, value);
+ return child;
+ }
+
+ public T setCompressed(boolean compressed) {
+ this.compressed = compressed;
+ return child;
+ }
+
+ public T setStoredAsSubDirectories(boolean storedAsSubDirectories) {
+ this.storedAsSubDirectories = storedAsSubDirectories;
+ return child;
+ }
+
+ public T setBucketCols(List bucketCols) {
+ this.bucketCols = bucketCols;
+ return child;
+ }
+
+ public T addBucketCol(String bucketCol) {
+ if (bucketCols == null) bucketCols = new ArrayList<>();
+ bucketCols.add(bucketCol);
+ return child;
+ }
+
+ public T setSkewedColNames(List skewedColNames) {
+ this.skewedColNames = skewedColNames;
+ return child;
+ }
+
+ public T addSkewedColName(String skewedColName) {
+ if (skewedColNames == null) skewedColNames = new ArrayList<>();
+ skewedColNames.add(skewedColName);
+ return child;
+ }
+
+ public T setSortCols(List sortCols) {
+ this.sortCols = sortCols;
+ return child;
+ }
+
+ public T addSortCol(String col, int order) {
+ if (sortCols == null) sortCols = new ArrayList<>();
+ sortCols.add(new Order(col, order));
+ return child;
+ }
+
+ // It is not at all clear how to flatten these last two out in a useful way, and no one uses
+ // these anyway.
+ public T setSkewedColValues(List> skewedColValues) {
+ this.skewedColValues = skewedColValues;
+ return child;
+ }
+
+ public T setSkewedColValueLocationMaps(
+ Map, String> skewedColValueLocationMaps) {
+ this.skewedColValueLocationMaps = skewedColValueLocationMaps;
+ return child;
+ }
+}
diff --git a/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/TableBuilder.java b/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/TableBuilder.java
new file mode 100644
index 000000000000..0b005858c06a
--- /dev/null
+++ b/metastore/src/java/org/apache/hadoop/hive/metastore/client/builder/TableBuilder.java
@@ -0,0 +1,155 @@
+/*
+ * 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
+ *
+ * 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.hadoop.hive.metastore.utils;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hive.thrift.DBTokenStore;
+import org.apache.hadoop.hive.thrift.DelegationTokenIdentifier;
+import org.apache.hadoop.hive.thrift.DelegationTokenSelector;
+import org.apache.hadoop.hive.thrift.MemoryTokenStore;
+import org.apache.hadoop.hive.thrift.ZooKeeperTokenStore;
+import org.apache.hadoop.io.Text;
+import org.apache.hadoop.security.SecurityUtil;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.security.authentication.util.KerberosUtil;
+import org.apache.hadoop.security.token.Token;
+import org.apache.hadoop.security.token.TokenIdentifier;
+import org.apache.hadoop.security.token.TokenSelector;
+import org.apache.zookeeper.client.ZooKeeperSaslClient;
+
+import javax.security.auth.login.AppConfigurationEntry;
+import org.apache.thrift.transport.TSSLTransportFactory;
+import org.apache.thrift.transport.TServerSocket;
+import org.apache.thrift.transport.TSocket;
+import org.apache.thrift.transport.TTransport;
+import org.apache.thrift.transport.TTransportException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.net.ssl.SSLParameters;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLSocket;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.net.InetSocketAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class SecurityUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(SecurityUtils.class);
+
+ public static UserGroupInformation getUGI() throws LoginException, IOException {
+ String doAs = System.getenv("HADOOP_USER_NAME");
+ if (doAs != null && doAs.length() > 0) {
+ /*
+ * this allows doAs (proxy user) to be passed along across process boundary where
+ * delegation tokens are not supported. For example, a DDL stmt via WebHCat with
+ * a doAs parameter, forks to 'hcat' which needs to start a Session that
+ * proxies the end user
+ */
+ return UserGroupInformation.createProxyUser(doAs, UserGroupInformation.getLoginUser());
+ }
+ return UserGroupInformation.getCurrentUser();
+ }
+ /**
+ * Dynamically sets up the JAAS configuration that uses kerberos
+ * @param principal
+ * @param keyTabFile
+ * @throws IOException
+ */
+ public static void setZookeeperClientKerberosJaasConfig(String principal, String keyTabFile) throws IOException {
+ // ZooKeeper property name to pick the correct JAAS conf section
+ final String SASL_LOGIN_CONTEXT_NAME = "HiveZooKeeperClient";
+ System.setProperty(ZooKeeperSaslClient.LOGIN_CONTEXT_NAME_KEY, SASL_LOGIN_CONTEXT_NAME);
+
+ principal = SecurityUtil.getServerPrincipal(principal, "0.0.0.0");
+ JaasConfiguration jaasConf = new JaasConfiguration(SASL_LOGIN_CONTEXT_NAME, principal, keyTabFile);
+
+ // Install the Configuration in the runtime.
+ javax.security.auth.login.Configuration.setConfiguration(jaasConf);
+ }
+
+ /**
+ * A JAAS configuration for ZooKeeper clients intended to use for SASL
+ * Kerberos.
+ */
+ private static class JaasConfiguration extends javax.security.auth.login.Configuration {
+ // Current installed Configuration
+ private static final boolean IBM_JAVA = System.getProperty("java.vendor")
+ .contains("IBM");
+ private final javax.security.auth.login.Configuration baseConfig = javax.security.auth.login.Configuration
+ .getConfiguration();
+ private final String loginContextName;
+ private final String principal;
+ private final String keyTabFile;
+
+ public JaasConfiguration(String hiveLoginContextName, String principal, String keyTabFile) {
+ this.loginContextName = hiveLoginContextName;
+ this.principal = principal;
+ this.keyTabFile = keyTabFile;
+ }
+
+ @Override
+ public AppConfigurationEntry[] getAppConfigurationEntry(String appName) {
+ if (loginContextName.equals(appName)) {
+ Map krbOptions = new HashMap();
+ if (IBM_JAVA) {
+ krbOptions.put("credsType", "both");
+ krbOptions.put("useKeytab", keyTabFile);
+ } else {
+ krbOptions.put("doNotPrompt", "true");
+ krbOptions.put("storeKey", "true");
+ krbOptions.put("useKeyTab", "true");
+ krbOptions.put("keyTab", keyTabFile);
+ }
+ krbOptions.put("principal", principal);
+ krbOptions.put("refreshKrb5Config", "true");
+ AppConfigurationEntry hiveZooKeeperClientEntry = new AppConfigurationEntry(
+ KerberosUtil.getKrb5LoginModuleName(), LoginModuleControlFlag.REQUIRED, krbOptions);
+ return new AppConfigurationEntry[] { hiveZooKeeperClientEntry };
+ }
+ // Try the base config
+ if (baseConfig != null) {
+ return baseConfig.getAppConfigurationEntry(appName);
+ }
+ return null;
+ }
+ }
+
+ /**
+ * Get the string form of the token given a token signature. The signature is used as the value of
+ * the "service" field in the token for lookup. Ref: AbstractDelegationTokenSelector in Hadoop. If
+ * there exists such a token in the token cache (credential store) of the job, the lookup returns
+ * that. This is relevant only when running against a "secure" hadoop release The method gets hold
+ * of the tokens if they are set up by hadoop - this should happen on the map/reduce tasks if the
+ * client added the tokens into hadoop's credential store in the front end during job submission.
+ * The method will select the hive delegation token among the set of tokens and return the string
+ * form of it
+ *
+ * @param tokenSignature
+ * @return the string form of the token found
+ * @throws IOException
+ */
+ public static String getTokenStrForm(String tokenSignature) throws IOException {
+ UserGroupInformation ugi = UserGroupInformation.getCurrentUser();
+ TokenSelector extends TokenIdentifier> tokenSelector = new DelegationTokenSelector();
+
+ Token extends TokenIdentifier> token = tokenSelector.selectToken(
+ tokenSignature == null ? new Text() : new Text(tokenSignature), ugi.getTokens());
+ return token != null ? token.encodeToUrlString() : null;
+ }
+
+ /**
+ * Create a delegation token object for the given token string and service. Add the token to given
+ * UGI
+ *
+ * @param ugi
+ * @param tokenStr
+ * @param tokenService
+ * @throws IOException
+ */
+ public static void setTokenStr(UserGroupInformation ugi, String tokenStr, String tokenService)
+ throws IOException {
+ Token delegationToken = createToken(tokenStr, tokenService);
+ ugi.addToken(delegationToken);
+ }
+
+ /**
+ * Create a new token using the given string and service
+ *
+ * @param tokenStr
+ * @param tokenService
+ * @return
+ * @throws IOException
+ */
+ private static Token createToken(String tokenStr, String tokenService)
+ throws IOException {
+ Token delegationToken = new Token();
+ delegationToken.decodeFromUrlString(tokenStr);
+ delegationToken.setService(new Text(tokenService));
+ return delegationToken;
+ }
+
+ private static final String DELEGATION_TOKEN_STORE_CLS = "hive.cluster.delegation.token.store.class";
+
+ /**
+ * This method should be used to return the metastore specific tokenstore class name to main
+ * backwards compatibility
+ *
+ * @param conf - HiveConf object
+ * @return the tokenStoreClass name from the HiveConf. It maps the hive specific tokenstoreclass
+ * name to metastore module specific class name. For eg:
+ * hive.cluster.delegation.token.store.class is set to
+ * org.apache.hadoop.hive.thrift.MemoryTokenStore it returns the equivalent tokenstore
+ * class defined in the metastore module which is
+ * org.apache.hadoop.hive.metastore.security.MemoryTokenStore Similarly,
+ * org.apache.hadoop.hive.thrift.DBTokenStore maps to
+ * org.apache.hadoop.hive.metastore.security.DBTokenStore and
+ * org.apache.hadoop.hive.thrift.ZooKeeperTokenStore maps to
+ * org.apache.hadoop.hive.metastore.security.ZooKeeperTokenStore
+ */
+ public static String getTokenStoreClassName(Configuration conf) {
+ String tokenStoreClass = conf.get(DELEGATION_TOKEN_STORE_CLS, "");
+ if (StringUtils.isBlank(tokenStoreClass)) {
+ // default tokenstore is MemoryTokenStore
+ return MemoryTokenStore.class.getName();
+ }
+ switch (tokenStoreClass) {
+ case "org.apache.hadoop.hive.thrift.DBTokenStore":
+ return DBTokenStore.class.getName();
+ case "org.apache.hadoop.hive.thrift.MemoryTokenStore":
+ return MemoryTokenStore.class.getName();
+ case "org.apache.hadoop.hive.thrift.ZooKeeperTokenStore":
+ return ZooKeeperTokenStore.class.getName();
+ default:
+ return tokenStoreClass;
+ }
+ }
+
+
+ /**
+ * @return the user name set in hadoop.job.ugi param or the current user from System
+ * @throws IOException if underlying Hadoop call throws LoginException
+ */
+ public static String getUser() throws IOException {
+ try {
+ UserGroupInformation ugi = getUGI();
+ return ugi.getUserName();
+ } catch (LoginException le) {
+ throw new IOException(le);
+ }
+ }
+
+ public static TServerSocket getServerSocket(String hiveHost, int portNum) throws TTransportException {
+ InetSocketAddress serverAddress;
+ if (hiveHost == null || hiveHost.isEmpty()) {
+ // Wildcard bind
+ serverAddress = new InetSocketAddress(portNum);
+ } else {
+ serverAddress = new InetSocketAddress(hiveHost, portNum);
+ }
+ return new TServerSocket(serverAddress);
+ }
+
+ public static TServerSocket getServerSSLSocket(String hiveHost, int portNum, String keyStorePath,
+ String keyStorePassWord, List sslVersionBlacklist) throws TTransportException,
+ UnknownHostException {
+ TSSLTransportFactory.TSSLTransportParameters params =
+ new TSSLTransportFactory.TSSLTransportParameters();
+ params.setKeyStore(keyStorePath, keyStorePassWord);
+ InetSocketAddress serverAddress;
+ if (hiveHost == null || hiveHost.isEmpty()) {
+ // Wildcard bind
+ serverAddress = new InetSocketAddress(portNum);
+ } else {
+ serverAddress = new InetSocketAddress(hiveHost, portNum);
+ }
+ TServerSocket thriftServerSocket =
+ TSSLTransportFactory.getServerSocket(portNum, 0, serverAddress.getAddress(), params);
+ if (thriftServerSocket.getServerSocket() instanceof SSLServerSocket) {
+ List sslVersionBlacklistLocal = new ArrayList<>();
+ for (String sslVersion : sslVersionBlacklist) {
+ sslVersionBlacklistLocal.add(sslVersion.trim().toLowerCase());
+ }
+ SSLServerSocket sslServerSocket = (SSLServerSocket) thriftServerSocket.getServerSocket();
+ List enabledProtocols = new ArrayList<>();
+ for (String protocol : sslServerSocket.getEnabledProtocols()) {
+ if (sslVersionBlacklistLocal.contains(protocol.toLowerCase())) {
+ LOG.debug("Disabling SSL Protocol: " + protocol);
+ } else {
+ enabledProtocols.add(protocol);
+ }
+ }
+ sslServerSocket.setEnabledProtocols(enabledProtocols.toArray(new String[0]));
+ LOG.info("SSL Server Socket Enabled Protocols: "
+ + Arrays.toString(sslServerSocket.getEnabledProtocols()));
+ }
+ return thriftServerSocket;
+ }
+
+ public static TTransport getSSLSocket(String host, int port, int loginTimeout,
+ String trustStorePath, String trustStorePassWord) throws TTransportException {
+ TSSLTransportFactory.TSSLTransportParameters params =
+ new TSSLTransportFactory.TSSLTransportParameters();
+ params.setTrustStore(trustStorePath, trustStorePassWord);
+ params.requireClientAuth(true);
+ // The underlying SSLSocket object is bound to host:port with the given SO_TIMEOUT and
+ // SSLContext created with the given params
+ TSocket tSSLSocket = TSSLTransportFactory.getClientSocket(host, port, loginTimeout, params);
+ return getSSLSocketWithHttps(tSSLSocket);
+ }
+
+ // Using endpoint identification algorithm as HTTPS enables us to do
+ // CNAMEs/subjectAltName verification
+ private static TSocket getSSLSocketWithHttps(TSocket tSSLSocket) throws TTransportException {
+ SSLSocket sslSocket = (SSLSocket) tSSLSocket.getSocket();
+ SSLParameters sslParams = sslSocket.getSSLParameters();
+ sslParams.setEndpointIdentificationAlgorithm("HTTPS");
+ sslSocket.setSSLParameters(sslParams);
+ return new TSocket(sslSocket);
+ }
+}
\ No newline at end of file
diff --git a/metastore/src/test/org/apache/hadoop/hive/metastore/client/MetaStoreFactoryForTests.java b/metastore/src/test/org/apache/hadoop/hive/metastore/client/MetaStoreFactoryForTests.java
new file mode 100644
index 000000000000..e57c6a1f670b
--- /dev/null
+++ b/metastore/src/test/org/apache/hadoop/hive/metastore/client/MetaStoreFactoryForTests.java
@@ -0,0 +1,107 @@
+/*
+ * 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.hadoop.hive.metastore.client;
+
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.hive.conf.HiveConf;
+import org.apache.hadoop.hive.metastore.DefaultPartitionExpressionProxy;
+import org.apache.hadoop.hive.metastore.minihms.AbstractMetaStoreService;
+import org.apache.hadoop.hive.metastore.minihms.MiniHMS;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Factory for creating specific
+ * {@link org.apache.hadoop.hive.metastore.minihms.AbstractMetaStoreService} implementations for
+ * tests.
+ */
+public class MetaStoreFactoryForTests {
+ private static final int DEFAULT_LIMIT_PARTITION_REQUEST = 100;
+
+ /**
+ * We would like to run the tests with 2 MetaStore configurations
+ * - Embedded - Where the MetaStore is running in the same thread, and does not use Thrift
+ * - Remote - Where the MetaStore is started in a different thread, and uses Thrift for
+ * communication
+ *
+ * Or if the test.hms.client.configs system property is set, it would return a single test
+ * MetaStoreService which uses these configs. In this case the MetaStore should be created
+ * manually or by an external application.
+ * @return The list of the test MetaStoreService implementations usable by @Parameterized
+ * .Parameters
+ */
+ public static List