Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
ToSqlTest.java
Go to the documentation of this file.
1 // Copyright 2013 Cloudera Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 package com.cloudera.impala.analysis;
16 
17 import static org.junit.Assert.fail;
18 
19 import org.junit.Ignore;
20 import org.junit.Test;
21 
25 import com.google.common.base.Preconditions;
26 
27 // TODO: Expand this test, in particular, because view creation relies
28 // on producing correct SQL.
29 public class ToSqlTest extends AnalyzerTest {
30 
31  // Helpers for templated join tests.
32  private static final String[] joinConditions_ =
33  new String[] {"USING (id)", "ON (a.id = b.id)"};
34 
35  // All left semi join types.
36  private static final String[] leftSemiJoinTypes_ =
37  new String[] {"LEFT SEMI JOIN", "LEFT ANTI JOIN"};
38 
39  // All right semi join types.
40  private static final String[] rightSemiJoinTypes_ =
41  new String[] {"RIGHT SEMI JOIN", "RIGHT ANTI JOIN"};
42 
43  // All join types that take an ON or USING clause, i.e., all joins except CROSS JOIN.
44  private static final String[] joinTypes_;
45 
46  // Same as joinTypes_, but excluding semi joins.
47  private static final String[] nonSemiJoinTypes_;
48 
49  static {
50  // Exclude the NULL AWARE LEFT ANTI JOIN operator because it cannot
51  // be directly expressed via SQL.
52  joinTypes_ = new String[JoinOperator.values().length - 2];
53  int numNonSemiJoinTypes = JoinOperator.values().length - 2 -
55  nonSemiJoinTypes_ = new String[numNonSemiJoinTypes];
56  int i = 0;
57  int j = 0;
58  for (JoinOperator op: JoinOperator.values()) {
59  if (op.isCrossJoin() || op.isNullAwareLeftAntiJoin()) continue;
60  joinTypes_[i++] = op.toString();
61  if (op.isSemiJoin()) continue;
62  nonSemiJoinTypes_[j++] = op.toString();
63  }
64  }
65 
66  private static AnalysisContext.AnalysisResult analyze(String query, String defaultDb) {
67  try {
68  AnalysisContext analysisCtx = new AnalysisContext(catalog_,
69  TestUtils.createQueryContext(defaultDb, System.getProperty("user.name")),
71  analysisCtx.analyze(query);
72  AnalysisContext.AnalysisResult analysisResult = analysisCtx.getAnalysisResult();
73  Preconditions.checkNotNull(analysisResult.getStmt());
74  return analysisResult;
75  } catch (Exception e) {
76  e.printStackTrace();
77  fail("Failed to analyze query: " + query + "\n" + e.getMessage());
78  }
79  return null;
80  }
81 
82  private void testToSql(String query, String expected) {
83  testToSql(query, System.getProperty("user.name"), expected);
84  }
85 
86  private void testToSql(String query, String defaultDb, String expected) {
87  String actual = null;
88  try {
89  ParseNode node = AnalyzesOk(query, createAnalyzer(defaultDb));
90  actual = node.toSql();
91  if (!actual.equals(expected)) {
92  String msg = "Expected: " + expected + "\n Actual: " + actual + "\n";
93  System.err.println(msg);
94  fail(msg);
95  }
96  } catch (Exception e) {
97  e.printStackTrace();
98  fail("Failed to analyze query: " + query + "\n" + e.getMessage());
99  }
100  // Parse and analyze the resulting SQL to ensure its validity.
101  AnalyzesOk(actual, createAnalyzer(defaultDb));
102  }
103 
104  private void runTestTemplate(String sql, String expectedSql, String[]... testDims) {
105  Object[] testVector = new Object[testDims.length];
106  runTestTemplate(sql, expectedSql, 0, testVector, testDims);
107  }
108 
109  private void runTestTemplate(String sql, String expectedSql, int dim,
110  Object[] testVector, String[]... testDims) {
111  if (dim >= testDims.length) {
112  testToSql(String.format(sql, testVector), String.format(expectedSql, testVector));
113  return;
114  }
115  for (String s: testDims[dim]) {
116  testVector[dim] = s;
117  runTestTemplate(sql, expectedSql, dim + 1, testVector, testDims);
118  }
119  }
120 
135  private void TblsTestToSql(String query, TableName tbl, String expectedSql) {
136  Preconditions.checkState(tbl.isFullyQualified());
137  Preconditions.checkState(query.contains("$TBL"));
138  String uqQuery = query.replace("$TBL", tbl.getTbl());
139  testToSql(uqQuery, tbl.getDb(), expectedSql);
140  AnalyzesOk(uqQuery, createAnalyzer(tbl.getDb()));
141  String fqQuery = query.replace("$TBL", tbl.toString());
142  testToSql(fqQuery, expectedSql);
143  }
144 
145  @Test
146  public void selectListTest() {
147  testToSql("select 1234, 1234.0, 1234.0 + 1, 1234.0 + 1.0, 1 + 1, \"abc\" " +
148  "from functional.alltypes",
149  "SELECT 1234, 1234.0, 1234.0 + 1, 1234.0 + 1.0, 1 + 1, 'abc' " +
150  "FROM functional.alltypes");
151  // Test aliases.
152  testToSql("select 1234 i, 1234.0 as j, (1234.0 + 1) k, (1234.0 + 1.0) as l " +
153  "from functional.alltypes",
154  "SELECT 1234 i, 1234.0 j, (1234.0 + 1) k, (1234.0 + 1.0) l " +
155  "FROM functional.alltypes");
156  // Test select without from.
157  testToSql("select 1234 i, 1234.0 as j, (1234.0 + 1) k, (1234.0 + 1.0) as l",
158  "SELECT 1234 i, 1234.0 j, (1234.0 + 1) k, (1234.0 + 1.0) l");
159  // Test select without from.
160  testToSql("select null, 1234 < 5678, 1234.0 < 5678.0, 1234 < null " +
161  "from functional.alltypes",
162  "SELECT NULL, 1234 < 5678, 1234.0 < 5678.0, 1234 < NULL " +
163  "FROM functional.alltypes");
164  }
165 
166  private boolean isCollectionTableRef(String tableName) {
167  return tableName.split("\\.").length > 0;
168  }
169 
174  private void testAllTableAliases(String[] tables, String[] columns)
175  throws AnalysisException {
176  for (String tbl: tables) {
177  TableName tblName = new TableName("functional", tbl);
178  String uqAlias = tbl.substring(tbl.lastIndexOf(".") + 1);
179  String fqAlias = "functional." + tbl;
180  boolean isCollectionTblRef = isCollectionTableRef(tbl);
181  for (String col: columns) {
182  // Test implicit table aliases with unqualified and fully qualified
183  // table/view names. Unqualified table/view names should be fully
184  // qualified in the generated SQL (IMPALA-962).
185  TblsTestToSql(String.format("select %s from $TBL", col), tblName,
186  String.format("SELECT %s FROM %s", col, fqAlias));
187  TblsTestToSql(String.format("select %s.%s from $TBL", uqAlias, col), tblName,
188  String.format("SELECT %s.%s FROM %s", uqAlias, col, fqAlias));
189  // Only references to base tables/views have a fully-qualified implicit alias.
190  if (!isCollectionTblRef) {
191  TblsTestToSql(String.format("select %s.%s from $TBL", fqAlias, col), tblName,
192  String.format("SELECT %s.%s FROM %s", fqAlias, col, fqAlias));
193  }
194 
195  // Explicit table alias.
196  TblsTestToSql(String.format("select %s from $TBL a", col), tblName,
197  String.format("SELECT %s FROM %s a", col, fqAlias));
198  TblsTestToSql(String.format("select a.%s from $TBL a", col), tblName,
199  String.format("SELECT a.%s FROM %s a", col, fqAlias));
200  }
201  }
202 
203  // Multiple implicit fully-qualified aliases work.
204  for (String t1: tables) {
205  for (String t2: tables) {
206  if (t1 == t2) continue;
207  // Collection tables do not have a fully-qualified implicit alias.
208  if (isCollectionTableRef(t1) && isCollectionTableRef(t2)) continue;
209  for (String col: columns) {
210  testToSql(String.format(
211  "select functional.%s.%s, functional.%s.%s " +
212  "from functional.%s, functional.%s", t1, col, t2, col, t1, t2),
213  String.format("SELECT functional.%s.%s, functional.%s.%s " +
214  "FROM functional.%s, functional.%s", t1, col, t2, col, t1, t2));
215  }
216  }
217  }
218  }
219 
225  private void testChildTableRefs(String childTable, String childColumn) {
226  TableName tbl = new TableName("functional", "allcomplextypes");
227 
228  // Child table uses unqualified implicit alias of parent table.
230  String.format("select %s from $TBL, allcomplextypes.%s",
231  childColumn, childTable), tbl,
232  String.format("SELECT %s FROM %s, functional.allcomplextypes.%s",
233  childColumn, tbl.toSql(), childTable));
234  // Child table uses fully qualified implicit alias of parent table.
236  String.format("select %s from $TBL, functional.allcomplextypes.%s",
237  childColumn, childTable), tbl,
238  String.format("SELECT %s FROM %s, functional.allcomplextypes.%s",
239  childColumn, tbl.toSql(), childTable));
240  // Child table uses explicit alias of parent table.
242  String.format("select %s from $TBL a, a.%s",
243  childColumn, childTable), tbl,
244  String.format("SELECT %s FROM %s a, a.%s",
245  childColumn, tbl.toSql(), childTable));
246 
247  // Parent/child/child join.
249  String.format("select b.%s from $TBL a, a.%s b, a.int_map_col c",
250  childColumn, childTable), tbl,
251  String.format("SELECT b.%s FROM %s a, a.%s b, a.int_map_col c",
252  childColumn, tbl.toSql(), childTable));
254  String.format("select c.%s from $TBL a, a.int_array_col b, a.%s c",
255  childColumn, childTable), tbl,
256  String.format("SELECT c.%s FROM %s a, a.int_array_col b, a.%s c",
257  childColumn, tbl.toSql(), childTable));
258 
259  // Test join types. Parent/child joins do not require an ON or USING clause.
260  for (String joinType: joinTypes_) {
261  TblsTestToSql(String.format("select 1 from $TBL %s allcomplextypes.%s",
262  joinType, childTable), tbl,
263  String.format("SELECT 1 FROM %s %s functional.allcomplextypes.%s",
264  tbl.toSql(), joinType, childTable));
265  TblsTestToSql(String.format("select 1 from $TBL a %s a.%s",
266  joinType, childTable), tbl,
267  String.format("SELECT 1 FROM %s a %s a.%s",
268  tbl.toSql(), joinType, childTable));
269  }
270 
271  // Legal, but not a parent/child join.
273  String.format("select %s from $TBL a, functional.allcomplextypes.%s",
274  childColumn, childTable), tbl,
275  String.format("SELECT %s FROM %s a, functional.allcomplextypes.%s",
276  childColumn, tbl.toSql(), childTable));
278  String.format("select %s from $TBL.%s, functional.allcomplextypes",
279  childColumn, childTable), tbl,
280  String.format("SELECT %s FROM %s.%s, functional.allcomplextypes",
281  childColumn, tbl.toSql(), childTable));
282  }
283 
284  @Test
285  public void TestTableAliases() throws AnalysisException {
286  String[] tables = new String[] { "alltypes", "alltypes_view" };
287  String[] columns = new String[] { "int_col", "*" };
288  testAllTableAliases(tables, columns);
289 
290  // Unqualified '*' is not ambiguous.
291  testToSql("select * from functional.alltypes " +
292  "cross join functional_parquet.alltypes",
293  "SELECT * FROM functional.alltypes CROSS JOIN functional_parquet.alltypes");
294  }
295 
296  @Test
297  public void TestStructFields() throws AnalysisException {
298  String[] tables = new String[] { "allcomplextypes", };
299  String[] columns = new String[] { "id", "int_struct_col.f1",
300  "nested_struct_col.f2.f12.f21" };
301  testAllTableAliases(tables, columns);
302  }
303 
304  @Test
306  // Test ARRAY type referenced as a table.
307  testAllTableAliases(new String[] {
308  "allcomplextypes.int_array_col"},
309  new String[] {Path.ARRAY_ITEM_FIELD_NAME, "*"});
310  testAllTableAliases(new String[] {
311  "allcomplextypes.struct_array_col"},
312  new String[] {"f1", "f2", "*"});
313 
314  // Test MAP type referenced as a table.
315  testAllTableAliases(new String[] {
316  "allcomplextypes.int_map_col"},
317  new String[] {
320  "*"});
321  testAllTableAliases(new String[] {
322  "allcomplextypes.struct_map_col"},
323  new String[] {Path.MAP_KEY_FIELD_NAME, "f1", "f2", "*"});
324 
325  // Test complex table ref path with structs and multiple collections.
326  testAllTableAliases(new String[] {
327  "allcomplextypes.complex_nested_struct_col.f2.f12"},
328  new String[] {Path.MAP_KEY_FIELD_NAME, "f21", "*"});
329 
330  // Test toSql() of child table refs.
333  testChildTableRefs("complex_nested_struct_col.f2.f12", "f21");
334  }
335 
340  @Test
341  public void TestIdentifierQuoting() {
342  // The quotes of quoted identifiers will be removed if they are unnecessary.
343  testToSql("select 1 as `abc`, 2.0 as 'xyz'", "SELECT 1 abc, 2.0 xyz");
344 
345  // These identifiers are lexable by Impala but not Hive. For view compatibility
346  // we enclose the idents in quotes.
347  testToSql("select 1 as _c0, 2.0 as $abc", "SELECT 1 `_c0`, 2.0 `$abc`");
348 
349  // Quoted identifiers that require quoting in both Impala and Hive.
350  testToSql("select 1 as `???`, 2.0 as '^^^'", "SELECT 1 `???`, 2.0 `^^^`");
351 
352  // Test quoting of identifiers that are Impala keywords.
353  testToSql("select `end`.`alter`, `end`.`table` from " +
354  "(select 1 as `alter`, 2 as `table`) `end`",
355  "SELECT `end`.`alter`, `end`.`table` FROM " +
356  "(SELECT 1 `alter`, 2 `table`) `end`");
357 
358  // Test quoting of inline view aliases.
359  testToSql("select a from (select 1 as a) as _t",
360  "SELECT a FROM (SELECT 1 a) `_t`");
361 
362  // Test quoting of WITH-clause views.
363  testToSql("with _t as (select 1 as a) select * from _t",
364  "WITH `_t` AS (SELECT 1 a) SELECT * FROM `_t`");
365 
366  // Test quoting of non-SlotRef exprs in inline views.
367  testToSql("select `1 + 10`, `trim('abc')` from (select 1 + 10, trim('abc')) as t",
368  "SELECT `1 + 10`, `trim('abc')` FROM (SELECT 1 + 10, trim('abc')) t");
369  }
370 
371  // Test the toSql() output of the where clause.
372  @Test
373  public void whereTest() {
374  testToSql("select id from functional.alltypes " +
375  "where tinyint_col < 40 OR int_col = 4 AND float_col > 1.4",
376  "SELECT id FROM functional.alltypes " +
377  "WHERE tinyint_col < 40 OR int_col = 4 AND float_col > 1.4");
378  testToSql("select id from functional.alltypes where string_col = \"abc\"",
379  "SELECT id FROM functional.alltypes WHERE string_col = 'abc'");
380  testToSql("select id from functional.alltypes where string_col = 'abc'",
381  "SELECT id FROM functional.alltypes WHERE string_col = 'abc'");
382  testToSql("select id from functional.alltypes " +
383  "where 5 between smallint_col and int_col",
384  "SELECT id FROM functional.alltypes WHERE 5 BETWEEN smallint_col AND int_col");
385  testToSql("select id from functional.alltypes " +
386  "where 5 not between smallint_col and int_col",
387  "SELECT id FROM functional.alltypes " +
388  "WHERE 5 NOT BETWEEN smallint_col AND int_col");
389  testToSql("select id from functional.alltypes where 5 in (smallint_col, int_col)",
390  "SELECT id FROM functional.alltypes WHERE 5 IN (smallint_col, int_col)");
391  testToSql("select id from functional.alltypes " +
392  "where 5 not in (smallint_col, int_col)",
393  "SELECT id FROM functional.alltypes WHERE 5 NOT IN (smallint_col, int_col)");
394  }
395 
396  // Test the toSql() output of joins in a standalone select block.
397  @Test
398  public void joinTest() {
399  testToSql("select * from functional.alltypes a, functional.alltypes b " +
400  "where a.id = b.id",
401  "SELECT * FROM functional.alltypes a, functional.alltypes b WHERE a.id = b.id");
402  testToSql("select * from functional.alltypes a cross join functional.alltypes b",
403  "SELECT * FROM functional.alltypes a CROSS JOIN functional.alltypes b");
404  runTestTemplate("select * from functional.alltypes a %s functional.alltypes b %s",
405  "SELECT * FROM functional.alltypes a %s functional.alltypes b %s",
407  }
408 
414  @Test
415  public void planHintsTest() {
416  String[][] hintStyles = new String[][] {
417  new String[] { "/* +", "*/" }, // traditional commented hint
418  new String[] { "\n-- +", "\n" }, // eol commented hint
419  new String[] { "[", "]" } // legacy style
420  };
421  for (String[] hintStyle: hintStyles) {
422  String prefix = hintStyle[0];
423  String suffix = hintStyle[1];
424 
425  // Join hint.
426  testToSql(String.format(
427  "select * from functional.alltypes a join %sbroadcast%s " +
428  "functional.alltypes b on a.id = b.id", prefix, suffix),
429  "SELECT * FROM functional.alltypes a INNER JOIN \n-- +broadcast\n " +
430  "functional.alltypes b ON a.id = b.id");
431 
432  // Insert hint.
433  testToSql(String.format(
434  "insert into functional.alltypes(int_col, bool_col) " +
435  "partition(year, month) %snoshuffle%s " +
436  "select int_col, bool_col, year, month from functional.alltypes",
437  prefix, suffix),
438  "INSERT INTO TABLE functional.alltypes(int_col, bool_col) " +
439  "PARTITION (year, month) \n-- +noshuffle\n " +
440  "SELECT int_col, bool_col, year, month FROM functional.alltypes");
441 
442  // Select-list hint. The legacy-style hint has no prefix and suffix.
443  if (prefix.contains("[")) {
444  prefix = "";
445  suffix = "";
446  }
447  // Comment-style select-list plan hint.
448  testToSql(String.format(
449  "select %sstraight_join%s * from functional.alltypes", prefix, suffix),
450  "SELECT \n-- +straight_join\n * FROM functional.alltypes");
451  testToSql(
452  String.format("select distinct %sstraight_join%s * from functional.alltypes",
453  prefix, suffix),
454  "SELECT DISTINCT \n-- +straight_join\n * FROM functional.alltypes");
455  }
456  }
457 
458  // Test the toSql() output of aggregate and group by expressions.
459  @Test
460  public void aggregationTest() {
461  testToSql("select COUNT(*), count(id), COUNT(id), SUM(id), AVG(id) " +
462  "from functional.alltypes group by tinyint_col",
463  "SELECT count(*), count(id), count(id), sum(id), avg(id) " +
464  "FROM functional.alltypes GROUP BY tinyint_col");
465  testToSql("select avg(float_col / id) from functional.alltypes group by tinyint_col",
466  "SELECT avg(float_col / id) " +
467  "FROM functional.alltypes GROUP BY tinyint_col");
468  testToSql("select avg(double_col) from functional.alltypes " +
469  "group by int_col, tinyint_col, bigint_col",
470  "SELECT avg(double_col) FROM functional.alltypes " +
471  "GROUP BY int_col, tinyint_col, bigint_col");
472  // Group by with having clause
473  testToSql("select avg(id) from functional.alltypes " +
474  "group by tinyint_col having count(tinyint_col) > 10",
475  "SELECT avg(id) FROM functional.alltypes " +
476  "GROUP BY tinyint_col HAVING count(tinyint_col) > 10");
477  testToSql("select sum(id) from functional.alltypes group by tinyint_col " +
478  "having avg(tinyint_col) > 10 AND count(tinyint_col) > 5",
479  "SELECT sum(id) FROM functional.alltypes GROUP BY tinyint_col " +
480  "HAVING avg(tinyint_col) > 10 AND count(tinyint_col) > 5");
481  }
482 
483  // Test the toSql() output of the order by clause.
484  @Test
485  public void orderByTest() {
486  testToSql("select id, string_col from functional.alltypes " +
487  "order by string_col ASC, float_col DESC, int_col ASC",
488  "SELECT id, string_col FROM functional.alltypes " +
489  "ORDER BY string_col ASC, float_col DESC, int_col ASC");
490  testToSql("select id, string_col from functional.alltypes " +
491  "order by string_col DESC, float_col ASC, int_col DESC",
492  "SELECT id, string_col FROM functional.alltypes " +
493  "ORDER BY string_col DESC, float_col ASC, int_col DESC");
494  testToSql("select id, string_col from functional.alltypes " +
495  "order by string_col ASC NULLS FIRST, float_col DESC NULLS LAST, " +
496  "int_col DESC",
497  "SELECT id, string_col FROM functional.alltypes " +
498  "ORDER BY string_col ASC NULLS FIRST, float_col DESC NULLS LAST, " +
499  "int_col DESC");
500  // Test limit/offset
501  testToSql("select id, string_col from functional.alltypes " +
502  "order by string_col ASC NULLS FIRST, float_col DESC NULLS LAST, " +
503  "int_col DESC LIMIT 10 OFFSET 5",
504  "SELECT id, string_col FROM functional.alltypes " +
505  "ORDER BY string_col ASC NULLS FIRST, float_col DESC NULLS LAST, " +
506  "int_col DESC LIMIT 10 OFFSET 5");
507  // Offset shouldn't be printed if it's not necessary
508  testToSql("select id, string_col from functional.alltypes " +
509  "order by string_col ASC NULLS FIRST, float_col DESC NULLS LAST, " +
510  "int_col DESC LIMIT 10 OFFSET 0",
511  "SELECT id, string_col FROM functional.alltypes " +
512  "ORDER BY string_col ASC NULLS FIRST, float_col DESC NULLS LAST, " +
513  "int_col DESC LIMIT 10");
514 
515  // Check we do not print NULLS FIRST/LAST unless necessary
516  testToSql("select id, string_col from functional.alltypes " +
517  "order by string_col DESC NULLS FIRST, float_col ASC NULLS LAST, " +
518  "int_col DESC",
519  "SELECT id, string_col FROM functional.alltypes " +
520  "ORDER BY string_col DESC, float_col ASC, " +
521  "int_col DESC");
522  }
523 
524  // Test the toSql() output of queries with all clauses.
525  @Test
526  public void allTest() {
527  testToSql("select bigint_col, avg(double_col), sum(tinyint_col) " +
528  "from functional.alltypes " +
529  "where double_col > 2.5 AND string_col != \"abc\"" +
530  "group by bigint_col, int_col " +
531  "having count(int_col) > 10 OR sum(bigint_col) > 20 " +
532  "order by 2 DESC NULLS LAST, 3 ASC",
533  "SELECT bigint_col, avg(double_col), sum(tinyint_col) " +
534  "FROM functional.alltypes " +
535  "WHERE double_col > 2.5 AND string_col != 'abc' " +
536  "GROUP BY bigint_col, int_col " +
537  "HAVING count(int_col) > 10 OR sum(bigint_col) > 20 " +
538  "ORDER BY 2 DESC NULLS LAST, 3 ASC");
539  }
540 
541  @Test
542  public void unionTest() {
543  testToSql("select bool_col, rank() over(order by id) from functional.alltypes " +
544  "union select bool_col, int_col from functional.alltypessmall " +
545  "union select bool_col, bigint_col from functional.alltypes",
546  "SELECT bool_col, rank() OVER (ORDER BY id ASC) FROM functional.alltypes " +
547  "UNION SELECT bool_col, int_col FROM functional.alltypessmall " +
548  "UNION SELECT bool_col, bigint_col FROM functional.alltypes");
549  testToSql("select bool_col, int_col from functional.alltypes " +
550  "union all select bool_col, int_col from functional.alltypessmall " +
551  "union all select bool_col, int_col from functional.alltypessmall " +
552  "union all select bool_col, int_col from functional.alltypessmall " +
553  "union all select bool_col, bigint_col from functional.alltypes",
554  "SELECT bool_col, int_col FROM functional.alltypes " +
555  "UNION ALL SELECT bool_col, int_col FROM functional.alltypessmall " +
556  "UNION ALL SELECT bool_col, int_col FROM functional.alltypessmall " +
557  "UNION ALL SELECT bool_col, int_col FROM functional.alltypessmall " +
558  "UNION ALL SELECT bool_col, bigint_col FROM functional.alltypes");
559  // With 'order by' and 'limit' on union, and also on last select.
560  testToSql("(select bool_col, int_col from functional.alltypes) " +
561  "union all (select bool_col, int_col from functional.alltypessmall) " +
562  "union all (select bool_col, bigint_col " +
563  "from functional.alltypes order by 1 nulls first limit 1) " +
564  "order by int_col nulls first, bool_col limit 5 + 5",
565  "SELECT bool_col, int_col FROM functional.alltypes " +
566  "UNION ALL SELECT bool_col, int_col FROM functional.alltypessmall " +
567  "UNION ALL SELECT bool_col, bigint_col " +
568  "FROM functional.alltypes ORDER BY 1 ASC NULLS FIRST LIMIT 1 " +
569  "ORDER BY int_col ASC NULLS FIRST, bool_col ASC LIMIT 5 + 5");
570  // With 'order by' and 'limit' on union but not on last select.
571  testToSql("select bool_col, int_col from functional.alltypes " +
572  "union all select bool_col, int_col from functional.alltypessmall " +
573  "union all (select bool_col, bigint_col from functional.alltypes) " +
574  "order by int_col nulls first, bool_col limit 10",
575  "SELECT bool_col, int_col FROM functional.alltypes " +
576  "UNION ALL SELECT bool_col, int_col FROM functional.alltypessmall " +
577  "UNION ALL (SELECT bool_col, bigint_col FROM functional.alltypes) " +
578  "ORDER BY int_col ASC NULLS FIRST, bool_col ASC LIMIT 10");
579  // Nested unions require parenthesis.
580  testToSql("select bool_col, int_col from functional.alltypes " +
581  "union all (select bool_col, int_col from functional.alltypessmall " +
582  "union distinct (select bool_col, bigint_col from functional.alltypes)) " +
583  "order by int_col, bool_col limit 10",
584  "SELECT bool_col, int_col FROM functional.alltypes UNION ALL " +
585  "(SELECT bool_col, int_col FROM functional.alltypessmall " +
586  "UNION SELECT bool_col, bigint_col FROM functional.alltypes) " +
587  "ORDER BY int_col ASC, bool_col ASC LIMIT 10");
588  }
589 
590  @Test
591  public void valuesTest() {
592  testToSql("values(1, 'a', 1.0)", "VALUES(1, 'a', 1.0)");
593  testToSql("values(1 as x, 'a' y, 1.0 as z)", "VALUES(1 x, 'a' y, 1.0 z)");
594  testToSql("values(1, 'a'), (2, 'b'), (3, 'c')",
595  "VALUES((1, 'a'), (2, 'b'), (3, 'c'))");
596  testToSql("values(1 x, 'a' as y), (2 as y, 'b'), (3, 'c' x)",
597  "VALUES((1 x, 'a' y), (2 y, 'b'), (3, 'c' x))");
598  testToSql("select * from (values(1, 'a'), (2, 'b')) as t",
599  "SELECT * FROM (VALUES((1, 'a'), (2, 'b'))) t");
600  testToSql("values(1, 'a'), (2, 'b') union all values(3, 'c')",
601  "VALUES((1, 'a'), (2, 'b')) UNION ALL (VALUES(3, 'c'))");
602  testToSql("insert into table functional.alltypessmall " +
603  "partition (year=2009, month=4) " +
604  "values(1, true, 1, 1, 10, 10, 10.0, 10.0, 'a', 'a', cast (0 as timestamp))",
605  "INSERT INTO TABLE functional.alltypessmall PARTITION (year=2009, month=4) " +
606  "VALUES(1, TRUE, 1, 1, 10, 10, 10.0, 10.0, 'a', 'a', CAST(0 AS TIMESTAMP))");
607  }
608 
612  @Test
613  public void inlineViewTest() {
614  // Test joins in an inline view.
615  testToSql("select t.* from " +
616  "(select a.* from functional.alltypes a, functional.alltypes b " +
617  "where a.id = b.id) t",
618  "SELECT t.* FROM " +
619  "(SELECT a.* FROM functional.alltypes a, functional.alltypes b " +
620  "WHERE a.id = b.id) t");
621  testToSql("select t.* from (select a.* from functional.alltypes a " +
622  "cross join functional.alltypes b) t",
623  "SELECT t.* FROM (SELECT a.* FROM functional.alltypes a " +
624  "CROSS JOIN functional.alltypes b) t");
625  runTestTemplate("select t.* from (select a.* from functional.alltypes a %s " +
626  "functional.alltypes b %s) t",
627  "SELECT t.* FROM (SELECT a.* FROM functional.alltypes a %s " +
628  "functional.alltypes b %s) t", nonSemiJoinTypes_, joinConditions_);
629  runTestTemplate("select t.* from (select a.* from functional.alltypes a %s " +
630  "functional.alltypes b %s) t",
631  "SELECT t.* FROM (SELECT a.* FROM functional.alltypes a %s " +
632  "functional.alltypes b %s) t", leftSemiJoinTypes_, joinConditions_);
633  runTestTemplate("select t.* from (select b.* from functional.alltypes a %s " +
634  "functional.alltypes b %s) t",
635  "SELECT t.* FROM (SELECT b.* FROM functional.alltypes a %s " +
636  "functional.alltypes b %s) t", rightSemiJoinTypes_, joinConditions_);
637 
638  // Test undoing expr substitution in select-list exprs and on clause.
639  testToSql("select t1.int_col, t2.int_col from " +
640  "(select int_col, rank() over (order by int_col) from functional.alltypes) " +
641  "t1 inner join " +
642  "(select int_col from functional.alltypes) t2 on (t1.int_col = t2.int_col)",
643  "SELECT t1.int_col, t2.int_col FROM " +
644  "(SELECT int_col, rank() OVER (ORDER BY int_col ASC) " +
645  "FROM functional.alltypes) t1 INNER JOIN " +
646  "(SELECT int_col FROM functional.alltypes) t2 ON (t1.int_col = t2.int_col)");
647  // Test undoing expr substitution in aggregates and group by and having clause.
648  testToSql("select count(t1.string_col), sum(t2.float_col) from " +
649  "(select id, string_col from functional.alltypes) t1 inner join " +
650  "(select id, float_col from functional.alltypes) t2 on (t1.id = t2.id) " +
651  "group by t1.id, t2.id having count(t2.float_col) > 2",
652  "SELECT count(t1.string_col), sum(t2.float_col) FROM " +
653  "(SELECT id, string_col FROM functional.alltypes) t1 INNER JOIN " +
654  "(SELECT id, float_col FROM functional.alltypes) t2 ON (t1.id = t2.id) " +
655  "GROUP BY t1.id, t2.id HAVING count(t2.float_col) > 2");
656  // Test undoing expr substitution in order by clause.
657  testToSql("select t1.id, t2.id from " +
658  "(select id, string_col from functional.alltypes) t1 inner join " +
659  "(select id, float_col from functional.alltypes) t2 on (t1.id = t2.id) " +
660  "order by t1.id, t2.id nulls first",
661  "SELECT t1.id, t2.id FROM " +
662  "(SELECT id, string_col FROM functional.alltypes) t1 INNER JOIN " +
663  "(SELECT id, float_col FROM functional.alltypes) t2 ON (t1.id = t2.id) " +
664  "ORDER BY t1.id ASC, t2.id ASC NULLS FIRST");
665  // Test undoing expr substitution in where-clause conjuncts.
666  testToSql("select t1.id, t2.id from " +
667  "(select id, string_col from functional.alltypes) t1, " +
668  "(select id, float_col from functional.alltypes) t2 " +
669  "where t1.id = t2.id and t1.string_col = 'abc' and t2.float_col < 10",
670  "SELECT t1.id, t2.id FROM " +
671  "(SELECT id, string_col FROM functional.alltypes) t1, " +
672  "(SELECT id, float_col FROM functional.alltypes) t2 " +
673  "WHERE t1.id = t2.id AND t1.string_col = 'abc' AND t2.float_col < 10");
674  }
675 
679  // TODO Fix testToSql to print the stmt after the first analysis phase and not
680  // after the rewrite.
681  @Ignore("Prints the rewritten statement")
682  @Test
683  public void subqueryTest() {
684  // Nested predicates
685  testToSql("select * from functional.alltypes where id in " +
686  "(select id from functional.alltypestiny)",
687  "SELECT * FROM functional.alltypes WHERE id IN " +
688  "(SELECT id FROM functional.alltypestiny)");
689  testToSql("select * from functional.alltypes where id not in " +
690  "(select id from functional.alltypestiny)",
691  "SELECT * FROM functional.alltypes WHERE id NOT IN " +
692  "(SELECT id FROM functional.alltypestiny)");
693  testToSql("select * from functional.alltypes where bigint_col = " +
694  "(select count(*) from functional.alltypestiny)",
695  "SELECT * FROM functional.alltypes WHERE bigint_col = " +
696  "(SELECT count(*) FROM functional.alltypestiny)");
697  testToSql("select * from functional.alltypes where exists " +
698  "(select * from functional.alltypestiny)",
699  "SELECT * FROM functional.alltypes WHERE EXISTS " +
700  "(SELECT * FROM functional.alltypestiny)");
701  testToSql("select * from functional.alltypes where not exists " +
702  "(select * from functional.alltypestiny)",
703  "SELECT * FROM functional.alltypes WHERE NOT EXISTS " +
704  "(SELECT * FROM functional.alltypestiny)");
705  // Multiple nested predicates in the WHERE clause
706  testToSql("select * from functional.alltypes where not (id < 10 and " +
707  "(int_col in (select int_col from functional.alltypestiny)) and " +
708  "(string_col = (select max(string_col) from functional.alltypestiny)))",
709  "SELECT * FROM functional.alltypes WHERE NOT (id < 10 AND " +
710  "(int_col IN (SELECT int_col FROM functional.alltypestiny)) AND " +
711  "(string_col = (SELECT max(string_col) FROM functional.alltypestiny)))");
712  // Multiple nesting levels
713  testToSql("select * from functional.alltypes where id in " +
714  "(select id from functional.alltypestiny where int_col = " +
715  "(select avg(int_col) from functional.alltypesagg))",
716  "SELECT * FROM functional.alltypes WHERE id IN " +
717  "(SELECT id FROM functional.alltypestiny WHERE int_col = " +
718  "(SELECT avg(int_col) FROM functional.alltypesagg))");
719  // Inline view with a subquery
720  testToSql("select * from (select id from functional.alltypes where " +
721  "int_col in (select int_col from functional.alltypestiny)) t where " +
722  "t.id < 10",
723  "SELECT * FROM (SELECT id FROM functional.alltypes WHERE " +
724  "int_col IN (SELECT int_col FROM functional.alltypestiny)) t WHERE " +
725  "t.id < 10");
726  // Subquery in a WITH clause
727  testToSql("with t as (select * from functional.alltypes where id in " +
728  "(select id from functional.alltypestiny)) select * from t",
729  "WITH t AS (SELECT * FROM functional.alltypes WHERE id IN " +
730  "(SELECT id FROM functional.alltypestiny)) SELECT * FROM t");
731  testToSql("with t as (select * from functional.alltypes s where id in " +
732  "(select id from functional.alltypestiny t where s.id = t.id)) " +
733  "select * from t t1, t t2 where t1.id = t2.id",
734  "WITH t AS (SELECT * FROM functional.alltypes s WHERE id IN " +
735  "(SELECT id FROM functional.alltypestiny t WHERE s.id = t.id)) " +
736  "SELECT * FROM t t1, t t2 WHERE t1.id = t2.id");
737  }
738 
739  @Test
740  public void withClauseTest() {
741  // WITH clause in select stmt.
742  testToSql("with t as (select * from functional.alltypes) select * from t",
743  "WITH t AS (SELECT * FROM functional.alltypes) SELECT * FROM t");
744  testToSql("with t as (select sum(int_col) over(partition by tinyint_col, " +
745  "bool_col order by float_col rows between unbounded preceding and " +
746  "current row) as x from functional.alltypes) " +
747  "select t1.x, t2.x from t t1 join t t2 on (t1.x = t2.x)",
748  "WITH t AS (SELECT sum(int_col) OVER (PARTITION BY tinyint_col, bool_col " +
749  "ORDER BY float_col ASC ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) " +
750  "x FROM functional.alltypes) SELECT t1.x, t2.x FROM t t1 INNER JOIN t t2 ON " +
751  "(t1.x = t2.x)");
752  // WITH clause in select stmt with a join and an ON clause.
753  testToSql("with t as (select * from functional.alltypes) " +
754  "select * from t a inner join t b on (a.int_col = b.int_col)",
755  "WITH t AS (SELECT * FROM functional.alltypes) " +
756  "SELECT * FROM t a INNER JOIN t b ON (a.int_col = b.int_col)");
757  // WITH clause in select stmt with a join and a USING clause.
758  testToSql("with t as (select * from functional.alltypes) " +
759  "select * from t a inner join t b using(int_col)",
760  "WITH t AS (SELECT * FROM functional.alltypes) " +
761  "SELECT * FROM t a INNER JOIN t b USING (int_col)");
762  // WITH clause in a union stmt.
763  testToSql("with t1 as (select * from functional.alltypes)" +
764  "select * from t1 union all select * from t1",
765  "WITH t1 AS (SELECT * FROM functional.alltypes) " +
766  "SELECT * FROM t1 UNION ALL SELECT * FROM t1");
767  // WITH clause in values stmt.
768  testToSql("with t1 as (select * from functional.alltypes) values(1, 2), (3, 4)",
769  "WITH t1 AS (SELECT * FROM functional.alltypes) VALUES((1, 2), (3, 4))");
770  // WITH clause in insert stmt.
771  testToSql("with t1 as (select * from functional.alltypes) " +
772  "insert into functional.alltypes partition(year, month) select * from t1",
773  "WITH t1 AS (SELECT * FROM functional.alltypes) " +
774  "INSERT INTO TABLE functional.alltypes PARTITION (year, month) " +
775  "SELECT * FROM t1");
776  // Test joins in WITH-clause view.
777  testToSql("with t as (select a.* from functional.alltypes a, " +
778  "functional.alltypes b where a.id = b.id) select * from t",
779  "WITH t AS (SELECT a.* FROM functional.alltypes a, " +
780  "functional.alltypes b WHERE a.id = b.id) SELECT * FROM t");
781  testToSql("with t as (select a.* from functional.alltypes a " +
782  "cross join functional.alltypes b) select * from t",
783  "WITH t AS (SELECT a.* FROM functional.alltypes a " +
784  "CROSS JOIN functional.alltypes b) SELECT * FROM t");
785  runTestTemplate("with t as (select a.* from functional.alltypes a %s " +
786  "functional.alltypes b %s) select * from t",
787  "WITH t AS (SELECT a.* FROM functional.alltypes a %s " +
788  "functional.alltypes b %s) SELECT * FROM t", nonSemiJoinTypes_, joinConditions_);
789  runTestTemplate("with t as (select a.* from functional.alltypes a %s " +
790  "functional.alltypes b %s) select * from t",
791  "WITH t AS (SELECT a.* FROM functional.alltypes a %s " +
792  "functional.alltypes b %s) SELECT * FROM t",
794  runTestTemplate("with t as (select b.* from functional.alltypes a %s " +
795  "functional.alltypes b %s) select * from t",
796  "WITH t AS (SELECT b.* FROM functional.alltypes a %s " +
797  "functional.alltypes b %s) SELECT * FROM t",
799  // WITH clause in complex query with joins and and order by + limit.
800  testToSql("with t as (select int_col x, bigint_col y from functional.alltypestiny " +
801  "order by id nulls first limit 2) " +
802  "select * from t t1 left outer join t t2 on t1.y = t2.x " +
803  "full outer join t t3 on t2.y = t3.x order by t1.x nulls first limit 5 * 2",
804  "WITH t AS (SELECT int_col x, bigint_col y FROM functional.alltypestiny " +
805  "ORDER BY id ASC NULLS FIRST LIMIT 2) " +
806  "SELECT * FROM t t1 LEFT OUTER JOIN t t2 ON t1.y = t2.x " +
807  "FULL OUTER JOIN t t3 ON t2.y = t3.x ORDER BY t1.x ASC NULLS FIRST LIMIT 5 * 2");
808  }
809 
810  // Test the toSql() output of insert queries.
811  @Test
812  public void insertTest() {
813  // Insert into unpartitioned table without partition clause.
814  testToSql("insert into table functional.alltypesnopart " +
815  "select id, bool_col, tinyint_col, smallint_col, int_col, bigint_col, " +
816  "float_col, double_col, date_string_col, string_col, timestamp_col " +
817  "from functional.alltypes",
818  "INSERT INTO TABLE functional.alltypesnopart " +
819  "SELECT id, bool_col, tinyint_col, " +
820  "smallint_col, int_col, bigint_col, float_col, double_col, date_string_col, " +
821  "string_col, timestamp_col FROM functional.alltypes");
822  // Insert into overwrite unpartitioned table without partition clause.
823  testToSql("insert overwrite table functional.alltypesnopart " +
824  "select id, bool_col, tinyint_col, smallint_col, int_col, bigint_col, " +
825  "float_col, double_col, date_string_col, string_col, timestamp_col " +
826  "from functional.alltypes",
827  "INSERT OVERWRITE TABLE functional.alltypesnopart " +
828  "SELECT id, bool_col, tinyint_col, " +
829  "smallint_col, int_col, bigint_col, float_col, double_col, date_string_col, " +
830  "string_col, timestamp_col FROM functional.alltypes");
831  // Static partition.
832  testToSql("insert into table functional.alltypessmall " +
833  "partition (year=2009, month=4)" +
834  "select id, bool_col, tinyint_col, smallint_col, int_col, bigint_col, " +
835  "float_col, double_col, date_string_col, string_col, timestamp_col " +
836  "from functional.alltypes",
837  "INSERT INTO TABLE functional.alltypessmall " +
838  "PARTITION (year=2009, month=4) SELECT id, " +
839  "bool_col, tinyint_col, smallint_col, int_col, bigint_col, float_col, " +
840  "double_col, date_string_col, string_col, timestamp_col " +
841  "FROM functional.alltypes");
842  // Fully dynamic partitions.
843  testToSql("insert into table functional.alltypessmall " +
844  "partition (year, month)" +
845  "select id, bool_col, tinyint_col, smallint_col, int_col, bigint_col, " +
846  "float_col, double_col, date_string_col, string_col, timestamp_col, year, " +
847  "month from functional.alltypes",
848  "INSERT INTO TABLE functional.alltypessmall " +
849  "PARTITION (year, month) SELECT id, bool_col, " +
850  "tinyint_col, smallint_col, int_col, bigint_col, float_col, double_col, " +
851  "date_string_col, string_col, timestamp_col, year, month " +
852  "FROM functional.alltypes");
853  // Partially dynamic partitions.
854  testToSql("insert into table functional.alltypessmall " +
855  "partition (year=2009, month)" +
856  "select id, bool_col, tinyint_col, smallint_col, int_col, bigint_col, " +
857  "float_col, double_col, date_string_col, string_col, timestamp_col, month " +
858  "from functional.alltypes",
859  "INSERT INTO TABLE functional.alltypessmall " +
860  "PARTITION (year=2009, month) SELECT id, " +
861  "bool_col, tinyint_col, smallint_col, int_col, bigint_col, float_col, " +
862  "double_col, date_string_col, string_col, timestamp_col, month " +
863  "FROM functional.alltypes");
864 
865  // Permutations
866  testToSql("insert into table functional.alltypesnopart(id, bool_col, tinyint_col) " +
867  " values(1, true, 0)",
868  "INSERT INTO TABLE functional.alltypesnopart(id, bool_col, tinyint_col) " +
869  "VALUES(1, TRUE, 0)");
870 
871  // Permutations that mention partition column
872  testToSql("insert into table functional.alltypes(id, year, month) " +
873  " values(1, 1990, 12)",
874  "INSERT INTO TABLE functional.alltypes(id, year, month) " +
875  "VALUES(1, 1990, 12)");
876 
877  // Empty permutation with no select statement
878  testToSql("insert into table functional.alltypesnopart()",
879  "INSERT INTO TABLE functional.alltypesnopart()");
880 
881  // Permutation and explicit partition clause
882  testToSql("insert into table functional.alltypes(id) " +
883  " partition (year=2009, month) values(1, 12)",
884  "INSERT INTO TABLE functional.alltypes(id) " +
885  "PARTITION (year=2009, month) VALUES(1, 12)");
886  }
887 
888  @Test
889  public void testAnalyticExprs() {
890  testToSql(
891  "select sum(int_col) over (partition by id order by tinyint_col "
892  + "rows between unbounded preceding and current row) from functional.alltypes",
893  "SELECT sum(int_col) OVER (PARTITION BY id ORDER BY tinyint_col ASC ROWS "
894  + "BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM functional.alltypes");
895  }
896 
901  @Test
902  public void testExprs() {
903  // AggregateExpr.
904  testToSql("select count(*), (count(*)), avg(int_col), (avg(int_col)), " +
905  "sum(int_col), (sum(int_col)), min(int_col), (min(int_col)), " +
906  "max(int_col), (max(int_col)) from functional.alltypes",
907  "SELECT count(*), (count(*)), avg(int_col), (avg(int_col)), " +
908  "sum(int_col), (sum(int_col)), min(int_col), (min(int_col)), " +
909  "max(int_col), (max(int_col)) FROM functional.alltypes");
910  // ArithmeticExpr.
911  testToSql("select 1 * 1, (1 * 1), 2 / 2, (2 / 2), 3 % 3, (3 % 3), " +
912  "4 DIV 4, (4 DIV 4), 5 + 5, (5 + 5), 6 - 6, (6 - 6), 7 & 7, (7 & 7), " +
913  "8 | 8, (8 | 8), 9 ^ 9, (9 ^ 9), ~10, (~10)",
914  "SELECT 1 * 1, (1 * 1), 2 / 2, (2 / 2), 3 % 3, (3 % 3), " +
915  "4 DIV 4, (4 DIV 4), 5 + 5, (5 + 5), 6 - 6, (6 - 6), 7 & 7, (7 & 7), " +
916  "8 | 8, (8 | 8), 9 ^ 9, (9 ^ 9), ~10, (~10)");
917  testToSql("select (((1 + 2) * (3 - 4) + 6) / 7)",
918  "SELECT (((1 + 2) * (3 - 4) + 6) / 7)");
919 
920  // CaseExpr.
921  // Single case without else clause. No case expr.
922  testToSql("select case when true then 1 end, " +
923  "(case when true then 1 end)",
924  "SELECT CASE WHEN TRUE THEN 1 END, " +
925  "(CASE WHEN TRUE THEN 1 END)");
926  // Multiple cases with else clause. No case expr.
927  testToSql("select case when true then 1 when false then 2 else 3 end, " +
928  "(case when true then 1 when false then 2 else 3 end)",
929  "SELECT CASE WHEN TRUE THEN 1 WHEN FALSE THEN 2 ELSE 3 END, " +
930  "(CASE WHEN TRUE THEN 1 WHEN FALSE THEN 2 ELSE 3 END)");
931  // Multiple cases with else clause with case expr.
932  testToSql("select case true when true then 1 when false then 2 else 3 end, " +
933  "(case true when true then 1 when false then 2 else 3 end)",
934  "SELECT CASE TRUE WHEN TRUE THEN 1 WHEN FALSE THEN 2 ELSE 3 END, " +
935  "(CASE TRUE WHEN TRUE THEN 1 WHEN FALSE THEN 2 ELSE 3 END)");
936  // DECODE version of CaseExpr.
937  testToSql("select decode(1, 2, 3), (decode(4, 5, 6))",
938  "SELECT decode(1, 2, 3), (decode(4, 5, 6))");
939  testToSql("select decode(1, 2, 3, 4, 5, 6), (decode(1, 2, 3, 4, 5, 6))",
940  "SELECT decode(1, 2, 3, 4, 5, 6), (decode(1, 2, 3, 4, 5, 6))");
941 
942  // CastExpr.
943  testToSql("select cast(NULL as INT), (cast(NULL as INT))",
944  "SELECT CAST(NULL AS INT), (CAST(NULL AS INT))");
945  // FunctionCallExpr.
946  testToSql("select pi(), (pi()), trim('a'), (trim('a'))",
947  "SELECT pi(), (pi()), trim('a'), (trim('a'))");
948  // LiteralExpr.
949  testToSql("select 10, (10), 20.0, (20.0), NULL, (NULL), 'abc', ('abc')",
950  "SELECT 10, (10), 20.0, (20.0), NULL, (NULL), 'abc', ('abc')");
951  // BetweenPredicate.
952  testToSql("select 5 between 10 and 20, (5 between 10 and 20)",
953  "SELECT 5 BETWEEN 10 AND 20, (5 BETWEEN 10 AND 20)");
954  testToSql("select 5 not between 10 and 20, (5 not between 10 and 20)",
955  "SELECT 5 NOT BETWEEN 10 AND 20, (5 NOT BETWEEN 10 AND 20)");
956  // BinaryPredicate.
957  testToSql("select 'a' = 'b', ('a' = 'b'), 'a' != 'b', ('a' != 'b'), " +
958  "1 < 2, (1 < 2), 1 <= 2, (1 <= 2), 1 > 2, (1 > 2), 1 >= 2, (1 >= 2)",
959  "SELECT 'a' = 'b', ('a' = 'b'), 'a' != 'b', ('a' != 'b'), " +
960  "1 < 2, (1 < 2), 1 <= 2, (1 <= 2), 1 > 2, (1 > 2), 1 >= 2, (1 >= 2)");
961  // CompoundPredicate.
962  testToSql("select true and false, (true and false), " +
963  "false or true, (false or true), " +
964  "!true, (!true), not false, (not false)",
965  "SELECT TRUE AND FALSE, (TRUE AND FALSE), " +
966  "FALSE OR TRUE, (FALSE OR TRUE), " +
967  "NOT TRUE, (NOT TRUE), NOT FALSE, (NOT FALSE)");
968  testToSql("select ((true and (false or false) or true) and (false or true))",
969  "SELECT ((TRUE AND (FALSE OR FALSE) OR TRUE) AND (FALSE OR TRUE))");
970  // InPredicate.
971  testToSql("select 5 in (4, 6, 7, 5), (5 in (4, 6, 7, 5))," +
972  "5 not in (4, 6, 7, 5), (5 not In (4, 6, 7, 5))",
973  "SELECT 5 IN (4, 6, 7, 5), (5 IN (4, 6, 7, 5)), " +
974  "5 NOT IN (4, 6, 7, 5), (5 NOT IN (4, 6, 7, 5))");
975  // IsNullPredicate.
976  testToSql("select 5 is null, (5 is null), 10 is not null, (10 is not null)",
977  "SELECT 5 IS NULL, (5 IS NULL), 10 IS NOT NULL, (10 IS NOT NULL)");
978  // LikePredicate.
979  testToSql("select 'a' LIKE '%b.', ('a' LIKE '%b.'), " +
980  "'b' RLIKE '.c%', ('b' RLIKE '.c%')," +
981  "'d' REGEXP '.e%', ('d' REGEXP '.e%')",
982  "SELECT 'a' LIKE '%b.', ('a' LIKE '%b.'), " +
983  "'b' RLIKE '.c%', ('b' RLIKE '.c%'), " +
984  "'d' REGEXP '.e%', ('d' REGEXP '.e%')");
985  // SlotRef.
986  testToSql("select bool_col, (bool_col), int_col, (int_col) " +
987  "string_col, (string_col), timestamp_col, (timestamp_col) " +
988  "from functional.alltypes",
989  "SELECT bool_col, (bool_col), int_col, (int_col) " +
990  "string_col, (string_col), timestamp_col, (timestamp_col) " +
991  "FROM functional.alltypes");
992 
993  // TimestampArithmeticExpr.
994  // Non-function-call like version.
995  testToSql("select timestamp_col + interval 10 years, " +
996  "(timestamp_col + interval 10 years) from functional.alltypes",
997  "SELECT timestamp_col + INTERVAL 10 years, " +
998  "(timestamp_col + INTERVAL 10 years) FROM functional.alltypes");
999  testToSql("select timestamp_col - interval 20 months, " +
1000  "(timestamp_col - interval 20 months) from functional.alltypes",
1001  "SELECT timestamp_col - INTERVAL 20 months, " +
1002  "(timestamp_col - INTERVAL 20 months) FROM functional.alltypes");
1003  // Reversed interval and timestamp using addition.
1004  testToSql("select interval 30 weeks + timestamp_col, " +
1005  "(interval 30 weeks + timestamp_col) from functional.alltypes",
1006  "SELECT INTERVAL 30 weeks + timestamp_col, " +
1007  "(INTERVAL 30 weeks + timestamp_col) FROM functional.alltypes");
1008  // Function-call like version.
1009  testToSql("select date_add(timestamp_col, interval 40 days), " +
1010  "(date_add(timestamp_col, interval 40 days)) from functional.alltypes",
1011  "SELECT DATE_ADD(timestamp_col, INTERVAL 40 days), " +
1012  "(DATE_ADD(timestamp_col, INTERVAL 40 days)) FROM functional.alltypes");
1013  testToSql("select date_sub(timestamp_col, interval 40 hours), " +
1014  "(date_sub(timestamp_col, interval 40 hours)) from functional.alltypes",
1015  "SELECT DATE_SUB(timestamp_col, INTERVAL 40 hours), " +
1016  "(DATE_SUB(timestamp_col, INTERVAL 40 hours)) FROM functional.alltypes");
1017  }
1018 
1022  @Test
1023  public void testDecimal() {
1024  testToSql("select cast(1 as decimal)", "SELECT CAST(1 AS DECIMAL(9,0))");
1025  }
1026 
1030  @Test
1031  public void testSet() {
1032  testToSql("set a = 1", "SET a='1'");
1033  testToSql("set `a b` = \"x y\"", "SET `a b`='x y'");
1034  testToSql("set", "SET");
1035  }
1036 }
void runTestTemplate(String sql, String expectedSql, String[]...testDims)
Definition: ToSqlTest.java:104
void testToSql(String query, String defaultDb, String expected)
Definition: ToSqlTest.java:86
void TblsTestToSql(String query, TableName tbl, String expectedSql)
Definition: ToSqlTest.java:135
void testToSql(String query, String expected)
Definition: ToSqlTest.java:82
static final String[] leftSemiJoinTypes_
Definition: ToSqlTest.java:36
static final String[] joinConditions_
Definition: ToSqlTest.java:32
static final String[] joinTypes_
Definition: ToSqlTest.java:44
Analyzer createAnalyzer(String defaultDb)
void runTestTemplate(String sql, String expectedSql, int dim, Object[] testVector, String[]...testDims)
Definition: ToSqlTest.java:109
uint64_t Test(T *ht, const ProbeTuple *input, uint64_t num_tuples)
static final String MAP_VALUE_FIELD_NAME
Definition: Path.java:79
static AnalysisContext.AnalysisResult analyze(String query, String defaultDb)
Definition: ToSqlTest.java:66
static final String[] rightSemiJoinTypes_
Definition: ToSqlTest.java:40
static final String ARRAY_ITEM_FIELD_NAME
Definition: Path.java:76
static final String[] nonSemiJoinTypes_
Definition: ToSqlTest.java:47
void testChildTableRefs(String childTable, String childColumn)
Definition: ToSqlTest.java:225
boolean isCollectionTableRef(String tableName)
Definition: ToSqlTest.java:166
static final String MAP_KEY_FIELD_NAME
Definition: Path.java:78
void testAllTableAliases(String[] tables, String[] columns)
Definition: ToSqlTest.java:174