You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@impala.apache.org by ta...@apache.org on 2018/09/27 20:43:17 UTC
[7/7] impala git commit: IMPALA-6202. mod and % should be equivalent.
IMPALA-6202. mod and % should be equivalent.
Currently in DECIMAL V2 mode, typeof(9.9 % 3) is DECIMAL(2,1) and typeof(mod(9.9, 3)) is
DECIMAL(4,1), while both are expected to be DECIMAL(2,1). This jira fixes V2 mode by
replacing "mod" with "%" at parser stage thus they share the same code path afterwards.
Testing:
Added unit tests and done real cluster testing.
Change-Id: Ib0067da04083859ffbf662a29007154461bea2ba
Reviewed-on: http://gerrit.cloudera.org:8080/11443
Tested-by: Impala Public Jenkins <im...@cloudera.com>
Reviewed-by: Tim Armstrong <ta...@cloudera.com>
Project: http://git-wip-us.apache.org/repos/asf/impala/repo
Commit: http://git-wip-us.apache.org/repos/asf/impala/commit/ba27b038
Tree: http://git-wip-us.apache.org/repos/asf/impala/tree/ba27b038
Diff: http://git-wip-us.apache.org/repos/asf/impala/diff/ba27b038
Branch: refs/heads/master
Commit: ba27b038148f0694662c14710f18ee6e94cf82b7
Parents: 3f78b74
Author: Yongjun Zhang <yz...@cloudera.com>
Authored: Thu Sep 20 12:25:06 2018 -0700
Committer: Tim Armstrong <ta...@cloudera.com>
Committed: Thu Sep 27 20:41:29 2018 +0000
----------------------------------------------------------------------
fe/src/main/cup/sql-parser.cup | 17 +++++-
.../impala/analysis/FunctionCallExpr.java | 14 ++++-
.../java/org/apache/impala/catalog/Type.java | 2 +
.../java/org/apache/impala/catalog/View.java | 2 +
.../org/apache/impala/service/Frontend.java | 11 +++-
.../impala/analysis/AnalyzeExprsTest.java | 57 ++++++++++++++------
.../org/apache/impala/analysis/ParserTest.java | 2 +
.../apache/impala/common/FrontendTestBase.java | 3 +-
.../org/apache/impala/service/JdbcTest.java | 2 +
.../PlannerTest/parquet-filtering-disabled.test | 6 +--
.../queries/PlannerTest/parquet-filtering.test | 16 +++---
.../queries/QueryTest/decimal-exprs.test | 28 ++++++++++
12 files changed, 127 insertions(+), 33 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/impala/blob/ba27b038/fe/src/main/cup/sql-parser.cup
----------------------------------------------------------------------
diff --git a/fe/src/main/cup/sql-parser.cup b/fe/src/main/cup/sql-parser.cup
index 4b6006a..ebe653a 100644
--- a/fe/src/main/cup/sql-parser.cup
+++ b/fe/src/main/cup/sql-parser.cup
@@ -52,6 +52,7 @@ import org.apache.impala.thrift.TFunctionCategory;
import org.apache.impala.thrift.THdfsFileFormat;
import org.apache.impala.thrift.TOwnerType;
import org.apache.impala.thrift.TPrivilegeLevel;
+import org.apache.impala.thrift.TQueryOptions;
import org.apache.impala.thrift.TShowStatsOp;
import org.apache.impala.thrift.TTablePropertyType;
import org.apache.impala.thrift.TPrincipalType;
@@ -68,6 +69,10 @@ parser code {:
// for generating syntax error message
private final List<Integer> expectedTokenIds_ = new ArrayList<Integer>();
+ // Currently used to tell if it's decimal V1 or V2 mode.
+ // TODO: remove when V1 code is dropped.
+ private TQueryOptions queryOptions;
+
// to avoid reporting trivial tokens as expected tokens in error messages
private boolean reportExpectedToken(Integer tokenId, int numExpectedTokens) {
if (SqlScanner.isKeyword(tokenId) ||
@@ -96,6 +101,14 @@ parser code {:
return msg;
}
+ public void setQueryOptions(TQueryOptions options) {
+ queryOptions = options;
+ }
+
+ public TQueryOptions getQueryOptions() {
+ return queryOptions;
+ }
+
// override to save error token
public void syntax_error(java_cup.runtime.Symbol token) {
errorToken_ = token;
@@ -2972,10 +2985,10 @@ function_call_expr ::=
function_name:fn_name LPAREN RPAREN
{:
RESULT = FunctionCallExpr.createExpr(
- fn_name, new FunctionParams(new ArrayList<Expr>()));
+ fn_name, new FunctionParams(new ArrayList<Expr>()), parser.getQueryOptions());
:}
| function_name:fn_name LPAREN function_params:params RPAREN
- {: RESULT = FunctionCallExpr.createExpr(fn_name, params); :}
+ {: RESULT = FunctionCallExpr.createExpr(fn_name, params, parser.getQueryOptions()); :}
// Below is a special case for EXTRACT. Idents are used to avoid adding new keywords.
| function_name:fn_name LPAREN ident_or_default:u KW_FROM expr:t RPAREN
{: RESULT = new ExtractFromExpr(fn_name, u, t); :}
http://git-wip-us.apache.org/repos/asf/impala/blob/ba27b038/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 291420f..36ef596 100644
--- a/fe/src/main/java/org/apache/impala/analysis/FunctionCallExpr.java
+++ b/fe/src/main/java/org/apache/impala/analysis/FunctionCallExpr.java
@@ -34,6 +34,7 @@ import org.apache.impala.thrift.TColumnType;
import org.apache.impala.thrift.TExprNode;
import org.apache.impala.thrift.TExprNodeType;
import org.apache.impala.thrift.TFunctionBinaryType;
+import org.apache.impala.thrift.TQueryOptions;
import com.google.common.base.Joiner;
import com.google.common.base.Objects;
@@ -80,9 +81,10 @@ public class FunctionCallExpr extends Expr {
/**
* Returns an Expr that evaluates the function call <fnName>(<params>). The returned
- * Expr is not necessarily a FunctionCallExpr (example: DECODE())
+ * Expr is not necessarily a FunctionCallExpr (example: DECODE()).
*/
- public static Expr createExpr(FunctionName fnName, FunctionParams params) {
+ public static Expr createExpr(FunctionName fnName, FunctionParams params,
+ TQueryOptions options) {
FunctionCallExpr functionCallExpr = new FunctionCallExpr(fnName, params);
if (functionNameEqualsBuiltin(fnName, "decode")) {
return new CaseExpr(functionCallExpr);
@@ -103,6 +105,14 @@ public class FunctionCallExpr extends Expr {
new NullLiteral() // NULL
));
}
+ // "mod" and "%" are equivalent in DECIMAL V2 mode.
+ Preconditions.checkArgument(options != null);
+ if (options.isDecimal_v2() && functionNameEqualsBuiltin(fnName, "mod")) {
+ List<Expr> plist = Lists.newArrayList(params.exprs());
+ Preconditions.checkArgument(plist.size() == 2);
+ return new ArithmeticExpr(ArithmeticExpr.Operator.MOD,
+ plist.get(0), plist.get(1));
+ }
return functionCallExpr;
}
http://git-wip-us.apache.org/repos/asf/impala/blob/ba27b038/fe/src/main/java/org/apache/impala/catalog/Type.java
----------------------------------------------------------------------
diff --git a/fe/src/main/java/org/apache/impala/catalog/Type.java b/fe/src/main/java/org/apache/impala/catalog/Type.java
index a85cd40..664fca1 100644
--- a/fe/src/main/java/org/apache/impala/catalog/Type.java
+++ b/fe/src/main/java/org/apache/impala/catalog/Type.java
@@ -28,6 +28,7 @@ import org.apache.impala.analysis.TypeDef;
import org.apache.impala.common.Pair;
import org.apache.impala.thrift.TColumnType;
import org.apache.impala.thrift.TPrimitiveType;
+import org.apache.impala.thrift.TQueryOptions;
import org.apache.impala.thrift.TScalarType;
import org.apache.impala.thrift.TStructField;
import org.apache.impala.thrift.TTypeNode;
@@ -264,6 +265,7 @@ public abstract class Type {
String stmt = String.format("CREATE TABLE $DUMMY ($DUMMY %s)", typeStr);
SqlScanner input = new SqlScanner(new StringReader(stmt));
SqlParser parser = new SqlParser(input);
+ parser.setQueryOptions(new TQueryOptions());
CreateTableStmt createTableStmt;
try {
Object o = parser.parse().value;
http://git-wip-us.apache.org/repos/asf/impala/blob/ba27b038/fe/src/main/java/org/apache/impala/catalog/View.java
----------------------------------------------------------------------
diff --git a/fe/src/main/java/org/apache/impala/catalog/View.java b/fe/src/main/java/org/apache/impala/catalog/View.java
index 8af5300..776c385 100644
--- a/fe/src/main/java/org/apache/impala/catalog/View.java
+++ b/fe/src/main/java/org/apache/impala/catalog/View.java
@@ -29,6 +29,7 @@ import org.apache.impala.analysis.QueryStmt;
import org.apache.impala.analysis.SqlParser;
import org.apache.impala.analysis.SqlScanner;
import org.apache.impala.thrift.TCatalogObjectType;
+import org.apache.impala.thrift.TQueryOptions;
import org.apache.impala.thrift.TTable;
import org.apache.impala.thrift.TTableDescriptor;
import org.apache.impala.thrift.TTableStats;
@@ -138,6 +139,7 @@ public class View extends Table implements FeView {
// populate a view definition.
SqlScanner input = new SqlScanner(new StringReader(inlineViewDef));
SqlParser parser = new SqlParser(input);
+ parser.setQueryOptions(new TQueryOptions());
ParseNode node = null;
try {
node = (ParseNode) parser.parse().value;
http://git-wip-us.apache.org/repos/asf/impala/blob/ba27b038/fe/src/main/java/org/apache/impala/service/Frontend.java
----------------------------------------------------------------------
diff --git a/fe/src/main/java/org/apache/impala/service/Frontend.java b/fe/src/main/java/org/apache/impala/service/Frontend.java
index 2c527cc..847e8b1 100644
--- a/fe/src/main/java/org/apache/impala/service/Frontend.java
+++ b/fe/src/main/java/org/apache/impala/service/Frontend.java
@@ -1033,9 +1033,17 @@ public class Frontend {
return result;
}
+ @VisibleForTesting
public StatementBase parse(String stmt) throws AnalysisException {
+ return parse(stmt, new TQueryOptions());
+ }
+
+ public StatementBase parse(String stmt, TQueryOptions options)
+ throws AnalysisException {
SqlScanner input = new SqlScanner(new StringReader(stmt));
SqlParser parser = new SqlParser(input);
+ Preconditions.checkArgument(options != null);
+ parser.setQueryOptions(options);
try {
return (StatementBase) parser.parse().value;
} catch (Exception e) {
@@ -1090,7 +1098,8 @@ public class Frontend {
private TExecRequest doCreateExecRequest(TQueryCtx queryCtx, EventSequence timeline,
StringBuilder explainString) throws ImpalaException {
// Parse stmt and collect/load metadata to populate a stmt-local table cache
- StatementBase stmt = parse(queryCtx.client_request.stmt);
+ StatementBase stmt =
+ parse(queryCtx.client_request.stmt, queryCtx.client_request.query_options);
StmtMetadataLoader metadataLoader =
new StmtMetadataLoader(this, queryCtx.session.database, timeline);
StmtTableCache stmtTableCache = metadataLoader.loadTables(stmt);
http://git-wip-us.apache.org/repos/asf/impala/blob/ba27b038/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 905fae6..1908c21 100644
--- a/fe/src/test/java/org/apache/impala/analysis/AnalyzeExprsTest.java
+++ b/fe/src/test/java/org/apache/impala/analysis/AnalyzeExprsTest.java
@@ -2319,30 +2319,38 @@ public class AnalyzeExprsTest extends AnalyzerTest {
testFuncExprDepthLimit("cast(", "1", " as int)");
}
- // Verifies the resulting expr decimal type is expectedType under decimal v1 and
+ // Verifies the resulting expr decimal type is expectedType under decimal v1 or
// decimal v2.
- private void testDecimalExpr(String expr,
- Type decimalV1ExpectedType, Type decimalV2ExpectedType) {
+ private void testDecimalExpr(String expr, Type decimalExpectedType, boolean isV2) {
TQueryOptions queryOpts = new TQueryOptions();
- queryOpts.setDecimal_v2(false);
+ queryOpts.setDecimal_v2(isV2);
SelectStmt selectStmt =
(SelectStmt) AnalyzesOk("select " + expr, createAnalysisCtx(queryOpts));
Expr root = selectStmt.resultExprs_.get(0);
Type actualType = root.getType();
Assert.assertTrue(
- "Expr: " + expr + " Decimal Version: 1" +
- " Expected: " + decimalV1ExpectedType + " Actual: " + actualType,
- decimalV1ExpectedType.equals(actualType));
-
- queryOpts.setDecimal_v2(true);
- selectStmt = (SelectStmt) AnalyzesOk("select " + expr, createAnalysisCtx(queryOpts));
- root = selectStmt.resultExprs_.get(0);
- actualType = root.getType();
- Assert.assertTrue(
- "Expr: " + expr + " Decimal Version: 2" +
- " Expected: " + decimalV2ExpectedType + " Actual: " + actualType,
- decimalV2ExpectedType.equals(actualType));
+ "Expr: " + expr + " Decimal Version: " + (isV2? "2" : "1") +
+ " Expected: " + decimalExpectedType + " Actual: " + actualType,
+ decimalExpectedType.equals(actualType));
+ }
+
+ // Verifies the resulting expr decimal type is expectedType under decimal v1.
+ private void testDecimalExprV1(String expr, Type decimalExpectedType) {
+ testDecimalExpr(expr, decimalExpectedType, false);
+ }
+
+ // Verifies the resulting expr decimal type is expectedType under decimal v2.
+ private void testDecimalExprV2(String expr, Type decimalExpectedType) {
+ testDecimalExpr(expr, decimalExpectedType, true);
+ }
+
+ // Verifies the resulting expr decimal type is expectedType under decimal v1 and
+ // decimal v2.
+ private void testDecimalExpr(String expr,
+ Type decimalV1ExpectedType, Type decimalV2ExpectedType) {
+ testDecimalExprV1(expr, decimalV1ExpectedType);
+ testDecimalExprV2(expr, decimalV2ExpectedType);
}
// Verifies the resulting expr decimal type is exptectedType
@@ -2350,6 +2358,23 @@ public class AnalyzeExprsTest extends AnalyzerTest {
testDecimalExpr(expr, expectedType, expectedType);
}
+ // Verify that mod and % returns the same type when it's DECIMAL V2 mdoe.
+ // See IMPALA-6202.
+ @Test
+ public void TestModReturnType() {
+ testDecimalExprV2("mod(9.8, 3)", ScalarType.createDecimalType(2,1));
+ testDecimalExprV2("9.7 % 3", ScalarType.createDecimalType(2,1));
+
+ testDecimalExprV2("mod(109.8, 3)", ScalarType.createDecimalType(4,1));
+ testDecimalExprV2("109.7 % 3", ScalarType.createDecimalType(4,1));
+
+ testDecimalExprV2("mod(109.8, 3.45)", ScalarType.createDecimalType(3,2));
+ testDecimalExprV2("109.7 % 3.45", ScalarType.createDecimalType(3,2));
+
+ testDecimalExprV1("mod(9.6, 3)", ScalarType.createDecimalType(4,1));
+ testDecimalExprV1("9.5 % 3", Type.DOUBLE);
+ }
+
@Test
public void TestDecimalArithmetic() {
String decimal_10_0 = "cast(1 as decimal(10,0))";
http://git-wip-us.apache.org/repos/asf/impala/blob/ba27b038/fe/src/test/java/org/apache/impala/analysis/ParserTest.java
----------------------------------------------------------------------
diff --git a/fe/src/test/java/org/apache/impala/analysis/ParserTest.java b/fe/src/test/java/org/apache/impala/analysis/ParserTest.java
index 5ad2876..f7d6bda 100644
--- a/fe/src/test/java/org/apache/impala/analysis/ParserTest.java
+++ b/fe/src/test/java/org/apache/impala/analysis/ParserTest.java
@@ -30,6 +30,7 @@ import org.apache.impala.analysis.TimestampArithmeticExpr.TimeUnit;
import org.apache.impala.common.AnalysisException;
import org.apache.impala.common.FrontendTestBase;
import org.apache.impala.compat.MetastoreShim;
+import org.apache.impala.thrift.TQueryOptions;
import org.junit.Test;
import com.google.common.base.Preconditions;
@@ -67,6 +68,7 @@ public class ParserTest extends FrontendTestBase {
public void ParserError(String stmt, String expectedErrorString) {
SqlScanner input = new SqlScanner(new StringReader(stmt));
SqlParser parser = new SqlParser(input);
+ parser.setQueryOptions(new TQueryOptions());
Object result = null; // Save this object to make debugging easier
try {
result = parser.parse().value;
http://git-wip-us.apache.org/repos/asf/impala/blob/ba27b038/fe/src/test/java/org/apache/impala/common/FrontendTestBase.java
----------------------------------------------------------------------
diff --git a/fe/src/test/java/org/apache/impala/common/FrontendTestBase.java b/fe/src/test/java/org/apache/impala/common/FrontendTestBase.java
index e13e51b..042b287 100644
--- a/fe/src/test/java/org/apache/impala/common/FrontendTestBase.java
+++ b/fe/src/test/java/org/apache/impala/common/FrontendTestBase.java
@@ -275,6 +275,7 @@ public class FrontendTestBase {
public ParseNode ParsesOk(String stmt) {
SqlScanner input = new SqlScanner(new StringReader(stmt));
SqlParser parser = new SqlParser(input);
+ parser.setQueryOptions(new TQueryOptions());
ParseNode node = null;
try {
node = (ParseNode) parser.parse().value;
@@ -439,7 +440,7 @@ public class FrontendTestBase {
protected AnalysisResult parseAndAnalyze(String stmt, AnalysisContext ctx, Frontend fe)
throws ImpalaException {
- StatementBase parsedStmt = fe.parse(stmt);
+ StatementBase parsedStmt = fe.parse(stmt, ctx.getQueryOptions());
StmtMetadataLoader mdLoader =
new StmtMetadataLoader(fe, ctx.getQueryCtx().session.database, null);
StmtTableCache stmtTableCache = mdLoader.loadTables(parsedStmt);
http://git-wip-us.apache.org/repos/asf/impala/blob/ba27b038/fe/src/test/java/org/apache/impala/service/JdbcTest.java
----------------------------------------------------------------------
diff --git a/fe/src/test/java/org/apache/impala/service/JdbcTest.java b/fe/src/test/java/org/apache/impala/service/JdbcTest.java
index 28b032b..0350897 100644
--- a/fe/src/test/java/org/apache/impala/service/JdbcTest.java
+++ b/fe/src/test/java/org/apache/impala/service/JdbcTest.java
@@ -40,6 +40,7 @@ import org.apache.impala.analysis.CreateTableStmt;
import org.apache.impala.analysis.SqlParser;
import org.apache.impala.analysis.SqlScanner;
import org.apache.impala.testutil.ImpalaJdbcClient;
+import org.apache.impala.thrift.TQueryOptions;
import org.apache.impala.util.Metrics;
import org.junit.After;
import org.junit.AfterClass;
@@ -100,6 +101,7 @@ public class JdbcTest {
// that we do not execute arbitrary SQL here and pollute the test setup.
SqlScanner input = new SqlScanner(new StringReader(createTableSql));
SqlParser parser = new SqlParser(input);
+ parser.setQueryOptions(new TQueryOptions());
Object result = parser.parse().value;
if (!(result instanceof CreateTableStmt)) {
throw new Exception("Given stmt is not a CREATE TABLE stmt: " + createTableSql);
http://git-wip-us.apache.org/repos/asf/impala/blob/ba27b038/testdata/workloads/functional-planner/queries/PlannerTest/parquet-filtering-disabled.test
----------------------------------------------------------------------
diff --git a/testdata/workloads/functional-planner/queries/PlannerTest/parquet-filtering-disabled.test b/testdata/workloads/functional-planner/queries/PlannerTest/parquet-filtering-disabled.test
index 0e7f58c..426ef38 100644
--- a/testdata/workloads/functional-planner/queries/PlannerTest/parquet-filtering-disabled.test
+++ b/testdata/workloads/functional-planner/queries/PlannerTest/parquet-filtering-disabled.test
@@ -58,7 +58,7 @@ PLAN-ROOT SINK
|
00:SCAN HDFS [functional_parquet.alltypes]
partitions=22/24 files=22 size=172.28KB
- predicates: bool_col, bigint_col < 5000, double_col > 100.00, float_col > 50.00, id = 1, tinyint_col < 50, string_col IN ('aaaa', 'bbbb', 'cccc'), smallint_col IN (1, 2, 3, 4, 5), mod(int_col, 2) = 1, timestamp_cmp(timestamp_col, TIMESTAMP '2016-11-20 00:00:00') = 1, date_string_col > '1993-10-01'
+ predicates: bool_col, bigint_col < 5000, double_col > 100.00, float_col > 50.00, id = 1, tinyint_col < 50, int_col % 2 = 1, string_col IN ('aaaa', 'bbbb', 'cccc'), smallint_col IN (1, 2, 3, 4, 5), timestamp_cmp(timestamp_col, TIMESTAMP '2016-11-20 00:00:00') = 1, date_string_col > '1993-10-01'
stored statistics:
table: rows=unavailable size=unavailable
partitions: 0/22 rows=unavailable
@@ -88,7 +88,7 @@ PLAN-ROOT SINK
|
00:SCAN HDFS [functional_parquet.alltypes]
partitions=24/24 files=24 size=188.29KB
- predicates: id IN (int_col), id NOT IN (0, 1, 2), string_col IN ('aaaa', 'bbbb', 'cccc', NULL), mod(int_col, 50) IN (0, 1)
+ predicates: id IN (int_col), id NOT IN (0, 1, 2), int_col % 50 IN (0, 1), string_col IN ('aaaa', 'bbbb', 'cccc', NULL)
stored statistics:
table: rows=unavailable size=unavailable
partitions: 0/24 rows=unavailable
@@ -334,7 +334,7 @@ PLAN-ROOT SINK
|
00:SCAN HDFS [functional.alltypesmixedformat]
partitions=4/4 files=4 size=66.61KB
- predicates: bool_col, bigint_col < 5000, double_col > 100.00, float_col > 50.00, id = 1, tinyint_col < 50, string_col IN ('aaaa', 'bbbb', 'cccc'), smallint_col IN (1, 2, 3, 4, 5), mod(int_col, 2) = 1, timestamp_cmp(timestamp_col, TIMESTAMP '2016-11-20 00:00:00') = 1, date_string_col > '1993-10-01'
+ predicates: bool_col, bigint_col < 5000, double_col > 100.00, float_col > 50.00, id = 1, tinyint_col < 50, int_col % 2 = 1, string_col IN ('aaaa', 'bbbb', 'cccc'), smallint_col IN (1, 2, 3, 4, 5), timestamp_cmp(timestamp_col, TIMESTAMP '2016-11-20 00:00:00') = 1, date_string_col > '1993-10-01'
stored statistics:
table: rows=unavailable size=unavailable
partitions: 0/4 rows=unavailable
http://git-wip-us.apache.org/repos/asf/impala/blob/ba27b038/testdata/workloads/functional-planner/queries/PlannerTest/parquet-filtering.test
----------------------------------------------------------------------
diff --git a/testdata/workloads/functional-planner/queries/PlannerTest/parquet-filtering.test b/testdata/workloads/functional-planner/queries/PlannerTest/parquet-filtering.test
index d5f07f5..247edb3 100644
--- a/testdata/workloads/functional-planner/queries/PlannerTest/parquet-filtering.test
+++ b/testdata/workloads/functional-planner/queries/PlannerTest/parquet-filtering.test
@@ -82,14 +82,14 @@ PLAN-ROOT SINK
|
00:SCAN HDFS [functional_parquet.alltypes]
partitions=22/24 files=22 size=172.93KB
- predicates: bool_col, bigint_col < 5000, double_col > 100.00, float_col > 50.00, id = 1, tinyint_col < 50, string_col IN ('aaaa', 'bbbb', 'cccc'), smallint_col IN (1, 2, 3, 4, 5), mod(int_col, 2) = 1, timestamp_cmp(timestamp_col, TIMESTAMP '2016-11-20 00:00:00') = 1, date_string_col > '1993-10-01'
+ predicates: bool_col, bigint_col < 5000, double_col > 100.00, float_col > 50.00, id = 1, tinyint_col < 50, int_col % 2 = 1, string_col IN ('aaaa', 'bbbb', 'cccc'), smallint_col IN (1, 2, 3, 4, 5), timestamp_cmp(timestamp_col, TIMESTAMP '2016-11-20 00:00:00') = 1, date_string_col > '1993-10-01'
stored statistics:
table: rows=unavailable size=unavailable
partitions: 0/22 rows=unavailable
columns missing stats: id, bool_col, tinyint_col, smallint_col, int_col, bigint_col, float_col, double_col, date_string_col, string_col, timestamp_col
extrapolated-rows=disabled max-scan-range-rows=unavailable
parquet statistics predicates: bigint_col < 5000, double_col > 100.00, float_col > 50.00, id = 1, tinyint_col < 50, string_col IN ('aaaa', 'bbbb', 'cccc'), smallint_col IN (1, 2, 3, 4, 5), date_string_col > '1993-10-01'
- parquet dictionary predicates: bool_col, bigint_col < 5000, double_col > 100.00, float_col > 50.00, id = 1, tinyint_col < 50, string_col IN ('aaaa', 'bbbb', 'cccc'), smallint_col IN (1, 2, 3, 4, 5), mod(int_col, 2) = 1, timestamp_cmp(timestamp_col, TIMESTAMP '2016-11-20 00:00:00') = 1, date_string_col > '1993-10-01'
+ parquet dictionary predicates: bool_col, bigint_col < 5000, double_col > 100.00, float_col > 50.00, id = 1, tinyint_col < 50, int_col % 2 = 1, string_col IN ('aaaa', 'bbbb', 'cccc'), smallint_col IN (1, 2, 3, 4, 5), timestamp_cmp(timestamp_col, TIMESTAMP '2016-11-20 00:00:00') = 1, date_string_col > '1993-10-01'
mem-estimate=128.00MB mem-reservation=88.00KB thread-reservation=1
tuple-ids=0 row-size=80B cardinality=unavailable
in pipelines: 00(GETNEXT)
@@ -116,7 +116,7 @@ PLAN-ROOT SINK
|
00:SCAN HDFS [functional.alltypes]
partitions=22/24 files=22 size=437.72KB
- predicates: id = 1, string_col IN ('aaaa', 'bbbb', 'cccc'), smallint_col IN (1, 2, 3, 4, 5), bool_col, bigint_col < 5000, double_col > 100.00, float_col > 50.00, tinyint_col < 50, mod(int_col, 2) = 1, timestamp_cmp(timestamp_col, TIMESTAMP '2016-11-20 00:00:00') = 1, date_string_col > '1993-10-01'
+ predicates: id = 1, string_col IN ('aaaa', 'bbbb', 'cccc'), smallint_col IN (1, 2, 3, 4, 5), bool_col, bigint_col < 5000, double_col > 100.00, float_col > 50.00, tinyint_col < 50, int_col % 2 = 1, timestamp_cmp(timestamp_col, TIMESTAMP '2016-11-20 00:00:00') = 1, date_string_col > '1993-10-01'
stored statistics:
table: rows=7300 size=478.45KB
partitions: 22/22 rows=6680
@@ -149,13 +149,13 @@ PLAN-ROOT SINK
|
00:SCAN HDFS [functional_parquet.alltypes]
partitions=24/24 files=24 size=188.92KB
- predicates: id IN (int_col), id NOT IN (0, 1, 2), string_col IN ('aaaa', 'bbbb', 'cccc', NULL), mod(int_col, 50) IN (0, 1)
+ predicates: id IN (int_col), id NOT IN (0, 1, 2), int_col % 50 IN (0, 1), string_col IN ('aaaa', 'bbbb', 'cccc', NULL)
stored statistics:
table: rows=unavailable size=unavailable
partitions: 0/24 rows=unavailable
columns: unavailable
extrapolated-rows=disabled max-scan-range-rows=unavailable
- parquet dictionary predicates: id NOT IN (0, 1, 2), string_col IN ('aaaa', 'bbbb', 'cccc', NULL), mod(int_col, 50) IN (0, 1)
+ parquet dictionary predicates: id NOT IN (0, 1, 2), int_col % 50 IN (0, 1), string_col IN ('aaaa', 'bbbb', 'cccc', NULL)
mem-estimate=48.00MB mem-reservation=24.00KB thread-reservation=1
tuple-ids=0 row-size=24B cardinality=unavailable
in pipelines: 00(GETNEXT)
@@ -582,14 +582,14 @@ PLAN-ROOT SINK
|
00:SCAN HDFS [functional.alltypesmixedformat]
partitions=4/4 files=4 size=66.61KB
- predicates: bool_col, bigint_col < 5000, double_col > 100.00, float_col > 50.00, id = 1, tinyint_col < 50, string_col IN ('aaaa', 'bbbb', 'cccc'), smallint_col IN (1, 2, 3, 4, 5), mod(int_col, 2) = 1, timestamp_cmp(timestamp_col, TIMESTAMP '2016-11-20 00:00:00') = 1, date_string_col > '1993-10-01'
+ predicates: bool_col, bigint_col < 5000, double_col > 100.00, float_col > 50.00, id = 1, tinyint_col < 50, int_col % 2 = 1, string_col IN ('aaaa', 'bbbb', 'cccc'), smallint_col IN (1, 2, 3, 4, 5), timestamp_cmp(timestamp_col, TIMESTAMP '2016-11-20 00:00:00') = 1, date_string_col > '1993-10-01'
stored statistics:
table: rows=unavailable size=unavailable
partitions: 0/4 rows=unavailable
columns missing stats: id, bool_col, tinyint_col, smallint_col, int_col, bigint_col, float_col, double_col, date_string_col, string_col, timestamp_col
extrapolated-rows=disabled max-scan-range-rows=unavailable
parquet statistics predicates: bigint_col < 5000, double_col > 100.00, float_col > 50.00, id = 1, tinyint_col < 50, string_col IN ('aaaa', 'bbbb', 'cccc'), smallint_col IN (1, 2, 3, 4, 5), date_string_col > '1993-10-01'
- parquet dictionary predicates: bool_col, bigint_col < 5000, double_col > 100.00, float_col > 50.00, id = 1, tinyint_col < 50, string_col IN ('aaaa', 'bbbb', 'cccc'), smallint_col IN (1, 2, 3, 4, 5), mod(int_col, 2) = 1, timestamp_cmp(timestamp_col, TIMESTAMP '2016-11-20 00:00:00') = 1, date_string_col > '1993-10-01'
+ parquet dictionary predicates: bool_col, bigint_col < 5000, double_col > 100.00, float_col > 50.00, id = 1, tinyint_col < 50, int_col % 2 = 1, string_col IN ('aaaa', 'bbbb', 'cccc'), smallint_col IN (1, 2, 3, 4, 5), timestamp_cmp(timestamp_col, TIMESTAMP '2016-11-20 00:00:00') = 1, date_string_col > '1993-10-01'
mem-estimate=128.00MB mem-reservation=88.00KB thread-reservation=1
tuple-ids=0 row-size=80B cardinality=unavailable
in pipelines: 00(GETNEXT)
@@ -617,7 +617,7 @@ PLAN-ROOT SINK
|
00:SCAN HDFS [functional.alltypesmixedformat]
partitions=0/4 files=0 size=0B
- predicates: bool_col, bigint_col < 5000, double_col > 100.00, float_col > 50.00, id = 1, tinyint_col < 50, string_col IN ('aaaa', 'bbbb', 'cccc'), smallint_col IN (1, 2, 3, 4, 5), mod(int_col, 2) = 1, timestamp_cmp(timestamp_col, TIMESTAMP '2016-11-20 00:00:00') = 1, date_string_col > '1993-10-01'
+ predicates: bool_col, bigint_col < 5000, double_col > 100.00, float_col > 50.00, id = 1, tinyint_col < 50, int_col % 2 = 1, string_col IN ('aaaa', 'bbbb', 'cccc'), smallint_col IN (1, 2, 3, 4, 5), timestamp_cmp(timestamp_col, TIMESTAMP '2016-11-20 00:00:00') = 1, date_string_col > '1993-10-01'
stored statistics:
table: rows=unavailable size=unavailable
partitions: 0/0 rows=unavailable
http://git-wip-us.apache.org/repos/asf/impala/blob/ba27b038/testdata/workloads/functional-query/queries/QueryTest/decimal-exprs.test
----------------------------------------------------------------------
diff --git a/testdata/workloads/functional-query/queries/QueryTest/decimal-exprs.test b/testdata/workloads/functional-query/queries/QueryTest/decimal-exprs.test
index a4bfb83..c1ec721 100644
--- a/testdata/workloads/functional-query/queries/QueryTest/decimal-exprs.test
+++ b/testdata/workloads/functional-query/queries/QueryTest/decimal-exprs.test
@@ -512,3 +512,31 @@ select cast("1234.5" as decimal(5, 2));
---- CATCH
UDF ERROR: String to Decimal cast overflowed
====
+---- QUERY
+# mod and % should be equivalent in Decimal V2 mode.
+set decimal_v2=true;
+select typeof(9.8 % 3);
+---- RESULTS
+'DECIMAL(2,1)'
+====
+---- QUERY
+# mod and % should be equivalent in Decimal V2 mode.
+set decimal_v2=true;
+select typeof(mod(9.7,3));
+---- RESULTS
+'DECIMAL(2,1)'
+====
+---- QUERY
+# mod and % are different in Decimal V1 mode for this case.
+set decimal_v2=false;
+select typeof(9.6 % 3);
+---- RESULTS
+'DOUBLE'
+====
+---- QUERY
+# mod and % are different in Decimal V1 mode for this case.
+set decimal_v2=false;
+select typeof(mod(9.6, 3));
+---- RESULTS
+'DECIMAL(4,1)'
+====