PageRenderTime 56ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/release-0.0.0-rc0/hive/external/ql/src/java/org/apache/hadoop/hive/ql/parse/BaseSemanticAnalyzer.java

#
Java | 743 lines | 582 code | 69 blank | 92 comment | 107 complexity | b52b2ee9a7f6bdb2cbd3c0b358ddc6e9 MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause, JSON, CPL-1.0
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. package org.apache.hadoop.hive.ql.parse;
  19. import java.io.Serializable;
  20. import java.io.UnsupportedEncodingException;
  21. import java.util.ArrayList;
  22. import java.util.HashMap;
  23. import java.util.HashSet;
  24. import java.util.LinkedHashMap;
  25. import java.util.LinkedHashSet;
  26. import java.util.List;
  27. import java.util.Map;
  28. import org.antlr.runtime.tree.CommonTree;
  29. import org.antlr.runtime.tree.Tree;
  30. import org.apache.commons.logging.Log;
  31. import org.apache.commons.logging.LogFactory;
  32. import org.apache.hadoop.hive.conf.HiveConf;
  33. import org.apache.hadoop.hive.metastore.api.FieldSchema;
  34. import org.apache.hadoop.hive.metastore.api.Order;
  35. import org.apache.hadoop.hive.ql.Context;
  36. import org.apache.hadoop.hive.ql.exec.FetchTask;
  37. import org.apache.hadoop.hive.ql.exec.Task;
  38. import org.apache.hadoop.hive.ql.exec.Utilities;
  39. import org.apache.hadoop.hive.ql.hooks.LineageInfo;
  40. import org.apache.hadoop.hive.ql.hooks.ReadEntity;
  41. import org.apache.hadoop.hive.ql.hooks.WriteEntity;
  42. import org.apache.hadoop.hive.ql.io.IgnoreKeyTextOutputFormat;
  43. import org.apache.hadoop.hive.ql.io.RCFileInputFormat;
  44. import org.apache.hadoop.hive.ql.io.RCFileOutputFormat;
  45. import org.apache.hadoop.hive.ql.metadata.Hive;
  46. import org.apache.hadoop.hive.ql.metadata.HiveException;
  47. import org.apache.hadoop.hive.ql.metadata.InvalidTableException;
  48. import org.apache.hadoop.hive.ql.metadata.Partition;
  49. import org.apache.hadoop.hive.ql.metadata.Table;
  50. import org.apache.hadoop.hive.ql.session.SessionState.LogHelper;
  51. import org.apache.hadoop.hive.serde.Constants;
  52. import org.apache.hadoop.hive.serde2.columnar.ColumnarSerDe;
  53. import org.apache.hadoop.mapred.SequenceFileInputFormat;
  54. import org.apache.hadoop.mapred.SequenceFileOutputFormat;
  55. import org.apache.hadoop.mapred.TextInputFormat;
  56. /**
  57. * BaseSemanticAnalyzer.
  58. *
  59. */
  60. public abstract class BaseSemanticAnalyzer {
  61. protected final Hive db;
  62. protected final HiveConf conf;
  63. protected List<Task<? extends Serializable>> rootTasks;
  64. protected FetchTask fetchTask;
  65. protected final Log LOG;
  66. protected final LogHelper console;
  67. protected Context ctx;
  68. protected HashMap<String, String> idToTableNameMap;
  69. public static int HIVE_COLUMN_ORDER_ASC = 1;
  70. public static int HIVE_COLUMN_ORDER_DESC = 0;
  71. /**
  72. * ReadEntitites that are passed to the hooks.
  73. */
  74. protected HashSet<ReadEntity> inputs;
  75. /**
  76. * List of WriteEntities that are passed to the hooks.
  77. */
  78. protected HashSet<WriteEntity> outputs;
  79. /**
  80. * Lineage information for the query.
  81. */
  82. protected LineageInfo linfo;
  83. protected static final String TEXTFILE_INPUT = TextInputFormat.class
  84. .getName();
  85. protected static final String TEXTFILE_OUTPUT = IgnoreKeyTextOutputFormat.class
  86. .getName();
  87. protected static final String SEQUENCEFILE_INPUT = SequenceFileInputFormat.class
  88. .getName();
  89. protected static final String SEQUENCEFILE_OUTPUT = SequenceFileOutputFormat.class
  90. .getName();
  91. protected static final String RCFILE_INPUT = RCFileInputFormat.class
  92. .getName();
  93. protected static final String RCFILE_OUTPUT = RCFileOutputFormat.class
  94. .getName();
  95. protected static final String COLUMNAR_SERDE = ColumnarSerDe.class.getName();
  96. class RowFormatParams {
  97. String fieldDelim = null;
  98. String fieldEscape = null;
  99. String collItemDelim = null;
  100. String mapKeyDelim = null;
  101. String lineDelim = null;
  102. protected void analyzeRowFormat(AnalyzeCreateCommonVars shared, ASTNode child) throws SemanticException {
  103. child = (ASTNode) child.getChild(0);
  104. int numChildRowFormat = child.getChildCount();
  105. for (int numC = 0; numC < numChildRowFormat; numC++) {
  106. ASTNode rowChild = (ASTNode) child.getChild(numC);
  107. switch (rowChild.getToken().getType()) {
  108. case HiveParser.TOK_TABLEROWFORMATFIELD:
  109. fieldDelim = unescapeSQLString(rowChild.getChild(0)
  110. .getText());
  111. if (rowChild.getChildCount() >= 2) {
  112. fieldEscape = unescapeSQLString(rowChild
  113. .getChild(1).getText());
  114. }
  115. break;
  116. case HiveParser.TOK_TABLEROWFORMATCOLLITEMS:
  117. collItemDelim = unescapeSQLString(rowChild
  118. .getChild(0).getText());
  119. break;
  120. case HiveParser.TOK_TABLEROWFORMATMAPKEYS:
  121. mapKeyDelim = unescapeSQLString(rowChild.getChild(0)
  122. .getText());
  123. break;
  124. case HiveParser.TOK_TABLEROWFORMATLINES:
  125. lineDelim = unescapeSQLString(rowChild.getChild(0)
  126. .getText());
  127. if (!lineDelim.equals("\n")
  128. && !lineDelim.equals("10")) {
  129. throw new SemanticException(
  130. ErrorMsg.LINES_TERMINATED_BY_NON_NEWLINE.getMsg());
  131. }
  132. break;
  133. default:
  134. assert false;
  135. }
  136. }
  137. }
  138. }
  139. class AnalyzeCreateCommonVars {
  140. String serde = null;
  141. Map<String, String> serdeProps = new HashMap<String, String>();
  142. }
  143. class StorageFormat {
  144. String inputFormat = null;
  145. String outputFormat = null;
  146. String storageHandler = null;
  147. protected boolean fillStorageFormat(ASTNode child, AnalyzeCreateCommonVars shared) {
  148. boolean storageFormat = false;
  149. switch(child.getToken().getType()) {
  150. case HiveParser.TOK_TBLSEQUENCEFILE:
  151. inputFormat = SEQUENCEFILE_INPUT;
  152. outputFormat = SEQUENCEFILE_OUTPUT;
  153. storageFormat = true;
  154. break;
  155. case HiveParser.TOK_TBLTEXTFILE:
  156. inputFormat = TEXTFILE_INPUT;
  157. outputFormat = TEXTFILE_OUTPUT;
  158. storageFormat = true;
  159. break;
  160. case HiveParser.TOK_TBLRCFILE:
  161. inputFormat = RCFILE_INPUT;
  162. outputFormat = RCFILE_OUTPUT;
  163. shared.serde = COLUMNAR_SERDE;
  164. storageFormat = true;
  165. break;
  166. case HiveParser.TOK_TABLEFILEFORMAT:
  167. inputFormat = unescapeSQLString(child.getChild(0).getText());
  168. outputFormat = unescapeSQLString(child.getChild(1).getText());
  169. storageFormat = true;
  170. break;
  171. case HiveParser.TOK_STORAGEHANDLER:
  172. storageHandler = unescapeSQLString(child.getChild(0).getText());
  173. if (child.getChildCount() == 2) {
  174. readProps(
  175. (ASTNode) (child.getChild(1).getChild(0)),
  176. shared.serdeProps);
  177. }
  178. storageFormat = true;
  179. break;
  180. }
  181. return storageFormat;
  182. }
  183. protected void fillDefaultStorageFormat(AnalyzeCreateCommonVars shared) {
  184. if ((inputFormat == null) && (storageHandler == null)) {
  185. if ("SequenceFile".equalsIgnoreCase(conf.getVar(HiveConf.ConfVars.HIVEDEFAULTFILEFORMAT))) {
  186. inputFormat = SEQUENCEFILE_INPUT;
  187. outputFormat = SEQUENCEFILE_OUTPUT;
  188. } else if ("RCFile".equalsIgnoreCase(conf.getVar(HiveConf.ConfVars.HIVEDEFAULTFILEFORMAT))) {
  189. inputFormat = RCFILE_INPUT;
  190. outputFormat = RCFILE_OUTPUT;
  191. shared.serde = COLUMNAR_SERDE;
  192. } else {
  193. inputFormat = TEXTFILE_INPUT;
  194. outputFormat = TEXTFILE_OUTPUT;
  195. }
  196. }
  197. }
  198. }
  199. public BaseSemanticAnalyzer(HiveConf conf) throws SemanticException {
  200. try {
  201. this.conf = conf;
  202. db = Hive.get(conf);
  203. rootTasks = new ArrayList<Task<? extends Serializable>>();
  204. LOG = LogFactory.getLog(this.getClass().getName());
  205. console = new LogHelper(LOG);
  206. idToTableNameMap = new HashMap<String, String>();
  207. inputs = new LinkedHashSet<ReadEntity>();
  208. outputs = new LinkedHashSet<WriteEntity>();
  209. } catch (Exception e) {
  210. throw new SemanticException(e);
  211. }
  212. }
  213. public HashMap<String, String> getIdToTableNameMap() {
  214. return idToTableNameMap;
  215. }
  216. public abstract void analyzeInternal(ASTNode ast) throws SemanticException;
  217. public void analyze(ASTNode ast, Context ctx) throws SemanticException {
  218. this.ctx = ctx;
  219. analyzeInternal(ast);
  220. }
  221. public void validate() throws SemanticException {
  222. // Implementations may choose to override this
  223. }
  224. public List<Task<? extends Serializable>> getRootTasks() {
  225. return rootTasks;
  226. }
  227. /**
  228. * @return the fetchTask
  229. */
  230. public FetchTask getFetchTask() {
  231. return fetchTask;
  232. }
  233. /**
  234. * @param fetchTask
  235. * the fetchTask to set
  236. */
  237. public void setFetchTask(FetchTask fetchTask) {
  238. this.fetchTask = fetchTask;
  239. }
  240. protected void reset() {
  241. rootTasks = new ArrayList<Task<? extends Serializable>>();
  242. }
  243. public static String stripQuotes(String val) throws SemanticException {
  244. if ((val.charAt(0) == '\'' && val.charAt(val.length() - 1) == '\'')
  245. || (val.charAt(0) == '\"' && val.charAt(val.length() - 1) == '\"')) {
  246. val = val.substring(1, val.length() - 1);
  247. }
  248. return val;
  249. }
  250. public static String charSetString(String charSetName, String charSetString)
  251. throws SemanticException {
  252. try {
  253. // The character set name starts with a _, so strip that
  254. charSetName = charSetName.substring(1);
  255. if (charSetString.charAt(0) == '\'') {
  256. return new String(unescapeSQLString(charSetString).getBytes(),
  257. charSetName);
  258. } else // hex input is also supported
  259. {
  260. assert charSetString.charAt(0) == '0';
  261. assert charSetString.charAt(1) == 'x';
  262. charSetString = charSetString.substring(2);
  263. byte[] bArray = new byte[charSetString.length() / 2];
  264. int j = 0;
  265. for (int i = 0; i < charSetString.length(); i += 2) {
  266. int val = Character.digit(charSetString.charAt(i), 16) * 16
  267. + Character.digit(charSetString.charAt(i + 1), 16);
  268. if (val > 127) {
  269. val = val - 256;
  270. }
  271. bArray[j++] = new Integer(val).byteValue();
  272. }
  273. String res = new String(bArray, charSetName);
  274. return res;
  275. }
  276. } catch (UnsupportedEncodingException e) {
  277. throw new SemanticException(e);
  278. }
  279. }
  280. /**
  281. * @param Get the name from a table node
  282. * @return if DB name is give, db.tab is returned. Otherwise, tab.
  283. */
  284. public static String getUnescapedName(ASTNode tableNameNode) {
  285. if (tableNameNode.getToken().getType() == HiveParser.TOK_TABNAME) {
  286. if (tableNameNode.getChildCount() == 2) {
  287. String dbName = unescapeIdentifier(tableNameNode.getChild(0).getText());
  288. String tableName = unescapeIdentifier(tableNameNode.getChild(1).getText());
  289. return dbName + "." + tableName;
  290. } else {
  291. return unescapeIdentifier(tableNameNode.getChild(0).getText());
  292. }
  293. }
  294. return unescapeIdentifier(tableNameNode.getText());
  295. }
  296. /**
  297. * Remove the encapsulating "`" pair from the identifier. We allow users to
  298. * use "`" to escape identifier for table names, column names and aliases, in
  299. * case that coincide with Hive language keywords.
  300. */
  301. public static String unescapeIdentifier(String val) {
  302. if (val == null) {
  303. return null;
  304. }
  305. if (val.charAt(0) == '`' && val.charAt(val.length() - 1) == '`') {
  306. val = val.substring(1, val.length() - 1);
  307. }
  308. return val;
  309. }
  310. /**
  311. * Converts parsed key/value properties pairs into a map.
  312. *
  313. * @param prop ASTNode parent of the key/value pairs
  314. *
  315. * @param mapProp property map which receives the mappings
  316. */
  317. public static void readProps(
  318. ASTNode prop, Map<String, String> mapProp) {
  319. for (int propChild = 0; propChild < prop.getChildCount(); propChild++) {
  320. String key = unescapeSQLString(prop.getChild(propChild).getChild(0)
  321. .getText());
  322. String value = unescapeSQLString(prop.getChild(propChild).getChild(1)
  323. .getText());
  324. mapProp.put(key, value);
  325. }
  326. }
  327. @SuppressWarnings("nls")
  328. public static String unescapeSQLString(String b) {
  329. Character enclosure = null;
  330. // Some of the strings can be passed in as unicode. For example, the
  331. // delimiter can be passed in as \002 - So, we first check if the
  332. // string is a unicode number, else go back to the old behavior
  333. StringBuilder sb = new StringBuilder(b.length());
  334. for (int i = 0; i < b.length(); i++) {
  335. char currentChar = b.charAt(i);
  336. if (enclosure == null) {
  337. if (currentChar == '\'' || b.charAt(i) == '\"') {
  338. enclosure = currentChar;
  339. }
  340. // ignore all other chars outside the enclosure
  341. continue;
  342. }
  343. if (enclosure.equals(currentChar)) {
  344. enclosure = null;
  345. continue;
  346. }
  347. if (currentChar == '\\' && (i + 4 < b.length())) {
  348. char i1 = b.charAt(i + 1);
  349. char i2 = b.charAt(i + 2);
  350. char i3 = b.charAt(i + 3);
  351. if ((i1 >= '0' && i1 <= '1') && (i2 >= '0' && i2 <= '7')
  352. && (i3 >= '0' && i3 <= '7')) {
  353. byte bVal = (byte) ((i3 - '0') + ((i2 - '0') * 8) + ((i1 - '0') * 8 * 8));
  354. byte[] bValArr = new byte[1];
  355. bValArr[0] = bVal;
  356. String tmp = new String(bValArr);
  357. sb.append(tmp);
  358. i += 3;
  359. continue;
  360. }
  361. }
  362. if (currentChar == '\\' && (i + 2 < b.length())) {
  363. char n = b.charAt(i + 1);
  364. switch (n) {
  365. case '0':
  366. sb.append("\0");
  367. break;
  368. case '\'':
  369. sb.append("'");
  370. break;
  371. case '"':
  372. sb.append("\"");
  373. break;
  374. case 'b':
  375. sb.append("\b");
  376. break;
  377. case 'n':
  378. sb.append("\n");
  379. break;
  380. case 'r':
  381. sb.append("\r");
  382. break;
  383. case 't':
  384. sb.append("\t");
  385. break;
  386. case 'Z':
  387. sb.append("\u001A");
  388. break;
  389. case '\\':
  390. sb.append("\\");
  391. break;
  392. // The following 2 lines are exactly what MySQL does
  393. case '%':
  394. sb.append("\\%");
  395. break;
  396. case '_':
  397. sb.append("\\_");
  398. break;
  399. default:
  400. sb.append(n);
  401. }
  402. i++;
  403. } else {
  404. sb.append(currentChar);
  405. }
  406. }
  407. return sb.toString();
  408. }
  409. public HashSet<ReadEntity> getInputs() {
  410. return inputs;
  411. }
  412. public HashSet<WriteEntity> getOutputs() {
  413. return outputs;
  414. }
  415. /**
  416. * @return the schema for the fields which will be produced
  417. * when the statement is executed, or null if not known
  418. */
  419. public List<FieldSchema> getResultSchema() {
  420. return null;
  421. }
  422. protected List<FieldSchema> getColumns(ASTNode ast) throws SemanticException {
  423. return getColumns(ast, true);
  424. }
  425. protected void handleGenericFileFormat(ASTNode node) throws SemanticException{
  426. ASTNode child = (ASTNode)node.getChild(0);
  427. throw new SemanticException("Unrecognized file format in STORED AS clause:"+
  428. " "+ (child == null ? "" : child.getText()));
  429. }
  430. /**
  431. * Get the list of FieldSchema out of the ASTNode.
  432. */
  433. public static List<FieldSchema> getColumns(ASTNode ast, boolean lowerCase) throws SemanticException {
  434. List<FieldSchema> colList = new ArrayList<FieldSchema>();
  435. int numCh = ast.getChildCount();
  436. for (int i = 0; i < numCh; i++) {
  437. FieldSchema col = new FieldSchema();
  438. ASTNode child = (ASTNode) ast.getChild(i);
  439. String name = child.getChild(0).getText();
  440. if(lowerCase) {
  441. name = name.toLowerCase();
  442. }
  443. // child 0 is the name of the column
  444. col.setName(unescapeIdentifier(name));
  445. // child 1 is the type of the column
  446. ASTNode typeChild = (ASTNode) (child.getChild(1));
  447. col.setType(getTypeStringFromAST(typeChild));
  448. // child 2 is the optional comment of the column
  449. if (child.getChildCount() == 3) {
  450. col.setComment(unescapeSQLString(child.getChild(2).getText()));
  451. }
  452. colList.add(col);
  453. }
  454. return colList;
  455. }
  456. protected List<String> getColumnNames(ASTNode ast) {
  457. List<String> colList = new ArrayList<String>();
  458. int numCh = ast.getChildCount();
  459. for (int i = 0; i < numCh; i++) {
  460. ASTNode child = (ASTNode) ast.getChild(i);
  461. colList.add(unescapeIdentifier(child.getText()).toLowerCase());
  462. }
  463. return colList;
  464. }
  465. protected List<Order> getColumnNamesOrder(ASTNode ast) {
  466. List<Order> colList = new ArrayList<Order>();
  467. int numCh = ast.getChildCount();
  468. for (int i = 0; i < numCh; i++) {
  469. ASTNode child = (ASTNode) ast.getChild(i);
  470. if (child.getToken().getType() == HiveParser.TOK_TABSORTCOLNAMEASC) {
  471. colList.add(new Order(unescapeIdentifier(child.getChild(0).getText()).toLowerCase(),
  472. HIVE_COLUMN_ORDER_ASC));
  473. } else {
  474. colList.add(new Order(unescapeIdentifier(child.getChild(0).getText()).toLowerCase(),
  475. HIVE_COLUMN_ORDER_DESC));
  476. }
  477. }
  478. return colList;
  479. }
  480. protected static String getTypeStringFromAST(ASTNode typeNode)
  481. throws SemanticException {
  482. switch (typeNode.getType()) {
  483. case HiveParser.TOK_LIST:
  484. return Constants.LIST_TYPE_NAME + "<"
  485. + getTypeStringFromAST((ASTNode) typeNode.getChild(0)) + ">";
  486. case HiveParser.TOK_MAP:
  487. return Constants.MAP_TYPE_NAME + "<"
  488. + getTypeStringFromAST((ASTNode) typeNode.getChild(0)) + ","
  489. + getTypeStringFromAST((ASTNode) typeNode.getChild(1)) + ">";
  490. case HiveParser.TOK_STRUCT:
  491. return getStructTypeStringFromAST(typeNode);
  492. case HiveParser.TOK_UNIONTYPE:
  493. return getUnionTypeStringFromAST(typeNode);
  494. default:
  495. return DDLSemanticAnalyzer.getTypeName(typeNode.getType());
  496. }
  497. }
  498. private static String getStructTypeStringFromAST(ASTNode typeNode)
  499. throws SemanticException {
  500. String typeStr = Constants.STRUCT_TYPE_NAME + "<";
  501. typeNode = (ASTNode) typeNode.getChild(0);
  502. int children = typeNode.getChildCount();
  503. if (children <= 0) {
  504. throw new SemanticException("empty struct not allowed.");
  505. }
  506. for (int i = 0; i < children; i++) {
  507. ASTNode child = (ASTNode) typeNode.getChild(i);
  508. typeStr += unescapeIdentifier(child.getChild(0).getText()) + ":";
  509. typeStr += getTypeStringFromAST((ASTNode) child.getChild(1));
  510. if (i < children - 1) {
  511. typeStr += ",";
  512. }
  513. }
  514. typeStr += ">";
  515. return typeStr;
  516. }
  517. private static String getUnionTypeStringFromAST(ASTNode typeNode)
  518. throws SemanticException {
  519. String typeStr = Constants.UNION_TYPE_NAME + "<";
  520. typeNode = (ASTNode) typeNode.getChild(0);
  521. int children = typeNode.getChildCount();
  522. if (children <= 0) {
  523. throw new SemanticException("empty union not allowed.");
  524. }
  525. for (int i = 0; i < children; i++) {
  526. typeStr += getTypeStringFromAST((ASTNode) typeNode.getChild(i));
  527. if (i < children - 1) {
  528. typeStr += ",";
  529. }
  530. }
  531. typeStr += ">";
  532. return typeStr;
  533. }
  534. /**
  535. * tableSpec.
  536. *
  537. */
  538. public static class tableSpec {
  539. public String tableName;
  540. public Table tableHandle;
  541. public Map<String, String> partSpec; // has to use LinkedHashMap to enforce order
  542. public Partition partHandle;
  543. public int numDynParts; // number of dynamic partition columns
  544. public List<Partition> partitions; // involved partitions in TableScanOperator/FileSinkOperator
  545. public static enum SpecType {TABLE_ONLY, STATIC_PARTITION, DYNAMIC_PARTITION};
  546. public SpecType specType;
  547. public tableSpec(Hive db, HiveConf conf, ASTNode ast)
  548. throws SemanticException {
  549. assert (ast.getToken().getType() == HiveParser.TOK_TAB || ast.getToken().getType() == HiveParser.TOK_TABTYPE);
  550. int childIndex = 0;
  551. numDynParts = 0;
  552. try {
  553. // get table metadata
  554. tableName = getUnescapedName((ASTNode)ast.getChild(0));
  555. boolean testMode = conf.getBoolVar(HiveConf.ConfVars.HIVETESTMODE);
  556. if (testMode) {
  557. tableName = conf.getVar(HiveConf.ConfVars.HIVETESTMODEPREFIX)
  558. + tableName;
  559. }
  560. tableHandle = db.getTable(tableName);
  561. } catch (InvalidTableException ite) {
  562. throw new SemanticException(ErrorMsg.INVALID_TABLE.getMsg(ast
  563. .getChild(0)), ite);
  564. } catch (HiveException e) {
  565. throw new SemanticException(ErrorMsg.GENERIC_ERROR.getMsg(ast
  566. .getChild(childIndex), e.getMessage()), e);
  567. }
  568. // get partition metadata if partition specified
  569. if (ast.getChildCount() == 2) {
  570. childIndex = 1;
  571. ASTNode partspec = (ASTNode) ast.getChild(1);
  572. partitions = new ArrayList<Partition>();
  573. // partSpec is a mapping from partition column name to its value.
  574. partSpec = new LinkedHashMap<String, String>(partspec.getChildCount());
  575. for (int i = 0; i < partspec.getChildCount(); ++i) {
  576. ASTNode partspec_val = (ASTNode) partspec.getChild(i);
  577. String val = null;
  578. String colName = unescapeIdentifier(partspec_val.getChild(0).getText().toLowerCase());
  579. if (partspec_val.getChildCount() < 2) { // DP in the form of T partition (ds, hr)
  580. ++numDynParts;
  581. } else { // in the form of T partition (ds="2010-03-03")
  582. val = stripQuotes(partspec_val.getChild(1).getText());
  583. }
  584. partSpec.put(colName, val);
  585. }
  586. // check if the columns specified in the partition() clause are actually partition columns
  587. Utilities.validatePartSpec(tableHandle, partSpec);
  588. // check if the partition spec is valid
  589. if (numDynParts > 0) {
  590. List<FieldSchema> parts = tableHandle.getPartitionKeys();
  591. int numStaPart = parts.size() - numDynParts;
  592. if (numStaPart == 0 &&
  593. conf.getVar(HiveConf.ConfVars.DYNAMICPARTITIONINGMODE).equalsIgnoreCase("strict")) {
  594. throw new SemanticException(ErrorMsg.DYNAMIC_PARTITION_STRICT_MODE.getMsg());
  595. }
  596. for (FieldSchema fs: parts) {
  597. if (partSpec.get(fs.getName().toLowerCase()) == null) {
  598. if (numStaPart > 0) { // found a DP, but there exists ST as subpartition
  599. throw new SemanticException(
  600. ErrorMsg.PARTITION_DYN_STA_ORDER.getMsg(ast.getChild(childIndex)));
  601. }
  602. break;
  603. } else {
  604. --numStaPart;
  605. }
  606. }
  607. partHandle = null;
  608. specType = SpecType.DYNAMIC_PARTITION;
  609. } else {
  610. try {
  611. // this doesn't create partition.
  612. partHandle = db.getPartition(tableHandle, partSpec, false);
  613. if (partHandle == null) {
  614. // if partSpec doesn't exists in DB, return a delegate one
  615. // and the actual partition is created in MoveTask
  616. partHandle = new Partition(tableHandle, partSpec, null);
  617. } else {
  618. partitions.add(partHandle);
  619. }
  620. } catch (HiveException e) {
  621. throw new SemanticException(
  622. ErrorMsg.INVALID_PARTITION.getMsg(ast.getChild(childIndex)));
  623. }
  624. specType = SpecType.STATIC_PARTITION;
  625. }
  626. } else {
  627. specType = SpecType.TABLE_ONLY;
  628. }
  629. }
  630. public Map<String, String> getPartSpec() {
  631. return this.partSpec;
  632. }
  633. public void setPartSpec(Map<String, String> partSpec) {
  634. this.partSpec = partSpec;
  635. }
  636. @Override
  637. public String toString() {
  638. if (partHandle != null) {
  639. return partHandle.toString();
  640. } else {
  641. return tableHandle.toString();
  642. }
  643. }
  644. }
  645. /**
  646. * Gets the lineage information.
  647. *
  648. * @return LineageInfo associated with the query.
  649. */
  650. public LineageInfo getLineageInfo() {
  651. return linfo;
  652. }
  653. /**
  654. * Sets the lineage information.
  655. *
  656. * @param linfo The LineageInfo structure that is set in the optimization phase.
  657. */
  658. public void setLineageInfo(LineageInfo linfo) {
  659. this.linfo = linfo;
  660. }
  661. protected HashMap<String, String> extractPartitionSpecs(Tree partspec)
  662. throws SemanticException {
  663. HashMap<String, String> partSpec = new LinkedHashMap<String, String>();
  664. for (int i = 0; i < partspec.getChildCount(); ++i) {
  665. CommonTree partspec_val = (CommonTree) partspec.getChild(i);
  666. String val = stripQuotes(partspec_val.getChild(1).getText());
  667. partSpec.put(partspec_val.getChild(0).getText().toLowerCase(), val);
  668. }
  669. return partSpec;
  670. }
  671. public Hive getDb() {
  672. return db;
  673. }
  674. }