[ 
https://issues.apache.org/jira/browse/IMPALA-7741?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16667658#comment-16667658
 ] 

Paul Rogers commented on IMPALA-7741:
-------------------------------------

We can solve the n^2 arguments problem by providing a custom function 
description class. For example:

{code:java}
  /**
   * Special case for
   * <code>nvl2(type1 expr, type2 ifNotNull, type2 ifNull)</code>.
   * Type check on the second and third arguments, since that drives the
   * return type. Accept any type for the first. This works because
   * <code>nvl2()</code> is rewritten to use <code>CASE</code>.
   */
  public static class Nvl2Function extends ScalarFunction {

    public Nvl2Function(Type retType) {
      super(new FunctionName(BuiltinsDb.NAME, "nvl2"),
          Lists.newArrayList(Type.NULL, retType, retType), retType, true);
    }

    @Override
    protected boolean isIndistinguishable(Function o) {
      return
          o.getArgs()[1].matchesType(this.getArgs()[1]) &&
          o.getArgs()[2].matchesType(this.getArgs()[2]);
    }

    @Override
    protected boolean isSuperTypeOf(Function other, boolean strict) {
      return
          Type.isImplicitlyCastable(
              other.getArgs()[1], this.getArgs()[1], strict, strict) &&
          Type.isImplicitlyCastable(
              other.getArgs()[2], this.getArgs()[2], strict, strict);
    }
  }
{code}

Then, add custom code to register this function:

{code:java}
  /**
   * Create entries for the odd-duck NVL2 function:
   * type1 nvl2(type2 expr, type1 ifNotNull, type1 ifNull).
   * The types form an n^2 matrix that can't easily be represented.
   * Instead, we define a special function that matches on the
   * second and third arguments, since they determine the return
   * type. We then ignore the first argument since we only care if
   * it is null, and CASE will take care of the details.
   */
  public static void initBuiltins(Db db) {
    for (Type t: Type.getSupportedTypes()) {
      if (t.isNull()) continue;
      if (t.isScalarType(PrimitiveType.CHAR)) continue;
      db.addBuiltin(new ScalarFunction.Nvl2Function(t));
    }
  }
{code}

With that, {{nvl2()}} acts like any other function and appears in the builtin 
functions table. It no longer needs custom rewrite rules in the parser; it can 
be rewritten in {{RewriteConditionalFnsRule()}} along with other functions. 
That is, remove the following from {{FunctionCallExpr}}:

{code:java}
    if (functionNameEqualsBuiltin(fnName, "nvl2")) {            
      List<Expr> plist = Lists.newArrayList(params.exprs());            
      if (!plist.isEmpty()) {           
        plist.set(0, new IsNullPredicate(plist.get(0), true));          
      }         
      return new FunctionCallExpr("if", plist);         
    }           
{code}

> Functions nvl2(), decode(), nullif() not listed in _impala_builtins
> -------------------------------------------------------------------
>
>                 Key: IMPALA-7741
>                 URL: https://issues.apache.org/jira/browse/IMPALA-7741
>             Project: IMPALA
>          Issue Type: Improvement
>    Affects Versions: Impala 3.0
>            Reporter: Paul Rogers
>            Priority: Major
>
> The 
> [docs|https://impala.apache.org/docs/build3x/html/topics/impala_show.html] 
> for {{SHOW FUNCTIONS}} says that we can use the following to list all 
> built-in functions:
> {code:sql}
> show functions in _impala_builtins like '*week*';
> {code}
> However several Impala functions are removed early in the FE planning process 
> and thus do not appear in the FE's function table in {{ScalarBuiltins}}: 
> {{nvl2()}}, {{decode()}}, and {{nullif()}}. For example:
> {noformat}
> show functions in _impala_builtins like '*decode**'
> +-------------+------------------------------+-------------+---------------+
> | return type | signature                    | binary type | is persistent |
> +-------------+------------------------------+-------------+---------------+
> | STRING      | base64decode(STRING)         | BUILTIN     | true          |
> | STRING      | madlib_decode_vector(STRING) | BUILTIN     | true          |
> +-------------+------------------------------+-------------+---------------+
> {noformat}
> However, since these three are perfectly valid functions, would have expected 
> them to appear in the table. How they are processed internally is an 
> implementation detail unimportant to the end user.



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to