This is an automated email from the ASF dual-hosted git repository.
sankarh pushed a commit to branch branch-3
in repository https://gitbox.apache.org/repos/asf/hive.git
The following commit(s) were added to refs/heads/branch-3 by this push:
new 5f0df2d9b25 HIVE-27785: Backport of HIVE-20467, HIVE-20508, HIVE-20550
to branch-3 (#4790)
5f0df2d9b25 is described below
commit 5f0df2d9b253e63f5105e75fb39398025efd84dd
Author: Aman Raj <[email protected]>
AuthorDate: Fri Oct 20 12:57:48 2023 +0530
HIVE-27785: Backport of HIVE-20467, HIVE-20508, HIVE-20550 to branch-3
(#4790)
* HIVE-20467: Allow IF NOT EXISTS/IF EXISTS in Resource plan creation/drop
* HIVE-20508: Hive does not support user names of type "user@realm" (Deepak
Jaiswal, reviewed by Thejas Nair)
* HIVE-20550: Switch WebHCat to use beeline to submit Hive queries (Daniel
Dai, reviewed by Thejas Nair)
---------
Co-authored-by: Miklos Gergely <[email protected]>
Co-authored-by: Deepak Jaiswal <[email protected]>
Co-authored-by: Daniel Dai <[email protected]>
Signed-off-by: Sankar Hariappan <[email protected]>
Closes (#4790)
---
.../java/org/apache/hadoop/hive/conf/HiveConf.java | 2 +
.../test/e2e/templeton/drivers/TestDriverCurl.pm | 6 +--
.../test/e2e/templeton/tests/jobsubmission.conf | 6 +--
.../hive/hcatalog/templeton/DeleteDelegator.java | 59 +++++++++++++++++++---
.../hive/hcatalog/templeton/HiveDelegator.java | 25 +++------
.../hive/hcatalog/templeton/JsonBuilder.java | 2 +-
.../hive/hcatalog/templeton/tool/JobState.java | 13 +++++
.../templeton/tool/JobSubmissionConstants.java | 3 ++
.../hive/hcatalog/templeton/tool/LaunchMapper.java | 23 ++++++---
.../hcatalog/templeton/tool/TempletonUtils.java | 6 +++
.../templeton/tool/TestTempletonUtils.java | 3 ++
.../java/org/apache/hadoop/hive/ql/ErrorMsg.java | 5 +-
.../org/apache/hadoop/hive/ql/exec/DDLTask.java | 6 +--
.../org/apache/hadoop/hive/ql/metadata/Hive.java | 12 ++++-
.../hadoop/hive/ql/parse/DDLSemanticAnalyzer.java | 18 ++++++-
.../hadoop/hive/ql/parse/ResourcePlanParser.g | 8 +--
.../hive/ql/plan/CreateResourcePlanDesc.java | 11 +++-
.../hadoop/hive/ql/plan/DropResourcePlanDesc.java | 14 ++++-
ql/src/test/queries/clientpositive/resourceplan.q | 10 ++++
.../results/clientpositive/llap/resourceplan.q.out | 18 +++++++
.../hive/service/cli/thrift/ThriftCLIService.java | 6 ++-
21 files changed, 202 insertions(+), 54 deletions(-)
diff --git a/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java
b/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java
index 6bd226c442f..deed2a66d64 100644
--- a/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java
+++ b/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java
@@ -2814,6 +2814,8 @@ public class HiveConf extends Configuration {
"hive.test.authz.sstd.hs2.mode", false, "test hs2 mode from .q tests",
true),
HIVE_AUTHORIZATION_ENABLED("hive.security.authorization.enabled", false,
"enable or disable the Hive client authorization"),
+
HIVE_AUTHORIZATION_KERBEROS_USE_SHORTNAME("hive.security.authorization.kerberos.use.shortname",
true,
+ "use short name in Kerberos cluster"),
HIVE_AUTHORIZATION_MANAGER("hive.security.authorization.manager",
"org.apache.hadoop.hive.ql.security.authorization.plugin.sqlstd.SQLStdHiveAuthorizerFactory",
"The Hive client authorization manager class name. The user defined
authorization class should implement \n" +
diff --git a/hcatalog/src/test/e2e/templeton/drivers/TestDriverCurl.pm
b/hcatalog/src/test/e2e/templeton/drivers/TestDriverCurl.pm
index 66a6ca14438..e62269b27f0 100644
--- a/hcatalog/src/test/e2e/templeton/drivers/TestDriverCurl.pm
+++ b/hcatalog/src/test/e2e/templeton/drivers/TestDriverCurl.pm
@@ -555,12 +555,12 @@ sub execCurlCmd(){
my %result;
my $out;
my $err;
- IPC::Run::run(\@curl_cmd, \undef, $out, $err)
+ IPC::Run::run(\@curl_cmd, \undef, $log, $log)
or die "Failed running curl cmd " . join ' ', @curl_cmd;
$result{'rc'} = $? >> 8;
- $result{'stderr'} = $err;
- $result{'stdout'} = $out;
+ $result{'stderr'} = $log;
+ $result{'stdout'} = $log;
$result{'body'} = `cat $res_body`;
my @full_header = `cat $res_header`;
diff --git a/hcatalog/src/test/e2e/templeton/tests/jobsubmission.conf
b/hcatalog/src/test/e2e/templeton/tests/jobsubmission.conf
index a1b02844216..824eb922a94 100644
--- a/hcatalog/src/test/e2e/templeton/tests/jobsubmission.conf
+++ b/hcatalog/src/test/e2e/templeton/tests/jobsubmission.conf
@@ -324,7 +324,7 @@ $cfg =
#results
'status_code' => 200,
'check_job_created' => 1,
- 'check_job_exit_value' => 64,
+ 'check_job_exit_value' => 1,
},
@@ -443,7 +443,7 @@ $cfg =
'num' => 9,
'method' => 'POST',
'url' => ':TEMPLETON_URL:/templeton/v1/hive?user.name=:UNAME:',
- 'post_options' => ['execute=add jar piggybank.jar',
'files=:INPDIR_HDFS:/piggybank.jar',],
+ 'post_options' => ['execute=add jar :INPDIR_HDFS:/piggybank.jar',],
'json_field_substr_match' => { 'id' => '\d+'},
#results
'status_code' => 200,
@@ -499,7 +499,7 @@ $cfg =
{
#enable logs
'num' => 13,
- 'ignore23' => 'Log collector does not work with Hadoop 2',
+ 'ignore' => 'Log collector does not work with Hadoop 2/3',
'method' => 'POST',
'url' => ':TEMPLETON_URL:/templeton/v1/hive?user.name=:UNAME:',
'post_options' => ['execute=select a,b from mynums',
'statusdir=:OUTDIR:/status', 'enablelog=true'],
diff --git
a/hcatalog/webhcat/svr/src/main/java/org/apache/hive/hcatalog/templeton/DeleteDelegator.java
b/hcatalog/webhcat/svr/src/main/java/org/apache/hive/hcatalog/templeton/DeleteDelegator.java
index 049c9a48aca..5afd1b9eb7b 100644
---
a/hcatalog/webhcat/svr/src/main/java/org/apache/hive/hcatalog/templeton/DeleteDelegator.java
+++
b/hcatalog/webhcat/svr/src/main/java/org/apache/hive/hcatalog/templeton/DeleteDelegator.java
@@ -19,8 +19,16 @@
package org.apache.hive.hcatalog.templeton;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+import org.apache.commons.io.IOUtils;
+import org.apache.hive.hcatalog.templeton.tool.TempletonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.hadoop.hive.shims.HadoopShims.WebHCatJTShim;
@@ -39,6 +47,36 @@ public class DeleteDelegator extends TempletonDelegator {
super(appConf);
}
+ private String runProgram(String[] cmd) throws IOException,
InterruptedException {
+ ProcessBuilder pb = new ProcessBuilder(cmd);
+ Set<String> keys = new HashSet<String>(pb.environment().keySet());
+ for (String key : keys) {
+ pb.environment().remove(key);
+ }
+ Process p = pb.start();
+ String stdout = IOUtils.toString(p.getInputStream());
+ String stderr = IOUtils.toString(p.getErrorStream());
+ int code = p.waitFor();
+ if (code != 0) {
+ throw new IOException("non-zero exit code " + code + " when running " +
Arrays.toString(cmd) + "\n"
+ + "stdout: " + stdout + "\n" + "stderr: " + stderr + "\n");
+ }
+ return stdout;
+ }
+
+ private void killHiveQuery(String user, String tag) throws IOException,
InterruptedException {
+ String[] cmd = new String[] {appConf.hivePath(),
"--getUrlsFromBeelineSite"};
+ String urlsString = runProgram(cmd);
+ String[] urls = urlsString.substring(6).split(",");
+ for (String url : urls) {
+ if (url != null && !url.trim().isEmpty()) {
+ cmd = new String[]{appConf.hivePath(), "-u", "jdbc:hive2://" + url,
"-n", user,
+ "-e", "kill query '" + tag + "'"};
+ runProgram(cmd);
+ }
+ }
+ }
+
public QueueStatusBean run(String user, String id)
throws NotAuthorizedException, BadParam, IOException, InterruptedException
{
@@ -53,13 +91,20 @@ public class DeleteDelegator extends TempletonDelegator {
throw new BadParam("Invalid jobid: " + id);
tracker.killJob(jobid);
state = new JobState(id, Main.getAppConfigInstance());
- List<JobState> children = state.getChildren();
- if (children != null) {
- for (JobState child : children) {
- try {
- tracker.killJob(StatusDelegator.StringToJobID(child.getId()));
- } catch (IOException e) {
- LOG.warn("templeton: fail to kill job " + child.getId());
+ if (state.getJobType() != null) {
+ LauncherDelegator.JobType jobType =
LauncherDelegator.JobType.valueOf(state.getJobType());
+ if (jobType == LauncherDelegator.JobType.HIVE) {
+ killHiveQuery(user, jobid.toString());
+ } else {
+ List<JobState> children = state.getChildren();
+ if (children != null) {
+ for (JobState child : children) {
+ try {
+ tracker.killJob(StatusDelegator.StringToJobID(child.getId()));
+ } catch (IOException e) {
+ LOG.warn("templeton: fail to kill job " + child.getId());
+ }
+ }
}
}
}
diff --git
a/hcatalog/webhcat/svr/src/main/java/org/apache/hive/hcatalog/templeton/HiveDelegator.java
b/hcatalog/webhcat/svr/src/main/java/org/apache/hive/hcatalog/templeton/HiveDelegator.java
index a3f57dff3e1..3f1968d7f15 100644
---
a/hcatalog/webhcat/svr/src/main/java/org/apache/hive/hcatalog/templeton/HiveDelegator.java
+++
b/hcatalog/webhcat/svr/src/main/java/org/apache/hive/hcatalog/templeton/HiveDelegator.java
@@ -52,13 +52,13 @@ public class HiveDelegator extends LauncherDelegator {
ExecuteException, IOException, InterruptedException,
TooManyRequestsException
{
runAs = user;
- List<String> args = makeArgs(execute, srcFile, defines, hiveArgs,
otherFiles, statusdir,
+ List<String> args = makeArgs(user, execute, srcFile, defines, hiveArgs,
otherFiles, statusdir,
completedUrl, enablelog, enableJobReconnect);
return enqueueController(user, userArgs, callback, args);
}
- private List<String> makeArgs(String execute, String srcFile,
+ private List<String> makeArgs(String user, String execute, String srcFile,
List<String> defines, List<String> hiveArgs, String otherFiles,
String statusdir, String completedUrl, boolean enablelog,
Boolean enableJobReconnect)
@@ -73,26 +73,15 @@ public class HiveDelegator extends LauncherDelegator {
args.add(appConf.hivePath());
- args.add("--service");
- args.add("cli");
-
- //the token file location as initial hiveconf arg
- args.add("--hiveconf");
- args.add(TempletonControllerJob.TOKEN_FILE_ARG_PLACEHOLDER);
-
- //this is needed specifcally for Hive on Tez (in addition to
- //JobSubmissionConstants.TOKEN_FILE_ARG_PLACEHOLDER)
- args.add("--hiveconf");
- args.add(JobSubmissionConstants.TOKEN_FILE_ARG_PLACEHOLDER_TEZ);
+ args.add("-n");
+ args.add(user);
+ args.add("-p");
+ args.add("default");
//add mapreduce job tag placeholder
args.add("--hiveconf");
- args.add(TempletonControllerJob.MAPREDUCE_JOB_TAGS_ARG_PLACEHOLDER);
+ args.add(TempletonControllerJob.HIVE_QUERY_TAG_ARG_PLACEHOLDER);
- for (String prop : appConf.hiveProps()) {
- args.add("--hiveconf");
- args.add(prop);
- }
for (String prop : defines) {
args.add("--hiveconf");
args.add(prop);
diff --git
a/hcatalog/webhcat/svr/src/main/java/org/apache/hive/hcatalog/templeton/JsonBuilder.java
b/hcatalog/webhcat/svr/src/main/java/org/apache/hive/hcatalog/templeton/JsonBuilder.java
index 6a38719525f..dfcdaef3e93 100644
---
a/hcatalog/webhcat/svr/src/main/java/org/apache/hive/hcatalog/templeton/JsonBuilder.java
+++
b/hcatalog/webhcat/svr/src/main/java/org/apache/hive/hcatalog/templeton/JsonBuilder.java
@@ -49,7 +49,7 @@ public class JsonBuilder {
hiveError2HttpStatusCode.put(ErrorMsg.INVALID_PARTITION.getErrorCode(),
HttpStatus.NOT_FOUND_404);
hiveError2HttpStatusCode.put(ErrorMsg.DUPLICATE_COLUMN_NAMES.getErrorCode(),
HttpStatus.CONFLICT_409);
-
hiveError2HttpStatusCode.put(ErrorMsg.DATABSAE_ALREADY_EXISTS.getErrorCode(),
HttpStatus.CONFLICT_409);
+
hiveError2HttpStatusCode.put(ErrorMsg.DATABASE_ALREADY_EXISTS.getErrorCode(),
HttpStatus.CONFLICT_409);
hiveError2HttpStatusCode.put(ErrorMsg.PARTITION_EXISTS.getErrorCode(),
HttpStatus.CONFLICT_409);
hiveError2HttpStatusCode.put(ErrorMsg.TABLE_ALREADY_EXISTS.getErrorCode(),
HttpStatus.CONFLICT_409);
}
diff --git
a/hcatalog/webhcat/svr/src/main/java/org/apache/hive/hcatalog/templeton/tool/JobState.java
b/hcatalog/webhcat/svr/src/main/java/org/apache/hive/hcatalog/templeton/tool/JobState.java
index 74cf1e5e838..52738b760f6 100644
---
a/hcatalog/webhcat/svr/src/main/java/org/apache/hive/hcatalog/templeton/tool/JobState.java
+++
b/hcatalog/webhcat/svr/src/main/java/org/apache/hive/hcatalog/templeton/tool/JobState.java
@@ -126,6 +126,19 @@ public class JobState {
setField("percentComplete", percent);
}
+ /**
+ * The job type
+ */
+ public String getJobType()
+ throws IOException {
+ return getField("jobType");
+ }
+
+ public void setJobType(String jobType)
+ throws IOException {
+ setField("jobType", jobType);
+ }
+
/**
* Add a jobid to the list of children of this job.
*
diff --git
a/hcatalog/webhcat/svr/src/main/java/org/apache/hive/hcatalog/templeton/tool/JobSubmissionConstants.java
b/hcatalog/webhcat/svr/src/main/java/org/apache/hive/hcatalog/templeton/tool/JobSubmissionConstants.java
index f3a79f63052..9e90b8de502 100644
---
a/hcatalog/webhcat/svr/src/main/java/org/apache/hive/hcatalog/templeton/tool/JobSubmissionConstants.java
+++
b/hcatalog/webhcat/svr/src/main/java/org/apache/hive/hcatalog/templeton/tool/JobSubmissionConstants.java
@@ -54,8 +54,11 @@ public interface JobSubmissionConstants {
// previously running child jobs can be killed before the child job is
launched
// again.
public static final String MAPREDUCE_JOB_TAGS = "mapreduce.job.tags";
+ public static final String HIVE_QUERY_TAG = "hive.query.tag";
public static final String MAPREDUCE_JOB_TAGS_ARG_PLACEHOLDER =
"__MR_JOB_TAGS_OPTION=MR_JOB_TAGS_JOBID__";
+ public static final String HIVE_QUERY_TAG_ARG_PLACEHOLDER =
+ "__HIVE_QUERY_TAG_OPTION=HIVE_QUERY_TAG_JOBID__";
public static final String HADOOP_CLASSPATH = "HADOOP_CLASSPATH";
/**
diff --git
a/hcatalog/webhcat/svr/src/main/java/org/apache/hive/hcatalog/templeton/tool/LaunchMapper.java
b/hcatalog/webhcat/svr/src/main/java/org/apache/hive/hcatalog/templeton/tool/LaunchMapper.java
index 5de04e35904..b1f4a6ac5e7 100644
---
a/hcatalog/webhcat/svr/src/main/java/org/apache/hive/hcatalog/templeton/tool/LaunchMapper.java
+++
b/hcatalog/webhcat/svr/src/main/java/org/apache/hive/hcatalog/templeton/tool/LaunchMapper.java
@@ -153,7 +153,8 @@ public class LaunchMapper extends Mapper<NullWritable,
NullWritable, Text, Text>
env.put(pathVarName, paths);
}
}
- protected Process startJob(Configuration conf, String jobId, String user,
String overrideClasspath)
+ protected Process startJob(Configuration conf, String jobId, String user,
String overrideClasspath,
+ LauncherDelegator.JobType jobType)
throws IOException, InterruptedException {
copyLocal(COPY_NAME, conf);
@@ -172,8 +173,14 @@ public class LaunchMapper extends Mapper<NullWritable,
NullWritable, Text, Text>
List<String> jarArgsList = new LinkedList<String>(Arrays.asList(jarArgs));
handleTokenFile(jarArgsList,
JobSubmissionConstants.TOKEN_FILE_ARG_PLACEHOLDER,
"mapreduce.job.credentials.binary");
handleTokenFile(jarArgsList,
JobSubmissionConstants.TOKEN_FILE_ARG_PLACEHOLDER_TEZ, "tez.credentials.path");
- handleMapReduceJobTag(jarArgsList,
JobSubmissionConstants.MAPREDUCE_JOB_TAGS_ARG_PLACEHOLDER,
- JobSubmissionConstants.MAPREDUCE_JOB_TAGS, jobId);
+ if (jobType == LauncherDelegator.JobType.HIVE) {
+ replaceJobTag(jarArgsList,
JobSubmissionConstants.HIVE_QUERY_TAG_ARG_PLACEHOLDER,
+ JobSubmissionConstants.HIVE_QUERY_TAG, jobId);
+ } else {
+ replaceJobTag(jarArgsList,
JobSubmissionConstants.MAPREDUCE_JOB_TAGS_ARG_PLACEHOLDER,
+ JobSubmissionConstants.MAPREDUCE_JOB_TAGS, jobId);
+ }
+
return TrivialExecService.getInstance().run(jarArgsList, removeEnv, env);
}
@@ -245,11 +252,11 @@ public class LaunchMapper extends Mapper<NullWritable,
NullWritable, Text, Text>
}
/**
- * Replace the placeholder mapreduce tags with our MR jobid so that all
child jobs
+ * Replace the placeholder tags with our MR jobid so that all child jobs or
hive queries are
* get tagged with it. This is used on launcher task restart to prevent from
having
* same jobs running in parallel.
*/
- private static void handleMapReduceJobTag(List<String> jarArgsList, String
placeholder,
+ private static void replaceJobTag(List<String> jarArgsList, String
placeholder,
String mapReduceJobTagsProp, String currentJobId) throws IOException {
String arg = String.format("%s=%s", mapReduceJobTagsProp, currentJobId);
for(int i = 0; i < jarArgsList.size(); i++) {
@@ -401,8 +408,12 @@ public class LaunchMapper extends Mapper<NullWritable,
NullWritable, Text, Text>
Process proc = startJob(conf,
context.getJobID().toString(),
conf.get("user.name"),
- conf.get(OVERRIDE_CLASSPATH));
+ conf.get(OVERRIDE_CLASSPATH),
+ jobType);
+ JobState state = new JobState(context.getJobID().toString(), conf);
+ state.setJobType(jobType.toString());
+ state.close();
ExecutorService pool = Executors.newCachedThreadPool();
executeWatcher(pool, conf, context.getJobID(),
proc.getInputStream(), statusdir, STDOUT_FNAME);
diff --git
a/hcatalog/webhcat/svr/src/main/java/org/apache/hive/hcatalog/templeton/tool/TempletonUtils.java
b/hcatalog/webhcat/svr/src/main/java/org/apache/hive/hcatalog/templeton/tool/TempletonUtils.java
index df8c32efb69..29499a289e8 100644
---
a/hcatalog/webhcat/svr/src/main/java/org/apache/hive/hcatalog/templeton/tool/TempletonUtils.java
+++
b/hcatalog/webhcat/svr/src/main/java/org/apache/hive/hcatalog/templeton/tool/TempletonUtils.java
@@ -115,6 +115,7 @@ public class TempletonUtils {
* groups that don't add information such as "Map 1: -/-"
*/
public static final Pattern HIVE_TEZ_COMPLETE =
Pattern.compile("(Map|Reducer) (\\d+:) (\\d+(\\(\\+\\d+\\))?/\\d+)");
+ public static final Pattern HIVE_BEELINE_COMPLETE =
Pattern.compile("VERTICES: .* (\\d+%)");
/**
* Pig on Tez produces progress report that looks like this
* DAG Status: status=RUNNING, progress=TotalTasks: 3 Succeeded: 0 Running:
0 Failed: 0 Killed: 0
@@ -139,6 +140,11 @@ public class TempletonUtils {
if (pig.find())
return pig.group().trim();
+ Matcher beeline = HIVE_BEELINE_COMPLETE.matcher(line);
+ if (beeline.find()) {
+ return beeline.group(1).trim() + " complete";
+ }
+
Matcher hive = HIVE_COMPLETE.matcher(line);
if(hive.find()) {
return "map " + hive.group(1) + " reduce " + hive.group(2);
diff --git
a/hcatalog/webhcat/svr/src/test/java/org/apache/hive/hcatalog/templeton/tool/TestTempletonUtils.java
b/hcatalog/webhcat/svr/src/test/java/org/apache/hive/hcatalog/templeton/tool/TestTempletonUtils.java
index 51ed86741e5..cf48221c81d 100644
---
a/hcatalog/webhcat/svr/src/test/java/org/apache/hive/hcatalog/templeton/tool/TestTempletonUtils.java
+++
b/hcatalog/webhcat/svr/src/test/java/org/apache/hive/hcatalog/templeton/tool/TestTempletonUtils.java
@@ -90,6 +90,9 @@ public class TestTempletonUtils {
String fifty = "2011-12-15 18:12:36,333 [main] INFO
org.apache.pig.backend.hadoop.executionengine.mapReduceLayer.MapReduceLauncher
- 50% complete";
Assert.assertEquals("50% complete",
TempletonUtils.extractPercentComplete(fifty));
+
+ String beeline = "VERTICES: 01/02 [==========================>>] 70%
ELAPSED TIME: 3.79 s";
+ Assert.assertEquals("70% complete",
TempletonUtils.extractPercentComplete(beeline));
}
@Test
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/ErrorMsg.java
b/ql/src/java/org/apache/hadoop/hive/ql/ErrorMsg.java
index 90c6d22252d..e0f8b5251be 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/ErrorMsg.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/ErrorMsg.java
@@ -334,7 +334,7 @@ public enum ErrorMsg {
"A column on which a partition/table is list bucketed cannot be
truncated."),
TABLE_NOT_PARTITIONED(10241, "Table {0} is not a partitioned table", true),
- DATABSAE_ALREADY_EXISTS(10242, "Database {0} already exists", true),
+ DATABASE_ALREADY_EXISTS(10242, "Database {0} already exists", true),
CANNOT_REPLACE_COLUMNS(10243, "Replace columns is not supported for table
{0}. SerDe may be incompatible.", true),
BAD_LOCATION_VALUE(10244, "{0} is not absolute. Please specify a complete
absolute uri."),
UNSUPPORTED_ALTER_TBL_OP(10245, "{0} alter table options is not supported"),
@@ -467,7 +467,8 @@ public enum ErrorMsg {
"insert-only transactional", true),
LOAD_DATA_LAUNCH_JOB_IO_ERROR(10415, "Encountered I/O error while parsing
rewritten load data into insert query"),
LOAD_DATA_LAUNCH_JOB_PARSE_ERROR(10416, "Encountered parse error while
parsing rewritten load data into insert query"),
-
+ RESOURCE_PLAN_ALREADY_EXISTS(10417, "Resource plan {0} already exists",
true),
+ RESOURCE_PLAN_NOT_EXISTS(10418, "Resource plan {0} does not exist", true),
//========================== 20000 range starts here
========================//
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/exec/DDLTask.java
b/ql/src/java/org/apache/hadoop/hive/ql/exec/DDLTask.java
index 815916c0926..f008e61b8ed 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/exec/DDLTask.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/exec/DDLTask.java
@@ -677,7 +677,7 @@ public class DDLTask extends Task<DDLWork> implements
Serializable {
private int createResourcePlan(Hive db, CreateResourcePlanDesc
createResourcePlanDesc)
throws HiveException {
db.createResourcePlan(createResourcePlanDesc.getResourcePlan(),
- createResourcePlanDesc.getCopyFromName());
+ createResourcePlanDesc.getCopyFromName(),
createResourcePlanDesc.getIfNotExists());
return 0;
}
@@ -787,7 +787,7 @@ public class DDLTask extends Task<DDLWork> implements
Serializable {
}
private int dropResourcePlan(Hive db, DropResourcePlanDesc desc) throws
HiveException {
- db.dropResourcePlan(desc.getRpName());
+ db.dropResourcePlan(desc.getRpName(), desc.getIfExists());
return 0;
}
@@ -4849,7 +4849,7 @@ public class DDLTask extends Task<DDLWork> implements
Serializable {
}
catch (AlreadyExistsException ex) {
//it would be better if AlreadyExistsException had an errorCode field....
- throw new HiveException(ex, ErrorMsg.DATABSAE_ALREADY_EXISTS,
crtDb.getName());
+ throw new HiveException(ex, ErrorMsg.DATABASE_ALREADY_EXISTS,
crtDb.getName());
}
return 0;
}
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/metadata/Hive.java
b/ql/src/java/org/apache/hadoop/hive/ql/metadata/Hive.java
index 74dbdfb9a95..b9fe739b7b8 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/metadata/Hive.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/metadata/Hive.java
@@ -5402,10 +5402,14 @@ private void constructOneLBLocationMap(FileStatus fSta,
}
- public void createResourcePlan(WMResourcePlan resourcePlan, String
copyFromName)
+ public void createResourcePlan(WMResourcePlan resourcePlan, String
copyFromName, boolean ifNotExists)
throws HiveException {
try {
getMSC().createResourcePlan(resourcePlan, copyFromName);
+ } catch (AlreadyExistsException e) {
+ if (!ifNotExists) {
+ throw new HiveException(e, ErrorMsg.RESOURCE_PLAN_ALREADY_EXISTS,
resourcePlan.getName());
+ }
} catch (Exception e) {
throw new HiveException(e);
}
@@ -5429,9 +5433,13 @@ private void constructOneLBLocationMap(FileStatus fSta,
}
}
- public void dropResourcePlan(String rpName) throws HiveException {
+ public void dropResourcePlan(String rpName, boolean ifExists) throws
HiveException {
try {
getMSC().dropResourcePlan(rpName);
+ } catch (NoSuchObjectException e) {
+ if (!ifExists) {
+ throw new HiveException(e, ErrorMsg.RESOURCE_PLAN_NOT_EXISTS, rpName);
+ }
} catch (Exception e) {
throw new HiveException(e);
}
diff --git
a/ql/src/java/org/apache/hadoop/hive/ql/parse/DDLSemanticAnalyzer.java
b/ql/src/java/org/apache/hadoop/hive/ql/parse/DDLSemanticAnalyzer.java
index 5f2a926cd56..647731629d0 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/parse/DDLSemanticAnalyzer.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/parse/DDLSemanticAnalyzer.java
@@ -907,6 +907,7 @@ public class DDLSemanticAnalyzer extends
BaseSemanticAnalyzer {
String resourcePlanName = unescapeIdentifier(ast.getChild(0).getText());
Integer queryParallelism = null;
String likeName = null;
+ boolean ifNotExists = false;
for (int i = 1; i < ast.getChildCount(); ++i) {
Tree child = ast.getChild(i);
switch (child.getType()) {
@@ -925,11 +926,14 @@ public class DDLSemanticAnalyzer extends
BaseSemanticAnalyzer {
throw new SemanticException("Conflicting create arguments " +
ast.toStringTree());
}
break;
+ case HiveParser.TOK_IFNOTEXISTS:
+ ifNotExists = true;
+ break;
default: throw new SemanticException("Invalid create arguments " +
ast.toStringTree());
}
}
CreateResourcePlanDesc desc = new CreateResourcePlanDesc(
- resourcePlanName, queryParallelism, likeName);
+ resourcePlanName, queryParallelism, likeName, ifNotExists);
addServiceOutput();
rootTasks.add(TaskFactory.get(new DDLWork(getInputs(), getOutputs(),
desc)));
}
@@ -1072,7 +1076,17 @@ public class DDLSemanticAnalyzer extends
BaseSemanticAnalyzer {
throw new SemanticException("Expected name in DROP RESOURCE PLAN
statement");
}
String rpName = unescapeIdentifier(ast.getChild(0).getText());
- DropResourcePlanDesc desc = new DropResourcePlanDesc(rpName);
+ boolean ifExists = false;
+ for (int i = 1; i < ast.getChildCount(); ++i) {
+ Tree child = ast.getChild(i);
+ switch (child.getType()) {
+ case HiveParser.TOK_IFEXISTS:
+ ifExists = true;
+ break;
+ default: throw new SemanticException("Invalid create arguments " +
ast.toStringTree());
+ }
+ }
+ DropResourcePlanDesc desc = new DropResourcePlanDesc(rpName, ifExists);
addServiceOutput();
rootTasks.add(TaskFactory.get(
new DDLWork(getInputs(), getOutputs(), desc)));
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/parse/ResourcePlanParser.g
b/ql/src/java/org/apache/hadoop/hive/ql/parse/ResourcePlanParser.g
index f8c47f972f2..0479c78f7bc 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/parse/ResourcePlanParser.g
+++ b/ql/src/java/org/apache/hadoop/hive/ql/parse/ResourcePlanParser.g
@@ -93,9 +93,9 @@ rpUnassignList
createResourcePlanStatement
@init { gParent.pushMsg("create resource plan statement", state); }
@after { gParent.popMsg(state); }
- : KW_CREATE KW_RESOURCE KW_PLAN (
- (name=identifier KW_LIKE likeName=identifier -> ^(TOK_CREATE_RP
$name ^(TOK_LIKERP $likeName)))
- | (name=identifier (KW_WITH rpAssignList)? -> ^(TOK_CREATE_RP $name
rpAssignList?))
+ : KW_CREATE KW_RESOURCE KW_PLAN ifNotExists? (
+ (name=identifier KW_LIKE likeName=identifier -> ^(TOK_CREATE_RP
$name ifNotExists? ^(TOK_LIKERP $likeName)))
+ | (name=identifier (KW_WITH rpAssignList)? -> ^(TOK_CREATE_RP $name
ifNotExists? rpAssignList?))
)
;
@@ -140,7 +140,7 @@ replaceResourcePlanStatement
dropResourcePlanStatement
@init { gParent.pushMsg("drop resource plan statement", state); }
@after { gParent.popMsg(state); }
- : KW_DROP KW_RESOURCE KW_PLAN name=identifier -> ^(TOK_DROP_RP $name)
+ : KW_DROP KW_RESOURCE KW_PLAN ifExists? name=identifier -> ^(TOK_DROP_RP
$name ifExists?)
;
poolPath
diff --git
a/ql/src/java/org/apache/hadoop/hive/ql/plan/CreateResourcePlanDesc.java
b/ql/src/java/org/apache/hadoop/hive/ql/plan/CreateResourcePlanDesc.java
index f645aa214e9..9c18f59d096 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/plan/CreateResourcePlanDesc.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/plan/CreateResourcePlanDesc.java
@@ -28,17 +28,20 @@ public class CreateResourcePlanDesc extends DDLDesc
implements Serializable {
private WMResourcePlan resourcePlan;
private String copyFromName;
+ private boolean ifNotExists;
// For serialization only.
public CreateResourcePlanDesc() {
}
- public CreateResourcePlanDesc(String planName, Integer queryParallelism,
String copyFromName) {
+ public CreateResourcePlanDesc(String planName, Integer queryParallelism,
String copyFromName,
+ boolean ifNotExists) {
resourcePlan = new WMResourcePlan(planName);
if (queryParallelism != null) {
resourcePlan.setQueryParallelism(queryParallelism);
}
this.copyFromName = copyFromName;
+ this.ifNotExists = ifNotExists;
}
@Explain(displayName="resourcePlan", explainLevels = { Level.USER,
Level.DEFAULT, Level.EXTENDED })
@@ -50,4 +53,10 @@ public class CreateResourcePlanDesc extends DDLDesc
implements Serializable {
public String getCopyFromName() {
return copyFromName;
}
+
+ @Explain(displayName="If not exists", explainLevels = { Level.USER,
Level.DEFAULT, Level.EXTENDED },
+ displayOnlyOnTrue = true)
+ public boolean getIfNotExists() {
+ return ifNotExists;
+ }
}
\ No newline at end of file
diff --git
a/ql/src/java/org/apache/hadoop/hive/ql/plan/DropResourcePlanDesc.java
b/ql/src/java/org/apache/hadoop/hive/ql/plan/DropResourcePlanDesc.java
index b67472de325..efaf0789b0d 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/plan/DropResourcePlanDesc.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/plan/DropResourcePlanDesc.java
@@ -27,11 +27,13 @@ public class DropResourcePlanDesc extends DDLDesc
implements Serializable {
private static final long serialVersionUID = 1258596919510047766L;
private String rpName;
+ private boolean ifExists;
public DropResourcePlanDesc() {}
- public DropResourcePlanDesc(String rpName) {
+ public DropResourcePlanDesc(String rpName, boolean ifExists) {
this.setRpName(rpName);
+ this.setIfExists(ifExists);
}
@Explain(displayName="resourcePlanName", explainLevels = { Level.USER,
Level.DEFAULT, Level.EXTENDED })
@@ -39,8 +41,18 @@ public class DropResourcePlanDesc extends DDLDesc implements
Serializable {
return rpName;
}
+ @Explain(displayName="ifExists", explainLevels = { Level.USER,
Level.DEFAULT, Level.EXTENDED },
+ displayOnlyOnTrue = true)
+ public boolean getIfExists() {
+ return ifExists;
+ }
+
public void setRpName(String rpName) {
this.rpName = rpName;
}
+ public void setIfExists(boolean ifExists) {
+ this.ifExists = ifExists;
+ }
+
}
\ No newline at end of file
diff --git a/ql/src/test/queries/clientpositive/resourceplan.q
b/ql/src/test/queries/clientpositive/resourceplan.q
index ecaa16533c5..3d4aa4028cc 100644
--- a/ql/src/test/queries/clientpositive/resourceplan.q
+++ b/ql/src/test/queries/clientpositive/resourceplan.q
@@ -34,6 +34,11 @@ SHOW RESOURCE PLANS;
SHOW RESOURCE PLAN plan_2;
SELECT * FROM SYS.WM_RESOURCEPLANS;
+-- Create plan with existing name, should fail
+CREATE RESOURCE PLAN plan_2;
+-- Create plan with existing name with IF NOT EXISTS
+CREATE RESOURCE PLAN IF NOT EXISTS plan_2;
+
-- Should fail cannot set pool in create.
CREATE RESOURCE PLAN plan_3 WITH QUERY_PARALLELISM=5, DEFAULT POOL = `all`;
@@ -138,6 +143,11 @@ DROP RESOURCE PLAN plan_2;
DROP RESOURCE PLAN plan_3;
SELECT * FROM SYS.WM_RESOURCEPLANS;
+-- Drop non existing resource plan, should fail
+DROP RESOURCE PLAN plan_99999;
+-- Drop non existing resource plan with IF EXISTS
+DROP RESOURCE PLAN IF EXISTS plan_99999;
+
-- Use reserved keyword table as name.
CREATE RESOURCE PLAN `table`;
ALTER RESOURCE PLAN `table` SET QUERY_PARALLELISM = 1;
diff --git a/ql/src/test/results/clientpositive/llap/resourceplan.q.out
b/ql/src/test/results/clientpositive/llap/resourceplan.q.out
index d88473429e2..d7e879c9dae 100644
--- a/ql/src/test/results/clientpositive/llap/resourceplan.q.out
+++ b/ql/src/test/results/clientpositive/llap/resourceplan.q.out
@@ -3231,6 +3231,15 @@ POSTHOOK: Input: sys@wm_resourceplans
#### A masked pattern was here ####
plan_1 DISABLED NULL default
plan_2 DISABLED 10 default
+PREHOOK: query: CREATE RESOURCE PLAN plan_2
+PREHOOK: type: CREATE RESOURCEPLAN
+PREHOOK: Output: dummyHostnameForTest
+FAILED: Execution Error, return code 1 from
org.apache.hadoop.hive.ql.exec.DDLTask. Resource plan plan_2 already exists
+PREHOOK: query: CREATE RESOURCE PLAN IF NOT EXISTS plan_2
+PREHOOK: type: CREATE RESOURCEPLAN
+PREHOOK: Output: dummyHostnameForTest
+POSTHOOK: query: CREATE RESOURCE PLAN IF NOT EXISTS plan_2
+POSTHOOK: type: CREATE RESOURCEPLAN
FAILED: SemanticException Invalid create arguments (tok_create_rp plan_3
(tok_query_parallelism 5) (tok_default_pool all))
PREHOOK: query: ALTER RESOURCE PLAN plan_1 RENAME TO plan_2
PREHOOK: type: ALTER RESOURCEPLAN
@@ -3548,6 +3557,15 @@ POSTHOOK: type: QUERY
POSTHOOK: Input: sys@wm_resourceplans
#### A masked pattern was here ####
plan_2 ACTIVE 10 default
+PREHOOK: query: DROP RESOURCE PLAN plan_99999
+PREHOOK: type: DROP RESOURCEPLAN
+PREHOOK: Output: dummyHostnameForTest
+FAILED: Execution Error, return code 1 from
org.apache.hadoop.hive.ql.exec.DDLTask. Resource plan plan_99999 does not exist
+PREHOOK: query: DROP RESOURCE PLAN IF EXISTS plan_99999
+PREHOOK: type: DROP RESOURCEPLAN
+PREHOOK: Output: dummyHostnameForTest
+POSTHOOK: query: DROP RESOURCE PLAN IF EXISTS plan_99999
+POSTHOOK: type: DROP RESOURCEPLAN
PREHOOK: query: CREATE RESOURCE PLAN `table`
PREHOOK: type: CREATE RESOURCEPLAN
PREHOOK: Output: dummyHostnameForTest
diff --git
a/service/src/java/org/apache/hive/service/cli/thrift/ThriftCLIService.java
b/service/src/java/org/apache/hive/service/cli/thrift/ThriftCLIService.java
index 8ba2d1892bf..1835af00667 100644
--- a/service/src/java/org/apache/hive/service/cli/thrift/ThriftCLIService.java
+++ b/service/src/java/org/apache/hive/service/cli/thrift/ThriftCLIService.java
@@ -428,7 +428,11 @@ public abstract class ThriftCLIService extends
AbstractService implements TCLISe
userName = req.getUsername();
}
- userName = getShortName(userName);
+ if
(cliService.getHiveConf().getBoolVar(ConfVars.HIVE_AUTHORIZATION_KERBEROS_USE_SHORTNAME))
+ {
+ userName = getShortName(userName);
+ }
+
String effectiveClientUser = getProxyUser(userName,
req.getConfiguration(), getIpAddress());
LOG.debug("Client's username: {}", effectiveClientUser);
return effectiveClientUser;