IMPALA-5030: Adds support for NVL2() function This change adds support to the function NVL2(expr1, expr2, expr3). This function returns expr2 if expr1 is not null, else it returns expr3. NVL2() is converted to IF() prior to analysis.
Change-Id: I32b03e9864f46c9c5e482280d1aa676ff7f02644 Reviewed-on: http://gerrit.cloudera.org:8080/6962 Reviewed-by: Alex Behm <[email protected]> Tested-by: Impala Public Jenkins Project: http://git-wip-us.apache.org/repos/asf/incubator-impala/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-impala/commit/3e58bf40 Tree: http://git-wip-us.apache.org/repos/asf/incubator-impala/tree/3e58bf40 Diff: http://git-wip-us.apache.org/repos/asf/incubator-impala/diff/3e58bf40 Branch: refs/heads/master Commit: 3e58bf4074d0ff22696127d7ec726fa0b6a6fd9d Parents: 24ff0f2 Author: Vincent Tran <[email protected]> Authored: Sat May 20 07:39:04 2017 -0400 Committer: Impala Public Jenkins <[email protected]> Committed: Thu May 25 07:50:18 2017 +0000 ---------------------------------------------------------------------- .../apache/impala/analysis/FunctionCallExpr.java | 11 +++++++++++ .../apache/impala/analysis/AnalyzeExprsTest.java | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/3e58bf40/fe/src/main/java/org/apache/impala/analysis/FunctionCallExpr.java ---------------------------------------------------------------------- diff --git a/fe/src/main/java/org/apache/impala/analysis/FunctionCallExpr.java b/fe/src/main/java/org/apache/impala/analysis/FunctionCallExpr.java index 5895326..8538492 100644 --- a/fe/src/main/java/org/apache/impala/analysis/FunctionCallExpr.java +++ b/fe/src/main/java/org/apache/impala/analysis/FunctionCallExpr.java @@ -91,6 +91,17 @@ public class FunctionCallExpr extends Expr { && fnName.getFnNamePath().get(1).equalsIgnoreCase("decode")) { return new CaseExpr(functionCallExpr); } + if (fnName.getFnNamePath().size() == 1 + && fnName.getFnNamePath().get(0).equalsIgnoreCase("nvl2") + || fnName.getFnNamePath().size() == 2 + && fnName.getFnNamePath().get(0).equalsIgnoreCase(Catalog.BUILTINS_DB) + && fnName.getFnNamePath().get(1).equalsIgnoreCase("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); + } return functionCallExpr; } http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/3e58bf40/fe/src/test/java/org/apache/impala/analysis/AnalyzeExprsTest.java ---------------------------------------------------------------------- diff --git a/fe/src/test/java/org/apache/impala/analysis/AnalyzeExprsTest.java b/fe/src/test/java/org/apache/impala/analysis/AnalyzeExprsTest.java index e2d0058..cc65a23 100644 --- a/fe/src/test/java/org/apache/impala/analysis/AnalyzeExprsTest.java +++ b/fe/src/test/java/org/apache/impala/analysis/AnalyzeExprsTest.java @@ -1602,6 +1602,24 @@ public class AnalyzeExprsTest extends AnalyzerTest { // IGNORE NULLS may only be used with first_value/last_value AnalysisError("select lower('FOO' ignore nulls)", "Function LOWER does not accept the keyword IGNORE NULLS."); + + // NVL2() is converted to IF() before analysis. + AnalyzesOk("select nvl2(1, 'not null', 'null')"); + AnalyzesOk("select nvl2(null, 'not null', 'null')"); + AnalyzesOk("select nvl2('null', 'not null', 'null')"); + AnalyzesOk("select nvl2(int_col, 'not null', 'null') from functional.alltypesagg"); + AnalyzesOk("select nvl2(int_col, extract (year from now()), extract (month from " + + "now())) from functional.alltypesagg"); + AnalyzesOk("select nvl2(nvl2(null, 1, 2), 'not null', 'null')"); + AnalyzesOk("select nvl2(nvl2(null, null, null), nvl2(null, 'not null', 'null'), " + + "nvl2(2, 'not null', 'null'))"); + AnalyzesOk("select int_col from functional.alltypesagg where nvl2(int_col, true, " + + "false)"); + AnalysisError("select nvl2('null', true, '4')", "No matching function with " + + "signature: if(BOOLEAN, BOOLEAN, STRING)."); + AnalysisError("select nvl2(now(), true)", "No matching function with signature: " + + "if(BOOLEAN, BOOLEAN)."); + AnalysisError("select nvl2()", "No matching function with signature: if()."); } @Test
