You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by jh...@apache.org on 2017/04/19 19:18:12 UTC
[1/3] calcite git commit: [CALCITE-1754] In Csv adapter,
convert DATE and TIME values to int, and TIMESTAMP values to long (Hongbin Ma)
Repository: calcite
Updated Branches:
refs/heads/master cd136985a -> cc8398742
[CALCITE-1754] In Csv adapter, convert DATE and TIME values to int, and TIMESTAMP values to long (Hongbin Ma)
Close apache/calcite#432
Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/cc839874
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/cc839874
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/cc839874
Branch: refs/heads/master
Commit: cc839874242c69a8199f92097eaf113e5195e4a3
Parents: 8b69e4d
Author: Hongbin Ma <ma...@apache.org>
Authored: Sun Apr 16 22:14:17 2017 +0800
Committer: Julian Hyde <jh...@apache.org>
Committed: Wed Apr 19 10:39:17 2017 -0700
----------------------------------------------------------------------
.../calcite/adapter/enumerable/RexImpTable.java | 6 +-
.../org/apache/calcite/util/BuiltInMethod.java | 1 +
.../calcite/adapter/csv/CsvEnumerator.java | 11 +--
.../calcite/adapter/csv/CsvFieldType.java | 4 +-
.../java/org/apache/calcite/test/CsvTest.java | 55 +++++++++++++
.../apache/calcite/adapter/file/SqlTest.java | 87 ++++++++++++++++++++
6 files changed, 157 insertions(+), 7 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/calcite/blob/cc839874/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
index 2182c7c..dc69ebb 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
@@ -2123,7 +2123,11 @@ public class RexImpTable {
case MINUS:
trop1 = Expressions.negate(trop1);
}
- return Expressions.call(BuiltInMethod.ADD_MONTHS.method, trop0, trop1);
+ final BuiltInMethod method =
+ operand0.getType().getSqlTypeName() == SqlTypeName.TIMESTAMP
+ ? BuiltInMethod.ADD_MONTHS
+ : BuiltInMethod.ADD_MONTHS_INT;
+ return Expressions.call(method.method, trop0, trop1);
case INTERVAL_DAY:
case INTERVAL_DAY_HOUR:
http://git-wip-us.apache.org/repos/asf/calcite/blob/cc839874/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
index 458444b..f5161b2 100644
--- a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
+++ b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
@@ -254,6 +254,7 @@ public enum BuiltInMethod {
FLOOR_DIV(DateTimeUtils.class, "floorDiv", long.class, long.class),
FLOOR_MOD(DateTimeUtils.class, "floorMod", long.class, long.class),
ADD_MONTHS(SqlFunctions.class, "addMonths", long.class, int.class),
+ ADD_MONTHS_INT(SqlFunctions.class, "addMonths", int.class, int.class),
SUBTRACT_MONTHS(SqlFunctions.class, "subtractMonths", long.class,
long.class),
FLOOR(SqlFunctions.class, "floor", int.class, int.class),
http://git-wip-us.apache.org/repos/asf/calcite/blob/cc839874/example/csv/src/main/java/org/apache/calcite/adapter/csv/CsvEnumerator.java
----------------------------------------------------------------------
diff --git a/example/csv/src/main/java/org/apache/calcite/adapter/csv/CsvEnumerator.java b/example/csv/src/main/java/org/apache/calcite/adapter/csv/CsvEnumerator.java
index 262c283..327464b 100644
--- a/example/csv/src/main/java/org/apache/calcite/adapter/csv/CsvEnumerator.java
+++ b/example/csv/src/main/java/org/apache/calcite/adapter/csv/CsvEnumerator.java
@@ -17,6 +17,7 @@
package org.apache.calcite.adapter.csv;
import org.apache.calcite.adapter.java.JavaTypeFactory;
+import org.apache.calcite.avatica.util.DateTimeUtils;
import org.apache.calcite.linq4j.Enumerator;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.sql.type.SqlTypeName;
@@ -142,7 +143,7 @@ class CsvEnumerator<E> implements Enumerator<E> {
}
final RelDataType type;
if (fieldType == null) {
- type = typeFactory.createJavaType(String.class);
+ type = typeFactory.createSqlType(SqlTypeName.VARCHAR);
} else {
type = fieldType.toType(typeFactory);
}
@@ -165,7 +166,7 @@ class CsvEnumerator<E> implements Enumerator<E> {
}
if (names.isEmpty()) {
names.add("line");
- types.add(typeFactory.createJavaType(String.class));
+ types.add(typeFactory.createSqlType(SqlTypeName.VARCHAR));
}
return typeFactory.createStructType(Pair.zip(names, types));
}
@@ -289,7 +290,7 @@ class CsvEnumerator<E> implements Enumerator<E> {
}
try {
Date date = TIME_FORMAT_DATE.parse(string);
- return new java.sql.Date(date.getTime());
+ return (int) (date.getTime() / DateTimeUtils.MILLIS_PER_DAY);
} catch (ParseException e) {
return null;
}
@@ -299,7 +300,7 @@ class CsvEnumerator<E> implements Enumerator<E> {
}
try {
Date date = TIME_FORMAT_TIME.parse(string);
- return new java.sql.Time(date.getTime());
+ return (int) date.getTime();
} catch (ParseException e) {
return null;
}
@@ -309,7 +310,7 @@ class CsvEnumerator<E> implements Enumerator<E> {
}
try {
Date date = TIME_FORMAT_TIMESTAMP.parse(string);
- return new java.sql.Timestamp(date.getTime());
+ return date.getTime();
} catch (ParseException e) {
return null;
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/cc839874/example/csv/src/main/java/org/apache/calcite/adapter/csv/CsvFieldType.java
----------------------------------------------------------------------
diff --git a/example/csv/src/main/java/org/apache/calcite/adapter/csv/CsvFieldType.java b/example/csv/src/main/java/org/apache/calcite/adapter/csv/CsvFieldType.java
index 7810926..cc9cd76 100644
--- a/example/csv/src/main/java/org/apache/calcite/adapter/csv/CsvFieldType.java
+++ b/example/csv/src/main/java/org/apache/calcite/adapter/csv/CsvFieldType.java
@@ -66,7 +66,9 @@ enum CsvFieldType {
}
public RelDataType toType(JavaTypeFactory typeFactory) {
- return typeFactory.createJavaType(clazz);
+ RelDataType javaType = typeFactory.createJavaType(clazz);
+ RelDataType sqlType = typeFactory.createSqlType(javaType.getSqlTypeName());
+ return typeFactory.createTypeWithNullability(sqlType, true);
}
public static CsvFieldType of(String typeString) {
http://git-wip-us.apache.org/repos/asf/calcite/blob/cc839874/example/csv/src/test/java/org/apache/calcite/test/CsvTest.java
----------------------------------------------------------------------
diff --git a/example/csv/src/test/java/org/apache/calcite/test/CsvTest.java b/example/csv/src/test/java/org/apache/calcite/test/CsvTest.java
index 8c2d1d3..5d731d6 100644
--- a/example/csv/src/test/java/org/apache/calcite/test/CsvTest.java
+++ b/example/csv/src/test/java/org/apache/calcite/test/CsvTest.java
@@ -25,6 +25,7 @@ import org.apache.calcite.util.Util;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Ordering;
import org.junit.Assert;
import org.junit.Ignore;
@@ -44,6 +45,7 @@ import java.sql.Statement;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
@@ -306,6 +308,26 @@ public class CsvTest {
};
}
+ /** Returns a function that checks the contents of a result set against an
+ * expected string. */
+ private static Function<ResultSet, Void> expectUnordered(String... expected) {
+ final List<String> expectedLines =
+ Ordering.natural().immutableSortedCopy(Arrays.asList(expected));
+ return new Function<ResultSet, Void>() {
+ public Void apply(ResultSet resultSet) {
+ try {
+ final List<String> lines = new ArrayList<>();
+ CsvTest.collect(lines, resultSet);
+ Collections.sort(lines);
+ Assert.assertEquals(expectedLines, lines);
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ return null;
+ }
+ };
+ }
+
private void checkSql(String sql, String model, Function<ResultSet, Void> fn)
throws SQLException {
Connection connection = null;
@@ -392,6 +414,33 @@ public class CsvTest {
.ok();
}
+ /** Test case for
+ * <a href="https://issues.apache.org/jira/browse/CALCITE-1754">[CALCITE-1754]
+ * In Csv adapter, convert DATE and TIME values to int, and TIMESTAMP values
+ * to long</a>. */
+ @Test public void testGroupByTimestampAdd() throws SQLException {
+ final String sql = "select count(*) as c,\n"
+ + " {fn timestampadd(SQL_TSI_DAY, 1, JOINEDAT) } as t\n"
+ + "from EMPS group by {fn timestampadd(SQL_TSI_DAY, 1, JOINEDAT ) } ";
+ sql("model", sql)
+ .returnsUnordered("C=1; T=1996-08-04",
+ "C=1; T=2002-05-04",
+ "C=1; T=2005-09-08",
+ "C=1; T=2007-01-02",
+ "C=1; T=2001-01-02")
+ .ok();
+
+ final String sql2 = "select count(*) as c,\n"
+ + " {fn timestampadd(SQL_TSI_MONTH, 1, JOINEDAT) } as t\n"
+ + "from EMPS group by {fn timestampadd(SQL_TSI_MONTH, 1, JOINEDAT ) } ";
+ sql("model", sql2)
+ .returnsUnordered("C=1; T=2002-06-03",
+ "C=1; T=2005-10-07",
+ "C=1; T=2007-02-01",
+ "C=1; T=2001-02-01",
+ "C=1; T=1996-09-03")
+ .ok();
+ }
@Test public void testBoolean() throws SQLException {
sql("smart", "select empno, slacker from emps where slacker")
.returns("EMPNO=100; SLACKER=true").ok();
@@ -801,6 +850,12 @@ public class CsvTest {
Fluent returns(String... expectedLines) {
return checking(expect(expectedLines));
}
+
+ /** Sets the rows that are expected to be returned from the SQL query,
+ * in no particular order. */
+ Fluent returnsUnordered(String... expectedLines) {
+ return checking(expectUnordered(expectedLines));
+ }
}
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/cc839874/file/src/test/java/org/apache/calcite/adapter/file/SqlTest.java
----------------------------------------------------------------------
diff --git a/file/src/test/java/org/apache/calcite/adapter/file/SqlTest.java b/file/src/test/java/org/apache/calcite/adapter/file/SqlTest.java
index ad39b64..27cc0f0 100644
--- a/file/src/test/java/org/apache/calcite/adapter/file/SqlTest.java
+++ b/file/src/test/java/org/apache/calcite/adapter/file/SqlTest.java
@@ -16,8 +16,12 @@
*/
package org.apache.calcite.adapter.file;
+import org.apache.calcite.util.Util;
+
import com.google.common.base.Function;
+import com.google.common.collect.Ordering;
+import org.junit.Assert;
import org.junit.Assume;
import org.junit.Test;
@@ -27,6 +31,10 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
import java.util.Properties;
import static org.hamcrest.CoreMatchers.is;
@@ -72,6 +80,44 @@ public class SqlTest {
};
}
+ /** Returns a function that checks the contents of a result set against an
+ * expected string. */
+ private static Function<ResultSet, Void> expectUnordered(String... expected) {
+ final List<String> expectedLines =
+ Ordering.natural().immutableSortedCopy(Arrays.asList(expected));
+ return new Function<ResultSet, Void>() {
+ public Void apply(ResultSet resultSet) {
+ try {
+ final List<String> lines = new ArrayList<>();
+ SqlTest.collect(lines, resultSet);
+ Collections.sort(lines);
+ Assert.assertEquals(expectedLines, lines);
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ return null;
+ }
+ };
+ }
+
+ private static void collect(List<String> result, ResultSet resultSet)
+ throws SQLException {
+ final StringBuilder buf = new StringBuilder();
+ while (resultSet.next()) {
+ buf.setLength(0);
+ int n = resultSet.getMetaData().getColumnCount();
+ String sep = "";
+ for (int i = 1; i <= n; i++) {
+ buf.append(sep)
+ .append(resultSet.getMetaData().getColumnLabel(i))
+ .append("=")
+ .append(resultSet.getString(i));
+ sep = "; ";
+ }
+ result.add(Util.toLinux(buf.toString()));
+ }
+ }
+
private void checkSql(String sql, String model, Function<ResultSet, Void> fn)
throws SQLException {
Connection connection = null;
@@ -229,6 +275,41 @@ public class SqlTest {
});
}
+ /** Test case for
+ * <a href="https://issues.apache.org/jira/browse/CALCITE-1754">[CALCITE-1754]
+ * In Csv adapter, convert DATE and TIME values to int, and TIMESTAMP values
+ * to long</a>. */
+ @Test public void testGroupByTimestampAdd() throws SQLException {
+ final String sql = "select count(*) as c,\n"
+ + " {fn timestampadd(SQL_TSI_DAY, 1, JOINEDAT) } as t\n"
+ + "from EMPS group by {fn timestampadd(SQL_TSI_DAY, 1, JOINEDAT ) } ";
+ sql("sales-csv", sql)
+ .returnsUnordered("C=1; T=1996-08-04",
+ "C=1; T=2002-05-04",
+ "C=1; T=2005-09-08",
+ "C=1; T=2007-01-02",
+ "C=1; T=2001-01-02")
+ .ok();
+ final String sql2 = "select count(*) as c,\n"
+ + " {fn timestampadd(SQL_TSI_MONTH, 1, JOINEDAT) } as t\n"
+ + "from EMPS group by {fn timestampadd(SQL_TSI_MONTH, 1, JOINEDAT ) } ";
+ sql("sales-csv", sql2)
+ .returnsUnordered("C=1; T=2002-06-03",
+ "C=1; T=2005-10-07",
+ "C=1; T=2007-02-01",
+ "C=1; T=2001-02-01",
+ "C=1; T=1996-09-03").ok();
+ final String sql3 = "select\n"
+ + " distinct {fn timestampadd(SQL_TSI_MONTH, 1, JOINEDAT) } as t\n"
+ + "from EMPS";
+ sql("sales-csv", sql3)
+ .returnsUnordered("T=2002-06-03",
+ "T=2005-10-07",
+ "T=2007-02-01",
+ "T=2001-02-01",
+ "T=1996-09-03").ok();
+ }
+
/** Fluent API to perform test actions. */
private class Fluent {
private final String model;
@@ -260,6 +341,12 @@ public class SqlTest {
Fluent returns(String... expectedLines) {
return checking(expect(expectedLines));
}
+
+ /** Sets the rows that are expected to be returned from the SQL query,
+ * in no particular order. */
+ Fluent returnsUnordered(String... expectedLines) {
+ return checking(expectUnordered(expectedLines));
+ }
}
}
[2/3] calcite git commit: Refactor CsvTest and SqlTest
Posted by jh...@apache.org.
Refactor CsvTest and SqlTest
Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/8b69e4da
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/8b69e4da
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/8b69e4da
Branch: refs/heads/master
Commit: 8b69e4da4a94985321b4ed0037255284093f4669
Parents: 0d2d11f
Author: Julian Hyde <jh...@apache.org>
Authored: Tue Apr 18 13:40:42 2017 -0700
Committer: Julian Hyde <jh...@apache.org>
Committed: Wed Apr 19 10:39:17 2017 -0700
----------------------------------------------------------------------
.../java/org/apache/calcite/test/CsvTest.java | 183 ++++++++++++-------
.../apache/calcite/adapter/file/SqlTest.java | 102 ++++++++---
2 files changed, 185 insertions(+), 100 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/calcite/blob/8b69e4da/example/csv/src/test/java/org/apache/calcite/test/CsvTest.java
----------------------------------------------------------------------
diff --git a/example/csv/src/test/java/org/apache/calcite/test/CsvTest.java b/example/csv/src/test/java/org/apache/calcite/test/CsvTest.java
index 8c056e8..8c2d1d3 100644
--- a/example/csv/src/test/java/org/apache/calcite/test/CsvTest.java
+++ b/example/csv/src/test/java/org/apache/calcite/test/CsvTest.java
@@ -19,11 +19,11 @@ package org.apache.calcite.test;
import org.apache.calcite.adapter.csv.CsvSchemaFactory;
import org.apache.calcite.adapter.csv.CsvStreamTableFactory;
import org.apache.calcite.jdbc.CalciteConnection;
-import org.apache.calcite.linq4j.function.Function1;
import org.apache.calcite.schema.Schema;
import org.apache.calcite.sql2rel.SqlToRelConverter;
import org.apache.calcite.util.Util;
+import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
import org.junit.Assert;
@@ -171,15 +171,15 @@ public class CsvTest {
* Reads from a table.
*/
@Test public void testSelect() throws SQLException {
- checkSql("model", "select * from EMPS");
+ sql("model", "select * from EMPS").ok();
}
@Test public void testSelectSingleProjectGz() throws SQLException {
- checkSql("smart", "select name from EMPS");
+ sql("smart", "select name from EMPS").ok();
}
@Test public void testSelectSingleProject() throws SQLException {
- checkSql("smart", "select name from DEPTS");
+ sql("smart", "select name from DEPTS").ok();
}
/** Test case for
@@ -189,7 +189,7 @@ public class CsvTest {
final String sql = "select empno * 3 as e3\n"
+ "from long_emps where empno = 100";
- checkSql(sql, "bug", new Function1<ResultSet, Void>() {
+ sql("bug", sql).checking(new Function<ResultSet, Void>() {
public Void apply(ResultSet resultSet) {
try {
assertThat(resultSet.next(), is(true));
@@ -201,74 +201,83 @@ public class CsvTest {
throw new RuntimeException(e);
}
}
- });
+ }).ok();
}
@Test public void testCustomTable() throws SQLException {
- checkSql("model-with-custom-table", "select * from CUSTOM_TABLE.EMPS");
+ sql("model-with-custom-table", "select * from CUSTOM_TABLE.EMPS").ok();
}
@Test public void testPushDownProjectDumb() throws SQLException {
// rule does not fire, because we're using 'dumb' tables in simple model
- checkSql("model", "explain plan for select * from EMPS",
- "PLAN=EnumerableInterpreter\n"
- + " BindableTableScan(table=[[SALES, EMPS]])\n");
+ final String sql = "explain plan for select * from EMPS";
+ final String expected = "PLAN=EnumerableInterpreter\n"
+ + " BindableTableScan(table=[[SALES, EMPS]])\n";
+ sql("model", sql).returns(expected).ok();
}
@Test public void testPushDownProject() throws SQLException {
- checkSql("smart", "explain plan for select * from EMPS",
- "PLAN=CsvTableScan(table=[[SALES, EMPS]], fields=[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])\n");
+ final String sql = "explain plan for select * from EMPS";
+ final String expected = "PLAN=CsvTableScan(table=[[SALES, EMPS]], "
+ + "fields=[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])\n";
+ sql("smart", sql).returns(expected).ok();
}
@Test public void testPushDownProject2() throws SQLException {
- checkSql("smart", "explain plan for select name, empno from EMPS",
- "PLAN=CsvTableScan(table=[[SALES, EMPS]], fields=[[1, 0]])\n");
+ sql("smart", "explain plan for select name, empno from EMPS")
+ .returns("PLAN=CsvTableScan(table=[[SALES, EMPS]], fields=[[1, 0]])\n")
+ .ok();
// make sure that it works...
- checkSql("smart", "select name, empno from EMPS",
- "NAME=Fred; EMPNO=100",
- "NAME=Eric; EMPNO=110",
- "NAME=John; EMPNO=110",
- "NAME=Wilma; EMPNO=120",
- "NAME=Alice; EMPNO=130");
+ sql("smart", "select name, empno from EMPS")
+ .returns("NAME=Fred; EMPNO=100",
+ "NAME=Eric; EMPNO=110",
+ "NAME=John; EMPNO=110",
+ "NAME=Wilma; EMPNO=120",
+ "NAME=Alice; EMPNO=130")
+ .ok();
}
@Test public void testFilterableSelect() throws SQLException {
- checkSql("filterable-model", "select name from EMPS");
+ sql("filterable-model", "select name from EMPS").ok();
}
@Test public void testFilterableSelectStar() throws SQLException {
- checkSql("filterable-model", "select * from EMPS");
+ sql("filterable-model", "select * from EMPS").ok();
}
/** Filter that can be fully handled by CsvFilterableTable. */
@Test public void testFilterableWhere() throws SQLException {
- checkSql("filterable-model",
- "select empno, gender, name from EMPS where name = 'John'",
- "EMPNO=110; GENDER=M; NAME=John");
+ final String sql =
+ "select empno, gender, name from EMPS where name = 'John'";
+ sql("filterable-model", sql)
+ .returns("EMPNO=110; GENDER=M; NAME=John").ok();
}
/** Filter that can be partly handled by CsvFilterableTable. */
@Test public void testFilterableWhere2() throws SQLException {
- checkSql("filterable-model",
- "select empno, gender, name from EMPS where gender = 'F' and empno > 125",
- "EMPNO=130; GENDER=F; NAME=Alice");
+ final String sql = "select empno, gender, name from EMPS\n"
+ + " where gender = 'F' and empno > 125";
+ sql("filterable-model", sql)
+ .returns("EMPNO=130; GENDER=F; NAME=Alice").ok();
}
@Test public void testJson() throws SQLException {
- checkSql("bug", "select _MAP['id'] as id,\n"
- + " _MAP['title'] as title,\n"
- + " CHAR_LENGTH(CAST(_MAP['title'] AS VARCHAR(30))) as len\n"
- + " from \"archers\"\n",
- "ID=19990101; TITLE=Tractor trouble.; LEN=16",
- "ID=19990103; TITLE=Charlie's surprise.; LEN=19");
+ final String sql = "select _MAP['id'] as id,\n"
+ + " _MAP['title'] as title,\n"
+ + " CHAR_LENGTH(CAST(_MAP['title'] AS VARCHAR(30))) as len\n"
+ + " from \"archers\"\n";
+ sql("bug", sql)
+ .returns("ID=19990101; TITLE=Tractor trouble.; LEN=16",
+ "ID=19990103; TITLE=Charlie's surprise.; LEN=19")
+ .ok();
}
- private void checkSql(String model, String sql) throws SQLException {
- checkSql(sql, model, output());
+ private Fluent sql(String model, String sql) {
+ return new Fluent(model, sql, output());
}
- private Function1<ResultSet, Void> output() {
- return new Function1<ResultSet, Void>() {
+ private Function<ResultSet, Void> output() {
+ return new Function<ResultSet, Void>() {
public Void apply(ResultSet resultSet) {
try {
output(resultSet, System.out);
@@ -280,15 +289,10 @@ public class CsvTest {
};
}
- private void checkSql(String model, String sql, final String... expected)
- throws SQLException {
- checkSql(sql, model, expect(expected));
- }
-
/** Returns a function that checks the contents of a result set against an
* expected string. */
- private static Function1<ResultSet, Void> expect(final String... expected) {
- return new Function1<ResultSet, Void>() {
+ private static Function<ResultSet, Void> expect(final String... expected) {
+ return new Function<ResultSet, Void>() {
public Void apply(ResultSet resultSet) {
try {
final List<String> lines = new ArrayList<>();
@@ -302,7 +306,7 @@ public class CsvTest {
};
}
- private void checkSql(String sql, String model, Function1<ResultSet, Void> fn)
+ private void checkSql(String sql, String model, Function<ResultSet, Void> fn)
throws SQLException {
Connection connection = null;
Statement statement = null;
@@ -370,34 +374,36 @@ public class CsvTest {
}
@Test public void testJoinOnString() throws SQLException {
- checkSql("smart",
- "select * from emps join depts on emps.name = depts.name");
+ final String sql = "select * from emps\n"
+ + "join depts on emps.name = depts.name";
+ sql("smart", sql).ok();
}
@Test public void testWackyColumns() throws SQLException {
- checkSql("select * from wacky_column_names where false", "bug",
- expect());
- checkSql(
- "select \"joined at\", \"naME\" from wacky_column_names where \"2gender\" = 'F'",
- "bug",
- expect(
- "joined at=2005-09-07; naME=Wilma",
- "joined at=2007-01-01; naME=Alice"));
+ final String sql = "select * from wacky_column_names where false";
+ sql("bug", sql).returns().ok();
+
+ final String sql2 = "select \"joined at\", \"naME\"\n"
+ + "from wacky_column_names\n"
+ + "where \"2gender\" = 'F'";
+ sql("bug", sql2)
+ .returns("joined at=2005-09-07; naME=Wilma",
+ "joined at=2007-01-01; naME=Alice")
+ .ok();
}
@Test public void testBoolean() throws SQLException {
- checkSql("smart",
- "select empno, slacker from emps where slacker",
- "EMPNO=100; SLACKER=true");
+ sql("smart", "select empno, slacker from emps where slacker")
+ .returns("EMPNO=100; SLACKER=true").ok();
}
@Test public void testReadme() throws SQLException {
- checkSql("SELECT d.name, COUNT(*) cnt"
- + " FROM emps AS e"
- + " JOIN depts AS d ON e.deptno = d.deptno"
- + " GROUP BY d.name",
- "smart",
- expect("NAME=Sales; CNT=1", "NAME=Marketing; CNT=2"));
+ final String sql = "SELECT d.name, COUNT(*) cnt"
+ + " FROM emps AS e"
+ + " JOIN depts AS d ON e.deptno = d.deptno"
+ + " GROUP BY d.name";
+ sql("smart", sql)
+ .returns("NAME=Sales; CNT=1", "NAME=Marketing; CNT=2").ok();
}
/** Test case for
@@ -410,10 +416,12 @@ public class CsvTest {
+ "FROM emps AS e\n"
+ "WHERE cast(e.empno as bigint) in ";
final int threshold = SqlToRelConverter.DEFAULT_IN_SUB_QUERY_THRESHOLD;
- checkSql(sql + range(130, threshold - 5), "smart", expect("NAME=Alice"));
- checkSql(sql + range(130, threshold), "smart", expect("NAME=Alice"));
- checkSql(sql + range(130, threshold + 1000), "smart",
- expect("NAME=Alice"));
+ sql("smart", sql + range(130, threshold - 5))
+ .returns("NAME=Alice").ok();
+ sql("smart", sql + range(130, threshold))
+ .returns("NAME=Alice").ok();
+ sql("smart", sql + range(130, threshold + 1000))
+ .returns("NAME=Alice").ok();
}
/** Test case for
@@ -424,7 +432,7 @@ public class CsvTest {
+ "FROM emps AS e\n"
+ "WHERE e.empno in "
+ range(130, SqlToRelConverter.DEFAULT_IN_SUB_QUERY_THRESHOLD);
- checkSql(sql, "smart", expect("NAME=Alice"));
+ sql("smart", sql).returns("NAME=Alice").ok();
}
private String range(int first, int count) {
@@ -604,7 +612,7 @@ public class CsvTest {
statement2.setString(1, "Sales");
final ResultSet resultSet1 = statement2.executeQuery();
- Function1<ResultSet, Void> expect = expect("DEPTNO=10; NAME=Sales");
+ Function<ResultSet, Void> expect = expect("DEPTNO=10; NAME=Sales");
expect.apply(resultSet1);
}
}
@@ -761,6 +769,39 @@ public class CsvTest {
}
}
}
+
+ /** Fluent API to perform test actions. */
+ private class Fluent {
+ private final String model;
+ private final String sql;
+ private final Function<ResultSet, Void> expect;
+
+ Fluent(String model, String sql, Function<ResultSet, Void> expect) {
+ this.model = model;
+ this.sql = sql;
+ this.expect = expect;
+ }
+
+ /** Runs the test. */
+ Fluent ok() {
+ try {
+ checkSql(sql, model, expect);
+ return this;
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /** Assigns a function to call to test whether output is correct. */
+ Fluent checking(Function<ResultSet, Void> expect) {
+ return new Fluent(model, sql, expect);
+ }
+
+ /** Sets the rows that are expected to be returned from the SQL query. */
+ Fluent returns(String... expectedLines) {
+ return checking(expect(expectedLines));
+ }
+ }
}
// End CsvTest.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/8b69e4da/file/src/test/java/org/apache/calcite/adapter/file/SqlTest.java
----------------------------------------------------------------------
diff --git a/file/src/test/java/org/apache/calcite/adapter/file/SqlTest.java b/file/src/test/java/org/apache/calcite/adapter/file/SqlTest.java
index 37d3bfe..ad39b64 100644
--- a/file/src/test/java/org/apache/calcite/adapter/file/SqlTest.java
+++ b/file/src/test/java/org/apache/calcite/adapter/file/SqlTest.java
@@ -40,14 +40,21 @@ import static org.junit.Assert.assertThat;
public class SqlTest {
// helper functions
- private void checkSql(String model, String sql, String... expectedLines)
- throws SQLException {
+ private Fluent sql(String model, String sql) {
+ return new Fluent(model, sql, new Function<ResultSet, Void>() {
+ public Void apply(ResultSet input) {
+ throw new AssertionError();
+ }
+ });
+ }
+
+ private Function<ResultSet, Void> expect(String... expectedLines) {
final StringBuilder b = new StringBuilder();
for (String s : expectedLines) {
b.append(s).append('\n');
}
final String expected = b.toString();
- checkSql(sql, model, new Function<ResultSet, Void>() {
+ return new Function<ResultSet, Void>() {
public Void apply(ResultSet resultSet) {
try {
String actual = SqlTest.toString(resultSet);
@@ -62,7 +69,7 @@ public class SqlTest {
}
return null;
}
- });
+ };
}
private void checkSql(String sql, String model, Function<ResultSet, Void> fn)
@@ -121,7 +128,7 @@ public class SqlTest {
/** Reads from a local file and checks the result. */
@Test public void testFileSelect() throws SQLException {
final String sql = "select H1 from T1 where H0 = 'R1C0'";
- checkSql("testModel", sql, "H1=R1C1");
+ sql("testModel", sql).returns("H1=R1C1").ok();
}
/** Reads from a local file without table headers <TH> and checks the
@@ -129,14 +136,14 @@ public class SqlTest {
@Test public void testNoThSelect() throws SQLException {
Assume.assumeTrue(FileSuite.hazNetwork());
final String sql = "select \"col1\" from T1_NO_TH where \"col0\" like 'R0%'";
- checkSql("testModel", sql, "col1=R0C1");
+ sql("testModel", sql).returns("col1=R0C1").ok();
}
/** Reads from a local file - finds larger table even without <TH>
* elements. */
@Test public void testFindBiggerNoTh() throws SQLException {
final String sql = "select \"col4\" from TABLEX2 where \"col0\" like 'R1%'";
- checkSql("testModel", sql, "col4=R1C4");
+ sql("testModel", sql).returns("col4=R1C4").ok();
}
/** Reads from a URL and checks the result. */
@@ -144,54 +151,59 @@ public class SqlTest {
Assume.assumeTrue(FileSuite.hazNetwork());
final String sql = "select \"State\", \"Statehood\" from \"States_as_of\"\n"
+ "where \"State\" = 'California'";
- checkSql("wiki", sql, "State=California; Statehood=1850-09-09");
+ sql("wiki", sql).returns("State=California; Statehood=1850-09-09").ok();
}
/** Reads the EMPS table. */
@Test public void testSalesEmps() throws SQLException {
final String sql = "select * from sales.emps";
- checkSql("sales", sql,
- "EMPNO=100; NAME=Fred; DEPTNO=30",
- "EMPNO=110; NAME=Eric; DEPTNO=20",
- "EMPNO=110; NAME=John; DEPTNO=40",
- "EMPNO=120; NAME=Wilma; DEPTNO=20",
- "EMPNO=130; NAME=Alice; DEPTNO=40");
+ sql("sales", sql)
+ .returns("EMPNO=100; NAME=Fred; DEPTNO=30",
+ "EMPNO=110; NAME=Eric; DEPTNO=20",
+ "EMPNO=110; NAME=John; DEPTNO=40",
+ "EMPNO=120; NAME=Wilma; DEPTNO=20",
+ "EMPNO=130; NAME=Alice; DEPTNO=40")
+ .ok();
}
/** Reads the DEPTS table. */
@Test public void testSalesDepts() throws SQLException {
final String sql = "select * from sales.depts";
- checkSql("sales", sql,
- "DEPTNO=10; NAME=Sales",
- "DEPTNO=20; NAME=Marketing",
- "DEPTNO=30; NAME=Accounts");
+ sql("sales", sql)
+ .returns("DEPTNO=10; NAME=Sales",
+ "DEPTNO=20; NAME=Marketing",
+ "DEPTNO=30; NAME=Accounts")
+ .ok();
}
/** Reads the DEPTS table from the CSV schema. */
@Test public void testCsvSalesDepts() throws SQLException {
final String sql = "select * from sales.depts";
- checkSql("sales-csv", sql,
- "DEPTNO=10; NAME=Sales",
- "DEPTNO=20; NAME=Marketing",
- "DEPTNO=30; NAME=Accounts");
+ sql("sales-csv", sql)
+ .returns("DEPTNO=10; NAME=Sales",
+ "DEPTNO=20; NAME=Marketing",
+ "DEPTNO=30; NAME=Accounts")
+ .ok();
}
/** Reads the EMPS table from the CSV schema. */
@Test public void testCsvSalesEmps() throws SQLException {
final String sql = "select * from sales.emps";
- checkSql("sales-csv", sql,
- "EMPNO=100; NAME=Fred; DEPTNO=10; GENDER=; CITY=; EMPID=30; AGE=25; SLACKER=true; MANAGER=false; JOINEDAT=1996-08-03",
- "EMPNO=110; NAME=Eric; DEPTNO=20; GENDER=M; CITY=San Francisco; EMPID=3; AGE=80; SLACKER=null; MANAGER=false; JOINEDAT=2001-01-01",
- "EMPNO=110; NAME=John; DEPTNO=40; GENDER=M; CITY=Vancouver; EMPID=2; AGE=null; SLACKER=false; MANAGER=true; JOINEDAT=2002-05-03",
- "EMPNO=120; NAME=Wilma; DEPTNO=20; GENDER=F; CITY=; EMPID=1; AGE=5; SLACKER=null; MANAGER=true; JOINEDAT=2005-09-07",
- "EMPNO=130; NAME=Alice; DEPTNO=40; GENDER=F; CITY=Vancouver; EMPID=2; AGE=null; SLACKER=false; MANAGER=true; JOINEDAT=2007-01-01");
+ final String[] lines = {
+ "EMPNO=100; NAME=Fred; DEPTNO=10; GENDER=; CITY=; EMPID=30; AGE=25; SLACKER=true; MANAGER=false; JOINEDAT=1996-08-03",
+ "EMPNO=110; NAME=Eric; DEPTNO=20; GENDER=M; CITY=San Francisco; EMPID=3; AGE=80; SLACKER=null; MANAGER=false; JOINEDAT=2001-01-01",
+ "EMPNO=110; NAME=John; DEPTNO=40; GENDER=M; CITY=Vancouver; EMPID=2; AGE=null; SLACKER=false; MANAGER=true; JOINEDAT=2002-05-03",
+ "EMPNO=120; NAME=Wilma; DEPTNO=20; GENDER=F; CITY=; EMPID=1; AGE=5; SLACKER=null; MANAGER=true; JOINEDAT=2005-09-07",
+ "EMPNO=130; NAME=Alice; DEPTNO=40; GENDER=F; CITY=Vancouver; EMPID=2; AGE=null; SLACKER=false; MANAGER=true; JOINEDAT=2007-01-01",
+ };
+ sql("sales-csv", sql).returns(lines).ok();
}
/** Reads the HEADER_ONLY table from the CSV schema. The CSV file has one
* line - the column headers - but no rows of data. */
@Test public void testCsvSalesHeaderOnly() throws SQLException {
final String sql = "select * from sales.header_only";
- checkSql("sales-csv", sql);
+ sql("sales-csv", sql).returns().ok();
}
/** Reads the EMPTY table from the CSV schema. The CSV file has no lines,
@@ -217,6 +229,38 @@ public class SqlTest {
});
}
+ /** Fluent API to perform test actions. */
+ private class Fluent {
+ private final String model;
+ private final String sql;
+ private final Function<ResultSet, Void> expect;
+
+ Fluent(String model, String sql, Function<ResultSet, Void> expect) {
+ this.model = model;
+ this.sql = sql;
+ this.expect = expect;
+ }
+
+ /** Runs the test. */
+ Fluent ok() {
+ try {
+ checkSql(sql, model, expect);
+ return this;
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /** Assigns a function to call to test whether output is correct. */
+ Fluent checking(Function<ResultSet, Void> expect) {
+ return new Fluent(model, sql, expect);
+ }
+
+ /** Sets the rows that are expected to be returned from the SQL query. */
+ Fluent returns(String... expectedLines) {
+ return checking(expect(expectedLines));
+ }
+ }
}
// End SqlTest.java
[3/3] calcite git commit: [CALCITE-1639] TIMESTAMPADD(MONTH,
...) should return last day of month if the day overflows (Hongbin Ma)
Posted by jh...@apache.org.
[CALCITE-1639] TIMESTAMPADD(MONTH, ...) should return last day of month if the day overflows (Hongbin Ma)
Close apache/calcite#431
Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/0d2d11f3
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/0d2d11f3
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/0d2d11f3
Branch: refs/heads/master
Commit: 0d2d11f3b8ab4a11279b4f73d0cd913902872880
Parents: cd13698
Author: Julian Hyde <jh...@apache.org>
Authored: Tue Apr 18 13:40:16 2017 -0700
Committer: Julian Hyde <jh...@apache.org>
Committed: Wed Apr 19 10:39:17 2017 -0700
----------------------------------------------------------------------
.../main/java/org/apache/calcite/runtime/SqlFunctions.java | 6 +-----
.../org/apache/calcite/sql/test/SqlOperatorBaseTest.java | 8 ++++++++
.../test/java/org/apache/calcite/test/SqlFunctionsTest.java | 8 ++++----
3 files changed, 13 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/calcite/blob/0d2d11f3/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
index baa2c6f..fec73c6 100644
--- a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
+++ b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
@@ -2089,11 +2089,7 @@ public class SqlFunctions {
m0 += m - y * 12;
int last = lastDay(y0, m0);
if (d0 > last) {
- d0 = 1;
- if (++m0 > 12) {
- m0 = 1;
- ++y0;
- }
+ d0 = last;
}
return DateTimeUtils.ymdToUnixDate(y0, m0, d0);
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/0d2d11f3/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java b/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
index 3e8cbd2..2ba92ac 100644
--- a/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
+++ b/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
@@ -5709,6 +5709,14 @@ public abstract class SqlOperatorBaseTest {
null, "TIMESTAMP(0)");
tester.checkScalar("timestampadd(DAY, 1, cast(null as date))",
null, "DATE");
+
+ // Round to the last day of previous month
+ tester.checkScalar("timestampadd(MONTH, 1, date '2016-05-31')",
+ "2016-06-30", "DATE NOT NULL");
+ tester.checkScalar("timestampadd(MONTH, 5, date '2016-01-31')",
+ "2016-06-30", "DATE NOT NULL");
+ tester.checkScalar("timestampadd(MONTH, -1, date '2016-03-31')",
+ "2016-02-29", "DATE NOT NULL");
}
@Test public void testTimestampDiff() {
http://git-wip-us.apache.org/repos/asf/calcite/blob/0d2d11f3/core/src/test/java/org/apache/calcite/test/SqlFunctionsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/SqlFunctionsTest.java b/core/src/test/java/org/apache/calcite/test/SqlFunctionsTest.java
index 12ef35b..4293654 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlFunctionsTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlFunctionsTest.java
@@ -365,10 +365,10 @@ public class SqlFunctionsTest {
checkAddMonths(2016, 1, 1, 2017, 2, 1, 13);
checkAddMonths(2016, 1, 1, 2015, 1, 1, -12);
checkAddMonths(2016, 1, 1, 2018, 10, 1, 33);
- checkAddMonths(2016, 1, 31, 2016, 5, 1, 3); // roll up
- checkAddMonths(2016, 4, 30, 2016, 7, 30, 3); // roll up
- checkAddMonths(2016, 1, 31, 2016, 3, 1, 1);
- checkAddMonths(2016, 3, 31, 2016, 3, 1, -1);
+ checkAddMonths(2016, 1, 31, 2016, 4, 30, 3);
+ checkAddMonths(2016, 4, 30, 2016, 7, 30, 3);
+ checkAddMonths(2016, 1, 31, 2016, 2, 29, 1);
+ checkAddMonths(2016, 3, 31, 2016, 2, 29, -1);
checkAddMonths(2016, 3, 31, 2116, 3, 31, 1200);
checkAddMonths(2016, 2, 28, 2116, 2, 28, 1200);
}