All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.hive.hplsql.functions.FunctionMisc Maven / Gradle / Ivy

The newest version!
/*
 * 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.hive.hplsql.functions;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import org.apache.hive.hplsql.Conn;
import org.apache.hive.hplsql.Exec;
import org.apache.hive.hplsql.HplsqlParser;
import org.apache.hive.hplsql.Utils;
import org.apache.hive.hplsql.Var;
import org.apache.hive.hplsql.executor.QueryException;
import org.apache.hive.hplsql.executor.QueryExecutor;
import org.apache.hive.hplsql.executor.QueryResult;

public class FunctionMisc extends BuiltinFunctions {
  public FunctionMisc(Exec e, QueryExecutor queryExecutor) {
    super(e, queryExecutor);
  }

  /** 
   * Register functions
   */
  @Override
  public void register(BuiltinFunctions f) {
    f.map.put("COALESCE", this::nvl);
    f.map.put("DECODE", this::decode);
    f.map.put("NVL", this::nvl);
    f.map.put("NVL2", this::nvl2);
    f.map.put("PART_COUNT_BY", this::partCountBy);
    f.map.put("MOD", this::modulo);

    f.specMap.put("ACTIVITY_COUNT", this::activityCount);
    f.specMap.put("CAST", this::cast);
    f.specMap.put("CURRENT", this::current);
    f.specMap.put("CURRENT_USER", this::currentUser);
    f.specMap.put("PART_COUNT", this::partCount);
    f.specMap.put("USER", this::currentUser);

    f.specSqlMap.put("CURRENT", this::currentSql);
  }
  
  /**
   * ACTIVITY_COUNT function (built-in variable)
   */
  void activityCount(HplsqlParser.Expr_spec_funcContext ctx) {
    evalInt(Long.valueOf(exec.getRowCount()));
  }

  /**
   * CAST function
   */
  void cast(HplsqlParser.Expr_spec_funcContext ctx) {
    if (ctx.expr().size() != 1) {
      evalNull();
      return;
    }
    String type = ctx.dtype().getText();
    String len = null;
    String scale = null;
    if (ctx.dtype_len() != null) {
      len = ctx.dtype_len().L_INT(0).getText();
      if (ctx.dtype_len().L_INT(1) != null) {
        scale = ctx.dtype_len().L_INT(1).getText();
      }
    }
    Var var = new Var(null, type, len, scale, null);
    Var value = evalPop(ctx.expr(0));
    if (value.type == Var.Type.STRING) {
      Var newValue = new Var(value.name, value.type, Utils.unquoteString(value.toString()));
      value = newValue;
    }
    if (value.type != Var.Type.NULL) {
      String valueUpper = value.toString().toUpperCase();
      if (valueUpper.startsWith("TIMESTAMP ") || valueUpper.startsWith("DATE ")) {
        boolean old = exec.buildSql;
        exec.buildSql = false;
        value = evalPop(ctx.expr(0));
        exec.buildSql = old;
      }
    }
    var.cast(value);
    if (exec.buildSql && var.type == Var.Type.STRING) {
      evalString(var.toSqlString());
    } else {
      evalVar(var);
    }
  }
  
  /**
   * CURRENT  function
   */
  void current(HplsqlParser.Expr_spec_funcContext ctx) {
    if (ctx.T_DATE() != null) {
      evalVar(FunctionDatetime.currentDate()); 
    }
    else if (ctx.T_TIMESTAMP() != null) {
      int precision = evalPop(ctx.expr(0), 3).intValue();
      evalVar(FunctionDatetime.currentTimestamp(precision)); 
    }
    else if (ctx.T_USER() != null) {
      evalVar(currentUser());
    }
    else {
      evalNull();
    }
  }
  
  /**
   * CURRENT  function in executable SQL statement
   */
  void currentSql(HplsqlParser.Expr_spec_funcContext ctx) {
    if (ctx.T_DATE() != null) {
      if (exec.getConnectionType() == Conn.Type.HIVE) {
        evalSqlString("TO_DATE(FROM_UNIXTIME(UNIX_TIMESTAMP()))");
      } 
      else {
        evalSqlString("CURRENT_DATE");
      }
    }
    else if (ctx.T_TIMESTAMP() != null) {
      if (exec.getConnectionType() == Conn.Type.HIVE) {
        evalSqlString("FROM_UNIXTIME(UNIX_TIMESTAMP())");
      } 
      else {
        evalSqlString("CURRENT_TIMESTAMP");
      }
    } else if (ctx.T_USER() != null) {
      evalSqlString("CURRENT_USER()");
    } else {
      evalSqlString(exec.getFormattedText(ctx));
    }
  }
  
  /**
   * CURRENT_USER function
   */
  void currentUser(HplsqlParser.Expr_spec_funcContext ctx) {
    evalVar(currentUser());
  }
  
  public Var currentUser() {
    String currentUser = System.getProperty("user.name");
    return new Var(currentUser);
  }
  
  /**
   * DECODE function
   */
  void decode(HplsqlParser.Expr_func_paramsContext ctx) {
    int cnt = ctx.func_param().size();
    if (cnt < 3) {
      evalNull();
      return;
    }
    Var value = evalPop(ctx.func_param(0).expr());
    int i = 1;
    while (i + 1 < cnt) {
      Var when = evalPop(ctx.func_param(i).expr());
      if ((value.isNull() && when.isNull()) || value.equals(when)) {
        eval(ctx.func_param(i + 1).expr());
        return;
      }
      i += 2;
    }    
    if (i < cnt) {           // ELSE expression
      eval(ctx.func_param(i).expr());
    }
    else {
      evalNull();
    }
  }

  /**
   * NVL function - Return first non-NULL expression
   */
  void nvl(HplsqlParser.Expr_func_paramsContext ctx) {
    for (int i=0; i < ctx.func_param().size(); i++) {
      Var v = evalPop(ctx.func_param(i).expr());
      if (v.type != Var.Type.NULL) {
        exec.stackPush(v);
        return;
      }
    }
    evalNull();
  }
  
  /**
   * NVL2 function - If expr1 is not NULL return expr2, otherwise expr3
   */
  void nvl2(HplsqlParser.Expr_func_paramsContext ctx) {
    if (ctx.func_param().size() == 3) {
      Var firstParam = evalPop(ctx.func_param(0).expr());
      if (!firstParam.isNull()) {
        eval(ctx.func_param(1).expr());
      }
      else {
        eval(ctx.func_param(2).expr());
      }
    }
    else {
      evalNull();
    }
  }
  
  /**
   * PART_COUNT function
   */
  public void partCount(HplsqlParser.Expr_spec_funcContext ctx) {
    String tabname = evalPop(ctx.expr(0)).toString();
    StringBuilder sql = new StringBuilder();
    sql.append("SHOW PARTITIONS ");
    sql.append(tabname);    
    int cnt = ctx.expr().size();   
    if (cnt > 1) {
      sql.append(" PARTITION (");
      int i = 1;
      while (i + 1 < cnt) {
        String col = evalPop(ctx.expr(i)).toString();
        String val = evalPop(ctx.expr(i + 1)).toSqlString();
        if (i > 2) {
          sql.append(", ");
        }
        sql.append(col);
        sql.append("=");
        sql.append(val);        
        i += 2;
      }
      sql.append(")");
    }
    if (trace) {
      trace(ctx, "Query: " + sql);
    }
    if (exec.getOffline()) {
      evalNull();
      return;
    }
    QueryResult query = queryExecutor.executeQuery(sql.toString(), ctx);
    if (query.error()) {
      evalNullClose(query);
      return;
    }
    int result = 0;
    try {
      while (query.next()) {
        result++;
      }
    } catch (Exception e) {
      evalNullClose(query);
      return;
    }
    evalInt(result);
    query.close();
  }

  public void modulo(HplsqlParser.Expr_func_paramsContext ctx) {
    if (ctx.func_param().size() == 2) {
      int a = evalPop(ctx.func_param(0).expr()).intValue();
      int b = evalPop(ctx.func_param(1).expr()).intValue();
      evalInt(a % b);
    } else {
      evalNull();
    }
  }

  /**
   * PART_COUNT_BY function
   */
  public void partCountBy(HplsqlParser.Expr_func_paramsContext ctx) {
    int cnt = ctx.func_param().size();
    if (cnt < 1 || exec.getOffline()) {
      return;
    }
    String tabname = evalPop(ctx.func_param(0).expr()).toString();
    ArrayList keys = null;
    if (cnt > 1) {
      keys = new ArrayList<>();
      for (int i = 1; i < cnt; i++) {
        keys.add(evalPop(ctx.func_param(i).expr()).toString().toUpperCase());
      }
    }    
    String sql = "SHOW PARTITIONS " + tabname;
    QueryResult query = queryExecutor.executeQuery(sql, ctx);
    if (query.error()) {
      query.close();
      return;
    }
    Map group = new HashMap<>();
    try {
      while (query.next()) {
        String part = query.column(0, String.class);
        String[] parts = part.split("/");
        String key = parts[0];
        if (cnt > 1) {
          StringBuilder k = new StringBuilder();
          for (int i = 0; i < parts.length; i++) {
            if (keys.contains(parts[i].split("=")[0].toUpperCase())) {
              if (k.length() > 0) {
                k.append("/");
              }
              k.append(parts[i]);
            }
          }
          key = k.toString();
        }
        Integer count = group.get(key);
        if (count == null) {
          count = Integer.valueOf(0);
        }
        group.put(key, count + 1);        
      }
    } catch (QueryException e) {
      query.close();
      return;
    }
    if (cnt == 1) {
      evalInt(group.size());
    }
    else {
      for (Map.Entry i : group.entrySet()) {
        console.printLine(i.getKey() + '\t' + i.getValue());
      }
    }
    query.close();
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy