細かすぎて伝わらないHiveのTips

なんかドキュメントには書いてないっぽいんだけど地味に気づいたことを書いときます。
Tipsというほどではないメモですね。2つあります。

1つめ

HiveQLのコメントは--です。

例:

--hoge
SELECT * FROM aaa

ANTLRの文法を定義したファイルであるHive.gは下記のようになってますね。

COMMENT
  : '--' (~('\n'|'\r'))*
    { $channel=HIDDEN; }
  ;

2つめ

UDFの使用例を見たい時はextendedをつける

例えば

hive> desc function instr;
OK
instr(str, substr) - Returns the index of the first occurance of substr in str

なら

hive> desc function extended instr;
OK
instr(str, substr) - Returns the index of the first occurance of substr in str
Example:
  > SELECT instr('Facebook', 'boo') FROM src LIMIT 1;
  5

ただこれはソースのDescriptionアノテーションのextendedに記述がある場合のみです。

instrのソースの該当部分はこんな感じ。どうでもいいですけどMySQL由来のようですね。

/**
 * Generic UDF for string function <code>INSTR(str,substr)</code>. This mimcs
 * the function from MySQL
 * http://dev.mysql.com/doc/refman/5.1/en/string-functions.html#function_instr
 * 
 * <pre>
 * usage:
 * INSTR(str, substr)
 * </pre>
 * <p>
 */
@Description(name = "instr",
    value = "_FUNC_(str, substr) - Returns the index of the first occurance of substr in str",
    extended = "Example:\n"
    + "  > SELECT _FUNC_('Facebook', 'boo') FROM src LIMIT 1;\n" + "  5")
public class GenericUDFInstr extends GenericUDF {

なのでこれがないisnullとかはdesc functionの結果もdesc function extendedの結果も変わりません。

このアノテーションを解釈して表示する部分の該当ソースはDDLTask#describeFunctionです。

  /**
   * Shows a description of a function.
   *
   * @param descFunc
   *          is the function we are describing
   * @throws HiveException
   */
  private int describeFunction(DescFunctionDesc descFunc) throws HiveException {
    String funcName = descFunc.getName();

    // write the results in the file
    try {
      Path resFile = new Path(descFunc.getResFile());
      FileSystem fs = resFile.getFileSystem(conf);
      DataOutput outStream = fs.create(resFile);

      // get the function documentation
      Description desc = null;
      Class<?> funcClass = null;
      FunctionInfo functionInfo = FunctionRegistry.getFunctionInfo(funcName);
      if (functionInfo != null) {
        funcClass = functionInfo.getFunctionClass();
      }
      if (funcClass != null) {
        desc = funcClass.getAnnotation(Description.class);
      }
      if (desc != null) {
        outStream.writeBytes(desc.value().replace("_FUNC_", funcName));
        if (descFunc.isExtended()) {
          Set<String> synonyms = FunctionRegistry.getFunctionSynonyms(funcName);
          if (synonyms.size() > 0) {
            outStream.writeBytes("\nSynonyms: " + join(synonyms, ", "));
          }
          if (desc.extended().length() > 0) {
            outStream.writeBytes("\n"
                + desc.extended().replace("_FUNC_", funcName));
          }
        }
      } else {
        if (funcClass != null) {
          outStream.writeBytes("There is no documentation for function '"
              + funcName + "'");
        } else {
          outStream.writeBytes("Function '" + funcName + "' does not exist.");
        }
      }

      outStream.write(terminator);

      ((FSDataOutputStream) outStream).close();
    } catch (FileNotFoundException e) {
      LOG.warn("describe function: " + stringifyException(e));
      return 1;
    } catch (IOException e) {
      LOG.warn("describe function: " + stringifyException(e));
      return 1;
    } catch (Exception e) {
      throw new HiveException(e.toString());
    }
    return 0;
  }