/**
* 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.ql.parse;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.antlr.runtime.tree.Tree;
import org.apache.hadoop.hive.ql.metadata.HiveUtils;
/**
* List of error messages thrown by the parser.
**/
public enum ErrorMsg {
// SQLStates are taken from Section 12.5 of ISO-9075.
// See http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt
// Most will just rollup to the generic syntax error state of 42000, but
// specific errors can override the that state.
// See this page for how MySQL uses SQLState codes:
// http://dev.mysql.com/doc/refman/5.0/en/connector-j-reference-error-sqlstates.html
GENERIC_ERROR("Exception while processing"),
INVALID_TABLE("Table not found", "42S02"),
INVALID_COLUMN("Invalid column reference"),
INVALID_INDEX("Invalid index"),
INVALID_TABLE_OR_COLUMN("Invalid table alias or column reference"),
AMBIGUOUS_TABLE_OR_COLUMN("Ambiguous table alias or column reference"),
INVALID_PARTITION("Partition not found"),
AMBIGUOUS_COLUMN("Ambiguous column reference"),
AMBIGUOUS_TABLE_ALIAS("Ambiguous table alias"),
INVALID_TABLE_ALIAS("Invalid table alias"),
NO_TABLE_ALIAS("No table alias"),
INVALID_FUNCTION("Invalid function"),
INVALID_FUNCTION_SIGNATURE("Function argument type mismatch"),
INVALID_OPERATOR_SIGNATURE("Operator argument type mismatch"),
INVALID_ARGUMENT("Wrong arguments"),
INVALID_ARGUMENT_LENGTH("Arguments length mismatch", "21000"),
INVALID_ARGUMENT_TYPE("Argument type mismatch"),
INVALID_JOIN_CONDITION_1("Both left and right aliases encountered in JOIN"),
INVALID_JOIN_CONDITION_2("Neither left nor right aliases encountered in JOIN"),
INVALID_JOIN_CONDITION_3("OR not supported in JOIN currently"),
INVALID_TRANSFORM("TRANSFORM with other SELECT columns not supported"),
DUPLICATE_GROUPBY_KEY("Repeated key in GROUP BY"),
UNSUPPORTED_MULTIPLE_DISTINCTS("DISTINCT on different columns not supported with skew in data"),
NO_SUBQUERY_ALIAS("No alias for subquery"),
NO_INSERT_INSUBQUERY("Cannot insert in a subquery. Inserting to table "),
NON_KEY_EXPR_IN_GROUPBY("Expression not in GROUP BY key"),
INVALID_XPATH("General . and [] operators are not supported"),
INVALID_PATH("Invalid path"), ILLEGAL_PATH("Path is not legal"),
INVALID_NUMERICAL_CONSTANT("Invalid numerical constant"),
INVALID_ARRAYINDEX_CONSTANT("Non-constant expressions for array indexes not supported"),
INVALID_MAPINDEX_CONSTANT("Non-constant expression for map indexes not supported"),
INVALID_MAPINDEX_TYPE("MAP key type does not match index expression type"),
NON_COLLECTION_TYPE("[] not valid on non-collection types"),
SELECT_DISTINCT_WITH_GROUPBY("SELECT DISTINCT and GROUP BY can not be in the same query"),
COLUMN_REPEATED_IN_PARTITIONING_COLS("Column repeated in partitioning columns"),
DUPLICATE_COLUMN_NAMES("Duplicate column name:"),
INVALID_BUCKET_NUMBER("Bucket number should be bigger than zero"),
COLUMN_REPEATED_IN_CLUSTER_SORT("Same column cannot appear in CLUSTER BY and SORT BY"),
SAMPLE_RESTRICTION("Cannot SAMPLE on more than two columns"),
SAMPLE_COLUMN_NOT_FOUND("SAMPLE column not found"),
NO_PARTITION_PREDICATE("No partition predicate found"),
INVALID_DOT(". Operator is only supported on struct or list of struct types"),
INVALID_TBL_DDL_SERDE("Either list of columns or a custom serializer should be specified"),
TARGET_TABLE_COLUMN_MISMATCH(
"Cannot insert into target table because column number/types are different"),
TABLE_ALIAS_NOT_ALLOWED("Table alias not allowed in sampling clause"),
CLUSTERBY_DISTRIBUTEBY_CONFLICT("Cannot have both CLUSTER BY and DISTRIBUTE BY clauses"),
ORDERBY_DISTRIBUTEBY_CONFLICT("Cannot have both ORDER BY and DISTRIBUTE BY clauses"),
CLUSTERBY_SORTBY_CONFLICT("Cannot have both CLUSTER BY and SORT BY clauses"),
ORDERBY_SORTBY_CONFLICT("Cannot have both ORDER BY and SORT BY clauses"),
CLUSTERBY_ORDERBY_CONFLICT("Cannot have both CLUSTER BY and ORDER BY clauses"),
NO_LIMIT_WITH_ORDERBY("In strict mode, if ORDER BY is specified, LIMIT must also be specified"),
NO_CARTESIAN_PRODUCT("In strict mode, cartesian product is not allowed. "
+ "If you really want to perform the operation, set hive.mapred.mode=nonstrict"),
UNION_NOTIN_SUBQ("Top level UNION is not supported currently; use a subquery for the UNION"),
INVALID_INPUT_FORMAT_TYPE("Input format must implement InputFormat"),
INVALID_OUTPUT_FORMAT_TYPE("Output Format must implement HiveOutputFormat, "
+ "otherwise it should be either IgnoreKeyTextOutputFormat or SequenceFileOutputFormat"),
NO_VALID_PARTN("The query does not reference any valid partition. "
+ "To run this query, set hive.mapred.mode=nonstrict"),
NO_OUTER_MAPJOIN("MAPJOIN cannot be performed with OUTER JOIN"),
INVALID_MAPJOIN_HINT("Neither table specified as map-table"),
INVALID_MAPJOIN_TABLE("Result of a union cannot be a map table"),
NON_BUCKETED_TABLE("Sampling expression needed for non-bucketed table"),
BUCKETED_NUMBERATOR_BIGGER_DENOMINATOR("Numberator should not be bigger than "
+ "denaminator in sample clause for table"),
NEED_PARTITION_ERROR("Need to specify partition columns because the destination "
+ "table is partitioned"),
CTAS_CTLT_COEXISTENCE("Create table command does not allow LIKE and AS-SELECT in "
+ "the same command"),
LINES_TERMINATED_BY_NON_NEWLINE("LINES TERMINATED BY only supports newline '\\n' right now"),
CTAS_COLLST_COEXISTENCE("CREATE TABLE AS SELECT command cannot specify the list of columns "
+ "for the target table"),
CTLT_COLLST_COEXISTENCE("CREATE TABLE LIKE command cannot specify the list of columns for "
+ "the target table"),
INVALID_SELECT_SCHEMA("Cannot derive schema from the select-clause"),
CTAS_PARCOL_COEXISTENCE("CREATE-TABLE-AS-SELECT does not support partitioning in the target "
+ "table"),
CTAS_MULTI_LOADFILE("CREATE-TABLE-AS-SELECT results in multiple file load"),
CTAS_EXTTBL_COEXISTENCE("CREATE-TABLE-AS-SELECT cannot create external table"),
INSERT_EXTERNAL_TABLE("Inserting into a external table is not allowed"),
DATABASE_NOT_EXISTS("Database does not exist:"),
TABLE_ALREADY_EXISTS("Table already exists:", "42S02"),
COLUMN_ALIAS_ALREADY_EXISTS("Column alias already exists:", "42S02"),
UDTF_MULTIPLE_EXPR("Only a single expression in the SELECT clause is supported with UDTF's"),
UDTF_REQUIRE_AS("UDTF's require an AS clause"),
UDTF_NO_GROUP_BY("GROUP BY is not supported with a UDTF in the SELECT clause"),
UDTF_NO_SORT_BY("SORT BY is not supported with a UDTF in the SELECT clause"),
UDTF_NO_CLUSTER_BY("CLUSTER BY is not supported with a UDTF in the SELECT clause"),
UDTF_NO_DISTRIBUTE_BY("DISTRUBTE BY is not supported with a UDTF in the SELECT clause"),
UDTF_INVALID_LOCATION("UDTF's are not supported outside the SELECT clause, nor nested "
+ "in expressions"),
UDTF_LATERAL_VIEW("UDTF's cannot be in a select expression when there is a lateral view"),
UDTF_ALIAS_MISMATCH("The number of aliases supplied in the AS clause does not match the "
+ "number of columns output by the UDTF"),
UDF_STATEFUL_INVALID_LOCATION("Stateful UDF's can only be invoked in the SELECT list"),
LATERAL_VIEW_WITH_JOIN("JOIN with a LATERAL VIEW is not supported"),
LATERAL_VIEW_INVALID_CHILD("LATERAL VIEW AST with invalid child"),
OUTPUT_SPECIFIED_MULTIPLE_TIMES("The same output cannot be present multiple times: "),
INVALID_AS("AS clause has an invalid number of aliases"),
VIEW_COL_MISMATCH("The number of columns produced by the SELECT clause does not match the "
+ "number of column names specified by CREATE VIEW"),
DML_AGAINST_VIEW("A view cannot be used as target table for LOAD or INSERT"),
ANALYZE_VIEW("ANALYZE is not supported for views"),
VIEW_PARTITION_TOTAL("At least one non-partitioning column must be present in view"),
VIEW_PARTITION_MISMATCH("Rightmost columns in view output do not match PARTITIONED ON clause"),
PARTITION_DYN_STA_ORDER("Dynamic partition cannot be the parent of a static partition"),
DYNAMIC_PARTITION_DISABLED("Dynamic partition is disabled. Either enable it by setting "
+ "hive.exec.dynamic.partition=true or specify partition column values"),
DYNAMIC_PARTITION_STRICT_MODE("Dynamic partition strict mode requires at least one "
+ "static partition column. To turn this off set hive.exec.dynamic.partition.mode=nonstrict"),
DYNAMIC_PARTITION_MERGE("Dynamic partition does not support merging using non-CombineHiveInputFormat"
+ "Please check your hive.input.format setting and make sure your Hadoop version support "
+ "CombineFileInputFormat"),
NONEXISTPARTCOL("Non-Partition column appears in the partition specification: "),
UNSUPPORTED_TYPE("DATETIME type isn't supported yet. Please use "
+ "TIMESTAMP instead"),
CREATE_NON_NATIVE_AS("CREATE TABLE AS SELECT cannot be used for a non-native table"),
LOAD_INTO_NON_NATIVE("A non-native table cannot be used as target for LOAD"),
LOCKMGR_NOT_SPECIFIED("Lock manager not specified correctly, set hive.lock.manager"),
LOCKMGR_NOT_INITIALIZED("Lock manager could not be initialized, check hive.lock.manager "),
LOCK_CANNOT_BE_ACQUIRED("Locks on the underlying objects cannot be acquired. retry after some time"),
ZOOKEEPER_CLIENT_COULD_NOT_BE_INITIALIZED("Check hive.zookeeper.quorum and hive.zookeeper.client.port"),
OVERWRITE_ARCHIVED_PART("Cannot overwrite an archived partition. " +
"Unarchive before running this command"),
ARCHIVE_METHODS_DISABLED("Archiving methods are currently disabled. " +
"Please see the Hive wiki for more information about enabling archiving"),
ARCHIVE_ON_MULI_PARTS("ARCHIVE can only be run on a single partition"),
UNARCHIVE_ON_MULI_PARTS("ARCHIVE can only be run on a single partition"),
ARCHIVE_ON_TABLE("ARCHIVE can only be run on partitions"),
RESERVED_PART_VAL("Partition value contains a reserved substring"),
HOLD_DDLTIME_ON_NONEXIST_PARTITIONS("HOLD_DDLTIME hint cannot be applied to dynamic " +
"partitions or non-existent partitions"),
OFFLINE_TABLE_OR_PARTITION("Query against an offline table or partition"),
OUTERJOIN_USES_FILTERS("The query results could be wrong. " +
"Turn on hive.outerjoin.supports.filters"),
NEED_PARTITION_SPECIFICATION("Table is partitioned and partition specification is needed"),
INVALID_METADATA("The metadata file could not be parsed "),
NEED_TABLE_SPECIFICATION("Table name could be determined; It should be specified "),
PARTITION_EXISTS("Partition already exists"),
TABLE_DATA_EXISTS("Table exists and contains data files"),
INCOMPATIBLE_SCHEMA("The existing table is not compatible with the import spec. "),
EXIM_FOR_NON_NATIVE("Export/Import cannot be done for a non-native table. "),
INSERT_INTO_BUCKETIZED_TABLE("Bucketized tables do not support INSERT INTO:"),
NO_COMPARE_BIGINT_STRING("In strict mode, comparing bigints and strings is not allowed, "
+ "it may result in a loss of precision. "
+ "If you really want to perform the operation, set hive.mapred.mode=nonstrict"),
NO_COMPARE_BIGINT_DOUBLE("In strict mode, comparing bigints and doubles is not allowed, "
+ "it may result in a loss of precision. "
+ "If you really want to perform the operation, set hive.mapred.mode=nonstrict"),
PARTSPEC_DIFFER_FROM_SCHEMA("Partition columns in partition specification are not the same as "
+ "that defined in the table schema. The names and orders have to be exactly the same."),
PARTITION_COLUMN_NON_PRIMITIVE("Partition column must be of primitive type."),
INSERT_INTO_DYNAMICPARTITION_IFNOTEXISTS(
"Dynamic partitions do not support IF NOT EXISTS. Specified partitions with value :"),
DROP_PARTITION_NON_STRING_PARTCOLS_NONEQUALITY("Drop partitions for a non string partition "
+ "columns is not allowed using non-equality")
;
private String mesg;
private String sqlState;
private static final char SPACE = ' ';
private static final Pattern ERROR_MESSAGE_PATTERN = Pattern.compile(".*line [0-9]+:[0-9]+ (.*)");
private static Map<String, ErrorMsg> mesgToErrorMsgMap = new HashMap<String, ErrorMsg>();
private static int minMesgLength = -1;
static {
for (ErrorMsg errorMsg : values()) {
mesgToErrorMsgMap.put(errorMsg.getMsg().trim(), errorMsg);
int length = errorMsg.getMsg().trim().length();
if (minMesgLength == -1 || length < minMesgLength) {
minMesgLength = length;
}
}
}
/**
* For a given error message string, searches for a <code>ErrorMsg</code> enum
* that appears to be a match. If an match is found, returns the
* <code>SQLState</code> associated with the <code>ErrorMsg</code>. If a match
* is not found or <code>ErrorMsg</code> has no <code>SQLState</code>, returns
* the <code>SQLState</code> bound to the <code>GENERIC_ERROR</code>
* <code>ErrorMsg</code>.
*
* @param mesg
* An error message string
* @return SQLState
*/
public static String findSQLState(String mesg) {
if (mesg == null) {
return GENERIC_ERROR.getSQLState();
}
// first see if there is a direct match
ErrorMsg errorMsg = mesgToErrorMsgMap.get(mesg);
if (errorMsg != null) {
if (errorMsg.getSQLState() != null) {
return errorMsg.getSQLState();
} else {
return GENERIC_ERROR.getSQLState();
}
}
// if not see if the mesg follows type of format, which is typically the
// case:
// line 1:14 Table not found table_name
String truncatedMesg = mesg.trim();
Matcher match = ERROR_MESSAGE_PATTERN.matcher(mesg);
if (match.matches()) {
truncatedMesg = match.group(1);
}
// appends might exist after the root message, so strip tokens off until we
// match
while (truncatedMesg.length() > minMesgLength) {
errorMsg = mesgToErrorMsgMap.get(truncatedMesg.trim());
if (errorMsg != null) {
if (errorMsg.getSQLState() != null) {
return errorMsg.getSQLState();
} else {
return GENERIC_ERROR.getSQLState();
}
}
int lastSpace = truncatedMesg.lastIndexOf(SPACE);
if (lastSpace == -1) {
break;
}
// hack off the last word and try again
truncatedMesg = truncatedMesg.substring(0, lastSpace).trim();
}
return GENERIC_ERROR.getSQLState();
}
ErrorMsg(String mesg) {
// 42000 is the generic SQLState for syntax error.
this(mesg, "42000");
}
ErrorMsg(String mesg, String sqlState) {
this.mesg = mesg;
this.sqlState = sqlState;
}
private static int getLine(ASTNode tree) {
if (tree.getChildCount() == 0) {
return tree.getToken().getLine();
}
return getLine((ASTNode) tree.getChild(0));
}
private static int getCharPositionInLine(ASTNode tree) {
if (tree.getChildCount() == 0) {
return tree.getToken().getCharPositionInLine();
}
return getCharPositionInLine((ASTNode) tree.getChild(0));
}
// Dirty hack as this will throw away spaces and other things - find a better
// way!
public static String getText(ASTNode tree) {
if (tree.getChildCount() == 0) {
return tree.getText();
}
return getText((ASTNode) tree.getChild(tree.getChildCount() - 1));
}
public String getMsg(ASTNode tree) {
StringBuilder sb = new StringBuilder();
renderPosition(sb, tree);
sb.append(" ");
sb.append(mesg);
sb.append(" '");
sb.append(getText(tree));
sb.append("'");
renderOrigin(sb, tree.getOrigin());
return sb.toString();
}
public static void renderOrigin(StringBuilder sb, ASTNodeOrigin origin) {
while (origin != null) {
sb.append(" in definition of ");
sb.append(origin.getObjectType());
sb.append(" ");
sb.append(origin.getObjectName());
sb.append(" [");
sb.append(HiveUtils.LINE_SEP);
sb.append(origin.getObjectDefinition());
sb.append(HiveUtils.LINE_SEP);
sb.append("] used as ");
sb.append(origin.getUsageAlias());
sb.append(" at ");
ASTNode usageNode = origin.getUsageNode();
renderPosition(sb, usageNode);
origin = usageNode.getOrigin();
}
}
private static void renderPosition(StringBuilder sb, ASTNode tree) {
sb.append("Line ");
sb.append(getLine(tree));
sb.append(":");
sb.append(getCharPositionInLine(tree));
}
public String getMsg(Tree tree) {
return getMsg((ASTNode) tree);
}
public String getMsg(ASTNode tree, String reason) {
return getMsg(tree) + ": " + reason;
}
public String getMsg(Tree tree, String reason) {
return getMsg((ASTNode) tree, reason);
}
public String getMsg(String reason) {
return mesg + " " + reason;
}
public String getMsg() {
return mesg;
}
public String getSQLState() {
return sqlState;
}
}