15 package com.cloudera.impala.analysis;
17 import static org.junit.Assert.assertNotNull;
18 import static org.junit.Assert.fail;
20 import java.io.StringReader;
21 import java.util.ArrayList;
22 import java.util.HashMap;
23 import java.util.List;
26 import junit.framework.Assert;
28 import org.junit.After;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
49 import com.cloudera.impala.thrift.TExpr;
50 import com.cloudera.impala.thrift.TQueryCtx;
51 import com.cloudera.impala.thrift.TQueryOptions;
52 import com.google.common.base.Joiner;
53 import com.google.common.base.Preconditions;
54 import com.google.common.collect.Lists;
57 protected final static Logger
LOG = LoggerFactory.getLogger(AnalyzerTest.class);
61 protected final List<Db>
testDbs_ = Lists.newArrayList();
62 protected final List<Table>
testTables_ = Lists.newArrayList();
68 new HashMap<ScalarType, String>();
72 typeToLiteralValue_.put(
Type.SMALLINT, (Byte.MAX_VALUE + 1) +
"");
73 typeToLiteralValue_.put(
Type.INT, (Short.MAX_VALUE + 1) +
"");
75 ((long) Integer.MAX_VALUE + 1) +
"");
76 typeToLiteralValue_.put(
Type.FLOAT,
"cast(1.0 as float)");
78 "cast(" + (Float.MAX_VALUE + 1) +
" as double)");
80 "cast('2012-12-21 00:00:00.000' as timestamp)");
81 typeToLiteralValue_.put(
Type.STRING,
"'Hello, World!'");
82 typeToLiteralValue_.put(
Type.NULL,
"NULL");
87 TestUtils.createQueryContext(defaultDb, System.getProperty(
"user.name"));
93 TQueryCtx queryCtx = TestUtils.createQueryContext();
94 queryCtx.request.query_options = queryOptions;
101 analyzer.setUseHiveColLabels(
true);
109 ArrayList<ScalarType> args,
boolean varArgs) {
115 return addTestFunction(
"default", name, Lists.newArrayList(arg), varArgs);
119 ArrayList<ScalarType> args,
boolean varArgs) {
120 ArrayList<Type> argTypes = Lists.newArrayList();
121 argTypes.addAll(args);
124 fn.setHasVarArgs(varArgs);
125 catalog_.addFunction(fn);
131 catalog_.addFunction(
141 Db db = catalog_.getDb(dbName);
142 Preconditions.checkState(db == null,
"Test db must not already exist.");
151 catalog_.removeDb(testDb.getName());
164 Preconditions.checkState(createTableStmt.getPartitionColumnDefs().isEmpty());
165 Db db = catalog_.getDb(createTableStmt.getDb());
166 Preconditions.checkNotNull(db,
"Test tables must be created in an existing db.");
168 createTableStmt.getOwner());
169 List<ColumnDef> columnDefs = createTableStmt.getColumnDefs();
170 for (
int i = 0; i < columnDefs.size(); ++i) {
174 db.addTable(dummyTable);
175 testTables_.add(dummyTable);
181 testTable.getDb().removeTable(testTable.getName());
196 List<Expr> selectListExprs = node.getResultExprs();
197 List<TExpr> thriftExprs = Expr.treesToThrift(selectListExprs);
198 LOG.info(
"select list:\n");
199 for (TExpr expr: thriftExprs) {
200 LOG.info(expr.toString() +
"\n");
202 for (
Expr expr: selectListExprs) {
206 TExpr thriftWhere = node.getWhereClause().treeToThrift();
207 LOG.info(
"WHERE pred: " + thriftWhere.toString() +
"\n");
211 if (aggInfo != null) {
213 LOG.info(
"grouping exprs:\n");
215 LOG.info(expr.treeToThrift().toString() +
"\n");
219 LOG.info(
"aggregate exprs:\n");
221 LOG.info(expr.treeToThrift().toString() +
"\n");
225 TExpr thriftHaving = node.getHavingPred().treeToThrift();
226 LOG.info(
"HAVING pred: " + thriftHaving.toString() +
"\n");
236 SqlScanner input =
new SqlScanner(
new StringReader(stmt));
237 SqlParser
parser =
new SqlParser(input);
241 }
catch (Exception e) {
243 fail(
"\nParser error:\n" + parser.getErrorMsg(stmt));
273 System.getProperty(
"user.name")),
275 analysisCtx.analyze(stmt, analyzer);
276 AnalysisContext.AnalysisResult analysisResult = analysisCtx.getAnalysisResult();
277 if (expectedWarning != null) {
278 List<String> actualWarnings = analysisResult.getAnalyzer().getWarnings();
279 boolean matchedWarning =
false;
280 for (String actualWarning: actualWarnings) {
281 if (actualWarning.startsWith(expectedWarning)) {
282 matchedWarning =
true;
286 if (!matchedWarning) {
287 fail(String.format(
"Did not produce expected warning.\n" +
288 "Expected warning:\n%s.\nActual warnings:\n%s",
289 expectedWarning, Joiner.on(
"\n").join(actualWarnings)));
292 Preconditions.checkNotNull(analysisResult.getStmt());
293 return analysisResult.getStmt();
294 }
catch (Exception e) {
296 fail(
"Error:\n" + e.toString());
328 Preconditions.checkNotNull(expectedErrorString,
"No expected error message given.");
329 LOG.info(
"processing " + stmt);
333 System.getProperty(
"user.name")),
335 analysisCtx.analyze(stmt, analyzer);
336 AnalysisContext.AnalysisResult analysisResult = analysisCtx.getAnalysisResult();
337 Preconditions.checkNotNull(analysisResult.getStmt());
338 }
catch (Exception e) {
339 String errorString = e.getMessage();
341 "got error:\n" + errorString +
"\nexpected:\n" + expectedErrorString,
342 errorString.startsWith(expectedErrorString));
345 fail(
"Stmt didn't result in analysis error: " + stmt);
361 Preconditions.checkState(tbl.isFullyQualified());
362 Preconditions.checkState(query.contains(
"$TBL"));
363 String uqQuery = query.replace(
"$TBL", tbl.getTbl());
365 String fqQuery = query.replace(
"$TBL", tbl.toString());
374 String expectedError) {
375 Preconditions.checkState(tbl.isFullyQualified());
376 Preconditions.checkState(query.contains(
"$TBL"));
377 String uqQuery = query.replace(
"$TBL", tbl.getTbl());
379 String fqQuery = query.replace(
"$TBL", tbl.toString());
390 Assert.assertEquals(expr.getChildren().size(), 2);
392 Assert.assertTrue(expr.getChild(0).getType() == expr.getChild(1).getType()
393 || expr.getChild(0).getType().isNull() || expr.getChild(1).getType().isNull());
395 for (
Expr child: expr.getChildren()) {
402 AnalyzesOk(
"SELECT count(*) FROM functional_text_lzo.tinyinttable");
419 AnalyzesOk(
"select * from functional.AllTypes");
423 slotD.setIsMaterialized(
true);
425 descTbl.computeMemLayout();
426 Assert.assertEquals(97.0f, tupleD.getAvgSerializedSize());
437 int strSlotSize = PrimitiveType.STRING.getSlotSize();
440 strSlotSize, 48 + strSlotSize, 1, 3);
448 AnalyzesOk(
"select count(int_col), count(*) from functional.AllTypes");
452 slotD.setIsMaterialized(
true);
454 descTbl.computeMemLayout();
455 Assert.assertEquals(16.0f, aggDesc.getAvgSerializedSize());
456 Assert.assertEquals(16, aggDesc.getByteSize());
468 AnalyzesOk(
"select sum(int_col), count(*) from functional.AllTypes");
472 slotD.setIsMaterialized(
true);
474 descTbl.computeMemLayout();
475 Assert.assertEquals(16.0f, aggDesc.getAvgSerializedSize());
476 Assert.assertEquals(24, aggDesc.getByteSize());
485 AnalyzesOk(
"select * from functional.alltypes");
488 ArrayList<SlotDescriptor> slots = tupleD.getSlots();
490 slotD.setIsMaterialized(
true);
493 slots.get(0).setIsMaterialized(
false);
494 slots.get(7).setIsMaterialized(
false);
495 slots.get(9).setIsMaterialized(
false);
497 descTbl.computeMemLayout();
498 Assert.assertEquals(68.0f, tupleD.getAvgSerializedSize());
512 int strSlotSize = PrimitiveType.STRING.getSlotSize();
517 int nullIndicatorByte,
int nullIndicatorBit) {
518 Assert.assertEquals(byteSize, d.getByteSize());
519 Assert.assertEquals(byteOffset, d.getByteOffset());
520 Assert.assertEquals(nullIndicatorByte, d.getNullIndicatorByte());
521 Assert.assertEquals(nullIndicatorBit, d.getNullIndicatorBit());
525 int nullIndicatorByte,
int nullIndicatorBit) {
534 Assert.assertEquals(select.getResultExprs().
get(0).getType(), type);
551 AnalyzesOk(
"select int_col, str_col, bigint_col from functional.unsupported_types");
554 AnalyzesOk(
"select int_col, str_col, bigint_col from functional.unsupported_types");
557 AnalysisError(
"select bin_col from functional.unsupported_types",
558 "Unsupported type 'BINARY' in 'bin_col'.");
561 "from functional.unsupported_types",
562 "Unsupported type 'BINARY' in 'bin_col'.");
564 AnalysisError(
"select * from functional.unsupported_partition_types",
565 "Failed to load metadata for table: 'functional.unsupported_partition_types'");
568 AnalyzesOk(
"describe functional_hbase.allcomplextypes");
573 AnalyzesOk(
"select * from functional_hbase.alltypessmallbinary");
579 "Failed to load metadata for table: 'functional.bad_serde'");
585 AnalyzesOk(
"invalidate metadata functional.alltypessmall");
586 AnalyzesOk(
"invalidate metadata functional.alltypes_view");
587 AnalyzesOk(
"invalidate metadata functional.bad_serde");
588 AnalyzesOk(
"refresh functional.alltypessmall");
589 AnalyzesOk(
"refresh functional.alltypes_view");
594 AnalyzesOk(
"invalidate metadata functional.unknown_table");
595 AnalyzesOk(
"invalidate metadata unknown_db.unknown_table");
598 "Table does not exist: functional.unknown_table");
600 "Database does not exist: unknown_db");
606 AnalysisError(
"explain insert into table functional.alltypessmall " +
607 "partition (year=2009, month=4, year=10)" +
608 "select id, bool_col, tinyint_col, smallint_col, int_col, bigint_col, " +
609 "float_col, double_col, date_string_col, string_col, timestamp_col " +
610 "from functional.alltypes",
611 "Duplicate column 'year' in partition clause");
615 "select id from (select id+2 from functional_hbase.alltypessmall) a",
616 "Could not resolve column/field reference: 'id'");
619 AnalyzesOk(
"explain select * from functional.AllTypes");
622 AnalyzesOk(
"explain insert into table functional.alltypessmall " +
623 "partition (year=2009, month=4)" +
624 "select id, bool_col, tinyint_col, smallint_col, int_col, int_col, " +
625 "float_col, float_col, date_string_col, string_col, timestamp_col " +
626 "from functional.alltypes");
632 AnalyzesOk(
"select * from functional.AllTypes limit 10 * 10 + 10 - 10 % 10");
633 AnalyzesOk(
"select * from functional.AllTypes limit 1 ^ 0 | 3 & 3");
635 AnalyzesOk(
"select * from functional.AllTypes order by id limit 10 offset 1+2*3%4");
637 AnalyzesOk(
"select t5.id from (select id from functional.AllTypes order by id " +
638 "limit 10 offset 2) t5");
639 AnalyzesOk(
"with t5 as (select id from functional.AllTypes order by id limit 10 " +
640 "offset 2) select * from t5");
643 AnalyzesOk(
"select id, bool_col from functional.AllTypes limit CAST(10.0 AS INT)");
644 AnalyzesOk(
"select id, bool_col from functional.AllTypes limit " +
645 "CAST(NOT FALSE AS INT)");
646 AnalyzesOk(
"select * from functional.AllTypes order by id limit 10 " +
647 "offset CAST(1.0 AS INT)");
650 AnalysisError(
"select * from functional.AllTypes limit 10 - 20",
651 "LIMIT must be a non-negative integer: 10 - 20 = -10");
652 AnalysisError(
"select * from functional.AllTypes order by id limit 10 " +
654 "OFFSET must be a non-negative integer: 10 - 20 = -10");
657 AnalysisError(
"select * from functional.AllTypes limit 10.0",
658 "LIMIT expression must be an integer type but is 'DECIMAL(3,1)': 10.0");
659 AnalysisError(
"select * from functional.AllTypes limit NOT FALSE",
660 "LIMIT expression must be an integer type but is 'BOOLEAN': NOT FALSE");
661 AnalysisError(
"select * from functional.AllTypes limit CAST(\"asdf\" AS INT)",
662 "LIMIT expression evaluates to NULL: CAST('asdf' AS INT)");
663 AnalysisError(
"select * from functional.AllTypes order by id limit 10 " +
665 "OFFSET expression must be an integer type but is 'DECIMAL(3,1)': 10.0");
666 AnalysisError(
"select * from functional.AllTypes order by id limit 10 " +
667 "offset CAST('asdf' AS INT)",
668 "OFFSET expression evaluates to NULL: CAST('asdf' AS INT)");
671 AnalysisError(
"select id, bool_col from functional.AllTypes limit id < 10",
672 "LIMIT expression must be a constant expression: id < 10");
673 AnalysisError(
"select id, bool_col from functional.AllTypes order by id limit 10 " +
675 "OFFSET expression must be a constant expression: id < 10");
679 "OFFSET requires an ORDER BY clause: LIMIT 10 OFFSET 5");
680 AnalysisError(
"SELECT x.id FROM (SELECT id FROM alltypesagg LIMIT 5 OFFSET 5) x " +
681 "ORDER BY x.id LIMIT 100 OFFSET 4",
682 "OFFSET requires an ORDER BY clause: LIMIT 5 OFFSET 5");
684 "OFFSET requires an ORDER BY clause: OFFSET 5");
685 AnalyzesOk(
"SELECT id FROM functional.Alltypes ORDER BY bool_col OFFSET 5");
690 AnalyzesOk(
"show create table functional.AllTypes");
692 "SHOW CREATE TABLE not supported on VIEW: functional.alltypes_view");
694 "Table does not exist: functional.not_a_table");
696 "Table does not exist: default.doesnt_exist");
751 Assert.assertFalse(fns[1].compare(fns[0], Function.CompareMode.IS_SUPERTYPE_OF));
752 Assert.assertTrue(fns[1].compare(fns[2], Function.CompareMode.IS_SUPERTYPE_OF));
753 Assert.assertTrue(fns[1].compare(fns[3], Function.CompareMode.IS_SUPERTYPE_OF));
754 Assert.assertTrue(fns[1].compare(fns[4], Function.CompareMode.IS_SUPERTYPE_OF));
755 Assert.assertFalse(fns[1].compare(fns[5], Function.CompareMode.IS_SUPERTYPE_OF));
756 Assert.assertFalse(fns[1].compare(fns[6], Function.CompareMode.IS_SUPERTYPE_OF));
757 Assert.assertFalse(fns[1].compare(fns[7], Function.CompareMode.IS_SUPERTYPE_OF));
758 Assert.assertFalse(fns[1].compare(fns[8], Function.CompareMode.IS_SUPERTYPE_OF));
760 Assert.assertTrue(fns[1].compare(fns[2], Function.CompareMode.IS_INDISTINGUISHABLE));
761 Assert.assertTrue(fns[3].compare(fns[4], Function.CompareMode.IS_INDISTINGUISHABLE));
762 Assert.assertTrue(fns[5].compare(fns[6], Function.CompareMode.IS_INDISTINGUISHABLE));
763 Assert.assertFalse(fns[5].compare(fns[7], Function.CompareMode.IS_INDISTINGUISHABLE));
764 Assert.assertFalse(fns[5].compare(fns[8], Function.CompareMode.IS_INDISTINGUISHABLE));
765 Assert.assertTrue(fns[6].compare(fns[7], Function.CompareMode.IS_INDISTINGUISHABLE));
766 Assert.assertTrue(fns[6].compare(fns[8], Function.CompareMode.IS_INDISTINGUISHABLE));
767 Assert.assertTrue(fns[7].compare(fns[8], Function.CompareMode.IS_INDISTINGUISHABLE));
768 Assert.assertFalse(fns[1].compare(fns[3], Function.CompareMode.IS_INDISTINGUISHABLE));
769 Assert.assertFalse(fns[1].compare(fns[4], Function.CompareMode.IS_INDISTINGUISHABLE));
771 Assert.assertFalse(fns[9].compare(fns[4], Function.CompareMode.IS_SUPERTYPE_OF));
772 Assert.assertTrue(fns[2].compare(fns[9], Function.CompareMode.IS_SUPERTYPE_OF));
774 Assert.assertTrue(fns[8].compare(fns[10], Function.CompareMode.IS_SUPERTYPE_OF));
775 Assert.assertFalse(fns[10].compare(fns[8], Function.CompareMode.IS_SUPERTYPE_OF));
777 Assert.assertTrue(fns[11].compare(fns[12], Function.CompareMode.IS_SUPERTYPE_OF));
778 Assert.assertFalse(fns[11].compare(fns[13], Function.CompareMode.IS_SUPERTYPE_OF));
780 for (
int i = 0; i < fns.length; ++i) {
781 for (
int j = 0; j < fns.length; ++j) {
784 fns[i].compare(fns[i], Function.CompareMode.IS_IDENTICAL));
786 fns[i].compare(fns[i], Function.CompareMode.IS_INDISTINGUISHABLE));
788 fns[i].compare(fns[i], Function.CompareMode.IS_SUPERTYPE_OF));
790 Assert.assertFalse(fns[i].compare(fns[j], Function.CompareMode.IS_IDENTICAL));
791 if (fns[i].compare(fns[j],
Function.CompareMode.IS_INDISTINGUISHABLE)) {
795 fns[i].compare(fns[j], Function.CompareMode.IS_SUPERTYPE_OF) ||
796 fns[j].compare(fns[i],
Function.CompareMode.IS_SUPERTYPE_OF));
797 }
else if (fns[i].compare(fns[j],
Function.CompareMode.IS_INDISTINGUISHABLE)) {
800 fns[j].compare(fns[i], Function.CompareMode.IS_INDISTINGUISHABLE));
ParseNode AnalyzesOk(String stmt, Analyzer analyzer)
void TblsAnalyzeOk(String query, TableName tbl)
static final ScalarType NULL
static final ScalarType BIGINT
void checkBinaryExprs(Expr expr)
Db addTestDb(String dbName)
static ImpaladCatalog catalog_
ArrayList< Expr > getGroupingExprs()
static final ScalarType STRING
static TQueryCtx createQueryContext()
static Map< ScalarType, String > typeToLiteralValue_
void AnalysisError(String stmt, String expectedErrorString)
Analyzer createAnalyzer(String defaultDb)
void checkExprType(String query, Type type)
static final ScalarType BOOLEAN
Analyzer createAnalyzerUsingHiveColLabels()
ArrayList< FunctionCallExpr > getAggregateExprs()
void TblsAnalysisError(String query, TableName tbl, String expectedError)
ParseNode AnalyzesOk(String stmt, String expectedWarning)
static final ScalarType SMALLINT
void TestAnalyzeShowCreateTable()
static final ScalarType FLOAT
ParseNode AnalyzesOk(String stmt)
final List< Db > testDbs_
void TestFunctionMatching()
void addTestUda(String name, Type retType, Type...argTypes)
void AnalysisError(String stmt, Analyzer analyzer, String expectedErrorString)
ParseNode AnalyzesOk(String stmt, Analyzer analyzer, String expectedWarning)
void TestUnsupportedTypes()
Analyzer createAnalyzer(TQueryOptions queryOptions)
static final ScalarType DOUBLE
void TestLimitAndOffset()
Table addTestTable(String createTableSql)
static final ScalarType TINYINT
Function createFunction(boolean hasVarArgs, Type...args)
Function addTestFunction(String name, ScalarType arg, boolean varArgs)
ParseNode ParsesOk(String stmt)
static final ScalarType INT
final List< Table > testTables_
void checkSelectToThrift(SelectStmt node)
static AuthorizationConfig createAuthDisabledConfig()
void TestBinaryHBaseTable()
uint64_t Test(T *ht, const ProbeTuple *input, uint64_t num_tuples)
Function addTestFunction(String name, ArrayList< ScalarType > args, boolean varArgs)
void checkLayoutParams(SlotDescriptor d, int byteSize, int byteOffset, int nullIndicatorByte, int nullIndicatorBit)
void checkLayoutParams(String colAlias, int byteSize, int byteOffset, int nullIndicatorByte, int nullIndicatorBit)
void TestUnsupportedSerde()
Function addTestFunction(String db, String fnName, ArrayList< ScalarType > args, boolean varArgs)
void AnalysisError(String stmt)
static final ScalarType INVALID
void TestCompressedText()
static final String DEFAULT_DB
static final ScalarType TIMESTAMP
void testNonMaterializedSlots()