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 2015/03/23 18:26:15 UTC
[1/9] incubator-calcite git commit: Update release HOWTO
Repository: incubator-calcite
Updated Branches:
refs/heads/master 60789a572 -> 574dc7cc8
Update release HOWTO
Project: http://git-wip-us.apache.org/repos/asf/incubator-calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-calcite/commit/3b10a6a5
Tree: http://git-wip-us.apache.org/repos/asf/incubator-calcite/tree/3b10a6a5
Diff: http://git-wip-us.apache.org/repos/asf/incubator-calcite/diff/3b10a6a5
Branch: refs/heads/master
Commit: 3b10a6a5589c6af9e234bc3acfbaa3b0d002db12
Parents: 60789a5
Author: Julian Hyde <jh...@apache.org>
Authored: Fri Mar 13 14:39:22 2015 -0700
Committer: Julian Hyde <jh...@apache.org>
Committed: Mon Mar 23 01:13:57 2015 -0700
----------------------------------------------------------------------
doc/HOWTO.md | 58 +++++++++++++++++++++++++++++++++++++++++--------------
1 file changed, 43 insertions(+), 15 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/3b10a6a5/doc/HOWTO.md
----------------------------------------------------------------------
diff --git a/doc/HOWTO.md b/doc/HOWTO.md
index a62ae5f..9e18dc7 100644
--- a/doc/HOWTO.md
+++ b/doc/HOWTO.md
@@ -318,6 +318,20 @@ Before you start:
a fix version assigned (most likely the version we are
just about to release)
+Create a release branch named after the release, e.g. `branch-1.1`, and push it to Apache.
+
+```bash
+$ git checkout -b branch-X.Y
+$ git push -u origin branch-X.Y
+
+We will use the branch for the entire the release process. Meanwhile,
+we do not allow commits to the master branch. After the release is
+final, we can use `git merge --ff-only` to append the changes on the
+release branch onto the master branch. (Apache does not allow reverts
+to the master branch, which makes it difficult to clean up the kind of
+messy commits that inevitably happen while you are trying to finalize
+a release.)
+
Now, set up your environment and do a dry run. The dry run will not
commit any changes back to git and gives you the opportunity to verify
that the release process will complete as expected.
@@ -353,9 +367,8 @@ Check the artifacts:
no binary distro), check that all files belong to a directory called
`apache-calcite-X.Y.Z-incubating-src`.
* That directory must contain files `DISCLAIMER`, `NOTICE`, `LICENSE`,
- `README`, `README.md`, `git.properties`
+ `README`, `README.md`
* Check that the version in `README` is correct
- * Check that `git.properties` is current
* In each .jar (for example
`core/target/calcite-core-X.Y.Z-incubating.jar` and
`mongodb/target/calcite-mongodb-X.Y.Z-incubating-sources.jar`), check
@@ -385,17 +398,25 @@ Verify the staged artifacts in the Nexus repository:
https://repository.apache.org/content/repositories/orgapachecalcite-1000
(or a similar URL)
-Upload the artifacts to a staging area (in this case, your
-people.apache.org home directory):
+Upload the artifacts via subversion to a staging area,
+https://dist.apache.org/repos/dist/dev/incubator/calcite/apache-calcite-X.Y.Z-incubating-rcN:
```bash
+# Create a subversion workspace, if you haven't already
+mkdir -p ~/dist/dev
+pushd ~/dist/dev
+svn co https://dist.apache.org/repos/dist/dev/incubator/calcite
+popd
+
# Move the files into a directory
cd target
-mkdir apache-calcite-X.Y.Z-incubating-rcN
-mv apache-calcite-* calcite-X.Y.Z-incubating-rcN
+mkdir ~/dist/dev/calcite/apache-calcite-X.Y.Z-incubating-rcN
+mv apache-calcite-* ~/dist/dev/calcite/apache-calcite-X.Y.Z-incubating-rcN
-# Upload to staging area (your people.apache.org home directory)
-scp -rp apache-calcite-X.Y.Z-incubating-rcN people.apache.org:public_html
+# Check in
+cd ~/dist/dev/calcite
+svn add apache-calcite-X.Y.Z-incubating-rcN
+svn ci
```
## Cleaning up after a failed release attempt (for Calcite committers)
@@ -482,7 +503,7 @@ http://git-wip-us.apache.org/repos/asf/incubator-calcite/commit/NNNNNN
Its hash is XXXX.
The artifacts to be voted on are located here:
-http://people.apache.org/~jhyde/apache-calcite-X.Y.Z-incubating-rcN/
+https://dist.apache.org/repos/dist/dev/incubator/calcite/apache-calcite-X.Y.Z-incubating-rcN/
The hashes of the artifacts are as follows:
src.tar.gz.md5 XXXX
@@ -567,7 +588,7 @@ http://git-wip-us.apache.org/repos/asf/incubator-calcite/commit/NNNNNN
Its hash is XXXX.
The artifacts to be voted on are located here:
-http://people.apache.org/~jhyde/apache-calcite-X.Y.Z-incubating-rcN/
+https://dist.apache.org/repos/dist/dev/incubator/calcite/apache-calcite-X.Y.Z-incubating-rcN/
The hashes of the artifacts are as follows:
src.tar.gz.md5 XXXX
@@ -630,12 +651,19 @@ Promote the staged nexus artifacts.
Check the artifacts into svn.
```bash
-ssh people.apache.org
-mkdir -p dist
-cd dist
-svn co https://dist.apache.org/repos/dist/release/incubator/calcite
+# Get the release candidate.
+mkdir -p ~/dist/dev
+cd ~/dist/dev
+svn co https://dist.apache.org/repos/dist/dev/incubator/calcite
+
# Copy the artifacts. Note that the copy does not have '-rcN' suffix.
-cp -rp ../public_html/apache-calcite-X.Y.Z-incubating-rcN calcite/apache-calcite-X.Y.Z-incubating
+mkdir -p ~/dist/release
+cd ~/dist/release
+svn co https://dist.apache.org/repos/dist/release/incubator/calcite
+cd calcite
+cp -rp ../../dev/calcite/apache-calcite-X.Y.Z-incubating-rcN apache-calcite-X.Y.Z-incubating
+svn add apache-calcite-X.Y.Z-incubating
+
# Check in.
svn ci
```
[6/9] incubator-calcite git commit: [CALCITE-627] Add Avatica support
for getTableTypes, getColumns (Xavier FH Leong)
Posted by jh...@apache.org.
[CALCITE-627] Add Avatica support for getTableTypes, getColumns (Xavier FH Leong)
Project: http://git-wip-us.apache.org/repos/asf/incubator-calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-calcite/commit/fe13dd3b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-calcite/tree/fe13dd3b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-calcite/diff/fe13dd3b
Branch: refs/heads/master
Commit: fe13dd3bcbac3998defa37929da0ab428372d2a1
Parents: 4d2f647
Author: Julian Hyde <jh...@apache.org>
Authored: Wed Mar 18 14:14:31 2015 -0700
Committer: Julian Hyde <jh...@apache.org>
Committed: Mon Mar 23 01:45:01 2015 -0700
----------------------------------------------------------------------
.../calcite/avatica/remote/JsonService.java | 16 ++++++++
.../calcite/avatica/remote/LocalService.java | 14 +++++++
.../calcite/avatica/remote/RemoteMeta.java | 15 +++++++
.../apache/calcite/avatica/remote/Service.java | 41 ++++++++++++++++++++
.../calcite/jdbc/CalciteRemoteDriverTest.java | 33 ++++++++++++++++
5 files changed, 119 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/fe13dd3b/avatica/src/main/java/org/apache/calcite/avatica/remote/JsonService.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/org/apache/calcite/avatica/remote/JsonService.java b/avatica/src/main/java/org/apache/calcite/avatica/remote/JsonService.java
index 7e110ff..cc0ca6e 100644
--- a/avatica/src/main/java/org/apache/calcite/avatica/remote/JsonService.java
+++ b/avatica/src/main/java/org/apache/calcite/avatica/remote/JsonService.java
@@ -82,6 +82,22 @@ public abstract class JsonService implements Service {
}
}
+ public ResultSetResponse apply(TableTypesRequest request) {
+ try {
+ return decode(apply(encode(request)), ResultSetResponse.class);
+ } catch (IOException e) {
+ throw handle(e);
+ }
+ }
+
+ public ResultSetResponse apply(ColumnsRequest request) {
+ try {
+ return decode(apply(encode(request)), ResultSetResponse.class);
+ } catch (IOException e) {
+ throw handle(e);
+ }
+ }
+
public PrepareResponse apply(PrepareRequest request) {
try {
return decode(apply(encode(request)), PrepareResponse.class);
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/fe13dd3b/avatica/src/main/java/org/apache/calcite/avatica/remote/LocalService.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/org/apache/calcite/avatica/remote/LocalService.java b/avatica/src/main/java/org/apache/calcite/avatica/remote/LocalService.java
index faf60b8..fa7611e 100644
--- a/avatica/src/main/java/org/apache/calcite/avatica/remote/LocalService.java
+++ b/avatica/src/main/java/org/apache/calcite/avatica/remote/LocalService.java
@@ -103,6 +103,20 @@ public class LocalService implements Service {
return toResponse(resultSet);
}
+ public ResultSetResponse apply(TableTypesRequest request) {
+ final Meta.MetaResultSet resultSet = meta.getTableTypes();
+ return toResponse(resultSet);
+ }
+
+ public ResultSetResponse apply(ColumnsRequest request) {
+ final Meta.MetaResultSet resultSet =
+ meta.getColumns(request.catalog,
+ Meta.Pat.of(request.schemaPattern),
+ Meta.Pat.of(request.tableNamePattern),
+ Meta.Pat.of(request.columnNamePattern));
+ return toResponse(resultSet);
+ }
+
public PrepareResponse apply(PrepareRequest request) {
final Meta.StatementHandle h =
new Meta.StatementHandle(request.statementId);
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/fe13dd3b/avatica/src/main/java/org/apache/calcite/avatica/remote/RemoteMeta.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/org/apache/calcite/avatica/remote/RemoteMeta.java b/avatica/src/main/java/org/apache/calcite/avatica/remote/RemoteMeta.java
index 83dd28c..10439ce 100644
--- a/avatica/src/main/java/org/apache/calcite/avatica/remote/RemoteMeta.java
+++ b/avatica/src/main/java/org/apache/calcite/avatica/remote/RemoteMeta.java
@@ -79,6 +79,21 @@ class RemoteMeta extends MetaImpl {
return toResultSet(MetaTable.class, response);
}
+ @Override public MetaResultSet getTableTypes() {
+ final Service.ResultSetResponse response =
+ service.apply(new Service.TableTypesRequest());
+ return toResultSet(MetaTableType.class, response);
+ }
+
+ @Override public MetaResultSet getColumns(String catalog, Pat schemaPattern,
+ Pat tableNamePattern, Pat columnNamePattern) {
+ final Service.ResultSetResponse response =
+ service.apply(
+ new Service.ColumnsRequest(catalog, schemaPattern.s,
+ tableNamePattern.s, columnNamePattern.s));
+ return toResultSet(MetaColumn.class, response);
+ }
+
@Override public Signature prepare(StatementHandle h, String sql,
int maxRowCount) {
final Service.PrepareResponse response =
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/fe13dd3b/avatica/src/main/java/org/apache/calcite/avatica/remote/Service.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/org/apache/calcite/avatica/remote/Service.java b/avatica/src/main/java/org/apache/calcite/avatica/remote/Service.java
index cf73b49..ed2c332 100644
--- a/avatica/src/main/java/org/apache/calcite/avatica/remote/Service.java
+++ b/avatica/src/main/java/org/apache/calcite/avatica/remote/Service.java
@@ -33,6 +33,8 @@ public interface Service {
ResultSetResponse apply(CatalogsRequest request);
ResultSetResponse apply(SchemasRequest request);
ResultSetResponse apply(TablesRequest request);
+ ResultSetResponse apply(TableTypesRequest request);
+ ResultSetResponse apply(ColumnsRequest request);
PrepareResponse apply(PrepareRequest request);
ResultSetResponse apply(PrepareAndExecuteRequest request);
FetchResponse apply(FetchRequest request);
@@ -52,6 +54,9 @@ public interface Service {
@JsonSubTypes.Type(value = CatalogsRequest.class, name = "getCatalogs"),
@JsonSubTypes.Type(value = SchemasRequest.class, name = "getSchemas"),
@JsonSubTypes.Type(value = TablesRequest.class, name = "getTables"),
+ @JsonSubTypes.Type(value = TableTypesRequest.class,
+ name = "getTableTypes"),
+ @JsonSubTypes.Type(value = ColumnsRequest.class, name = "getColumns"),
@JsonSubTypes.Type(value = PrepareRequest.class, name = "prepare"),
@JsonSubTypes.Type(value = PrepareAndExecuteRequest.class,
name = "prepareAndExecute"),
@@ -127,11 +132,47 @@ public interface Service {
}
}
+ /** Request for
+ * {@link Meta#getTableTypes()}. */
+ class TableTypesRequest extends Request {
+
+ ResultSetResponse accept(Service service) {
+ return service.apply(this);
+ }
+ }
+
+ /** Request for
+ * {@link Meta#getColumns(String, org.apache.calcite.avatica.Meta.Pat, org.apache.calcite.avatica.Meta.Pat, org.apache.calcite.avatica.Meta.Pat)}.
+ */
+ class ColumnsRequest extends Request {
+ public final String catalog;
+ public final String schemaPattern;
+ public final String tableNamePattern;
+ public final String columnNamePattern;
+
+ @JsonCreator
+ public ColumnsRequest(@JsonProperty("catalog") String catalog,
+ @JsonProperty("schemaPattern") String schemaPattern,
+ @JsonProperty("tableNamePattern") String tableNamePattern,
+ @JsonProperty("columnNamePattern") String columnNamePattern) {
+ this.catalog = catalog;
+ this.schemaPattern = schemaPattern;
+ this.tableNamePattern = tableNamePattern;
+ this.columnNamePattern = columnNamePattern;
+ }
+
+ ResultSetResponse accept(Service service) {
+ return service.apply(this);
+ }
+ }
+
/** Response that contains a result set.
*
* <p>Several types of request, including
* {@link org.apache.calcite.avatica.Meta#getCatalogs()} and
* {@link org.apache.calcite.avatica.Meta#getSchemas(String, org.apache.calcite.avatica.Meta.Pat)}
+ * {@link Meta#getTables(String, org.apache.calcite.avatica.Meta.Pat, org.apache.calcite.avatica.Meta.Pat, List<String>)}
+ * {@link Meta#getTableTypes()}
* return this response. */
class ResultSetResponse extends Response {
public final int statementId;
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/fe13dd3b/core/src/test/java/org/apache/calcite/jdbc/CalciteRemoteDriverTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/jdbc/CalciteRemoteDriverTest.java b/core/src/test/java/org/apache/calcite/jdbc/CalciteRemoteDriverTest.java
index 0d5f91e..8d10a98 100644
--- a/core/src/test/java/org/apache/calcite/jdbc/CalciteRemoteDriverTest.java
+++ b/core/src/test/java/org/apache/calcite/jdbc/CalciteRemoteDriverTest.java
@@ -81,6 +81,26 @@ public class CalciteRemoteDriverTest {
}
}
};
+ private static final Function<Connection, ResultSet> GET_COLUMNS =
+ new Function<Connection, ResultSet>() {
+ public ResultSet apply(Connection input) {
+ try {
+ return input.getMetaData().getColumns(null, null, null, null);
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+ private static final Function<Connection, ResultSet> GET_TABLE_TYPES =
+ new Function<Connection, ResultSet>() {
+ public ResultSet apply(Connection input) {
+ try {
+ return input.getMetaData().getTableTypes();
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
private static Connection localConnection;
private static Connection remoteConnection;
@@ -159,6 +179,19 @@ public class CalciteRemoteDriverTest {
+ "TABLE_SCHEM=metadata; TABLE_CATALOG=null\n");
}
+ @Test public void testRemoteColumns() throws Exception {
+ CalciteAssert.hr().with(REMOTE_CONNECTION_FACTORY)
+ .metaData(GET_COLUMNS)
+ .returns(CalciteAssert.checkResultContains("COLUMN_NAME=EMPNO"));
+ }
+
+ @Test public void testRemoteTableTypes() throws Exception {
+ CalciteAssert.hr().with(REMOTE_CONNECTION_FACTORY)
+ .metaData(GET_TABLE_TYPES)
+ .returns("TABLE_TYPE=TABLE\n"
+ + "TABLE_TYPE=VIEW\n");
+ }
+
@Test public void testRemoteExecuteQuery() throws Exception {
CalciteAssert.hr().with(REMOTE_CONNECTION_FACTORY)
.query("values (1, 'a'), (cast(null as integer), 'b')")
[9/9] incubator-calcite git commit: [CALCITE-335] Remove uses of
linq4j Functions.adapt
Posted by jh...@apache.org.
[CALCITE-335] Remove uses of linq4j Functions.adapt
Project: http://git-wip-us.apache.org/repos/asf/incubator-calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-calcite/commit/574dc7cc
Tree: http://git-wip-us.apache.org/repos/asf/incubator-calcite/tree/574dc7cc
Diff: http://git-wip-us.apache.org/repos/asf/incubator-calcite/diff/574dc7cc
Branch: refs/heads/master
Commit: 574dc7cc89c6319ed51629f316d3a87eedfb1c0f
Parents: 0fe2637
Author: Julian Hyde <jh...@apache.org>
Authored: Mon Mar 23 02:51:56 2015 -0700
Committer: Julian Hyde <jh...@apache.org>
Committed: Mon Mar 23 02:51:56 2015 -0700
----------------------------------------------------------------------
.../calcite/adapter/clone/ColumnLoader.java | 33 ++++++++++----------
.../apache/calcite/adapter/jdbc/JdbcTable.java | 14 ++++-----
.../materialize/MaterializationService.java | 12 +++----
.../org/apache/calcite/rel/core/Project.java | 9 +++---
.../org/apache/calcite/rel/core/Values.java | 17 +++++-----
.../calcite/linq4j/function/Functions.java | 20 +++++++-----
.../calcite/linq4j/tree/ConstantExpression.java | 13 ++++----
.../linq4j/tree/ConstructorDeclaration.java | 8 ++---
.../calcite/linq4j/tree/MethodDeclaration.java | 8 ++---
.../calcite/linq4j/function/FunctionTest.java | 15 ---------
10 files changed, 66 insertions(+), 83 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/574dc7cc/core/src/main/java/org/apache/calcite/adapter/clone/ColumnLoader.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/clone/ColumnLoader.java b/core/src/main/java/org/apache/calcite/adapter/clone/ColumnLoader.java
index 86bb77f..d33ee61 100644
--- a/core/src/main/java/org/apache/calcite/adapter/clone/ColumnLoader.java
+++ b/core/src/main/java/org/apache/calcite/adapter/clone/ColumnLoader.java
@@ -21,13 +21,14 @@ import org.apache.calcite.avatica.ColumnMetaData;
import org.apache.calcite.avatica.util.DateTimeUtils;
import org.apache.calcite.linq4j.Enumerable;
import org.apache.calcite.linq4j.Ord;
-import org.apache.calcite.linq4j.function.Function1;
-import org.apache.calcite.linq4j.function.Functions;
import org.apache.calcite.linq4j.tree.Primitive;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeField;
import org.apache.calcite.rel.type.RelProtoDataType;
+import com.google.common.base.Function;
+import com.google.common.collect.Lists;
+
import java.lang.reflect.Type;
import java.sql.Date;
import java.sql.Time;
@@ -52,15 +53,15 @@ class ColumnLoader<T> {
0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000, 0xFFFFFFFF00000000L};
static final int[] LONG_S = {1, 2, 4, 8, 16, 32};
- private static final Function1<Timestamp, Long> TIMESTAMP_TO_LONG =
- new Function1<Timestamp, Long>() {
+ private static final Function<Timestamp, Long> TIMESTAMP_TO_LONG =
+ new Function<Timestamp, Long>() {
public Long apply(Timestamp a0) {
return a0 == null ? null : a0.getTime();
}
};
- private static final Function1<Time, Integer> TIME_TO_INT =
- new Function1<Time, Integer>() {
+ private static final Function<Time, Integer> TIME_TO_INT =
+ new Function<Time, Integer>() {
public Integer apply(Time a0) {
return a0 == null
? null
@@ -68,8 +69,8 @@ class ColumnLoader<T> {
}
};
- private static final Function1<Date, Integer> DATE_TO_INT =
- new Function1<Date, Integer>() {
+ private static final Function<Date, Integer> DATE_TO_INT =
+ new Function<Date, Integer>() {
public Integer apply(Date a0) {
return a0 == null
? null
@@ -77,9 +78,8 @@ class ColumnLoader<T> {
}
};
- public final List<T> list = new ArrayList<T>();
- public final List<ArrayTable.Column> representationValues =
- new ArrayList<ArrayTable.Column>();
+ public final List<T> list = new ArrayList<>();
+ public final List<ArrayTable.Column> representationValues = new ArrayList<>();
private final JavaTypeFactory typeFactory;
public final int sortField;
@@ -264,21 +264,21 @@ class ColumnLoader<T> {
switch (rep) {
case OBJECT:
case JAVA_SQL_TIMESTAMP:
- return Functions.adapt(list, TIMESTAMP_TO_LONG);
+ return Lists.transform(list, TIMESTAMP_TO_LONG);
}
break;
case TIME:
switch (rep) {
case OBJECT:
case JAVA_SQL_TIME:
- return Functions.adapt(list, TIME_TO_INT);
+ return Lists.transform(list, TIME_TO_INT);
}
break;
case DATE:
switch (rep) {
case OBJECT:
case JAVA_SQL_DATE:
- return Functions.adapt(list, DATE_TO_INT);
+ return Lists.transform(list, DATE_TO_INT);
}
break;
}
@@ -291,9 +291,8 @@ class ColumnLoader<T> {
*/
static class ValueSet {
final Class clazz;
- final Map<Comparable, Comparable> map =
- new HashMap<Comparable, Comparable>();
- final List<Comparable> values = new ArrayList<Comparable>();
+ final Map<Comparable, Comparable> map = new HashMap<>();
+ final List<Comparable> values = new ArrayList<>();
Comparable min;
Comparable max;
boolean containsNull;
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/574dc7cc/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcTable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcTable.java b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcTable.java
index 7e68c52..976e311 100644
--- a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcTable.java
+++ b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcTable.java
@@ -24,8 +24,6 @@ import org.apache.calcite.linq4j.Enumerable;
import org.apache.calcite.linq4j.Enumerator;
import org.apache.calcite.linq4j.QueryProvider;
import org.apache.calcite.linq4j.Queryable;
-import org.apache.calcite.linq4j.function.Function1;
-import org.apache.calcite.linq4j.function.Functions;
import org.apache.calcite.linq4j.tree.Primitive;
import org.apache.calcite.plan.RelOptTable;
import org.apache.calcite.rel.RelNode;
@@ -48,6 +46,9 @@ import org.apache.calcite.sql.util.SqlString;
import org.apache.calcite.util.Pair;
import org.apache.calcite.util.Util;
+import com.google.common.base.Function;
+import com.google.common.collect.Lists;
+
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
@@ -110,9 +111,8 @@ class JdbcTable extends AbstractQueryableTable
private List<Pair<Primitive, Integer>> fieldClasses(
final JavaTypeFactory typeFactory) {
final RelDataType rowType = protoRowType.apply(typeFactory);
- return Functions.adapt(
- rowType.getFieldList(),
- new Function1<RelDataTypeField, Pair<Primitive, Integer>>() {
+ return Lists.transform(rowType.getFieldList(),
+ new Function<RelDataTypeField, Pair<Primitive, Integer>>() {
public Pair<Primitive, Integer> apply(RelDataTypeField field) {
RelDataType type = field.getType();
Class clazz = (Class) typeFactory.getJavaClass(type);
@@ -137,7 +137,7 @@ class JdbcTable extends AbstractQueryableTable
}
SqlIdentifier tableName() {
- final List<String> strings = new ArrayList<String>();
+ final List<String> strings = new ArrayList<>();
if (jdbcSchema.catalog != null) {
strings.add(jdbcSchema.catalog);
}
@@ -156,7 +156,7 @@ class JdbcTable extends AbstractQueryableTable
public <T> Queryable<T> asQueryable(QueryProvider queryProvider,
SchemaPlus schema, String tableName) {
- return new JdbcTableQueryable<T>(queryProvider, schema, tableName);
+ return new JdbcTableQueryable<>(queryProvider, schema, tableName);
}
public Enumerable<Object[]> scan(DataContext root) {
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/574dc7cc/core/src/main/java/org/apache/calcite/materialize/MaterializationService.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/materialize/MaterializationService.java b/core/src/main/java/org/apache/calcite/materialize/MaterializationService.java
index 2d4c3f2..3d98567 100644
--- a/core/src/main/java/org/apache/calcite/materialize/MaterializationService.java
+++ b/core/src/main/java/org/apache/calcite/materialize/MaterializationService.java
@@ -28,8 +28,6 @@ import org.apache.calcite.jdbc.CalciteSchema;
import org.apache.calcite.linq4j.AbstractQueryable;
import org.apache.calcite.linq4j.Enumerator;
import org.apache.calcite.linq4j.QueryProvider;
-import org.apache.calcite.linq4j.function.Function1;
-import org.apache.calcite.linq4j.function.Functions;
import org.apache.calcite.linq4j.tree.Expression;
import org.apache.calcite.prepare.Prepare;
import org.apache.calcite.rel.type.RelDataType;
@@ -41,6 +39,7 @@ import org.apache.calcite.util.ImmutableBitSet;
import org.apache.calcite.util.Pair;
import org.apache.calcite.util.Util;
+import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
@@ -123,8 +122,8 @@ public class MaterializationService {
materializedTable =
CloneSchema.createCloneTable(typeFactory,
RelDataTypeImpl.proto(calciteSignature.rowType),
- Functions.adapt(calciteSignature.columns,
- new Function1<ColumnMetaData, ColumnMetaData.Rep>() {
+ Lists.transform(calciteSignature.columns,
+ new Function<ColumnMetaData, ColumnMetaData.Rep>() {
public ColumnMetaData.Rep apply(ColumnMetaData column) {
return column.type.rep;
}
@@ -245,7 +244,7 @@ public class MaterializationService {
// through all tiles.
if (!exact) {
final PriorityQueue<Pair<CalciteSchema.TableEntry, TileKey>> queue =
- new PriorityQueue<Pair<CalciteSchema.TableEntry, TileKey>>(1, C);
+ new PriorityQueue<>(1, C);
for (Map.Entry<TileKey, MaterializationKey> entry
: actor.keyByTile.entrySet()) {
final TileKey tileKey2 = entry.getKey();
@@ -327,8 +326,7 @@ public class MaterializationService {
* with the current schema. Especially in a test run, the contents of two
* root schemas may look similar.) */
public List<Prepare.Materialization> query(CalciteSchema rootSchema) {
- final List<Prepare.Materialization> list =
- new ArrayList<Prepare.Materialization>();
+ final List<Prepare.Materialization> list = new ArrayList<>();
for (MaterializationActor.Materialization materialization
: actor.keyMap.values()) {
if (materialization.rootSchema == rootSchema
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/574dc7cc/core/src/main/java/org/apache/calcite/rel/core/Project.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/core/Project.java b/core/src/main/java/org/apache/calcite/rel/core/Project.java
index af24c58..09c2ec9 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/Project.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/Project.java
@@ -17,8 +17,6 @@
package org.apache.calcite.rel.core;
import org.apache.calcite.linq4j.Ord;
-import org.apache.calcite.linq4j.function.Function1;
-import org.apache.calcite.linq4j.function.Functions;
import org.apache.calcite.plan.RelOptCluster;
import org.apache.calcite.plan.RelOptCost;
import org.apache.calcite.plan.RelOptPlanner;
@@ -46,7 +44,9 @@ import org.apache.calcite.util.Util;
import org.apache.calcite.util.mapping.MappingType;
import org.apache.calcite.util.mapping.Mappings;
+import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
import java.util.List;
@@ -202,9 +202,8 @@ public abstract class Project extends SingleRel {
}
//CHECKSTYLE: IGNORE 1
if (false && !Util.isDistinct(
- Functions.adapt(
- exps,
- new Function1<RexNode, Object>() {
+ Lists.transform(exps,
+ new Function<RexNode, Object>() {
public Object apply(RexNode a0) {
return a0.toString();
}
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/574dc7cc/core/src/main/java/org/apache/calcite/rel/core/Values.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/core/Values.java b/core/src/main/java/org/apache/calcite/rel/core/Values.java
index e6a3bfe..2f4b6ba 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/Values.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/Values.java
@@ -16,8 +16,6 @@
*/
package org.apache.calcite.rel.core;
-import org.apache.calcite.linq4j.function.Function1;
-import org.apache.calcite.linq4j.function.Functions;
import org.apache.calcite.plan.RelOptCluster;
import org.apache.calcite.plan.RelOptCost;
import org.apache.calcite.plan.RelOptPlanner;
@@ -34,8 +32,10 @@ import org.apache.calcite.sql.SqlExplainLevel;
import org.apache.calcite.sql.type.SqlTypeUtil;
import org.apache.calcite.util.Pair;
+import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
import java.util.List;
@@ -47,8 +47,8 @@ public abstract class Values extends AbstractRelNode {
/**
* Lambda that helps render tuples as strings.
*/
- private static final Function1<ImmutableList<RexLiteral>, Object> F =
- new Function1<ImmutableList<RexLiteral>, Object>() {
+ private static final Function<ImmutableList<RexLiteral>, Object> F =
+ new Function<ImmutableList<RexLiteral>, Object>() {
public Object apply(ImmutableList<RexLiteral> tuple) {
String s = tuple.toString();
assert s.startsWith("[");
@@ -171,13 +171,10 @@ public abstract class Values extends AbstractRelNode {
return super.explainTerms(pw)
// For rel digest, include the row type since a rendered
// literal may leave the type ambiguous (e.g. "null").
- .itemIf(
- "type", rowType,
+ .itemIf("type", rowType,
pw.getDetailLevel() == SqlExplainLevel.DIGEST_ATTRIBUTES)
- .itemIf(
- "type", rowType.getFieldList(),
- pw.nest())
- .itemIf("tuples", Functions.adapt(tuples, F), !pw.nest())
+ .itemIf("type", rowType.getFieldList(), pw.nest())
+ .itemIf("tuples", Lists.transform(tuples, F), !pw.nest())
.itemIf("tuples", tuples, pw.nest());
}
}
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/574dc7cc/linq4j/src/main/java/org/apache/calcite/linq4j/function/Functions.java
----------------------------------------------------------------------
diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/function/Functions.java b/linq4j/src/main/java/org/apache/calcite/linq4j/function/Functions.java
index 129c9a2..bd7a446 100644
--- a/linq4j/src/main/java/org/apache/calcite/linq4j/function/Functions.java
+++ b/linq4j/src/main/java/org/apache/calcite/linq4j/function/Functions.java
@@ -54,8 +54,7 @@ public abstract class Functions {
private static final Map<Class, Class<? extends Function>> FUNCTION1_CLASSES =
Collections.unmodifiableMap(
- new HashMap<Class, Class<? extends Function>>(
- inverse(FUNCTION_RESULT_TYPES)));
+ new HashMap<>(inverse(FUNCTION_RESULT_TYPES)));
private static final Comparator NULLS_FIRST_COMPARATOR =
new NullsFirstComparator();
@@ -91,7 +90,7 @@ public abstract class Functions {
@SuppressWarnings("unchecked")
private static <K, V> Map<K, V> map(K k, V v, Object... rest) {
- final Map<K, V> map = new HashMap<K, V>();
+ final Map<K, V> map = new HashMap<>();
map.put(k, v);
for (int i = 0; i < rest.length; i++) {
map.put((K) rest[i++], (V) rest[i++]);
@@ -100,7 +99,7 @@ public abstract class Functions {
}
private static <K, V> Map<V, K> inverse(Map<K, V> map) {
- HashMap<V, K> inverseMap = new HashMap<V, K>();
+ HashMap<V, K> inverseMap = new HashMap<>();
for (Map.Entry<K, V> entry : map.entrySet()) {
inverseMap.put(entry.getValue(), entry.getKey());
}
@@ -306,7 +305,10 @@ public abstract class Functions {
/**
* Creates a view of a list that applies a function to each element.
+ *
+ * @deprecated Use {@link com.google.common.collect.Lists#transform}
*/
+ @Deprecated // to be removed before 2.0
public static <T1, R> List<R> adapt(final List<T1> list,
final Function1<T1, R> f) {
return new AbstractList<R>() {
@@ -322,7 +324,11 @@ public abstract class Functions {
/**
* Creates a view of an array that applies a function to each element.
+ *
+ * @deprecated Use {@link com.google.common.collect.Lists#transform}
+ * and {@link Arrays#asList(Object[])}
*/
+ @Deprecated // to be removed before 2.0
public static <T, R> List<R> adapt(final T[] ts,
final Function1<T, R> f) {
return new AbstractList<R>() {
@@ -341,7 +347,7 @@ public abstract class Functions {
*/
public static <T1, R> List<R> apply(final List<T1> list,
final Function1<T1, R> f) {
- final ArrayList<R> list2 = new ArrayList<R>(list.size());
+ final List<R> list2 = new ArrayList<>(list.size());
for (T1 t : list) {
list2.add(f.apply(t));
}
@@ -376,7 +382,7 @@ public abstract class Functions {
return list;
}
}
- final List<E> list2 = new ArrayList<E>(list.size());
+ final List<E> list2 = new ArrayList<>(list.size());
for (E e : list) {
if (predicate.apply(e)) {
list2.add(e);
@@ -504,7 +510,7 @@ public abstract class Functions {
*/
public static <T, T2> EqualityComparer<T> selectorComparer(
Function1<T, T2> selector) {
- return new SelectorEqualityComparer<T, T2>(selector);
+ return new SelectorEqualityComparer<>(selector);
}
/** Array equality comparer. */
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/574dc7cc/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ConstantExpression.java
----------------------------------------------------------------------
diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ConstantExpression.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ConstantExpression.java
index dcc1962..c9a22de 100644
--- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ConstantExpression.java
+++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ConstantExpression.java
@@ -16,14 +16,15 @@
*/
package org.apache.calcite.linq4j.tree;
-import org.apache.calcite.linq4j.function.Function1;
-import org.apache.calcite.linq4j.function.Functions;
+import com.google.common.base.Function;
+import com.google.common.collect.Lists;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
+import java.util.Arrays;
import java.util.List;
/**
@@ -89,8 +90,7 @@ public class ConstantExpression extends Expression {
case BYTE:
return writer.append("(byte)").append(((Byte) value).intValue());
case CHAR:
- return writer.append("(char)")
- .append((int) ((Character) value).charValue());
+ return writer.append("(char)").append((int) (Character) value);
case SHORT:
return writer.append("(short)").append(((Short) value).intValue());
case LONG:
@@ -149,11 +149,10 @@ public class ConstantExpression extends Expression {
}
Constructor constructor = matchingConstructor(value);
if (constructor != null) {
- final Field[] fields = value.getClass().getFields();
writer.append("new ").append(value.getClass());
list(writer,
- Functions.adapt(fields,
- new Function1<Field, Object>() {
+ Lists.transform(Arrays.asList(value.getClass().getFields()),
+ new Function<Field, Object>() {
public Object apply(Field field) {
try {
return field.get(value);
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/574dc7cc/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ConstructorDeclaration.java
----------------------------------------------------------------------
diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ConstructorDeclaration.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ConstructorDeclaration.java
index 95b4f1c..835e94e 100644
--- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ConstructorDeclaration.java
+++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ConstructorDeclaration.java
@@ -16,8 +16,8 @@
*/
package org.apache.calcite.linq4j.tree;
-import org.apache.calcite.linq4j.function.Function1;
-import org.apache.calcite.linq4j.function.Functions;
+import com.google.common.base.Function;
+import com.google.common.collect.Lists;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
@@ -63,8 +63,8 @@ public class ConstructorDeclaration extends MemberDeclaration {
writer
.append(resultType)
.list("(", ", ", ")",
- Functions.adapt(parameters,
- new Function1<ParameterExpression, String>() {
+ Lists.transform(parameters,
+ new Function<ParameterExpression, String>() {
public String apply(ParameterExpression parameter) {
final String modifiers =
Modifier.toString(parameter.modifier);
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/574dc7cc/linq4j/src/main/java/org/apache/calcite/linq4j/tree/MethodDeclaration.java
----------------------------------------------------------------------
diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/MethodDeclaration.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/MethodDeclaration.java
index 0e4c99a..646a9cd 100644
--- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/MethodDeclaration.java
+++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/MethodDeclaration.java
@@ -16,8 +16,8 @@
*/
package org.apache.calcite.linq4j.tree;
-import org.apache.calcite.linq4j.function.Function1;
-import org.apache.calcite.linq4j.function.Functions;
+import com.google.common.base.Function;
+import com.google.common.collect.Lists;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
@@ -64,8 +64,8 @@ public class MethodDeclaration extends MemberDeclaration {
.append(' ')
.append(name)
.list("(", ", ", ")",
- Functions.adapt(parameters,
- new Function1<ParameterExpression, String>() {
+ Lists.transform(parameters,
+ new Function<ParameterExpression, String>() {
public String apply(ParameterExpression a0) {
return a0.declString();
}
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/574dc7cc/linq4j/src/test/java/org/apache/calcite/linq4j/function/FunctionTest.java
----------------------------------------------------------------------
diff --git a/linq4j/src/test/java/org/apache/calcite/linq4j/function/FunctionTest.java b/linq4j/src/test/java/org/apache/calcite/linq4j/function/FunctionTest.java
index 9db57a5..998aed3 100644
--- a/linq4j/src/test/java/org/apache/calcite/linq4j/function/FunctionTest.java
+++ b/linq4j/src/test/java/org/apache/calcite/linq4j/function/FunctionTest.java
@@ -129,21 +129,6 @@ public class FunctionTest {
// ok
}
}
-
- /** Unit test for {@link Functions#adapt(Object[], Function1)}. */
- @Test public void testAdaptArray() {
- String[] abc = {"a", "b", "c"};
- final Function1<String, String> toUpper =
- new Function1<String, String>() {
- public String apply(String s) {
- return s.toUpperCase();
- }
- };
- Assert.assertEquals("[A, B, C]",
- Functions.adapt(abc, toUpper).toString());
- Assert.assertEquals("[]",
- Functions.adapt(new String[0], toUpper).toString());
- }
}
// End FunctionTest.java
[7/9] incubator-calcite git commit: [CALCITE-638] SQL standard REAL
is 4 bytes, FLOAT is 8 bytes
Posted by jh...@apache.org.
[CALCITE-638] SQL standard REAL is 4 bytes, FLOAT is 8 bytes
Add tests for [CALCITE-630] Flesh out AvaticaParameter#setObject
Move class SqlType to top-level, and add metadata about conversions allowed by JDBC spec
Project: http://git-wip-us.apache.org/repos/asf/incubator-calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-calcite/commit/76a0665c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-calcite/tree/76a0665c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-calcite/diff/76a0665c
Branch: refs/heads/master
Commit: 76a0665c071fe127a514e4425e875bfe2a9d0e1f
Parents: 8b9a577
Author: Julian Hyde <jh...@apache.org>
Authored: Sun Mar 22 22:56:06 2015 -0700
Committer: Julian Hyde <jh...@apache.org>
Committed: Mon Mar 23 02:16:28 2015 -0700
----------------------------------------------------------------------
.../calcite/avatica/AvaticaParameter.java | 63 ++-
.../apache/calcite/avatica/ColumnMetaData.java | 55 --
.../org/apache/calcite/avatica/SqlType.java | 532 +++++++++++++++++++
.../apache/calcite/avatica/remote/Service.java | 2 +-
.../calcite/avatica/util/AbstractCursor.java | 2 +-
.../calcite/jdbc/JavaTypeFactoryImpl.java | 2 +-
.../apache/calcite/rel/metadata/RelMdSize.java | 2 +-
.../apache/calcite/runtime/SqlFunctions.java | 8 +
.../calcite/jdbc/CalciteRemoteDriverTest.java | 311 +++++++++++
.../org/apache/calcite/sql/test/SqlTests.java | 2 +-
.../java/org/apache/calcite/test/JdbcTest.java | 111 ----
11 files changed, 900 insertions(+), 190 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/76a0665c/avatica/src/main/java/org/apache/calcite/avatica/AvaticaParameter.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/org/apache/calcite/avatica/AvaticaParameter.java b/avatica/src/main/java/org/apache/calcite/avatica/AvaticaParameter.java
index c2c0992..8cbe5e4 100644
--- a/avatica/src/main/java/org/apache/calcite/avatica/AvaticaParameter.java
+++ b/avatica/src/main/java/org/apache/calcite/avatica/AvaticaParameter.java
@@ -248,14 +248,6 @@ public class AvaticaParameter {
setBlob(slots, index, (InputStream) x);
}
throw unsupportedCast(x.getClass(), Blob.class);
- case Types.CHAR:
- case Types.NCHAR:
- String s = toString(x);
- if (s.length() == 1) {
- setChar(slots, index, s.charAt(0));
- break;
- }
- throw unsupportedCast(x.getClass(), Character.TYPE);
case Types.DATE:
setDate(slots, index, toDate(x));
break;
@@ -266,7 +258,7 @@ public class AvaticaParameter {
case Types.DISTINCT:
throw notImplemented();
case Types.DOUBLE:
- case Types.FLOAT:
+ case Types.FLOAT: // yes really; SQL FLOAT is up to 8 bytes
setDouble(slots, index, toDouble(x));
break;
case Types.INTEGER:
@@ -279,6 +271,8 @@ public class AvaticaParameter {
case Types.LONGVARCHAR:
case Types.NVARCHAR:
case Types.VARCHAR:
+ case Types.CHAR:
+ case Types.NCHAR:
setString(slots, index, toString(x));
break;
case Types.REAL:
@@ -366,7 +360,13 @@ public class AvaticaParameter {
} else if (x instanceof BigInteger) {
return new BigDecimal((BigInteger) x);
} else if (x instanceof Number) {
- return new BigDecimal(x.toString());
+ if (x instanceof Double || x instanceof Float) {
+ return new BigDecimal(((Number) x).doubleValue());
+ } else {
+ return new BigDecimal(((Number) x).longValue());
+ }
+ } else if (x instanceof Boolean) {
+ return (Boolean) x ? BigDecimal.ONE : BigDecimal.ZERO;
} else if (x instanceof String) {
return new BigDecimal((String) x);
}
@@ -392,6 +392,8 @@ public class AvaticaParameter {
private static byte toByte(Object x) {
if (x instanceof Number) {
return ((Number) x).byteValue();
+ } else if (x instanceof Boolean) {
+ return (Boolean) x ? (byte) 1 : (byte) 0;
} else if (x instanceof String) {
return Byte.parseByte((String) x);
} else {
@@ -403,16 +405,38 @@ public class AvaticaParameter {
if (x instanceof byte[]) {
return (byte[]) x;
}
+ if (x instanceof String) {
+ return ((String) x).getBytes();
+ }
throw unsupportedCast(x.getClass(), byte[].class);
}
private static Date toDate(Object x) {
+ if (x instanceof String) {
+ return Date.valueOf((String) x);
+ }
return new Date(toLong(x));
}
+ private static Time toTime(Object x) {
+ if (x instanceof String) {
+ return Time.valueOf((String) x);
+ }
+ return new Time(toLong(x));
+ }
+
+ private static Timestamp toTimestamp(Object x) {
+ if (x instanceof String) {
+ return Timestamp.valueOf((String) x);
+ }
+ return new Timestamp(toLong(x));
+ }
+
private static double toDouble(Object x) {
if (x instanceof Number) {
return ((Number) x).doubleValue();
+ } else if (x instanceof Boolean) {
+ return (Boolean) x ? 1D : 0D;
} else if (x instanceof String) {
return Double.parseDouble((String) x);
} else {
@@ -423,6 +447,8 @@ public class AvaticaParameter {
private static float toFloat(Object x) {
if (x instanceof Number) {
return ((Number) x).floatValue();
+ } else if (x instanceof Boolean) {
+ return (Boolean) x ? 1F : 0F;
} else if (x instanceof String) {
return Float.parseFloat((String) x);
} else {
@@ -433,6 +459,8 @@ public class AvaticaParameter {
private static int toInt(Object x) {
if (x instanceof Number) {
return ((Number) x).intValue();
+ } else if (x instanceof Boolean) {
+ return (Boolean) x ? 1 : 0;
} else if (x instanceof String) {
return Integer.parseInt((String) x);
} else {
@@ -443,6 +471,8 @@ public class AvaticaParameter {
private static long toLong(Object x) {
if (x instanceof Number) {
return ((Number) x).longValue();
+ } else if (x instanceof Boolean) {
+ return (Boolean) x ? 1L : 0L;
} else if (x instanceof String) {
return Long.parseLong((String) x);
} else {
@@ -453,6 +483,8 @@ public class AvaticaParameter {
private static short toShort(Object x) {
if (x instanceof Number) {
return ((Number) x).shortValue();
+ } else if (x instanceof Boolean) {
+ return (Boolean) x ? (short) 1 : (short) 0;
} else if (x instanceof String) {
return Short.parseShort((String) x);
} else {
@@ -463,20 +495,13 @@ public class AvaticaParameter {
private static String toString(Object x) {
if (x instanceof String) {
return (String) x;
- } else if (x instanceof Character) {
+ } else if (x instanceof Character
+ || x instanceof Boolean) {
return x.toString();
}
throw unsupportedCast(x.getClass(), String.class);
}
- private static Time toTime(Object x) {
- return new Time(toLong(x));
- }
-
- private static Timestamp toTimestamp(Object x) {
- return new Timestamp(toLong(x));
- }
-
/** Singleton value to denote parameters that have been set to null (as
* opposed to not set).
*
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/76a0665c/avatica/src/main/java/org/apache/calcite/avatica/ColumnMetaData.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/org/apache/calcite/avatica/ColumnMetaData.java b/avatica/src/main/java/org/apache/calcite/avatica/ColumnMetaData.java
index 8e9930f..0a4f90a 100644
--- a/avatica/src/main/java/org/apache/calcite/avatica/ColumnMetaData.java
+++ b/avatica/src/main/java/org/apache/calcite/avatica/ColumnMetaData.java
@@ -22,8 +22,6 @@ import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import java.lang.reflect.Type;
-import java.math.BigDecimal;
-import java.sql.Array;
import java.sql.DatabaseMetaData;
import java.sql.ResultSetMetaData;
import java.sql.Time;
@@ -284,59 +282,6 @@ public class ColumnMetaData {
this.component = component;
}
}
-
- /** Extends the information in {@link java.sql.Types}. */
- private enum SqlType {
- BOOLEAN(Types.BOOLEAN, Boolean.class),
- TINYINT(Types.TINYINT, Byte.class),
- SMALLINT(Types.SMALLINT, Short.class),
- INTEGER(Types.INTEGER, Integer.class),
- BIGINT(Types.BIGINT, Long.class),
- DECIMAL(Types.DECIMAL, BigDecimal.class),
- FLOAT(Types.FLOAT, Float.class),
- REAL(Types.REAL, Float.class),
- DOUBLE(Types.DOUBLE, Double.class),
- DATE(Types.DATE, java.sql.Date.class),
- TIME(Types.TIME, Time.class),
- TIMESTAMP(Types.TIMESTAMP, Timestamp.class),
- INTERVAL_YEAR_MONTH(Types.OTHER, Boolean.class),
- INTERVAL_DAY_TIME(Types.OTHER, Boolean.class),
- CHAR(Types.CHAR, String.class),
- VARCHAR(Types.VARCHAR, String.class),
- BINARY(Types.BINARY, byte[].class),
- VARBINARY(Types.VARBINARY, byte[].class),
- NULL(Types.NULL, Void.class),
- ANY(Types.JAVA_OBJECT, Object.class),
- SYMBOL(Types.OTHER, Object.class),
- MULTISET(Types.ARRAY, List.class),
- ARRAY(Types.ARRAY, Array.class),
- MAP(Types.OTHER, Map.class),
- DISTINCT(Types.DISTINCT, Object.class),
- STRUCTURED(Types.STRUCT, Object.class),
- ROW(Types.STRUCT, Object.class),
- OTHER(Types.OTHER, Object.class),
- CURSOR(2012, Object.class),
- COLUMN_LIST(Types.OTHER + 2, Object.class);
-
- private final int type;
- private final Class clazz;
-
- private static final Map<Integer, SqlType> BY_ID = new HashMap<>();
- static {
- for (SqlType sqlType : values()) {
- BY_ID.put(sqlType.type, sqlType);
- }
- }
-
- SqlType(int type, Class clazz) {
- this.type = type;
- this.clazz = clazz;
- }
-
- public static SqlType valueOf(int type) {
- return BY_ID.get(type);
- }
- }
}
// End ColumnMetaData.java
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/76a0665c/avatica/src/main/java/org/apache/calcite/avatica/SqlType.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/org/apache/calcite/avatica/SqlType.java b/avatica/src/main/java/org/apache/calcite/avatica/SqlType.java
new file mode 100644
index 0000000..90e9cba
--- /dev/null
+++ b/avatica/src/main/java/org/apache/calcite/avatica/SqlType.java
@@ -0,0 +1,532 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.avatica;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.net.URL;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.NClob;
+import java.sql.PreparedStatement;
+import java.sql.Ref;
+import java.sql.RowId;
+import java.sql.Struct;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.sql.Types;
+import java.util.AbstractMap;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/** Extends the information in {@link java.sql.Types}.
+ *
+ * <p>The information in the following conversions tables
+ * (from the JDBC 4.1 specification) is held in members of this class.
+ *
+ * <p>Table B-1: JDBC Types Mapped to Java Types
+ *
+ * <pre>
+ * JDBC Type Java Type
+ * ============= =========================
+ * CHAR String
+ * VARCHAR String
+ * LONGVARCHAR String
+ * NUMERIC java.math.BigDecimal
+ * DECIMAL java.math.BigDecimal
+ * BIT boolean
+ * BOOLEAN boolean
+ * TINYINT byte
+ * SMALLINT short
+ * INTEGER int
+ * BIGINT long
+ * REAL float
+ * FLOAT double
+ * DOUBLE double
+ * BINARY byte[]
+ * VARBINARY byte[]
+ * LONGVARBINARY byte[]
+ * DATE java.sql.Date
+ * TIME java.sql.Time
+ * TIMESTAMP java.sql.Timestamp
+ * CLOB java.sql.Clob
+ * BLOB java.sql.Blob
+ * ARRAY java.sql.Array
+ * DISTINCT mapping of underlying type
+ * STRUCT java.sql.Struct
+ * REF java.sql.Ref
+ * DATALINK java.net.URL
+ * JAVA_OBJECT underlying Java class
+ * ROWID java.sql.RowId
+ * NCHAR String
+ * NVARCHAR String
+ * LONGNVARCHAR String
+ * NCLOB java.sql.NClob
+ * SQLXML java.sql.SQLXML
+ * </pre>
+ *
+ * <p>Table B-2: Standard Mapping from Java Types to JDBC Types
+ *
+ * <pre>
+ * Java Type JDBC Type
+ * ==================== ==============================================
+ * String CHAR, VARCHAR, LONGVARCHAR, NCHAR, NVARCHAR or
+ * LONGNVARCHAR
+ * java.math.BigDecimal NUMERIC
+ * boolean BIT or BOOLEAN
+ * byte TINYINT
+ * short SMALLINT
+ * int INTEGER
+ * long BIGINT
+ * float REAL
+ * double DOUBLE
+ * byte[] BINARY, VARBINARY, or LONGVARBINARY
+ * java.sql.Date DATE
+ * java.sql.Time TIME
+ * java.sql.Timestamp TIMESTAMP
+ * java.sql.Clob CLOB
+ * java.sql.Blob BLOB
+ * java.sql.Array ARRAY
+ * java.sql.Struct STRUCT
+ * java.sql.Ref REF
+ * java.net.URL DATALINK
+ * Java class JAVA_OBJECT
+ * java.sql.RowId ROWID
+ * java.sql.NClob NCLOB
+ * java.sql.SQLXML SQLXML
+ * </pre>
+ *
+ * <p>TABLE B-3: Mapping from JDBC Types to Java Object Types
+ *
+ * <pre>
+ * JDBC Type Java Object Type
+ * ============= ======================
+ * CHAR String
+ * VARCHAR String
+ * LONGVARCHAR String
+ * NUMERIC java.math.BigDecimal
+ * DECIMAL java.math.BigDecimal
+ * BIT Boolean
+ * BOOLEAN Boolean
+ * TINYINT Integer
+ * SMALLINT Integer
+ * INTEGER Integer
+ * BIGINT Long
+ * REAL Float
+ * FLOAT Double
+ * DOUBLE Double
+ * BINARY byte[]
+ * VARBINARY byte[]
+ * LONGVARBINARY byte[]
+ * DATE java.sql.Date
+ * TIME java.sql.Time
+ * TIMESTAMP java.sql.Timestamp
+ * DISTINCT Object type of underlying type
+ * CLOB java.sql.Clob
+ * BLOB java.sql.Blob
+ * ARRAY java.sql.Array
+ * STRUCT java.sql.Struct or java.sql.SQLData
+ * REF java.sql.Ref
+ * DATALINK java.net.URL
+ * JAVA_OBJECT underlying Java class
+ * ROWID java.sql.RowId
+ * NCHAR String
+ * NVARCHAR String
+ * LONGNVARCHAR String
+ * NCLOB java.sql.NClob
+ * SQLXML java.sql.SQLXML
+ * </pre>
+ *
+ * <p>TABLE B-4: Mapping from Java Object Types to JDBC Types
+ *
+ * <pre>
+ * Java Object Type JDBC Type
+ * ==================== ===========================================
+ * String CHAR, VARCHAR, LONGVARCHAR, NCHAR, NVARCHAR
+ * or LONGNVARCHAR
+ * java.math.BigDecimal NUMERIC
+ * Boolean BIT or BOOLEAN
+ * Byte TINYINT
+ * Short SMALLINT
+ * Integer INTEGER
+ * Long BIGINT
+ * Float REAL
+ * Double DOUBLE
+ * byte[] BINARY, VARBINARY, or LONGVARBINARY
+ * java.math.BigInteger BIGINT
+ * java.sql.Date DATE
+ * java.sql.Time TIME
+ * java.sql.Timestamp TIMESTAMP
+ * java.sql.Clob CLOB
+ * java.sql.Blob BLOB
+ * java.sql.Array ARRAY
+ * java.sql.Struct STRUCT
+ * java.sql.Ref REF
+ * java.net.URL DATALINK
+ * Java class JAVA_OBJECT
+ * java.sql.RowId ROWID
+ * java.sql.NClob NCLOB
+ * java.sql.SQLXML SQLXML
+ * java.util.Calendar TIMESTAMP
+ * java.util.Date TIMESTAMP
+ * </pre>
+ *
+ * <p><a name="B5">TABLE B-5</a>: Conversions performed by {@code setObject} and
+ * {@code setNull} between Java object types and target JDBC types
+ *
+ * <!--
+ * CHECKSTYLE: OFF
+ * -->
+ * <pre>
+ * T S I B R F D D N B B C V L B V L D T T A B C S R D J R N N L N S
+ * I M N I E L O E U I O H A O I A O A I I R L L T E A A O C V O C Q
+ * N A T G A O U C M T O A R N N R N T M M R O O R F T V W H A N L L
+ * Y L E I L A B I E L R C G A B G E E E A B B U A A I A R G O X
+ * I L G N T L M R E H V R I V E S Y C L _ D R C N B M
+ * N I E T E A I A A A Y N A T T I O H V L
+ * T N R L C N R R A R A N B A A
+ * T C R B M K J R R
+ * H Y I P C
+ * Java type
+ * ==================== = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+ * String x x x x x x x x x x x x x x x x x x x x . . . . . . . . x x x . .
+ * java.math.BigDecimal x x x x x x x x x x x x x . . . . . . . . . . . . . . . . . . . .
+ * Boolean x x x x x x x x x x x x x . . . . . . . . . . . . . . . . . . . .
+ * Byte x x x x x x x x x x x x x . . . . . . . . . . . . . . . . . . . .
+ * Short x x x x x x x x x x x x x . . . . . . . . . . . . . . . . . . . .
+ * Integer x x x x x x x x x x x x x . . . . . . . . . . . . . . . . . . . .
+ * Long x x x x x x x x x x x x x . . . . . . . . . . . . . . . . . . . .
+ * Float x x x x x x x x x x x x x . . . . . . . . . . . . . . . . . . . .
+ * Double x x x x x x x x x x x x x . . . . . . . . . . . . . . . . . . . .
+ * byte[] . . . . . . . . . . . . . . x x x . . . . . . . . . . . . . . . .
+ * java.math.BigInteger . . . x . . . . . . . x x x . . . . . . . . . . . . . . . . . . .
+ * java.sql.Date . . . . . . . . . . . x x x . . . x . x . . . . . . . . . . . . .
+ * java.sql.Time . . . . . . . . . . . x x x . . . . x x . . . . . . . . . . . . .
+ * java.sql.Timestamp . . . . . . . . . . . x x x . . . x x x . . . . . . . . . . . . .
+ * java.sql.Array . . . . . . . . . . . . . . . . . . . . x . . . . . . . . . . . .
+ * java.sql.Blob . . . . . . . . . . . . . . . . . . . . . x . . . . . . . . . . .
+ * java.sql.Clob . . . . . . . . . . . . . . . . . . . . . . x . . . . . . . . . .
+ * java.sql.Struct . . . . . . . . . . . . . . . . . . . . . . . x . . . . . . . . .
+ * java.sql.Ref . . . . . . . . . . . . . . . . . . . . . . . . x . . . . . . . .
+ * java.net.URL . . . . . . . . . . . . . . . . . . . . . . . . . x . . . . . . .
+ * Java class . . . . . . . . . . . . . . . . . . . . . . . . . . x . . . . . .
+ * java.sql.Rowid . . . . . . . . . . . . . . . . . . . . . . . . . . . x . . . . .
+ * java.sql.NClob . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . x .
+ * java.sql.SQLXML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . x
+ * java.util.Calendar . . . . . . . . . . . x x x . . . x x x . . . . . . . . . . . . .
+ * java.util.Date . . . . . . . . . . . x x x . . . x x x . . . . . . . . . . . . .
+ * </pre>
+ * <!--
+ * CHECKSTYLE: ON
+ * -->
+ *
+ * <p><a name="B6">TABLE B-6</a>: Use of {@code ResultSet} getter methods to
+ * retrieve JDBC data types
+ *
+ * <!--
+ * CHECKSTYLE: OFF
+ * -->
+ * <pre>
+ * T S I B R F D D N B B C V L B V L D T T C B A R D S J R N N L N S
+ * I M N I E L O E U I O H A O I A O A I I L L R E A T A O C V O C Q
+ * N A T G A O U C M T O A R N N R N T M M O O R F T R V W H A N L L
+ * Y L E I L A B I E L R C G A B G E E E B B A A U A I A R G O X
+ * I L G N T L M R E H V R I V E S Y L C _ D R C N B M
+ * N I E T E A I A A A Y N A T I T O H V L
+ * T N R L C N R R A R A N B A A
+ * T C R B M K J R R
+ * H Y I P C
+ * Java type
+ * ==================== = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+ * getByte X x x x x x x x x x x x x . . . . . . . . . . . . . . x . . . . .
+ * getShort x X x x x x x x x x x x x . . . . . . . . . . . . . . . . . . . .
+ * getInt x x X x x x x x x x x x x . . . . . . . . . . . . . . . . . . . .
+ * getLong x x x X x x x x x x x x x . . . . . . . . . . . . . . . . . . . .
+ * getFloat x x x x X x x x x x x x x . . . . . . . . . . . . . . . . . . . .
+ * getDouble x x x x x X X x x x x x x . . . . . . . . . . . . . . . . . . . .
+ * getBigDecimal x x x x x x x X X x x x x . . . . . . . . . . . . . . . . . . . .
+ * getBoolean x x x x x x x x x X x x x . . . . . . . . . . . . . . . . . . . .
+ * getString x x x x x x x x x x x X X x x x x x x x . . . . x . . . x x x . .
+ * getNString x x x x x x x x x x x x x x x x x x x x . . . . x . . . X X x . .
+ * getBytes . . . . . . . . . . . . . . X X x . . . . . . . . . . . . . . . .
+ * getDate . . . . . . . . . . . x x x . . . X . x . . . . . . . . . . . . .
+ * getTime . . . . . . . . . . . x x x . . . . X x . . . . . . . . . . . . .
+ * getTimestamp . . . . . . . . . . . x x x . . . x x X . . . . . . . . . . . x .
+ * getAsciiStream . . . . . . . . . . . x x X x x x . . . x . . . . . . . . . . . x
+ * getBinaryStream . . . . . . . . . . . . . . x x X . . . . x . . . . . . . . . x x
+ * getCharacterStream . . . . . . . . . . . x x X x x x . . . x . . . . . . . x x x x x
+ * getNCharacterStream . . . . . . . . . . . x x x x x x . . . x . . . . . . . x x X x x
+ * getClob . . . . . . . . . . . . . . . . . . . . X . . . . . . . . . . x .
+ * getNClob . . . . . . . . . . . . . . . . . . . . x . . . . . . . . . . X .
+ * getBlob . . . . . . . . . . . . . . . . . . . . . X . . . . . . . . . . .
+ * getArray . . . . . . . . . . . . . . . . . . . . . . X . . . . . . . . . .
+ * getRef . . . . . . . . . . . . . . . . . . . . . . . X . . . . . . . . .
+ * getURL . . . . . . . . . . . . . . . . . . . . . . . . X . . . . . . . .
+ * getObject x x x x x x x x x x x x x x x x x x x x x x x x x X X x x x x x x
+ * getRowId . . . . . . . . . . . . . . . . . . . . . . . . . . . X . . . . .
+ * getSQLXML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . X
+ * </pre>
+ * <!--
+ * CHECKSTYLE: ON
+ * -->
+ */
+public enum SqlType {
+ BIT(Types.BIT, Boolean.class),
+ BOOLEAN(Types.BOOLEAN, Boolean.class),
+ TINYINT(Types.TINYINT, Byte.class),
+ SMALLINT(Types.SMALLINT, Short.class),
+ INTEGER(Types.INTEGER, Integer.class),
+ BIGINT(Types.BIGINT, Long.class),
+ NUMERIC(Types.NUMERIC, Object.class),
+ DECIMAL(Types.DECIMAL, BigDecimal.class),
+ FLOAT(Types.FLOAT, Double.class),
+ REAL(Types.REAL, Float.class),
+ DOUBLE(Types.DOUBLE, Double.class),
+ DATE(Types.DATE, java.sql.Date.class),
+ TIME(Types.TIME, Time.class),
+ TIMESTAMP(Types.TIMESTAMP, Timestamp.class),
+ INTERVAL_YEAR_MONTH(Types.OTHER, Boolean.class),
+ INTERVAL_DAY_TIME(Types.OTHER, Boolean.class),
+ CHAR(Types.CHAR, String.class),
+ VARCHAR(Types.VARCHAR, String.class),
+ LONGVARCHAR(Types.LONGVARCHAR, String.class),
+ BINARY(Types.BINARY, byte[].class),
+ VARBINARY(Types.VARBINARY, byte[].class),
+ LONGVARBINARY(Types.LONGVARBINARY, byte[].class),
+ NULL(Types.NULL, Void.class),
+ ANY(Types.JAVA_OBJECT, Object.class),
+ SYMBOL(Types.OTHER, Object.class),
+ MULTISET(Types.ARRAY, List.class),
+ ARRAY(Types.ARRAY, Array.class),
+ BLOB(Types.BLOB, Blob.class),
+ CLOB(Types.CLOB, Clob.class),
+ SQLXML(Types.SQLXML, java.sql.SQLXML.class),
+ MAP(Types.OTHER, Map.class),
+ DISTINCT(Types.DISTINCT, Object.class),
+ STRUCT(Types.STRUCT, Object.class),
+ REF(Types.REF, Ref.class),
+ DATALINK(Types.DATALINK, URL.class),
+ JAVA_OBJECT(Types.JAVA_OBJECT, Object.class),
+ ROWID(Types.ROWID, RowId.class),
+ NCHAR(Types.NCHAR, String.class),
+ NVARCHAR(Types.NVARCHAR, String.class),
+ LONGNVARCHAR(Types.LONGNVARCHAR, String.class),
+ NCLOB(Types.NCLOB, NClob.class),
+ ROW(Types.STRUCT, Object.class),
+ OTHER(Types.OTHER, Object.class),
+ CURSOR(2012, Object.class),
+ COLUMN_LIST(Types.OTHER + 2, Object.class);
+
+ /** Type id as appears in {@link java.sql.Types},
+ * e.g. {@link java.sql.Types#INTEGER}. */
+ public final int id;
+ public final Class clazz;
+
+ private static final Map<Integer, SqlType> BY_ID = new HashMap<>();
+ static {
+ for (SqlType sqlType : values()) {
+ BY_ID.put(sqlType.id, sqlType);
+ }
+ }
+
+ SqlType(int id, Class clazz) {
+ this.id = id;
+ this.clazz = clazz;
+ }
+
+ public static SqlType valueOf(int type) {
+ final SqlType sqlType = BY_ID.get(type);
+ if (sqlType == null) {
+ throw new IllegalArgumentException("Unknown SQL type " + type);
+ }
+ return sqlType;
+ }
+
+ /** Returns the entries in JDBC table B-5. */
+ public static Iterable<Map.Entry<Class, SqlType>> getSetConversions() {
+ final ArrayList<Map.Entry<Class, SqlType>> list = new ArrayList<>();
+ for (Map.Entry<Class, EnumSet<SqlType>> entry : SET_LIST.entrySet()) {
+ for (SqlType sqlType : entry.getValue()) {
+ list.add(new AbstractMap.SimpleEntry<>(entry.getKey(), sqlType));
+ }
+ }
+ return list;
+ }
+
+ public static final Map<Class, EnumSet<SqlType>> SET_LIST;
+ public static final Map<Method, EnumSet<SqlType>> GET_LIST;
+
+ static {
+ SET_LIST = new HashMap<>();
+ GET_LIST = new HashMap<>();
+ EnumSet<SqlType> numericTypes = EnumSet.of(TINYINT, SMALLINT, INTEGER,
+ BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, BOOLEAN);
+ Class[] numericClasses = {
+ BigDecimal.class, Boolean.class, Byte.class, Short.class, Integer.class,
+ Long.class, Float.class, Double.class
+ };
+ EnumSet<SqlType> charTypes = EnumSet.of(CHAR, VARCHAR, LONGVARCHAR);
+ EnumSet<SqlType> ncharTypes = EnumSet.of(NCHAR, NVARCHAR, LONGNVARCHAR);
+ EnumSet<SqlType> binaryTypes = EnumSet.of(BINARY, VARBINARY, LONGVARBINARY);
+ EnumSet<SqlType> dateTimeTypes = EnumSet.of(DATE, TIME, TIMESTAMP);
+ final EnumSet<SqlType> numericCharTypes = concat(numericTypes, charTypes);
+ SET_LIST.put(String.class,
+ concat(numericCharTypes, binaryTypes, dateTimeTypes, ncharTypes));
+ for (Class clazz : numericClasses) {
+ SET_LIST.put(clazz, numericCharTypes);
+ }
+ SET_LIST.put(byte[].class, binaryTypes);
+ SET_LIST.put(BigInteger.class,
+ EnumSet.of(BIGINT, CHAR, VARCHAR, LONGVARCHAR));
+ SET_LIST.put(java.sql.Date.class,
+ concat(charTypes, EnumSet.of(DATE, TIMESTAMP)));
+ SET_LIST.put(Time.class,
+ concat(charTypes, EnumSet.of(TIME, TIMESTAMP)));
+ SET_LIST.put(Timestamp.class,
+ concat(charTypes, EnumSet.of(DATE, TIME, TIMESTAMP)));
+ SET_LIST.put(Array.class, EnumSet.of(ARRAY));
+ SET_LIST.put(Blob.class, EnumSet.of(BLOB));
+ SET_LIST.put(Clob.class, EnumSet.of(CLOB));
+ SET_LIST.put(Struct.class, EnumSet.of(STRUCT));
+ SET_LIST.put(Ref.class, EnumSet.of(REF));
+ SET_LIST.put(URL.class, EnumSet.of(DATALINK));
+ SET_LIST.put(Class.class, EnumSet.of(JAVA_OBJECT));
+ SET_LIST.put(RowId.class, EnumSet.of(ROWID));
+ SET_LIST.put(NClob.class, EnumSet.of(NCLOB));
+ SET_LIST.put(java.sql.SQLXML.class, EnumSet.of(SQLXML));
+ SET_LIST.put(Calendar.class,
+ concat(charTypes, EnumSet.of(DATE, TIME, TIMESTAMP)));
+ SET_LIST.put(java.util.Date.class,
+ concat(charTypes, EnumSet.of(DATE, TIME, TIMESTAMP)));
+
+ EnumSet<Method> numericMethods =
+ EnumSet.of(Method.GET_BYTE, Method.GET_SHORT, Method.GET_INT,
+ Method.GET_LONG, Method.GET_FLOAT, Method.GET_DOUBLE,
+ Method.GET_BIG_DECIMAL, Method.GET_BOOLEAN);
+ for (Method method : numericMethods) {
+ GET_LIST.put(method, numericCharTypes);
+ }
+ GET_LIST.put(Method.GET_BYTE, EnumSet.of(ROWID));
+ for (Method method : EnumSet.of(Method.GET_STRING, Method.GET_N_STRING)) {
+ GET_LIST.put(method,
+ concat(numericCharTypes, binaryTypes, dateTimeTypes,
+ EnumSet.of(DATALINK), ncharTypes));
+ }
+ GET_LIST.put(Method.GET_BYTES, binaryTypes);
+ GET_LIST.put(Method.GET_DATE,
+ concat(charTypes, EnumSet.of(DATE, TIMESTAMP)));
+ GET_LIST.put(Method.GET_TIME,
+ concat(charTypes, EnumSet.of(TIME, TIMESTAMP)));
+ GET_LIST.put(Method.GET_TIMESTAMP,
+ concat(charTypes, EnumSet.of(DATE, TIME, TIMESTAMP)));
+ GET_LIST.put(Method.GET_ASCII_STREAM,
+ concat(charTypes, binaryTypes, EnumSet.of(CLOB, NCLOB)));
+ GET_LIST.put(Method.GET_BINARY_STREAM,
+ concat(binaryTypes, EnumSet.of(BLOB, SQLXML)));
+ GET_LIST.put(Method.GET_CHARACTER_STREAM,
+ concat(charTypes, binaryTypes, ncharTypes,
+ EnumSet.of(CLOB, NCLOB, SQLXML)));
+ GET_LIST.put(Method.GET_N_CHARACTER_STREAM,
+ concat(charTypes, binaryTypes, ncharTypes,
+ EnumSet.of(CLOB, NCLOB, SQLXML)));
+ GET_LIST.put(Method.GET_CLOB, EnumSet.of(CLOB, NCLOB));
+ GET_LIST.put(Method.GET_N_CLOB, EnumSet.of(CLOB, NCLOB));
+ GET_LIST.put(Method.GET_BLOB, EnumSet.of(BLOB));
+ GET_LIST.put(Method.GET_ARRAY, EnumSet.of(ARRAY));
+ GET_LIST.put(Method.GET_REF, EnumSet.of(REF));
+ GET_LIST.put(Method.GET_BLOB, EnumSet.of(BLOB));
+ GET_LIST.put(Method.GET_URL, EnumSet.of(DATALINK));
+ GET_LIST.put(Method.GET_OBJECT, EnumSet.allOf(SqlType.class));
+ GET_LIST.put(Method.GET_ROW_ID, EnumSet.of(ROWID));
+ GET_LIST.put(Method.GET_SQLXML, EnumSet.of(SQLXML));
+ }
+
+ @SafeVarargs
+ private static <E extends Enum<E>> EnumSet<E> concat(Collection<E>... ess) {
+ final List<E> list = new ArrayList<>();
+ for (Collection<E> es : ess) {
+ list.addAll(es);
+ }
+ return EnumSet.copyOf(list);
+ }
+
+ /** Returns whether {@link java.sql.PreparedStatement#setObject} and
+ * {@link PreparedStatement#setNull} can assign a value of a particular class
+ * to a column of a particular SQL type.
+ *
+ * <p>The JDBC standard describes the mapping in table <a href="#B5">B-5</a>.
+ */
+ public static boolean canSet(Class aClass, SqlType sqlType) {
+ final EnumSet<SqlType> sqlTypes = SET_LIST.get(aClass);
+ return sqlTypes != null && sqlTypes.contains(sqlType);
+ }
+
+ /** Returns whether {@link java.sql.ResultSet#getInt(int)} and similar methods
+ * can convert a value to a particular SQL type.
+ *
+ * <p>The JDBC standard describes the mapping in table <a href="#B6">B-6</a>.
+ */
+ public static boolean canGet(Method aClass, SqlType sqlType) {
+ final EnumSet<SqlType> sqlTypes = GET_LIST.get(aClass);
+ return sqlTypes != null && sqlTypes.contains(sqlType);
+ }
+
+ /** Getter methods in {@link java.sql.ResultSet}. */
+ public enum Method {
+ GET_BYTE("getByte"),
+ GET_SHORT("getShort"),
+ GET_INT("getInt"),
+ GET_LONG("getLong"),
+ GET_FLOAT("getFloat"),
+ GET_DOUBLE("getDouble"),
+ GET_BIG_DECIMAL("getBigDecimal"),
+ GET_BOOLEAN("getBoolean"),
+ GET_STRING("getString"),
+ GET_N_STRING("getNString"),
+ GET_BYTES("getBytes"),
+ GET_DATE("getDate"),
+ GET_TIME("getTime"),
+ GET_TIMESTAMP("getTimestamp"),
+ GET_ASCII_STREAM("getAsciiStream"),
+ GET_BINARY_STREAM("getBinaryStream"),
+ GET_CHARACTER_STREAM("getCharacterStream"),
+ GET_N_CHARACTER_STREAM("getNCharacterStream"),
+ GET_CLOB("getClob"),
+ GET_N_CLOB("getNClob"),
+ GET_BLOB("getBlob"),
+ GET_ARRAY("getArray"),
+ GET_REF("getRef"),
+ GET_URL("getURL"),
+ GET_OBJECT("getObject"),
+ GET_ROW_ID("getRowId"),
+ GET_SQLXML("getSQLXML");
+
+ public final String methodName;
+
+ Method(String methodName) {
+ this.methodName = methodName;
+ }
+ }
+}
+
+// End SqlType.java
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/76a0665c/avatica/src/main/java/org/apache/calcite/avatica/remote/Service.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/org/apache/calcite/avatica/remote/Service.java b/avatica/src/main/java/org/apache/calcite/avatica/remote/Service.java
index ed2c332..da897da 100644
--- a/avatica/src/main/java/org/apache/calcite/avatica/remote/Service.java
+++ b/avatica/src/main/java/org/apache/calcite/avatica/remote/Service.java
@@ -171,7 +171,7 @@ public interface Service {
* <p>Several types of request, including
* {@link org.apache.calcite.avatica.Meta#getCatalogs()} and
* {@link org.apache.calcite.avatica.Meta#getSchemas(String, org.apache.calcite.avatica.Meta.Pat)}
- * {@link Meta#getTables(String, org.apache.calcite.avatica.Meta.Pat, org.apache.calcite.avatica.Meta.Pat, List<String>)}
+ * {@link Meta#getTables(String, Meta.Pat, Meta.Pat, List)}
* {@link Meta#getTableTypes()}
* return this response. */
class ResultSetResponse extends Response {
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/76a0665c/avatica/src/main/java/org/apache/calcite/avatica/util/AbstractCursor.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/org/apache/calcite/avatica/util/AbstractCursor.java b/avatica/src/main/java/org/apache/calcite/avatica/util/AbstractCursor.java
index 42731ba..fec143e 100644
--- a/avatica/src/main/java/org/apache/calcite/avatica/util/AbstractCursor.java
+++ b/avatica/src/main/java/org/apache/calcite/avatica/util/AbstractCursor.java
@@ -88,9 +88,9 @@ public abstract class AbstractCursor implements Cursor {
return new LongAccessor(getter);
case Types.BOOLEAN:
return new BooleanAccessor(getter);
- case Types.FLOAT:
case Types.REAL:
return new FloatAccessor(getter);
+ case Types.FLOAT:
case Types.DOUBLE:
return new DoubleAccessor(getter);
case Types.NUMERIC:
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/76a0665c/core/src/main/java/org/apache/calcite/jdbc/JavaTypeFactoryImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/jdbc/JavaTypeFactoryImpl.java b/core/src/main/java/org/apache/calcite/jdbc/JavaTypeFactoryImpl.java
index 7349b07..0ef9128 100644
--- a/core/src/main/java/org/apache/calcite/jdbc/JavaTypeFactoryImpl.java
+++ b/core/src/main/java/org/apache/calcite/jdbc/JavaTypeFactoryImpl.java
@@ -152,9 +152,9 @@ public class JavaTypeFactoryImpl
case BOOLEAN:
return type.isNullable() ? Boolean.class : boolean.class;
case DOUBLE:
+ case FLOAT: // sic
return type.isNullable() ? Double.class : double.class;
case REAL:
- case FLOAT:
return type.isNullable() ? Float.class : float.class;
case BINARY:
case VARBINARY:
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/76a0665c/core/src/main/java/org/apache/calcite/rel/metadata/RelMdSize.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdSize.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdSize.java
index 41c21ab..1a42f01 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdSize.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdSize.java
@@ -265,13 +265,13 @@ public class RelMdSize {
case SMALLINT:
return 2d;
case INTEGER:
- case FLOAT:
case REAL:
case DATE:
case TIME:
return 4d;
case BIGINT:
case DOUBLE:
+ case FLOAT: // sic
case TIMESTAMP:
case INTERVAL_DAY_TIME:
case INTERVAL_YEAR_MONTH:
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/76a0665c/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 77e6827..256d15a 100644
--- a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
+++ b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
@@ -693,6 +693,10 @@ public class SqlFunctions {
return Math.floor(b0);
}
+ public static float floor(float b0) {
+ return (float) Math.floor(b0);
+ }
+
public static BigDecimal floor(BigDecimal b0) {
return b0.setScale(0, BigDecimal.ROUND_FLOOR);
}
@@ -750,6 +754,10 @@ public class SqlFunctions {
return Math.ceil(b0);
}
+ public static float ceil(float b0) {
+ return (float) Math.ceil(b0);
+ }
+
public static BigDecimal ceil(BigDecimal b0) {
return b0.setScale(0, BigDecimal.ROUND_CEILING);
}
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/76a0665c/core/src/test/java/org/apache/calcite/jdbc/CalciteRemoteDriverTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/jdbc/CalciteRemoteDriverTest.java b/core/src/test/java/org/apache/calcite/jdbc/CalciteRemoteDriverTest.java
index 8d10a98..05f54b7 100644
--- a/core/src/test/java/org/apache/calcite/jdbc/CalciteRemoteDriverTest.java
+++ b/core/src/test/java/org/apache/calcite/jdbc/CalciteRemoteDriverTest.java
@@ -18,27 +18,53 @@ package org.apache.calcite.jdbc;
import org.apache.calcite.avatica.AvaticaConnection;
import org.apache.calcite.avatica.Meta;
+import org.apache.calcite.avatica.SqlType;
import org.apache.calcite.avatica.remote.LocalJsonService;
import org.apache.calcite.avatica.remote.LocalService;
import org.apache.calcite.avatica.remote.Service;
import org.apache.calcite.avatica.server.HttpServer;
import org.apache.calcite.avatica.server.Main;
+import org.apache.calcite.prepare.CalcitePrepareImpl;
import org.apache.calcite.test.CalciteAssert;
import com.google.common.base.Function;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
import org.hamcrest.CoreMatchers;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.net.URL;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.Clob;
import java.sql.Connection;
import java.sql.DriverManager;
+import java.sql.NClob;
+import java.sql.PreparedStatement;
+import java.sql.Ref;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
+import java.sql.RowId;
import java.sql.SQLException;
+import java.sql.SQLXML;
import java.sql.Statement;
+import java.sql.Struct;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.util.Calendar;
+import java.util.Date;
import java.util.List;
+import java.util.Map;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
@@ -53,6 +79,10 @@ import static org.junit.Assert.assertTrue;
public class CalciteRemoteDriverTest {
public static final String LJS = Factory2.class.getName();
+ private final PrintStream out =
+ CalcitePrepareImpl.DEBUG ? System.out
+ : new PrintStream(new ByteArrayOutputStream());
+
private static final CalciteAssert.ConnectionFactory
REMOTE_CONNECTION_FACTORY =
new CalciteAssert.ConnectionFactory() {
@@ -211,6 +241,287 @@ public class CalciteRemoteDriverTest {
assertThat(n, equalTo(2));
}
+ /** For each (source, destination) type, make sure that we can convert bind
+ * variables. */
+ @Test public void testParameterConvert() throws Exception {
+ final StringBuilder sql = new StringBuilder("select 1");
+ final Map<SqlType, Integer> map = Maps.newHashMap();
+ for (Map.Entry<Class, SqlType> entry : SqlType.getSetConversions()) {
+ final SqlType sqlType = entry.getValue();
+ switch (sqlType) {
+ case BIT:
+ case LONGVARCHAR:
+ case LONGVARBINARY:
+ case NCHAR:
+ case NVARCHAR:
+ case LONGNVARCHAR:
+ case BLOB:
+ case CLOB:
+ case NCLOB:
+ case ARRAY:
+ case REF:
+ case STRUCT:
+ case DATALINK:
+ case ROWID:
+ case JAVA_OBJECT:
+ case SQLXML:
+ continue;
+ }
+ if (!map.containsKey(sqlType)) {
+ sql.append(", cast(? as ").append(sqlType).append(")");
+ map.put(sqlType, map.size() + 1);
+ }
+ }
+ sql.append(" from (values 1)");
+ final PreparedStatement statement =
+ localConnection.prepareStatement(sql.toString());
+ for (Map.Entry<SqlType, Integer> entry : map.entrySet()) {
+ statement.setNull(entry.getValue(), entry.getKey().id);
+ }
+ for (Map.Entry<Class, SqlType> entry : SqlType.getSetConversions()) {
+ final SqlType sqlType = entry.getValue();
+ if (!map.containsKey(sqlType)) {
+ continue;
+ }
+ int param = map.get(sqlType);
+ Class clazz = entry.getKey();
+ for (Object sampleValue : values(sqlType.clazz)) {
+ switch (sqlType) {
+ case DATE:
+ case TIME:
+ case TIMESTAMP:
+ continue; // FIXME
+ }
+ if (clazz == Calendar.class) {
+ continue; // FIXME
+ }
+ final Object o;
+ try {
+ o = convert(sampleValue, clazz);
+ } catch (IllegalArgumentException | ParseException e) {
+ continue;
+ }
+ out.println("check " + o + " (originally "
+ + sampleValue.getClass() + ", now " + o.getClass()
+ + ") converted to " + sqlType);
+ if (o instanceof Double && o.equals(Double.POSITIVE_INFINITY)
+ || o instanceof Float && o.equals(Float.POSITIVE_INFINITY)) {
+ continue;
+ }
+ statement.setObject(param, o, sqlType.id);
+ final ResultSet resultSet = statement.executeQuery();
+ assertThat(resultSet.next(), is(true));
+ out.println(resultSet.getString(param + 1));
+ }
+ }
+ statement.close();
+ }
+
+ /** Check that the "set" conversion table looks like Table B-5 in JDBC 4.1
+ * specification */
+ @Test public void testTableB5() {
+ SqlType[] columns = {
+ SqlType.TINYINT, SqlType.SMALLINT, SqlType.INTEGER, SqlType.BIGINT,
+ SqlType.REAL, SqlType.FLOAT, SqlType.DOUBLE, SqlType.DECIMAL,
+ SqlType.NUMERIC, SqlType.BIT, SqlType.BOOLEAN, SqlType.CHAR,
+ SqlType.VARCHAR, SqlType.LONGVARCHAR, SqlType.BINARY, SqlType.VARBINARY,
+ SqlType.LONGVARBINARY, SqlType.DATE, SqlType.TIME, SqlType.TIMESTAMP,
+ SqlType.ARRAY, SqlType.BLOB, SqlType.CLOB, SqlType.STRUCT, SqlType.REF,
+ SqlType.DATALINK, SqlType.JAVA_OBJECT, SqlType.ROWID, SqlType.NCHAR,
+ SqlType.NVARCHAR, SqlType.LONGNVARCHAR, SqlType.NCLOB, SqlType.SQLXML
+ };
+ Class[] rows = {
+ String.class, BigDecimal.class, Boolean.class, Byte.class, Short.class,
+ Integer.class, Long.class, Float.class, Double.class, byte[].class,
+ BigInteger.class, java.sql.Date.class, Time.class, Timestamp.class,
+ Array.class, Blob.class, Clob.class, Struct.class, Ref.class,
+ URL.class, Class.class, RowId.class, NClob.class, SQLXML.class,
+ Calendar.class, java.util.Date.class
+ };
+ for (Class row : rows) {
+ final String s = row == Date.class ? row.getName() : row.getSimpleName();
+ out.print(pad(s));
+ for (SqlType column : columns) {
+ out.print(SqlType.canSet(row, column) ? "x " : ". ");
+ }
+ out.println();
+ }
+ }
+
+ private String pad(String x) {
+ while (x.length() < 20) {
+ x = x + " ";
+ }
+ return x;
+ }
+
+ /** Check that the "get" conversion table looks like Table B-5 in JDBC 4.1
+ * specification */
+ @Test public void testTableB6() {
+ SqlType[] columns = {
+ SqlType.TINYINT, SqlType.SMALLINT, SqlType.INTEGER, SqlType.BIGINT,
+ SqlType.REAL, SqlType.FLOAT, SqlType.DOUBLE, SqlType.DECIMAL,
+ SqlType.NUMERIC, SqlType.BIT, SqlType.BOOLEAN, SqlType.CHAR,
+ SqlType.VARCHAR, SqlType.LONGVARCHAR, SqlType.BINARY, SqlType.VARBINARY,
+ SqlType.LONGVARBINARY, SqlType.DATE, SqlType.TIME, SqlType.TIMESTAMP,
+ SqlType.CLOB, SqlType.BLOB, SqlType.ARRAY, SqlType.REF,
+ SqlType.DATALINK, SqlType.STRUCT, SqlType.JAVA_OBJECT, SqlType.ROWID,
+ SqlType.NCHAR, SqlType.NVARCHAR, SqlType.LONGNVARCHAR, SqlType.NCLOB,
+ SqlType.SQLXML
+ };
+ final PrintStream out =
+ CalcitePrepareImpl.DEBUG ? System.out
+ : new PrintStream(new ByteArrayOutputStream());
+ for (SqlType.Method row : SqlType.Method.values()) {
+ out.print(pad(row.methodName));
+ for (SqlType column : columns) {
+ out.print(SqlType.canGet(row, column) ? "x " : ". ");
+ }
+ out.println();
+ }
+ }
+
+ /** A bunch of sample values of various types. */
+ private static final List<Object> SAMPLE_VALUES =
+ ImmutableList.<Object>of(false, true,
+ // byte
+ (byte) 0, (byte) 1, Byte.MIN_VALUE, Byte.MAX_VALUE,
+ // short
+ (short) 0, (short) 1, Short.MIN_VALUE, Short.MAX_VALUE,
+ (short) Byte.MIN_VALUE, (short) Byte.MAX_VALUE,
+ // int
+ 0, 1, -3, Integer.MIN_VALUE, Integer.MAX_VALUE,
+ (int) Short.MIN_VALUE, (int) Short.MAX_VALUE,
+ (int) Byte.MIN_VALUE, (int) Byte.MAX_VALUE,
+ // long
+ 0L, 1L, -2L, Long.MIN_VALUE, Long.MAX_VALUE,
+ (long) Integer.MIN_VALUE, (long) Integer.MAX_VALUE,
+ (long) Short.MIN_VALUE, (long) Short.MAX_VALUE,
+ (long) Byte.MIN_VALUE, (long) Byte.MAX_VALUE,
+ // float
+ 0F, 1.5F, -10F, Float.MIN_VALUE, Float.MAX_VALUE,
+ // double
+ 0D, Math.PI, Double.MIN_VALUE, Double.MAX_VALUE,
+ (double) Float.MIN_VALUE, (double) Float.MAX_VALUE,
+ (double) Integer.MIN_VALUE, (double) Integer.MAX_VALUE,
+ // BigDecimal
+ BigDecimal.ZERO, BigDecimal.ONE, BigDecimal.valueOf(2.5D),
+ BigDecimal.valueOf(Double.MAX_VALUE),
+ BigDecimal.valueOf(Long.MIN_VALUE),
+ // datetime
+ new Timestamp(0),
+ new java.sql.Date(0),
+ new Time(0),
+ // string
+ "", "foo", " foo! Baz ",
+ // byte[]
+ new byte[0], "hello".getBytes());
+
+ private static List<Object> values(Class clazz) {
+ final List<Object> list = Lists.newArrayList();
+ for (Object sampleValue : SAMPLE_VALUES) {
+ if (sampleValue.getClass() == clazz) {
+ list.add(sampleValue);
+ }
+ }
+ return list;
+ }
+
+ private Object convert(Object o, Class clazz) throws ParseException {
+ if (o.getClass() == clazz) {
+ return o;
+ }
+ if (clazz == String.class) {
+ return o.toString();
+ }
+ if (clazz == Boolean.class) {
+ return o instanceof Number
+ && ((Number) o).intValue() != 0
+ || o instanceof String
+ && ((String) o).equalsIgnoreCase("true");
+ }
+ if (clazz == byte[].class) {
+ if (o instanceof String) {
+ return ((String) o).getBytes();
+ }
+ }
+ if (clazz == Timestamp.class) {
+ if (o instanceof String) {
+ return Timestamp.valueOf((String) o);
+ }
+ }
+ if (clazz == Time.class) {
+ if (o instanceof String) {
+ return Time.valueOf((String) o);
+ }
+ }
+ if (clazz == java.sql.Date.class) {
+ if (o instanceof String) {
+ return java.sql.Date.valueOf((String) o);
+ }
+ }
+ if (clazz == java.util.Date.class) {
+ if (o instanceof String) {
+ return DateFormat.getInstance().parse((String) o);
+ }
+ }
+ if (clazz == Calendar.class) {
+ if (o instanceof String) {
+ return Calendar.getInstance(); // TODO:
+ }
+ }
+ if (o instanceof Boolean) {
+ o = (Boolean) o ? 1 : 0;
+ }
+ if (o instanceof Number) {
+ final Number number = (Number) o;
+ if (Number.class.isAssignableFrom(clazz)) {
+ if (clazz == BigDecimal.class) {
+ if (o instanceof Double || o instanceof Float) {
+ return new BigDecimal(number.doubleValue());
+ } else {
+ return new BigDecimal(number.longValue());
+ }
+ } else if (clazz == BigInteger.class) {
+ return new BigInteger(o.toString());
+ } else if (clazz == Byte.class || clazz == byte.class) {
+ return number.byteValue();
+ } else if (clazz == Short.class || clazz == short.class) {
+ return number.shortValue();
+ } else if (clazz == Integer.class || clazz == int.class) {
+ return number.intValue();
+ } else if (clazz == Long.class || clazz == long.class) {
+ return number.longValue();
+ } else if (clazz == Float.class || clazz == float.class) {
+ return number.floatValue();
+ } else if (clazz == Double.class || clazz == double.class) {
+ return number.doubleValue();
+ }
+ }
+ }
+ if (Number.class.isAssignableFrom(clazz)) {
+ if (clazz == BigDecimal.class) {
+ return new BigDecimal(o.toString());
+ } else if (clazz == BigInteger.class) {
+ return new BigInteger(o.toString());
+ } else if (clazz == Byte.class || clazz == byte.class) {
+ return Byte.valueOf(o.toString());
+ } else if (clazz == Short.class || clazz == short.class) {
+ return Short.valueOf(o.toString());
+ } else if (clazz == Integer.class || clazz == int.class) {
+ return Integer.valueOf(o.toString());
+ } else if (clazz == Long.class || clazz == long.class) {
+ return Long.valueOf(o.toString());
+ } else if (clazz == Float.class || clazz == float.class) {
+ return Float.valueOf(o.toString());
+ } else if (clazz == Double.class || clazz == double.class) {
+ return Double.valueOf(o.toString());
+ }
+ }
+ throw new AssertionError("cannot convert " + o + "(" + o.getClass()
+ + ") to " + clazz);
+ }
+
/** Creates a {@link Meta} that can see the test databases. */
public static class Factory implements Meta.Factory {
public Meta create(List<String> args) {
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/76a0665c/core/src/test/java/org/apache/calcite/sql/test/SqlTests.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/sql/test/SqlTests.java b/core/src/test/java/org/apache/calcite/sql/test/SqlTests.java
index b5c2fd6..4f15f7d 100644
--- a/core/src/test/java/org/apache/calcite/sql/test/SqlTests.java
+++ b/core/src/test/java/org/apache/calcite/sql/test/SqlTests.java
@@ -187,7 +187,7 @@ public abstract class SqlTests {
return ColumnMetaData.Rep.INTEGER;
case Types.BIGINT:
return ColumnMetaData.Rep.LONG;
- case Types.FLOAT:
+ case Types.REAL:
return ColumnMetaData.Rep.FLOAT;
case Types.DOUBLE:
return ColumnMetaData.Rep.DOUBLE;
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/76a0665c/core/src/test/java/org/apache/calcite/test/JdbcTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/JdbcTest.java b/core/src/test/java/org/apache/calcite/test/JdbcTest.java
index 989243f..6eed428 100644
--- a/core/src/test/java/org/apache/calcite/test/JdbcTest.java
+++ b/core/src/test/java/org/apache/calcite/test/JdbcTest.java
@@ -86,7 +86,6 @@ import org.apache.calcite.util.Util;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableMultimap;
import net.hydromatic.quidem.Quidem;
@@ -2381,116 +2380,6 @@ public class JdbcTest {
.returns("EXPR$0=-3\n");
}
- /**
- * Conversions table, per JDBC 1.1 specification, table 6.
- *
- * <pre>
- * T S I B R F D D N B C V L B V L D T T
- * I M N I E L O E U I H A O I A O A I I
- * N A T G A O U C M T A R N N R N T M M
- * Y L E I L A B I E R C G A B G E E E
- * I L G N L M R H V R I V E S
- * N I E T E A I A A Y A T
- * T N R L C R R R A
- * T C B M
- * H I P
- * Java type
- * ================== = = = = = = = = = = = = = = = = = = =
- * String x x x x x x x x x x x x x x x x x x x
- * BigDecimal x x x x x x x x x x x x . . . . . . .
- * Boolean x x x x x x x x x x x x . . . . . . .
- * Integer x x x x x x x x x x x x . . . . . . .
- * Long x x x x x x x x x x x x . . . . . . .
- * Float x x x x x x x x x x x x . . . . . . .
- * Double x x x x x x x x x x x x . . . . . . .
- * byte[] . . . . . . . . . . . . . x x x . . .
- * java.sql.Date . . . . . . . . . . x x x . . . x . x
- * java.sql.Time . . . . . . . . . . x x x . . . . x .
- * java.sql.Timestamp . . . . . . . . . . x x x . . . x x x
- * </pre>
- */
- public static final ImmutableMultimap<Class, Integer> CONVERSIONS = x();
-
- private static ImmutableMultimap<Class, Integer> x() {
- final ImmutableMultimap.Builder<Class, Integer> builder =
- ImmutableMultimap.builder();
- int[] allTypes = {
- java.sql.Types.TINYINT,
- java.sql.Types.SMALLINT,
- java.sql.Types.INTEGER,
- java.sql.Types.BIGINT,
- java.sql.Types.REAL,
- java.sql.Types.FLOAT,
- java.sql.Types.DOUBLE,
- java.sql.Types.DECIMAL,
- java.sql.Types.NUMERIC,
- java.sql.Types.BIT,
- java.sql.Types.CHAR,
- java.sql.Types.VARCHAR,
- java.sql.Types.LONGVARCHAR,
- java.sql.Types.BINARY,
- java.sql.Types.VARBINARY,
- java.sql.Types.LONGVARBINARY,
- java.sql.Types.DATE,
- java.sql.Types.TIME,
- java.sql.Types.TIMESTAMP
- };
- int[] numericTypes = {
- java.sql.Types.TINYINT,
- java.sql.Types.SMALLINT,
- java.sql.Types.INTEGER,
- java.sql.Types.BIGINT,
- java.sql.Types.REAL,
- java.sql.Types.FLOAT,
- java.sql.Types.DOUBLE,
- java.sql.Types.DECIMAL,
- java.sql.Types.NUMERIC,
- java.sql.Types.BIT
- };
- Class[] numericClasses = {
- BigDecimal.class, Boolean.class, Integer.class, Long.class, Float.class,
- Double.class
- };
- Class[] allClasses = {
- String.class, BigDecimal.class, Boolean.class, Integer.class,
- Long.class, Float.class, Double.class, byte[].class,
- java.sql.Date.class, java.sql.Time.class, java.sql.Timestamp.class,
- };
- int[] charTypes = {
- java.sql.Types.CHAR,
- java.sql.Types.VARCHAR,
- java.sql.Types.LONGVARCHAR
- };
- int[] binaryTypes = {
- java.sql.Types.BINARY,
- java.sql.Types.VARBINARY,
- java.sql.Types.LONGVARBINARY
- };
- for (int type : allTypes) {
- builder.put(String.class, type);
- }
- for (Class clazz : numericClasses) {
- for (int type : numericTypes) {
- builder.put(clazz, type);
- }
- }
- for (int type : charTypes) {
- for (Class clazz : allClasses) {
- builder.put(clazz, type);
- }
- }
- for (int type : binaryTypes) {
- builder.put(byte[].class, type);
- }
- builder.put(java.sql.Date.class, java.sql.Types.DATE);
- builder.put(java.sql.Date.class, java.sql.Types.TIMESTAMP);
- builder.put(java.sql.Time.class, java.sql.Types.TIME);
- builder.put(java.sql.Timestamp.class, java.sql.Types.DATE);
- builder.put(java.sql.Time.class, java.sql.Types.TIME);
- builder.put(java.sql.Timestamp.class, java.sql.Types.TIMESTAMP);
- return builder.build();
- }
-
/** Tests a table constructor that has multiple rows and multiple columns.
*
* <p>Note that the character literals become CHAR(3) and that the first is
[3/9] incubator-calcite git commit: [CALCITE-618] Add Avatica support
for getTables (Julian Hyde and Nick Dimiduk)
Posted by jh...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/avatica/src/test/java/org/apache/calcite/avatica/test/RemoteDriverTest.java
----------------------------------------------------------------------
diff --git a/avatica/src/test/java/org/apache/calcite/avatica/test/RemoteDriverTest.java b/avatica/src/test/java/org/apache/calcite/avatica/test/RemoteDriverTest.java
index 5cf1ea5..c007f02 100644
--- a/avatica/src/test/java/org/apache/calcite/avatica/test/RemoteDriverTest.java
+++ b/avatica/src/test/java/org/apache/calcite/avatica/test/RemoteDriverTest.java
@@ -16,21 +16,34 @@
*/
package org.apache.calcite.avatica.test;
+import org.apache.calcite.avatica.AvaticaConnection;
+import org.apache.calcite.avatica.jdbc.JdbcMeta;
import org.apache.calcite.avatica.remote.LocalJsonService;
+import org.apache.calcite.avatica.remote.LocalService;
import org.apache.calcite.avatica.remote.MockJsonService;
+import org.apache.calcite.avatica.remote.Service;
+
+import net.hydromatic.scott.data.hsqldb.ScottHsqldb;
import org.junit.Ignore;
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
+import java.sql.ParameterMetaData;
+import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
/**
* Unit test for Avatica Remote JDBC driver.
@@ -40,7 +53,20 @@ public class RemoteDriverTest {
MockJsonService.Factory.class.getName();
public static final String LJS =
- LocalJsonService.Factory.class.getName();
+ LocalJdbcServiceFactory.class.getName();
+
+ public static final String QRJS =
+ QuasiRemoteJdbcServiceFactory.class.getName();
+
+ private static final ConnectionSpec CONNECTION_SPEC = ConnectionSpec.HSQLDB;
+
+ private Connection mjs() throws SQLException {
+ return DriverManager.getConnection("jdbc:avatica:remote:factory=" + MJS);
+ }
+
+ private Connection ljs() throws SQLException {
+ return DriverManager.getConnection("jdbc:avatica:remote:factory=" + QRJS);
+ }
@Test public void testRegister() throws Exception {
final Connection connection =
@@ -50,6 +76,33 @@ public class RemoteDriverTest {
assertThat(connection.isClosed(), is(true));
}
+ @Test public void testSchemas() throws Exception {
+ final Connection connection = mjs();
+ final ResultSet resultSet =
+ connection.getMetaData().getSchemas(null, null);
+ assertFalse(resultSet.next());
+ final ResultSetMetaData metaData = resultSet.getMetaData();
+ assertTrue(metaData.getColumnCount() >= 2);
+ assertEquals("TABLE_CATALOG", metaData.getColumnName(1));
+ assertEquals("TABLE_SCHEM", metaData.getColumnName(2));
+ resultSet.close();
+ connection.close();
+ }
+
+ @Test public void testTables() throws Exception {
+ final Connection connection = mjs();
+ final ResultSet resultSet =
+ connection.getMetaData().getTables(null, null, null, new String[0]);
+ assertFalse(resultSet.next());
+ final ResultSetMetaData metaData = resultSet.getMetaData();
+ assertTrue(metaData.getColumnCount() >= 3);
+ assertEquals("TABLE_CAT", metaData.getColumnName(1));
+ assertEquals("TABLE_SCHEM", metaData.getColumnName(2));
+ assertEquals("TABLE_NAME", metaData.getColumnName(3));
+ resultSet.close();
+ connection.close();
+ }
+
@Ignore
@Test public void testNoFactory() throws Exception {
final Connection connection =
@@ -68,8 +121,7 @@ public class RemoteDriverTest {
@Ignore
@Test public void testCatalogsMock() throws Exception {
- final Connection connection =
- DriverManager.getConnection("jdbc:avatica:remote:factory=" + MJS);
+ final Connection connection = mjs();
assertThat(connection.isClosed(), is(false));
final ResultSet resultSet = connection.getMetaData().getSchemas();
assertFalse(resultSet.next());
@@ -81,6 +133,164 @@ public class RemoteDriverTest {
connection.close();
assertThat(connection.isClosed(), is(true));
}
+
+ @Test public void testStatementExecuteQueryLocal() throws Exception {
+ checkStatementExecuteQuery(ljs(), false);
+ }
+
+ @Ignore
+ @Test public void testStatementExecuteQueryMock() throws Exception {
+ checkStatementExecuteQuery(mjs(), false);
+ }
+
+ @Ignore
+ @Test public void testPrepareExecuteQueryLocal() throws Exception {
+ checkStatementExecuteQuery(ljs(), true);
+ }
+
+ @Ignore
+ @Test public void testPrepareExecuteQueryMock() throws Exception {
+ checkStatementExecuteQuery(mjs(), true);
+ }
+
+ private void checkStatementExecuteQuery(Connection connection,
+ boolean prepare) throws SQLException {
+ final String sql = "select * from (\n"
+ + " values (1, 'a'), (null, 'b'), (3, 'c')) as t (c1, c2)";
+ final Statement statement;
+ final ResultSet resultSet;
+ final ParameterMetaData parameterMetaData;
+ if (prepare) {
+ final PreparedStatement ps = connection.prepareStatement(sql);
+ statement = ps;
+ parameterMetaData = ps.getParameterMetaData();
+ resultSet = ps.executeQuery();
+ } else {
+ statement = connection.createStatement();
+ parameterMetaData = null;
+ resultSet = statement.executeQuery(sql);
+ }
+ if (parameterMetaData != null) {
+ assertThat(parameterMetaData.getParameterCount(), equalTo(2));
+ }
+ final ResultSetMetaData metaData = resultSet.getMetaData();
+ assertEquals(2, metaData.getColumnCount());
+ assertEquals("C1", metaData.getColumnName(1));
+ assertEquals("C2", metaData.getColumnName(2));
+ assertTrue(resultSet.next());
+ assertTrue(resultSet.next());
+ assertTrue(resultSet.next());
+ assertFalse(resultSet.next());
+ resultSet.close();
+ statement.close();
+ connection.close();
+ }
+
+ @Test public void testPrepareBindExecuteFetch() throws Exception {
+ checkPrepareBindExecuteFetch(ljs());
+ }
+
+ private void checkPrepareBindExecuteFetch(Connection connection)
+ throws SQLException {
+ final String sql = "select cast(? as integer) * 3 as c, 'x' as x\n"
+ + "from (values (1, 'a'))";
+ final PreparedStatement ps =
+ connection.prepareStatement(sql);
+ final ResultSetMetaData metaData = ps.getMetaData();
+ assertEquals(2, metaData.getColumnCount());
+ assertEquals("C", metaData.getColumnName(1));
+ assertEquals("X", metaData.getColumnName(2));
+ try {
+ final ResultSet resultSet = ps.executeQuery();
+ fail("expected error, got " + resultSet);
+ } catch (SQLException e) {
+ assertThat(e.getMessage(),
+ equalTo("exception while executing query: unbound parameter"));
+ }
+
+ final ParameterMetaData parameterMetaData = ps.getParameterMetaData();
+ assertThat(parameterMetaData.getParameterCount(), equalTo(1));
+
+ ps.setInt(1, 10);
+ final ResultSet resultSet = ps.executeQuery();
+ assertTrue(resultSet.next());
+ assertThat(resultSet.getInt(1), equalTo(30));
+ assertFalse(resultSet.next());
+ resultSet.close();
+
+ ps.setInt(1, 20);
+ final ResultSet resultSet2 = ps.executeQuery();
+ assertFalse(resultSet2.isClosed());
+ assertTrue(resultSet2.next());
+ assertThat(resultSet2.getInt(1), equalTo(60));
+ assertThat(resultSet2.wasNull(), is(false));
+ assertFalse(resultSet2.next());
+ resultSet2.close();
+
+ ps.setObject(1, null);
+ final ResultSet resultSet3 = ps.executeQuery();
+ assertTrue(resultSet3.next());
+ assertThat(resultSet3.getInt(1), equalTo(0));
+ assertThat(resultSet3.wasNull(), is(true));
+ assertFalse(resultSet3.next());
+ resultSet3.close();
+
+ ps.close();
+ connection.close();
+ }
+
+ /** Factory that creates a service based on a local JDBC connection. */
+ public static class LocalJdbcServiceFactory implements Service.Factory {
+ @Override public Service create(AvaticaConnection connection) {
+ try {
+ Connection connection1 =
+ DriverManager.getConnection(CONNECTION_SPEC.url,
+ CONNECTION_SPEC.username, CONNECTION_SPEC.password);
+ return new LocalService(new JdbcMeta(connection1));
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /** Factory that creates a service based on a local JDBC connection. */
+ public static class QuasiRemoteJdbcServiceFactory implements Service.Factory {
+ @Override public Service create(AvaticaConnection connection) {
+ try {
+ Connection connection1 =
+ DriverManager.getConnection(CONNECTION_SPEC.url,
+ CONNECTION_SPEC.username, CONNECTION_SPEC.password);
+ final JdbcMeta jdbcMeta = new JdbcMeta(connection1);
+ final LocalService localService = new LocalService(jdbcMeta);
+ final LocalJsonService localJsonService =
+ new LocalJsonService(localService);
+ return localJsonService;
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /** Information necessary to create a JDBC connection. Specify one to run
+ * tests against a different database. (hsqldb is the default.) */
+ public static class ConnectionSpec {
+ public final String url;
+ public final String username;
+ public final String password;
+ public final String driver;
+
+ public ConnectionSpec(String url, String username, String password,
+ String driver) {
+ this.url = url;
+ this.username = username;
+ this.password = password;
+ this.driver = driver;
+ }
+
+ public static final ConnectionSpec HSQLDB =
+ new ConnectionSpec(ScottHsqldb.URI, ScottHsqldb.USER,
+ ScottHsqldb.PASSWORD, "org.hsqldb.jdbcDriver");
+ }
}
// End RemoteDriverTest.java
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/core/pom.xml
----------------------------------------------------------------------
diff --git a/core/pom.xml b/core/pom.xml
index 36a88f5..34059f7 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -89,6 +89,11 @@ limitations under the License.
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>net.hydromatic</groupId>
+ <artifactId>scott-data-hsqldb</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>org.codehaus.janino</groupId>
<artifactId>janino</artifactId>
</dependency>
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/core/src/main/java/org/apache/calcite/jdbc/CalciteJdbc41Factory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/jdbc/CalciteJdbc41Factory.java b/core/src/main/java/org/apache/calcite/jdbc/CalciteJdbc41Factory.java
index 0b87f0f..e5a567c 100644
--- a/core/src/main/java/org/apache/calcite/jdbc/CalciteJdbc41Factory.java
+++ b/core/src/main/java/org/apache/calcite/jdbc/CalciteJdbc41Factory.java
@@ -91,13 +91,13 @@ public class CalciteJdbc41Factory extends CalciteFactory {
}
public CalciteResultSet newResultSet(AvaticaStatement statement,
- Meta.Signature signature, TimeZone timeZone, Iterable<Object> iterable) {
+ Meta.Signature signature, TimeZone timeZone, Meta.Frame firstFrame) {
final ResultSetMetaData metaData =
newResultSetMetaData(statement, signature);
final CalcitePrepare.CalciteSignature calciteSignature =
(CalcitePrepare.CalciteSignature) signature;
return new CalciteResultSet(statement, calciteSignature, metaData, timeZone,
- iterable);
+ firstFrame);
}
public ResultSetMetaData newResultSetMetaData(AvaticaStatement statement,
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/core/src/main/java/org/apache/calcite/jdbc/CalciteMetaImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/jdbc/CalciteMetaImpl.java b/core/src/main/java/org/apache/calcite/jdbc/CalciteMetaImpl.java
index 152e918..cf395f6 100644
--- a/core/src/main/java/org/apache/calcite/jdbc/CalciteMetaImpl.java
+++ b/core/src/main/java/org/apache/calcite/jdbc/CalciteMetaImpl.java
@@ -157,7 +157,7 @@ public class CalciteMetaImpl extends MetaImpl {
final Iterable<Object> iterable = (Iterable<Object>) (Iterable) enumerable;
return createResultSet(Collections.<String, Object>emptyMap(),
columns, CursorFactory.record(clazz, fields, fieldNames),
- iterable);
+ new Frame(0, true, iterable));
}
@Override protected <E> MetaResultSet
@@ -165,12 +165,12 @@ public class CalciteMetaImpl extends MetaImpl {
final List<ColumnMetaData> columns = fieldMetaData(clazz).columns;
final CursorFactory cursorFactory = CursorFactory.deduce(columns, clazz);
return createResultSet(Collections.<String, Object>emptyMap(), columns,
- cursorFactory, Collections.emptyList());
+ cursorFactory, Frame.EMPTY);
}
protected MetaResultSet createResultSet(
Map<String, Object> internalParameters, List<ColumnMetaData> columns,
- CursorFactory cursorFactory, final Iterable<Object> iterable) {
+ CursorFactory cursorFactory, final Frame firstFrame) {
try {
final CalciteConnectionImpl connection = getConnection();
final AvaticaStatement statement = connection.createStatement();
@@ -180,10 +180,10 @@ public class CalciteMetaImpl extends MetaImpl {
columns, cursorFactory, -1, null) {
@Override public Enumerable<Object> enumerable(
DataContext dataContext) {
- return Linq4j.asEnumerable(iterable);
+ return Linq4j.asEnumerable(firstFrame.rows);
}
};
- return new MetaResultSet(statement.getId(), true, signature, iterable);
+ return new MetaResultSet(statement.getId(), true, signature, firstFrame);
} catch (SQLException e) {
throw new RuntimeException(e);
}
@@ -441,7 +441,7 @@ public class CalciteMetaImpl extends MetaImpl {
}
@Override public Iterable<Object> createIterable(StatementHandle handle,
- Signature signature, Iterable<Object> iterable) {
+ Signature signature, List<Object> parameterValues, Frame firstFrame) {
try {
//noinspection unchecked
final CalcitePrepare.CalciteSignature<Object> calciteSignature =
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/core/src/main/java/org/apache/calcite/jdbc/CalciteResultSet.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/jdbc/CalciteResultSet.java b/core/src/main/java/org/apache/calcite/jdbc/CalciteResultSet.java
index 72f31ef..777524b 100644
--- a/core/src/main/java/org/apache/calcite/jdbc/CalciteResultSet.java
+++ b/core/src/main/java/org/apache/calcite/jdbc/CalciteResultSet.java
@@ -20,6 +20,7 @@ import org.apache.calcite.avatica.AvaticaResultSet;
import org.apache.calcite.avatica.AvaticaStatement;
import org.apache.calcite.avatica.ColumnMetaData;
import org.apache.calcite.avatica.Handler;
+import org.apache.calcite.avatica.Meta;
import org.apache.calcite.avatica.util.Cursor;
import org.apache.calcite.linq4j.Enumerator;
import org.apache.calcite.linq4j.Linq4j;
@@ -42,8 +43,8 @@ public class CalciteResultSet extends AvaticaResultSet {
CalciteResultSet(AvaticaStatement statement,
CalcitePrepare.CalciteSignature calciteSignature,
ResultSetMetaData resultSetMetaData, TimeZone timeZone,
- Iterable<Object> iterable) {
- super(statement, calciteSignature, resultSetMetaData, timeZone, iterable);
+ Meta.Frame firstFrame) {
+ super(statement, calciteSignature, resultSetMetaData, timeZone, firstFrame);
}
@Override protected CalciteResultSet execute() throws SQLException {
@@ -68,7 +69,7 @@ public class CalciteResultSet extends AvaticaResultSet {
final CalciteResultSet resultSet =
new CalciteResultSet(statement,
(CalcitePrepare.CalciteSignature) signature, resultSetMetaData,
- localCalendar.getTimeZone(), iterable);
+ localCalendar.getTimeZone(), new Meta.Frame(0, true, iterable));
final Cursor cursor = resultSet.createCursor(elementType, iterable);
final List<ColumnMetaData> columnMetaDataList;
if (elementType instanceof ColumnMetaData.StructType) {
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/core/src/main/java/org/apache/calcite/materialize/MaterializationService.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/materialize/MaterializationService.java b/core/src/main/java/org/apache/calcite/materialize/MaterializationService.java
index 0819dcf..2d4c3f2 100644
--- a/core/src/main/java/org/apache/calcite/materialize/MaterializationService.java
+++ b/core/src/main/java/org/apache/calcite/materialize/MaterializationService.java
@@ -126,7 +126,7 @@ public class MaterializationService {
Functions.adapt(calciteSignature.columns,
new Function1<ColumnMetaData, ColumnMetaData.Rep>() {
public ColumnMetaData.Rep apply(ColumnMetaData column) {
- return column.type.representation;
+ return column.type.rep;
}
}),
new AbstractQueryable<Object>() {
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/core/src/test/java/org/apache/calcite/test/CalciteAssert.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/CalciteAssert.java b/core/src/test/java/org/apache/calcite/test/CalciteAssert.java
index 97eb68a..298f8d6 100644
--- a/core/src/test/java/org/apache/calcite/test/CalciteAssert.java
+++ b/core/src/test/java/org/apache/calcite/test/CalciteAssert.java
@@ -50,6 +50,7 @@ import com.google.common.collect.ImmutableMultiset;
import com.google.common.collect.Lists;
import net.hydromatic.foodmart.data.hsqldb.FoodmartHsqldb;
+import net.hydromatic.scott.data.hsqldb.ScottHsqldb;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -100,11 +101,11 @@ public class CalciteAssert {
* MySQL manually with the foodmart data set, otherwise there will be test
* failures. To run against MySQL, specify '-Dcalcite.test.db=mysql' on the
* java command line. */
- public static final ConnectionSpec CONNECTION_SPEC =
+ public static final DatabaseInstance DB =
Util.first(System.getProperty("calcite.test.db"), "hsqldb")
.equals("mysql")
- ? ConnectionSpec.MYSQL
- : ConnectionSpec.HSQLDB;
+ ? DatabaseInstance.MYSQL
+ : DatabaseInstance.HSQLDB;
/** Whether to enable slow tests. Default is false. */
public static final boolean ENABLE_SLOW =
@@ -633,12 +634,9 @@ public class CalciteAssert {
return rootSchema.add("foodmart",
new ReflectiveSchema(new JdbcTest.FoodmartSchema()));
case JDBC_FOODMART:
+ final ConnectionSpec cs = DB.foodmart;
final DataSource dataSource =
- JdbcSchema.dataSource(
- CONNECTION_SPEC.url,
- CONNECTION_SPEC.driver,
- CONNECTION_SPEC.username,
- CONNECTION_SPEC.password);
+ JdbcSchema.dataSource(cs.url, cs.driver, cs.username, cs.password);
return rootSchema.add("foodmart",
JdbcSchema.create(rootSchema, "foodmart", dataSource, null,
"foodmart"));
@@ -1438,23 +1436,22 @@ public class CalciteAssert {
/** Information necessary to create a JDBC connection. Specify one to run
* tests against a different database. (hsqldb is the default.) */
- public enum ConnectionSpec {
- HSQLDB(FoodmartHsqldb.URI, "FOODMART", "FOODMART",
- "org.hsqldb.jdbcDriver"),
- MYSQL("jdbc:mysql://localhost/foodmart", "foodmart", "foodmart",
- "com.mysql.jdbc.Driver");
-
- public final String url;
- public final String username;
- public final String password;
- public final String driver;
-
- ConnectionSpec(String url, String username, String password,
- String driver) {
- this.url = url;
- this.username = username;
- this.password = password;
- this.driver = driver;
+ public enum DatabaseInstance {
+ HSQLDB(
+ new ConnectionSpec(FoodmartHsqldb.URI, "FOODMART", "FOODMART",
+ "org.hsqldb.jdbcDriver"),
+ new ConnectionSpec(ScottHsqldb.URI, ScottHsqldb.USER,
+ ScottHsqldb.PASSWORD, "org.hsqldb.jdbcDriver")),
+ MYSQL(
+ new ConnectionSpec("jdbc:mysql://localhost/foodmart", "foodmart",
+ "foodmart", "com.mysql.jdbc.Driver"), null);
+
+ public final ConnectionSpec foodmart;
+ public final ConnectionSpec scott;
+
+ DatabaseInstance(ConnectionSpec foodmart, ConnectionSpec scott) {
+ this.foodmart = foodmart;
+ this.scott = scott;
}
}
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/core/src/test/java/org/apache/calcite/test/ConnectionSpec.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/ConnectionSpec.java b/core/src/test/java/org/apache/calcite/test/ConnectionSpec.java
new file mode 100644
index 0000000..4142083
--- /dev/null
+++ b/core/src/test/java/org/apache/calcite/test/ConnectionSpec.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.test;
+
+/** Information necessary to create a JDBC connection.
+ *
+ * <p>Specify one to run tests against a different database. */
+public class ConnectionSpec {
+ public final String url;
+ public final String username;
+ public final String password;
+ public final String driver;
+
+ public ConnectionSpec(String url, String username, String password,
+ String driver) {
+ this.url = url;
+ this.username = username;
+ this.password = password;
+ this.driver = driver;
+ }
+}
+
+// End ConnectionSpec.java
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java b/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java
index 08d2903..78c1249 100644
--- a/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java
+++ b/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java
@@ -32,7 +32,7 @@ public class JdbcAdapterTest {
+ " JdbcTableScan(table=[[foodmart, sales_fact_1997]])\n"
+ " JdbcTableScan(table=[[foodmart, sales_fact_1998]])")
.runs()
- .enable(CalciteAssert.CONNECTION_SPEC.url.startsWith("jdbc:hsqldb:"))
+ .enable(CalciteAssert.DB == CalciteAssert.DatabaseInstance.HSQLDB)
.planHasSql("SELECT *\n"
+ "FROM \"foodmart\".\"sales_fact_1997\"\n"
+ "UNION ALL\n"
@@ -48,7 +48,7 @@ public class JdbcAdapterTest {
+ " select * from \"sales_fact_1998\")\n"
+ "where \"product_id\" = 1")
.runs()
- .enable(CalciteAssert.CONNECTION_SPEC.url.startsWith("jdbc:hsqldb:"))
+ .enable(CalciteAssert.DB == CalciteAssert.DatabaseInstance.HSQLDB)
.planHasSql("SELECT *\n"
+ "FROM \"foodmart\".\"sales_fact_1997\"\n"
+ "WHERE \"product_id\" = 1\n"
@@ -63,7 +63,7 @@ public class JdbcAdapterTest {
.query("select \"store_id\", \"store_name\" from \"store\"\n"
+ "where \"store_name\" in ('Store 1', 'Store 10', 'Store 11', 'Store 15', 'Store 16', 'Store 24', 'Store 3', 'Store 7')")
.runs()
- .enable(CalciteAssert.CONNECTION_SPEC.url.startsWith("jdbc:hsqldb:"))
+ .enable(CalciteAssert.DB == CalciteAssert.DatabaseInstance.HSQLDB)
.planHasSql(
"SELECT \"store_id\", \"store_name\"\n"
+ "FROM \"foodmart\".\"store\"\n"
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/core/src/test/java/org/apache/calcite/test/JdbcTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/JdbcTest.java b/core/src/test/java/org/apache/calcite/test/JdbcTest.java
index 0024bf1..989243f 100644
--- a/core/src/test/java/org/apache/calcite/test/JdbcTest.java
+++ b/core/src/test/java/org/apache/calcite/test/JdbcTest.java
@@ -177,10 +177,10 @@ public class JdbcTest {
public static final String FOODMART_SCHEMA = " {\n"
+ " type: 'jdbc',\n"
+ " name: 'foodmart',\n"
- + " jdbcDriver: '" + CalciteAssert.CONNECTION_SPEC.driver + "',\n"
- + " jdbcUser: '" + CalciteAssert.CONNECTION_SPEC.username + "',\n"
- + " jdbcPassword: '" + CalciteAssert.CONNECTION_SPEC.password + "',\n"
- + " jdbcUrl: '" + CalciteAssert.CONNECTION_SPEC.url + "',\n"
+ + " jdbcDriver: '" + CalciteAssert.DB.foodmart.driver + "',\n"
+ + " jdbcUser: '" + CalciteAssert.DB.foodmart.username + "',\n"
+ + " jdbcPassword: '" + CalciteAssert.DB.foodmart.password + "',\n"
+ + " jdbcUrl: '" + CalciteAssert.DB.foodmart.url + "',\n"
+ " jdbcCatalog: null,\n"
+ " jdbcSchema: 'foodmart'\n"
+ " }\n";
@@ -4644,8 +4644,21 @@ public class JdbcTest {
+ "from \"hr\".\"emps\"\n"
+ "where \"deptno\" < ? and \"name\" like ?");
+ // execute with vars unbound - gives error
+ ResultSet resultSet;
+ try {
+ resultSet = preparedStatement.executeQuery();
+ fail("expected error, got " + resultSet);
+ } catch (SQLException e) {
+ assertThat(e.getMessage(),
+ equalTo(
+ "exception while executing query: unbound parameter"));
+ }
+
// execute with both vars null - no results
- ResultSet resultSet = preparedStatement.executeQuery();
+ preparedStatement.setNull(1, java.sql.Types.INTEGER);
+ preparedStatement.setNull(2, java.sql.Types.VARCHAR);
+ resultSet = preparedStatement.executeQuery();
assertFalse(resultSet.next());
// execute with ?0=15, ?1='%' - 3 rows
@@ -5943,7 +5956,7 @@ public class JdbcTest {
}
})
.returns("C=0\n");
- switch (CalciteAssert.CONNECTION_SPEC) {
+ switch (CalciteAssert.DB) {
case HSQLDB:
assertThat(Util.toLinux(sqls[0]),
equalTo("SELECT COUNT(*) AS \"C\"\n"
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/doc/avatica.md
----------------------------------------------------------------------
diff --git a/doc/avatica.md b/doc/avatica.md
new file mode 100644
index 0000000..32cc905
--- /dev/null
+++ b/doc/avatica.md
@@ -0,0 +1,81 @@
+# Avatica
+
+## Introduction
+
+Avatica is a framework for building JDBC and ODBC drivers for databases,
+and an RPC wire protocol.
+
+![Avatica Architecture]
+(https://raw.githubusercontent.com/julianhyde/share/master/slides/avatica-architecture.png)
+
+Avatica's Java binding has very few dependencies.
+Even though it is part of Apache Calcite it does not depend on other parts of
+Calcite. It depends only on JDK 1.7+ and Jackson.
+
+Avatica's wire protocol is JSON over HTTP.
+The Java implementation uses Jackson to convert request/response command
+objects to/from JSON.
+
+Avatica-Server is a Java implementation of Avatica RPC.
+It embeds the Jetty HTTP server.
+
+Core concepts:
+* Meta is a local API sufficient to implement any Avatica provider
+* Factory creates implementations of the JDBC classes (Driver, Connection,
+ Statement, ResultSet) on top of a Meta
+* Service is an interface that implements the functions of Meta in terms
+ of request and response command objects
+
+## JDBC
+
+Avatica implements JDBC by means of Factory.
+Factory creates implementations of the JDBC classes (Driver, Connection,
+Statement, PreparedStatement, ResultSet) on top of a Meta.
+
+## ODBC
+
+Work has not started on Avatica ODBC.
+
+Avatica ODBC would use the same wire protocol and could use the same server
+implementation in Java. The ODBC client would be written in C or C++.
+
+Since the Avatica protocol abstracts many of the differences between providers,
+the same ODBC client could be used for different databases.
+
+## Project structure
+
+We know that it is important that client libraries have minimal dependencies.
+
+Avatica is currently part of Apache Calcite.
+It does not depend upon any other part of Calcite.
+At some point Avatica could become a separate project.
+
+Packages:
+* [org.apache.calcite.avatica](http://www.hydromatic.net/calcite/apidocs/org/apache/calcite/avatica/package-summary.html) Core framework
+* [org.apache.calcite.avatica.remote](http://www.hydromatic.net/calcite/apidocs/org/apache/calcite/avatica/remote/package-summary.html) JDBC driver that uses remote procedure calls
+* [org.apache.calcite.avatica.server](http://www.hydromatic.net/calcite/apidocs/org/apache/calcite/avatica/server/package-summary.html) HTTP server
+* [org.apache.calcite.avatica.util](http://www.hydromatic.net/calcite/apidocs/org/apache/calcite/avatica/util/package-summary.html) Utilities
+
+## Status
+
+### Implemented
+* Create connection, create statement, metadata, prepare, bind, execute, fetch
+* RPC using JSON over HTTP
+* Local implementation
+* Implementation over an existing JDBC driver
+* Composite RPCs (combining several requests into one round trip)
+ * Execute-Fetch
+ * Metadata-Fetch (metadata calls such as getTables return all rows)
+
+### Not implemented
+* ODBC
+* RPCs
+ * CloseStatement
+ * CloseConnection
+* Composite RPCs
+ * CreateStatement-Prepare
+ * CloseStatement-CloseConnection
+ * Prepare-Execute-Fetch (Statement.executeQuery should fetch first N rows)
+* Remove statements from statement table
+* DML (INSERT, UPDATE, DELETE)
+* Statement.execute applied to SELECT statement
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 54fd593..683f173 100644
--- a/pom.xml
+++ b/pom.xml
@@ -131,6 +131,11 @@ limitations under the License.
<version>11.0.2</version>
</dependency>
<dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.11</version>
+ </dependency>
+ <dependency>
<groupId>io.airlift.tpch</groupId>
<artifactId>tpch</artifactId>
<version>0.1</version>
@@ -159,7 +164,21 @@ limitations under the License.
<groupId>net.hydromatic</groupId>
<artifactId>quidem</artifactId>
<version>0.3</version>
- <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>net.hydromatic</groupId>
+ <artifactId>scott-data-hsqldb</artifactId>
+ <version>0.1</version>
+ </dependency>
+ <dependency>
+ <groupId>net.hydromatic</groupId>
+ <artifactId>tpcds</artifactId>
+ <version>0.3</version>
+ </dependency>
+ <dependency>
+ <groupId>net.sf.opencsv</groupId>
+ <artifactId>opencsv</artifactId>
+ <version>2.3</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
@@ -192,17 +211,6 @@ limitations under the License.
<version>5.1.5-jhyde</version>
</dependency>
<dependency>
- <groupId>net.hydromatic</groupId>
- <artifactId>tpcds</artifactId>
- <version>0.3</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>net.sf.opencsv</groupId>
- <artifactId>opencsv</artifactId>
- <version>2.3</version>
- </dependency>
- <dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.10</artifactId>
<version>0.9.0-incubating</version>
@@ -228,11 +236,6 @@ limitations under the License.
<version>0.7.1</version>
</dependency>
<dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>4.11</version>
- </dependency>
- <dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.9.1</version>
[2/9] incubator-calcite git commit: [CALCITE-596] JDBC adapter
incorrectly reads null values as 0 (Ng Jiunn Jye)
Posted by jh...@apache.org.
[CALCITE-596] JDBC adapter incorrectly reads null values as 0 (Ng Jiunn Jye)
Project: http://git-wip-us.apache.org/repos/asf/incubator-calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-calcite/commit/2b07a9e9
Tree: http://git-wip-us.apache.org/repos/asf/incubator-calcite/tree/2b07a9e9
Diff: http://git-wip-us.apache.org/repos/asf/incubator-calcite/diff/2b07a9e9
Branch: refs/heads/master
Commit: 2b07a9e9680e662a6d9785deb2a4ed140026e95f
Parents: 3b10a6a
Author: Julian Hyde <jh...@apache.org>
Authored: Mon Mar 23 01:39:12 2015 -0700
Committer: Julian Hyde <jh...@apache.org>
Committed: Mon Mar 23 01:39:12 2015 -0700
----------------------------------------------------------------------
.../adapter/jdbc/JdbcToEnumerableConverter.java | 11 ++++
.../java/org/apache/calcite/test/JdbcTest.java | 60 ++++++++++++++++++++
2 files changed, 71 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/2b07a9e9/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcToEnumerableConverter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcToEnumerableConverter.java b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcToEnumerableConverter.java
index 3fbf778..125d61b 100644
--- a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcToEnumerableConverter.java
+++ b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcToEnumerableConverter.java
@@ -232,6 +232,17 @@ public class JdbcToEnumerableConverter
Expressions.statement(
Expressions.assign(
target, source)));
+
+ // [CALCITE-596] If primitive type columns contain null value, returns null
+ // object
+ if (primitive != null) {
+ builder.add(
+ Expressions.ifThen(
+ Expressions.call(resultSet_, "wasNull"),
+ Expressions.statement(
+ Expressions.assign(target,
+ Expressions.constant(null)))));
+ }
}
private Method getMethod(SqlTypeName sqlTypeName, boolean nullable,
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/2b07a9e9/core/src/test/java/org/apache/calcite/test/JdbcTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/JdbcTest.java b/core/src/test/java/org/apache/calcite/test/JdbcTest.java
index 0942334..0024bf1 100644
--- a/core/src/test/java/org/apache/calcite/test/JdbcTest.java
+++ b/core/src/test/java/org/apache/calcite/test/JdbcTest.java
@@ -6137,6 +6137,66 @@ public class JdbcTest {
.returnsUnordered("DID=1", "DID=2");
}
+ /**
+ * Test case for
+ * <a href="https://issues.apache.org/jira/browse/CALCITE-596">[CALCITE-596]
+ * JDBC adapter incorrectly reads null values as 0</a>.
+ */
+ @Test public void testPrimitiveColumnsWithNullValues() throws Exception {
+ String hsqldbMemUrl = "jdbc:hsqldb:mem:.";
+ Connection baseConnection = DriverManager.getConnection(hsqldbMemUrl);
+ Statement baseStmt = baseConnection.createStatement();
+ baseStmt.execute("CREATE TABLE T1 (\n"
+ + "ID INTEGER,\n"
+ + "VALS DOUBLE)");
+ baseStmt.execute("INSERT INTO T1 VALUES (1, 1.0)");
+ baseStmt.execute("INSERT INTO T1 VALUES (2, null)");
+ baseStmt.execute("INSERT INTO T1 VALUES (null, 2.0)");
+
+ baseStmt.close();
+ baseConnection.commit();
+
+ Properties info = new Properties();
+ info.put("model",
+ "inline:"
+ + "{\n"
+ + " version: '1.0',\n"
+ + " defaultSchema: 'BASEJDBC',\n"
+ + " schemas: [\n"
+ + " {\n"
+ + " type: 'jdbc',\n"
+ + " name: 'BASEJDBC',\n"
+ + " jdbcDriver: '" + jdbcDriver.class.getName() + "',\n"
+ + " jdbcUrl: '" + hsqldbMemUrl + "',\n"
+ + " jdbcCatalog: null,\n"
+ + " jdbcSchema: null\n"
+ + " }\n"
+ + " ]\n"
+ + "}");
+
+ Connection calciteConnection = DriverManager.getConnection(
+ "jdbc:calcite:", info);
+
+ ResultSet rs = calciteConnection.prepareStatement("select * from t1")
+ .executeQuery();
+
+ assertThat(rs.next(), is(true));
+ assertThat((Integer) rs.getObject("ID"), equalTo(1));
+ assertThat((Double) rs.getObject("VALS"), equalTo(1.0));
+
+ assertThat(rs.next(), is(true));
+ assertThat((Integer) rs.getObject("ID"), equalTo(2));
+ assertThat((Double) rs.getObject("VALS"), nullValue());
+
+ assertThat(rs.next(), is(true));
+ assertThat(rs.getObject("ID"), nullValue());
+ assertThat((Double) rs.getObject("VALS"), equalTo(2.0));
+
+ rs.close();
+ calciteConnection.close();
+
+ }
+
// Disable checkstyle, so it doesn't complain about fields like "customer_id".
//CHECKSTYLE: OFF
[4/9] incubator-calcite git commit: [CALCITE-618] Add Avatica support
for getTables (Julian Hyde and Nick Dimiduk)
Posted by jh...@apache.org.
[CALCITE-618] Add Avatica support for getTables (Julian Hyde and Nick Dimiduk)
Also add getSchemas.
Remove dependencies on Guava. (Avatica depends only on JDK and Jackson.)
Add JdbcMeta; implement remote execute query
Rename some fields of AvaticaType to prevent clash between JSON "type" and type field.
Add FetchRequest; if FetchRequest has parameters, executes first.
Document Avatica
Move class ConnectionSpec to top-level
Use scott-data-hsqldb rather than foodmart-data-hsqldb for testing Avatica; it is smaller and therefore loads faster
Work around JSON's mangling of small longs into ints
Project: http://git-wip-us.apache.org/repos/asf/incubator-calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-calcite/commit/4d2f647a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-calcite/tree/4d2f647a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-calcite/diff/4d2f647a
Branch: refs/heads/master
Commit: 4d2f647a6d397a4a7c99fcc2d3d6359baf937943
Parents: 2b07a9e
Author: Julian Hyde <jh...@apache.org>
Authored: Thu Mar 12 14:51:14 2015 -0700
Committer: Julian Hyde <jh...@apache.org>
Committed: Mon Mar 23 01:44:36 2015 -0700
----------------------------------------------------------------------
avatica/pom.xml | 11 +
.../calcite/avatica/AvaticaConnection.java | 30 +-
.../apache/calcite/avatica/AvaticaFactory.java | 11 +-
.../calcite/avatica/AvaticaJdbc41Factory.java | 4 +-
.../avatica/AvaticaPreparedStatement.java | 12 +-
.../calcite/avatica/AvaticaResultSet.java | 12 +-
.../avatica/AvaticaResultSetMetaData.java | 4 +-
.../calcite/avatica/AvaticaStatement.java | 33 +-
.../apache/calcite/avatica/ColumnMetaData.java | 46 +-
.../java/org/apache/calcite/avatica/Meta.java | 90 +++-
.../org/apache/calcite/avatica/MetaImpl.java | 131 ++++--
.../calcite/avatica/UnregisteredDriver.java | 2 +-
.../apache/calcite/avatica/jdbc/JdbcMeta.java | 442 +++++++++++++++++++
.../calcite/avatica/jdbc/JdbcResultSet.java | 105 +++++
.../calcite/avatica/jdbc/package-info.java | 22 +
.../calcite/avatica/remote/JsonService.java | 23 +-
.../calcite/avatica/remote/LocalService.java | 78 +++-
.../calcite/avatica/remote/MockJsonService.java | 44 +-
.../calcite/avatica/remote/RemoteMeta.java | 45 +-
.../apache/calcite/avatica/remote/Service.java | 75 +++-
.../calcite/avatica/util/AbstractCursor.java | 75 +++-
.../apache/calcite/avatica/util/ArrayImpl.java | 8 +-
.../calcite/avatica/test/RemoteDriverTest.java | 216 ++++++++-
core/pom.xml | 5 +
.../calcite/jdbc/CalciteJdbc41Factory.java | 4 +-
.../apache/calcite/jdbc/CalciteMetaImpl.java | 12 +-
.../apache/calcite/jdbc/CalciteResultSet.java | 7 +-
.../materialize/MaterializationService.java | 2 +-
.../org/apache/calcite/test/CalciteAssert.java | 47 +-
.../org/apache/calcite/test/ConnectionSpec.java | 37 ++
.../apache/calcite/test/JdbcAdapterTest.java | 6 +-
.../java/org/apache/calcite/test/JdbcTest.java | 25 +-
doc/avatica.md | 81 ++++
pom.xml | 37 +-
34 files changed, 1566 insertions(+), 216 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/avatica/pom.xml
----------------------------------------------------------------------
diff --git a/avatica/pom.xml b/avatica/pom.xml
index 58aec3c..3e6040c 100644
--- a/avatica/pom.xml
+++ b/avatica/pom.xml
@@ -45,6 +45,17 @@ limitations under the License.
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>net.hydromatic</groupId>
+ <artifactId>scott-data-hsqldb</artifactId>
+ <version>0.1</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hsqldb</groupId>
+ <artifactId>hsqldb</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/avatica/src/main/java/org/apache/calcite/avatica/AvaticaConnection.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/org/apache/calcite/avatica/AvaticaConnection.java b/avatica/src/main/java/org/apache/calcite/avatica/AvaticaConnection.java
index 492ec5f..bc8c3eb 100644
--- a/avatica/src/main/java/org/apache/calcite/avatica/AvaticaConnection.java
+++ b/avatica/src/main/java/org/apache/calcite/avatica/AvaticaConnection.java
@@ -269,7 +269,17 @@ public abstract class AvaticaConnection implements Connection {
int resultSetType,
int resultSetConcurrency,
int resultSetHoldability) throws SQLException {
- throw new UnsupportedOperationException(); // TODO:
+ try {
+ // TODO: cut out round-trip to create a statement handle
+ final Meta.ConnectionHandle ch = new Meta.ConnectionHandle(id);
+ final Meta.StatementHandle h = meta.createStatement(ch);
+
+ final Meta.Signature x = meta.prepare(h, sql, -1);
+ return factory.newPreparedStatement(this, h, x, resultSetType,
+ resultSetConcurrency, resultSetHoldability);
+ } catch (RuntimeException e) {
+ throw helper.createException("while preparing SQL: " + sql, e);
+ }
}
public CallableStatement prepareCall(
@@ -391,12 +401,12 @@ public abstract class AvaticaConnection implements Connection {
*
* @param statement Statement
* @param signature Prepared query
- * @param iterable List of rows, or null if we need to execute
+ * @param firstFrame First frame of rows, or null if we need to execute
* @return Result set
* @throws java.sql.SQLException if a database error occurs
*/
protected ResultSet executeQueryInternal(AvaticaStatement statement,
- Meta.Signature signature, Iterable<Object> iterable) throws SQLException {
+ Meta.Signature signature, Meta.Frame firstFrame) throws SQLException {
// Close the previous open result set, if there is one.
synchronized (statement) {
if (statement.openResultSet != null) {
@@ -412,7 +422,7 @@ public abstract class AvaticaConnection implements Connection {
final TimeZone timeZone = getTimeZone();
statement.openResultSet =
- factory.newResultSet(statement, signature, timeZone, iterable);
+ factory.newResultSet(statement, signature, timeZone, firstFrame);
}
// Release the monitor before executing, to give another thread the
// opportunity to call cancel.
@@ -447,11 +457,12 @@ public abstract class AvaticaConnection implements Connection {
}
}
- public void assign(Meta.Signature signature,
- Iterable<Object> iterable) throws SQLException {
+ public void assign(Meta.Signature signature, Meta.Frame firstFrame)
+ throws SQLException {
final TimeZone timeZone = getTimeZone();
statement.openResultSet =
- factory.newResultSet(statement, signature, timeZone, iterable);
+ factory.newResultSet(statement, signature, timeZone,
+ firstFrame);
}
public void execute() throws SQLException {
@@ -467,9 +478,8 @@ public abstract class AvaticaConnection implements Connection {
final Meta.StatementHandle h =
new Meta.StatementHandle(metaResultSet.statementId);
final AvaticaStatement statement = lookupStatement(h);
- return executeQueryInternal(statement,
- metaResultSet.signature,
- metaResultSet.iterable);
+ return executeQueryInternal(statement, metaResultSet.signature.sanitize(),
+ metaResultSet.firstFrame);
}
/** Creates a statement wrapper around an existing handle. */
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/avatica/src/main/java/org/apache/calcite/avatica/AvaticaFactory.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/org/apache/calcite/avatica/AvaticaFactory.java b/avatica/src/main/java/org/apache/calcite/avatica/AvaticaFactory.java
index 0139ef3..c6d2ede 100644
--- a/avatica/src/main/java/org/apache/calcite/avatica/AvaticaFactory.java
+++ b/avatica/src/main/java/org/apache/calcite/avatica/AvaticaFactory.java
@@ -50,20 +50,15 @@ public interface AvaticaFactory {
* Creates a result set. You will then need to call
* {@link AvaticaResultSet#execute()} on it.
*
- * <p>If {@code signature} implements
- * {@link org.apache.calcite.avatica.MetaImpl.WithIterable} we do not need
- * to execute; we can use pre-canned data. This mechanism is used for
- * metadata requests such as {@code getTables}.
- *
* @param statement Statement
* @param signature Prepared statement
* @param timeZone Time zone
- * @param iterable Iterable over rows in result, or null if an execute/fetch
- * is required
+ * @param firstFrame Frame containing the first (or perhaps only) rows in the
+ * result, or null if an execute/fetch is required
* @return Result set
*/
AvaticaResultSet newResultSet(AvaticaStatement statement,
- Meta.Signature signature, TimeZone timeZone, Iterable<Object> iterable)
+ Meta.Signature signature, TimeZone timeZone, Meta.Frame firstFrame)
throws SQLException;
/**
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/avatica/src/main/java/org/apache/calcite/avatica/AvaticaJdbc41Factory.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/org/apache/calcite/avatica/AvaticaJdbc41Factory.java b/avatica/src/main/java/org/apache/calcite/avatica/AvaticaJdbc41Factory.java
index 4b2f721..6a70a26 100644
--- a/avatica/src/main/java/org/apache/calcite/avatica/AvaticaJdbc41Factory.java
+++ b/avatica/src/main/java/org/apache/calcite/avatica/AvaticaJdbc41Factory.java
@@ -84,11 +84,11 @@ class AvaticaJdbc41Factory implements AvaticaFactory {
}
public AvaticaResultSet newResultSet(AvaticaStatement statement,
- Meta.Signature signature, TimeZone timeZone, Iterable<Object> iterable) {
+ Meta.Signature signature, TimeZone timeZone, Meta.Frame firstFrame) {
final ResultSetMetaData metaData =
newResultSetMetaData(statement, signature);
return new AvaticaResultSet(statement, signature, metaData, timeZone,
- iterable);
+ firstFrame);
}
public AvaticaResultSetMetaData newResultSetMetaData(
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/avatica/src/main/java/org/apache/calcite/avatica/AvaticaPreparedStatement.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/org/apache/calcite/avatica/AvaticaPreparedStatement.java b/avatica/src/main/java/org/apache/calcite/avatica/AvaticaPreparedStatement.java
index a40e8d1..9324db7 100644
--- a/avatica/src/main/java/org/apache/calcite/avatica/AvaticaPreparedStatement.java
+++ b/avatica/src/main/java/org/apache/calcite/avatica/AvaticaPreparedStatement.java
@@ -32,7 +32,7 @@ import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
-import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
@@ -76,11 +76,7 @@ public abstract class AvaticaPreparedStatement
}
@Override protected List<Object> getParameterValues() {
- final List<Object> list = new ArrayList<Object>();
- for (Object o : slots) {
- list.add(o == AvaticaParameter.DUMMY_VALUE ? null : o);
- }
- return list;
+ return Arrays.asList(slots);
}
// implement PreparedStatement
@@ -174,7 +170,9 @@ public abstract class AvaticaPreparedStatement
}
public void clearParameters() throws SQLException {
- throw new UnsupportedOperationException();
+ for (int i = 0; i < slots.length; i++) {
+ slots[i] = null;
+ }
}
public void setObject(int parameterIndex, Object x, int targetSqlType)
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/avatica/src/main/java/org/apache/calcite/avatica/AvaticaResultSet.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/org/apache/calcite/avatica/AvaticaResultSet.java b/avatica/src/main/java/org/apache/calcite/avatica/AvaticaResultSet.java
index 8d2fbee..fca227f 100644
--- a/avatica/src/main/java/org/apache/calcite/avatica/AvaticaResultSet.java
+++ b/avatica/src/main/java/org/apache/calcite/avatica/AvaticaResultSet.java
@@ -49,7 +49,7 @@ import java.util.TimeZone;
public class AvaticaResultSet implements ResultSet, ArrayImpl.Factory {
protected final AvaticaStatement statement;
protected final Meta.Signature signature;
- protected final Iterable<Object> iterable;
+ protected final Meta.Frame firstFrame;
protected final List<ColumnMetaData> columnMetaDataList;
protected final ResultSetMetaData resultSetMetaData;
protected final Calendar localCalendar;
@@ -71,10 +71,10 @@ public class AvaticaResultSet implements ResultSet, ArrayImpl.Factory {
Meta.Signature signature,
ResultSetMetaData resultSetMetaData,
TimeZone timeZone,
- Iterable<Object> iterable) {
+ Meta.Frame firstFrame) {
this.statement = statement;
this.signature = signature;
- this.iterable = iterable;
+ this.firstFrame = firstFrame;
this.columnMetaDataList = signature.columns;
this.type = statement.resultSetType;
this.concurrency = statement.resultSetConcurrency;
@@ -179,9 +179,11 @@ public class AvaticaResultSet implements ResultSet, ArrayImpl.Factory {
* @throws SQLException if execute fails for some reason.
*/
protected AvaticaResultSet execute() throws SQLException {
- this.cursor = MetaImpl.createCursor(signature.cursorFactory,
+ final List<Object> parameterValues = statement.getBoundParameterValues();
+ final Iterable<Object> iterable1 =
statement.connection.meta.createIterable(statement.handle, signature,
- iterable));
+ parameterValues, firstFrame);
+ this.cursor = MetaImpl.createCursor(signature.cursorFactory, iterable1);
this.accessorList =
cursor.createAccessors(columnMetaDataList, localCalendar, this);
this.row = -1;
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/avatica/src/main/java/org/apache/calcite/avatica/AvaticaResultSetMetaData.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/org/apache/calcite/avatica/AvaticaResultSetMetaData.java b/avatica/src/main/java/org/apache/calcite/avatica/AvaticaResultSetMetaData.java
index cb67a89..b4e8892 100644
--- a/avatica/src/main/java/org/apache/calcite/avatica/AvaticaResultSetMetaData.java
+++ b/avatica/src/main/java/org/apache/calcite/avatica/AvaticaResultSetMetaData.java
@@ -104,11 +104,11 @@ public class AvaticaResultSetMetaData implements ResultSetMetaData {
}
public int getColumnType(int column) throws SQLException {
- return getColumnMetaData(column).type.type;
+ return getColumnMetaData(column).type.id;
}
public String getColumnTypeName(int column) throws SQLException {
- return getColumnMetaData(column).type.typeName;
+ return getColumnMetaData(column).type.name;
}
public boolean isReadOnly(int column) throws SQLException {
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/avatica/src/main/java/org/apache/calcite/avatica/AvaticaStatement.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/org/apache/calcite/avatica/AvaticaStatement.java b/avatica/src/main/java/org/apache/calcite/avatica/AvaticaStatement.java
index fb0a6f5..6df3528 100644
--- a/avatica/src/main/java/org/apache/calcite/avatica/AvaticaStatement.java
+++ b/avatica/src/main/java/org/apache/calcite/avatica/AvaticaStatement.java
@@ -20,6 +20,7 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Statement;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
@@ -53,7 +54,7 @@ public abstract class AvaticaStatement
final int resultSetHoldability;
private int fetchSize;
private int fetchDirection;
- protected int maxRowCount;
+ protected int maxRowCount = 0;
/**
* Creates an AvaticaStatement.
@@ -98,17 +99,6 @@ public abstract class AvaticaStatement
}
}
- public ResultSet executeQueryOld(String sql) throws SQLException {
- try {
- final int maxRowCount1 = maxRowCount <= 0 ? -1 : maxRowCount;
- Meta.Signature x = connection.meta.prepare(handle, sql, maxRowCount1);
- return executeQueryInternal(x);
- } catch (RuntimeException e) {
- throw connection.helper.createException(
- "error while executing SQL \"" + sql + "\": " + e.getMessage(), e);
- }
- }
-
public ResultSet executeQuery(String sql) throws SQLException {
try {
// In JDBC, maxRowCount = 0 means no limit; in prepare it means LIMIT 0
@@ -417,6 +407,25 @@ public abstract class AvaticaStatement
protected List<Object> getParameterValues() {
return Collections.emptyList();
}
+
+ /** Returns a list of bound parameter values.
+ *
+ * <p>If any of the parameters have not been bound, throws.
+ * If parameters have been bound to null, the value in the list is null.
+ */
+ protected List<Object> getBoundParameterValues() throws SQLException {
+ final List<Object> list = new ArrayList<>();
+ for (Object parameterValue : getParameterValues()) {
+ if (parameterValue == null) {
+ throw new SQLException("unbound parameter");
+ }
+ if (parameterValue == AvaticaParameter.DUMMY_VALUE) {
+ parameterValue = null;
+ }
+ list.add(parameterValue);
+ }
+ return list;
+ }
}
// End AvaticaStatement.java
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/avatica/src/main/java/org/apache/calcite/avatica/ColumnMetaData.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/org/apache/calcite/avatica/ColumnMetaData.java b/avatica/src/main/java/org/apache/calcite/avatica/ColumnMetaData.java
index 0b6856d..8e9930f 100644
--- a/avatica/src/main/java/org/apache/calcite/avatica/ColumnMetaData.java
+++ b/avatica/src/main/java/org/apache/calcite/avatica/ColumnMetaData.java
@@ -160,6 +160,13 @@ public class ColumnMetaData {
type.columnClassName());
}
+ public ColumnMetaData setTypeId(int typeId) {
+ return new ColumnMetaData(ordinal, autoIncrement, caseSensitive, searchable,
+ currency, nullable, signed, displaySize, label, columnName, schemaName,
+ precision, scale, tableName, catalogName, type.setId(typeId), readOnly,
+ writable, definitelyWritable, columnClassName);
+ }
+
/** Description of the type used to internally represent a value. For example,
* a {@link java.sql.Date} might be represented as a {@link #PRIMITIVE_INT}
* if not nullable, or a {@link #JAVA_SQL_DATE}. */
@@ -192,7 +199,7 @@ public class ColumnMetaData {
public static final Map<Class, Rep> VALUE_MAP;
static {
- Map<Class, Rep> builder = new HashMap<Class, Rep>();
+ Map<Class, Rep> builder = new HashMap<>();
for (Rep rep : values()) {
builder.put(rep.clazz, rep);
}
@@ -220,31 +227,39 @@ public class ColumnMetaData {
@JsonSubTypes.Type(value = StructType.class, name = "struct"),
@JsonSubTypes.Type(value = ArrayType.class, name = "array") })
public static class AvaticaType {
- public final int type;
- public final String typeName;
+ public final int id;
+ public final String name;
/** The type of the field that holds the value. Not a JDBC property. */
- public final Rep representation;
+ public final Rep rep;
- protected AvaticaType(int type, String typeName, Rep representation) {
- this.type = type;
- this.typeName = typeName;
- this.representation = representation;
- assert representation != null;
+ protected AvaticaType(int id, String name, Rep rep) {
+ this.id = id;
+ this.name = name;
+ this.rep = rep;
+ assert rep != null;
}
public String columnClassName() {
- return SqlType.valueOf(type).clazz.getName();
+ return SqlType.valueOf(id).clazz.getName();
+ }
+
+ public AvaticaType setId(int rep) {
+ throw new UnsupportedOperationException();
}
}
/** Scalar type. */
public static class ScalarType extends AvaticaType {
@JsonCreator
- public ScalarType(@JsonProperty("type") int type,
- @JsonProperty("typeName") String typeName,
- @JsonProperty("representation") Rep representation) {
- super(type, typeName, representation);
+ public ScalarType(@JsonProperty("id") int id,
+ @JsonProperty("name") String name,
+ @JsonProperty("rep") Rep rep) {
+ super(id, name, rep);
+ }
+
+ @Override public AvaticaType setId(int id) {
+ return new ScalarType(id, name, rep);
}
}
@@ -306,8 +321,7 @@ public class ColumnMetaData {
private final int type;
private final Class clazz;
- private static final Map<Integer, SqlType> BY_ID =
- new HashMap<Integer, SqlType>();
+ private static final Map<Integer, SqlType> BY_ID = new HashMap<>();
static {
for (SqlType sqlType : values()) {
BY_ID.put(sqlType.type, sqlType);
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/avatica/src/main/java/org/apache/calcite/avatica/Meta.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/org/apache/calcite/avatica/Meta.java b/avatica/src/main/java/org/apache/calcite/avatica/Meta.java
index 107c4c9..f7f3b80 100644
--- a/avatica/src/main/java/org/apache/calcite/avatica/Meta.java
+++ b/avatica/src/main/java/org/apache/calcite/avatica/Meta.java
@@ -26,6 +26,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
/**
* Command handler for getting various metadata. Should be implemented by each
@@ -148,7 +149,7 @@ public interface Meta {
* requires to be not null; derived classes may instead choose to execute the
* relational expression in {@code signature}. */
Iterable<Object> createIterable(StatementHandle handle, Signature signature,
- Iterable<Object> iterable);
+ List<Object> parameterValues, Frame firstFrame);
/** Prepares a statement.
*
@@ -170,6 +171,25 @@ public interface Meta {
MetaResultSet prepareAndExecute(StatementHandle h, String sql,
int maxRowCount, PrepareCallback callback);
+ /** Returns a frame of rows.
+ *
+ * <p>The frame describes whether there may be another frame. If there is not
+ * another frame, the current iteration is done when we have finished the
+ * rows in the this frame.
+ *
+ * <p>The default implementation always returns null.
+ *
+ * @param h Statement handle
+ * @param parameterValues A list of parameter values, if statement is to be
+ * executed; otherwise null
+ * @param offset Zero-based offset of first row in the requested frame
+ * @param fetchMaxRowCount Maximum number of rows to return; negative means
+ * no limit
+ * @return Frame, or null if there are no more
+ */
+ Frame fetch(StatementHandle h, List<Object> parameterValues, int offset,
+ int fetchMaxRowCount);
+
/** Called during the creation of a statement to allocate a new handle.
*
* @param ch Connection handle
@@ -201,15 +221,15 @@ public interface Meta {
class MetaResultSet {
public final int statementId;
public final boolean ownStatement;
- public final Iterable<Object> iterable;
+ public final Frame firstFrame;
public final Signature signature;
public MetaResultSet(int statementId, boolean ownStatement,
- Signature signature, Iterable<Object> iterable) {
- this.signature = signature;
+ Signature signature, Frame firstFrame) {
+ this.signature = Objects.requireNonNull(signature);
this.statementId = statementId;
this.ownStatement = ownStatement;
- this.iterable = iterable;
+ this.firstFrame = firstFrame; // may be null
}
}
@@ -227,7 +247,7 @@ public interface Meta {
assert (fieldNames != null)
== (style == Style.RECORD_PROJECTION || style == Style.MAP);
assert (fields != null) == (style == Style.RECORD_PROJECTION);
- this.style = style;
+ this.style = Objects.requireNonNull(style);
this.clazz = clazz;
this.fields = fields;
this.fieldNames = fieldNames;
@@ -271,7 +291,7 @@ public interface Meta {
public static CursorFactory record(Class resultClass, List<Field> fields,
List<String> fieldNames) {
if (fields == null) {
- fields = new ArrayList<Field>();
+ fields = new ArrayList<>();
for (String fieldName : fieldNames) {
try {
fields.add(resultClass.getField(fieldName));
@@ -348,6 +368,60 @@ public interface Meta {
return new Signature(columns, sql, parameters, internalParameters,
cursorFactory);
}
+
+ /** Creates a copy of this Signature with null lists and maps converted to
+ * empty. */
+ public Signature sanitize() {
+ if (columns == null || parameters == null || internalParameters == null) {
+ return new Signature(sanitize(columns), sql, sanitize(parameters),
+ sanitize(internalParameters), cursorFactory);
+ }
+ return this;
+ }
+
+ private <E> List<E> sanitize(List<E> list) {
+ return list == null ? Collections.<E>emptyList() : list;
+ }
+
+ private <K, V> Map<K, V> sanitize(Map<K, V> map) {
+ return map == null ? Collections.<K, V>emptyMap() : map;
+ }
+ }
+
+ /** A collection of rows. */
+ class Frame {
+ /** Frame that has zero rows and is the last frame. */
+ public static final Frame EMPTY =
+ new Frame(0, true, Collections.emptyList());
+
+ /** Frame that has zero rows but may have another frame. */
+ public static final Frame MORE =
+ new Frame(0, false, Collections.emptyList());
+
+ /** Zero-based offset of first row. */
+ public final int offset;
+ /** Whether this is definitely the last frame of rows.
+ * If true, there are no more rows.
+ * If false, there may or may not be more rows. */
+ public final boolean done;
+ /** The rows. */
+ public final Iterable<Object> rows;
+
+ public Frame(int offset, boolean done, Iterable<Object> rows) {
+ this.offset = offset;
+ this.done = done;
+ this.rows = rows;
+ }
+
+ @JsonCreator
+ public static Frame create(@JsonProperty("offset") int offset,
+ @JsonProperty("done") boolean done,
+ @JsonProperty("rows") List<Object> rows) {
+ if (offset == 0 && done && rows.isEmpty()) {
+ return EMPTY;
+ }
+ return new Frame(offset, done, rows);
+ }
}
/** Connection handle. */
@@ -383,7 +457,7 @@ public interface Meta {
interface PrepareCallback {
Object getMonitor();
void clear() throws SQLException;
- void assign(Signature signature, Iterable<Object> iterable)
+ void assign(Signature signature, Frame firstFrame)
throws SQLException;
void execute() throws SQLException;
}
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/avatica/src/main/java/org/apache/calcite/avatica/MetaImpl.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/org/apache/calcite/avatica/MetaImpl.java b/avatica/src/main/java/org/apache/calcite/avatica/MetaImpl.java
index 9b2be07..a6c5f3c 100644
--- a/avatica/src/main/java/org/apache/calcite/avatica/MetaImpl.java
+++ b/avatica/src/main/java/org/apache/calcite/avatica/MetaImpl.java
@@ -36,8 +36,10 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.NoSuchElementException;
/**
* Basic implementation of {@link Meta}.
@@ -171,7 +173,7 @@ public abstract class MetaImpl implements Meta {
return createResultSet(Collections.<String, Object>emptyMap(),
fieldMetaData(clazz).columns,
CursorFactory.deduce(fieldMetaData(clazz).columns, null),
- Collections.emptyList());
+ Frame.EMPTY);
}
protected static ColumnMetaData columnMetaData(String name, int index,
@@ -207,14 +209,13 @@ public abstract class MetaImpl implements Meta {
protected MetaResultSet createResultSet(
Map<String, Object> internalParameters, List<ColumnMetaData> columns,
- CursorFactory cursorFactory, Iterable<Object> iterable) {
+ CursorFactory cursorFactory, Frame firstFrame) {
try {
final AvaticaStatement statement = connection.createStatement();
- final SignatureWithIterable signature =
- new SignatureWithIterable(internalParameters, columns, "",
- Collections.<AvaticaParameter>emptyList(), cursorFactory,
- iterable);
- return new MetaResultSet(statement.getId(), true, signature, iterable);
+ final Signature signature =
+ new Signature(columns, "", Collections.<AvaticaParameter>emptyList(),
+ internalParameters, cursorFactory);
+ return new MetaResultSet(statement.getId(), true, signature, firstFrame);
} catch (SQLException e) {
throw new RuntimeException(e);
}
@@ -646,8 +647,16 @@ public abstract class MetaImpl implements Meta {
}
public Iterable<Object> createIterable(StatementHandle handle,
- Signature signature, Iterable<Object> iterable) {
- return iterable;
+ Signature signature, List<Object> parameterValues, Frame firstFrame) {
+ if (firstFrame != null && firstFrame.done) {
+ return firstFrame.rows;
+ }
+ return new FetchIterable(handle, firstFrame, parameterValues);
+ }
+
+ public Frame fetch(StatementHandle h, List<Object> parameterValues,
+ int offset, int fetchMaxRowCount) {
+ return null;
}
/** Information about a type. */
@@ -691,27 +700,99 @@ public abstract class MetaImpl implements Meta {
}
}
- /** Prepare result with a iterable. Use this for simple statements
- * that have a canned response and don't need to be executed. */
- protected interface WithIterable {
- Iterable getIterable();
+ /** Iterator that never returns any elements. */
+ private static class EmptyIterator implements Iterator<Object> {
+ public static final Iterator<Object> INSTANCE = new EmptyIterator();
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean hasNext() {
+ return false;
+ }
+
+ public Object next() {
+ throw new NoSuchElementException();
+ }
+ }
+
+ /** Iterable that yields an iterator over rows coming from a sequence of
+ * {@link Frame}s. */
+ private class FetchIterable implements Iterable<Object> {
+ private final StatementHandle handle;
+ private final Frame firstFrame;
+ private final List<Object> parameterValues;
+
+ public FetchIterable(StatementHandle handle, Frame firstFrame,
+ List<Object> parameterValues) {
+ this.handle = handle;
+ this.firstFrame = firstFrame;
+ this.parameterValues = parameterValues;
+ }
+
+ public Iterator<Object> iterator() {
+ return new FetchIterator(handle, firstFrame, parameterValues);
+ }
}
- /** Prepare result that contains an iterable. */
- protected static class SignatureWithIterable extends Signature
- implements WithIterable {
- private final Iterable iterable;
+ /** Iterator over rows coming from a sequence of {@link Frame}s. */
+ private class FetchIterator implements Iterator<Object> {
+ private final StatementHandle handle;
+ private Frame frame;
+ private Iterator<Object> rows;
+ private List<Object> parameterValues;
+
+ public FetchIterator(StatementHandle handle, Frame firstFrame,
+ List<Object> parameterValues) {
+ this.handle = handle;
+ this.parameterValues = parameterValues;
+ if (firstFrame == null) {
+ frame = Frame.MORE;
+ rows = EmptyIterator.INSTANCE;
+ } else {
+ frame = firstFrame;
+ rows = firstFrame.rows.iterator();
+ }
+ moveNext();
+ }
- public SignatureWithIterable(Map<String, Object> internalParameters,
- List<ColumnMetaData> columns, String sql,
- List<AvaticaParameter> parameters, CursorFactory cursorFactory,
- Iterable<Object> iterable) {
- super(columns, sql, parameters, internalParameters, cursorFactory);
- this.iterable = iterable;
+ public void remove() {
+ throw new UnsupportedOperationException("remove");
}
- public Iterable getIterable() {
- return iterable;
+ public boolean hasNext() {
+ return rows != null;
+ }
+
+ public Object next() {
+ if (rows == null) {
+ throw new NoSuchElementException();
+ }
+ final Object o = rows.next();
+ moveNext();
+ return o;
+ }
+
+ private void moveNext() {
+ for (;;) {
+ if (rows.hasNext()) {
+ break;
+ }
+ if (frame.done) {
+ rows = null;
+ break;
+ }
+ frame = fetch(handle, parameterValues, frame.offset, 100);
+ parameterValues = null; // don't execute next time
+ if (frame == null) {
+ rows = null;
+ break;
+ }
+ // It is valid for rows to be empty, so we go around the loop again to
+ // check
+ rows = frame.rows.iterator();
+ }
}
}
}
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/avatica/src/main/java/org/apache/calcite/avatica/UnregisteredDriver.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/org/apache/calcite/avatica/UnregisteredDriver.java b/avatica/src/main/java/org/apache/calcite/avatica/UnregisteredDriver.java
index 07883f6..fefd5f4 100644
--- a/avatica/src/main/java/org/apache/calcite/avatica/UnregisteredDriver.java
+++ b/avatica/src/main/java/org/apache/calcite/avatica/UnregisteredDriver.java
@@ -43,7 +43,7 @@ import java.util.logging.Logger;
* <p>The provider must implement:</p>
* <ul>
* <li>{@link Meta#prepare(org.apache.calcite.avatica.Meta.StatementHandle, String, int)}
- * <li>{@link Meta#createIterable(org.apache.calcite.avatica.Meta.StatementHandle, org.apache.calcite.avatica.Meta.Signature, Iterable)}
+ * <li>{@link Meta#createIterable(org.apache.calcite.avatica.Meta.StatementHandle, org.apache.calcite.avatica.Meta.Signature, java.util.List, Meta.Frame)}
* </ul>
*/
public abstract class UnregisteredDriver implements java.sql.Driver {
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/avatica/src/main/java/org/apache/calcite/avatica/jdbc/JdbcMeta.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/org/apache/calcite/avatica/jdbc/JdbcMeta.java b/avatica/src/main/java/org/apache/calcite/avatica/jdbc/JdbcMeta.java
new file mode 100644
index 0000000..56c20c4
--- /dev/null
+++ b/avatica/src/main/java/org/apache/calcite/avatica/jdbc/JdbcMeta.java
@@ -0,0 +1,442 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.avatica.jdbc;
+
+import org.apache.calcite.avatica.AvaticaParameter;
+import org.apache.calcite.avatica.ColumnMetaData;
+import org.apache.calcite.avatica.Meta;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Type;
+import java.math.BigDecimal;
+import java.sql.Connection;
+import java.sql.ParameterMetaData;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Types;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/** Implementation of {@link Meta} upon an existing JDBC data source. */
+public class JdbcMeta implements Meta {
+ /**
+ * JDBC Types Mapped to Java Types
+ *
+ * @see <a href="https://docs.oracle.com/javase/1.5.0/docs/guide/jdbc/getstart/mapping.html#1051555">JDBC Types Mapped to Java Types</a>
+ */
+ protected static final Map<Integer, Type> SQL_TYPE_TO_JAVA_TYPE =
+ new HashMap<>();
+ static {
+ SQL_TYPE_TO_JAVA_TYPE.put(Types.CHAR, String.class);
+ SQL_TYPE_TO_JAVA_TYPE.put(Types.VARCHAR, String.class);
+ SQL_TYPE_TO_JAVA_TYPE.put(Types.LONGNVARCHAR, String.class);
+ SQL_TYPE_TO_JAVA_TYPE.put(Types.NUMERIC, BigDecimal.class);
+ SQL_TYPE_TO_JAVA_TYPE.put(Types.DECIMAL, BigDecimal.class);
+ SQL_TYPE_TO_JAVA_TYPE.put(Types.BIT, Boolean.TYPE);
+ SQL_TYPE_TO_JAVA_TYPE.put(Types.TINYINT, Byte.TYPE);
+ SQL_TYPE_TO_JAVA_TYPE.put(Types.SMALLINT, Short.TYPE);
+ SQL_TYPE_TO_JAVA_TYPE.put(Types.INTEGER, Integer.TYPE);
+ SQL_TYPE_TO_JAVA_TYPE.put(Types.BIGINT, Long.TYPE);
+ SQL_TYPE_TO_JAVA_TYPE.put(Types.REAL, Float.TYPE);
+ SQL_TYPE_TO_JAVA_TYPE.put(Types.FLOAT, Double.TYPE);
+ SQL_TYPE_TO_JAVA_TYPE.put(Types.DOUBLE, Double.TYPE);
+ SQL_TYPE_TO_JAVA_TYPE.put(Types.BINARY, byte[].class);
+ SQL_TYPE_TO_JAVA_TYPE.put(Types.VARBINARY, byte[].class);
+ SQL_TYPE_TO_JAVA_TYPE.put(Types.LONGVARBINARY, byte[].class);
+ SQL_TYPE_TO_JAVA_TYPE.put(Types.DATE, java.sql.Date.class);
+ SQL_TYPE_TO_JAVA_TYPE.put(Types.TIME, java.sql.Time.class);
+ SQL_TYPE_TO_JAVA_TYPE.put(Types.TIMESTAMP, java.sql.Timestamp.class);
+ //put(Types.CLOB, Clob);
+ //put(Types.BLOB, Blob);
+ SQL_TYPE_TO_JAVA_TYPE.put(Types.ARRAY, Array.class);
+ }
+
+ private final Map<Integer, StatementInfo> statementMap = new HashMap<>();
+
+ /**
+ * Convert from JDBC metadata to Avatica columns.
+ */
+ protected static List<ColumnMetaData>
+ columns(ResultSetMetaData metaData) throws SQLException {
+ final List<ColumnMetaData> columns = new ArrayList<>();
+ for (int i = 1; i <= metaData.getColumnCount(); i++) {
+ final Type javaType =
+ SQL_TYPE_TO_JAVA_TYPE.get(metaData.getColumnType(i));
+ ColumnMetaData.AvaticaType t =
+ ColumnMetaData.scalar(metaData.getColumnType(i),
+ metaData.getColumnTypeName(i), ColumnMetaData.Rep.of(javaType));
+ ColumnMetaData md =
+ new ColumnMetaData(i - 1, metaData.isAutoIncrement(i),
+ metaData.isCaseSensitive(i), metaData.isSearchable(i),
+ metaData.isCurrency(i), metaData.isNullable(i),
+ metaData.isSigned(i), metaData.getColumnDisplaySize(i),
+ metaData.getColumnLabel(i), metaData.getColumnName(i),
+ metaData.getSchemaName(i), metaData.getPrecision(i),
+ metaData.getScale(i), metaData.getTableName(i),
+ metaData.getCatalogName(i), t, metaData.isReadOnly(i),
+ metaData.isWritable(i), metaData.isDefinitelyWritable(i),
+ metaData.getColumnClassName(i));
+ columns.add(md);
+ }
+ return columns;
+ }
+
+ /**
+ * Converts from JDBC metadata to AvaticaParameters
+ */
+ protected static List<AvaticaParameter> parameters(ParameterMetaData metaData)
+ throws SQLException {
+ if (metaData == null) {
+ return Collections.emptyList();
+ }
+ final List<AvaticaParameter> params = new ArrayList<>();
+ for (int i = 1; i <= metaData.getParameterCount(); i++) {
+ params.add(
+ new AvaticaParameter(metaData.isSigned(i), metaData.getPrecision(i),
+ metaData.getScale(i), metaData.getParameterType(i),
+ metaData.getParameterTypeName(i),
+ metaData.getParameterClassName(i), "?" + i));
+ }
+ return params;
+ }
+
+ protected static Signature signature(ResultSetMetaData metaData,
+ ParameterMetaData parameterMetaData, String sql) throws SQLException {
+ return new Signature(columns(metaData), sql, parameters(parameterMetaData),
+ null, CursorFactory.ARRAY);
+ }
+
+ protected static Signature signature(ResultSetMetaData metaData)
+ throws SQLException {
+ return signature(metaData, null, null);
+ }
+
+ protected final Connection connection;
+
+ public JdbcMeta(Connection connection) {
+ this.connection = connection;
+ }
+
+ public String getSqlKeywords() {
+ try {
+ return connection.getMetaData().getSQLKeywords();
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public String getNumericFunctions() {
+ try {
+ return connection.getMetaData().getNumericFunctions();
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public String getStringFunctions() {
+ return null;
+ }
+
+ public String getSystemFunctions() {
+ return null;
+ }
+
+ public String getTimeDateFunctions() {
+ return null;
+ }
+
+ public MetaResultSet getTables(String catalog, Pat schemaPattern,
+ Pat tableNamePattern, List<String> typeList) {
+ try {
+ String[] types = new String[typeList == null ? 0 : typeList.size()];
+ return JdbcResultSet.create(
+ connection.getMetaData().getTables(catalog, schemaPattern.s,
+ tableNamePattern.s,
+ typeList == null ? types : typeList.toArray(types)));
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public MetaResultSet getColumns(String catalog, Pat schemaPattern,
+ Pat tableNamePattern, Pat columnNamePattern) {
+ try {
+ return JdbcResultSet.create(
+ connection.getMetaData().getColumns(catalog, schemaPattern.s,
+ tableNamePattern.s, columnNamePattern.s));
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public MetaResultSet getSchemas(String catalog, Pat schemaPattern) {
+ try {
+ return JdbcResultSet.create(
+ connection.getMetaData().getSchemas(catalog, schemaPattern.s));
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public MetaResultSet getCatalogs() {
+ try {
+ return JdbcResultSet.create(connection.getMetaData().getCatalogs());
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public MetaResultSet getTableTypes() {
+ try {
+ return JdbcResultSet.create(connection.getMetaData().getTableTypes());
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public MetaResultSet getProcedures(String catalog, Pat schemaPattern,
+ Pat procedureNamePattern) {
+ try {
+ return JdbcResultSet.create(
+ connection.getMetaData().getProcedures(catalog, schemaPattern.s,
+ procedureNamePattern.s));
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public MetaResultSet getProcedureColumns(String catalog, Pat schemaPattern,
+ Pat procedureNamePattern, Pat columnNamePattern) {
+ try {
+ return JdbcResultSet.create(
+ connection.getMetaData().getProcedureColumns(catalog,
+ schemaPattern.s, procedureNamePattern.s, columnNamePattern.s));
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public MetaResultSet getColumnPrivileges(String catalog, String schema,
+ String table, Pat columnNamePattern) {
+ try {
+ return JdbcResultSet.create(
+ connection.getMetaData().getColumnPrivileges(catalog, schema,
+ table, columnNamePattern.s));
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public MetaResultSet getTablePrivileges(String catalog, Pat schemaPattern,
+ Pat tableNamePattern) {
+ try {
+ return JdbcResultSet.create(
+ connection.getMetaData().getTablePrivileges(catalog,
+ schemaPattern.s, tableNamePattern.s));
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public MetaResultSet getBestRowIdentifier(String catalog, String schema,
+ String table, int scope, boolean nullable) {
+ try {
+ return JdbcResultSet.create(
+ connection.getMetaData().getBestRowIdentifier(catalog, schema,
+ table, scope, nullable));
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public MetaResultSet getVersionColumns(String catalog, String schema,
+ String table) {
+ try {
+ return JdbcResultSet.create(
+ connection.getMetaData().getVersionColumns(catalog, schema, table));
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public MetaResultSet getPrimaryKeys(String catalog, String schema,
+ String table) {
+ try {
+ return JdbcResultSet.create(
+ connection.getMetaData().getPrimaryKeys(catalog, schema, table));
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public MetaResultSet getImportedKeys(String catalog, String schema,
+ String table) {
+ return null;
+ }
+
+ public MetaResultSet getExportedKeys(String catalog, String schema,
+ String table) {
+ return null;
+ }
+
+ public MetaResultSet getCrossReference(String parentCatalog,
+ String parentSchema, String parentTable, String foreignCatalog,
+ String foreignSchema, String foreignTable) {
+ return null;
+ }
+
+ public MetaResultSet getTypeInfo() {
+ return null;
+ }
+
+ public MetaResultSet getIndexInfo(String catalog, String schema, String table,
+ boolean unique, boolean approximate) {
+ return null;
+ }
+
+ public MetaResultSet getUDTs(String catalog, Pat schemaPattern,
+ Pat typeNamePattern, int[] types) {
+ return null;
+ }
+
+ public MetaResultSet getSuperTypes(String catalog, Pat schemaPattern,
+ Pat typeNamePattern) {
+ return null;
+ }
+
+ public MetaResultSet getSuperTables(String catalog, Pat schemaPattern,
+ Pat tableNamePattern) {
+ return null;
+ }
+
+ public MetaResultSet getAttributes(String catalog, Pat schemaPattern,
+ Pat typeNamePattern, Pat attributeNamePattern) {
+ return null;
+ }
+
+ public MetaResultSet getClientInfoProperties() {
+ return null;
+ }
+
+ public MetaResultSet getFunctions(String catalog, Pat schemaPattern,
+ Pat functionNamePattern) {
+ return null;
+ }
+
+ public MetaResultSet getFunctionColumns(String catalog, Pat schemaPattern,
+ Pat functionNamePattern, Pat columnNamePattern) {
+ return null;
+ }
+
+ public MetaResultSet getPseudoColumns(String catalog, Pat schemaPattern,
+ Pat tableNamePattern, Pat columnNamePattern) {
+ return null;
+ }
+
+ public Iterable<Object> createIterable(StatementHandle handle,
+ Signature signature, List<Object> parameterValues, Frame firstFrame) {
+ return null;
+ }
+
+ public StatementHandle createStatement(ConnectionHandle ch) {
+ try {
+ final Statement statement = connection.createStatement();
+ final int id = statementMap.size();
+ statementMap.put(id, new StatementInfo(statement));
+ return new StatementHandle(id);
+ } catch (SQLException e) {
+ throw propagate(e);
+ }
+ }
+
+ private RuntimeException propagate(Throwable e) {
+ if (e instanceof RuntimeException) {
+ throw (RuntimeException) e;
+ } else if (e instanceof Error) {
+ throw (Error) e;
+ } else {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public Signature prepare(StatementHandle h, String sql, int maxRowCount) {
+ // TODO: can't actually prepare an existing statement...
+ try {
+ PreparedStatement statement = connection.prepareStatement(sql);
+ statementMap.put(h.id, new StatementInfo(statement));
+ return signature(statement.getMetaData(),
+ statement.getParameterMetaData(), sql);
+ } catch (SQLException e) {
+ throw propagate(e);
+ }
+ }
+
+ public MetaResultSet prepareAndExecute(StatementHandle h, String sql,
+ int maxRowCount, PrepareCallback callback) {
+ final StatementInfo statementInfo = statementMap.get(h.id);
+ try {
+ statementInfo.resultSet = statementInfo.statement.executeQuery(sql);
+ return JdbcResultSet.create(statementInfo.resultSet);
+ } catch (SQLException e) {
+ throw propagate(e);
+ }
+ }
+
+ public Frame fetch(StatementHandle h, List<Object> parameterValues,
+ int offset, int fetchMaxRowCount) {
+ final StatementInfo statementInfo = statementMap.get(h.id);
+ try {
+ if (statementInfo.resultSet == null || parameterValues != null) {
+ if (statementInfo.resultSet != null) {
+ statementInfo.resultSet.close();
+ }
+ final PreparedStatement preparedStatement =
+ (PreparedStatement) statementInfo.statement;
+ if (parameterValues != null) {
+ for (int i = 0; i < parameterValues.size(); i++) {
+ Object o = parameterValues.get(i);
+ preparedStatement.setObject(i + 1, o);
+ }
+ }
+ statementInfo.resultSet = preparedStatement.executeQuery();
+ }
+ return JdbcResultSet.frame(statementInfo.resultSet, offset,
+ fetchMaxRowCount);
+ } catch (SQLException e) {
+ throw propagate(e);
+ }
+ }
+
+ /** All we know about a statement. */
+ private static class StatementInfo {
+ final Statement statement; // sometimes a PreparedStatement
+ ResultSet resultSet;
+
+ private StatementInfo(Statement statement) {
+ this.statement = Objects.requireNonNull(statement);
+ }
+ }
+}
+
+// End JdbcMeta.java
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/avatica/src/main/java/org/apache/calcite/avatica/jdbc/JdbcResultSet.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/org/apache/calcite/avatica/jdbc/JdbcResultSet.java b/avatica/src/main/java/org/apache/calcite/avatica/jdbc/JdbcResultSet.java
new file mode 100644
index 0000000..ac4aeb5
--- /dev/null
+++ b/avatica/src/main/java/org/apache/calcite/avatica/jdbc/JdbcResultSet.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.avatica.jdbc;
+
+import org.apache.calcite.avatica.Meta;
+
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.ArrayList;
+import java.util.List;
+
+/** Implementation of {@link org.apache.calcite.avatica.Meta.MetaResultSet}
+ * upon a JDBC {@link java.sql.ResultSet}.
+ *
+ * @see org.apache.calcite.avatica.jdbc.JdbcMeta */
+class JdbcResultSet extends Meta.MetaResultSet {
+ protected JdbcResultSet(int statementId, boolean ownStatement,
+ Meta.Signature signature, Meta.Frame firstFrame) {
+ super(statementId, ownStatement, signature, firstFrame);
+ }
+
+ /** Creates a result set. */
+ public static JdbcResultSet create(ResultSet resultSet) {
+ try {
+ int id = resultSet.getStatement().hashCode();
+ Meta.Signature sig = JdbcMeta.signature(resultSet.getMetaData());
+ final Meta.Frame firstFrame = frame(resultSet, 0, -1);
+ resultSet.close();
+ return new JdbcResultSet(id, true, sig, firstFrame);
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /** Creates a frame containing a given number or unlimited number of rows
+ * from a result set. */
+ static Meta.Frame frame(ResultSet resultSet, int offset,
+ int fetchMaxRowCount) throws SQLException {
+ final ResultSetMetaData metaData = resultSet.getMetaData();
+ final int columnCount = metaData.getColumnCount();
+ final int[] types = new int[columnCount];
+ for (int i = 0; i < types.length; i++) {
+ types[i] = metaData.getColumnType(i + 1);
+ }
+ final List<Object> rows = new ArrayList<>();
+ boolean done = false;
+ for (int i = 0; fetchMaxRowCount < 0 || i < fetchMaxRowCount; i++) {
+ if (!resultSet.next()) {
+ done = true;
+ break;
+ }
+ Object[] columns = new Object[columnCount];
+ for (int j = 0; j < columnCount; j++) {
+ columns[j] = getValue(resultSet, types[j], j);
+ }
+ rows.add(columns);
+ }
+ return new Meta.Frame(offset, done, rows);
+ }
+
+ private static Object getValue(ResultSet resultSet, int type, int j)
+ throws SQLException {
+ switch (type) {
+ case Types.BIGINT:
+ final long aLong = resultSet.getLong(j + 1);
+ return aLong == 0 && resultSet.wasNull() ? null : aLong;
+ case Types.INTEGER:
+ final int anInt = resultSet.getInt(j + 1);
+ return anInt == 0 && resultSet.wasNull() ? null : anInt;
+ case Types.SMALLINT:
+ final short aShort = resultSet.getShort(j + 1);
+ return aShort == 0 && resultSet.wasNull() ? null : aShort;
+ case Types.TINYINT:
+ final byte aByte = resultSet.getByte(j + 1);
+ return aByte == 0 && resultSet.wasNull() ? null : aByte;
+ case Types.DOUBLE:
+ case Types.FLOAT:
+ final double aDouble = resultSet.getDouble(j + 1);
+ return aDouble == 0D && resultSet.wasNull() ? null : aDouble;
+ case Types.REAL:
+ final float aFloat = resultSet.getFloat(j + 1);
+ return aFloat == 0D && resultSet.wasNull() ? null : aFloat;
+ default:
+ return resultSet.getObject(j + 1);
+ }
+ }
+}
+
+// End JdbcResultSet.java
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/avatica/src/main/java/org/apache/calcite/avatica/jdbc/package-info.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/org/apache/calcite/avatica/jdbc/package-info.java b/avatica/src/main/java/org/apache/calcite/avatica/jdbc/package-info.java
new file mode 100644
index 0000000..8b8fb76
--- /dev/null
+++ b/avatica/src/main/java/org/apache/calcite/avatica/jdbc/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** Implements an Avatica provider on top of an existing JDBC data source. */
+package org.apache.calcite.avatica.jdbc;
+
+
+// End package-info.java
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/avatica/src/main/java/org/apache/calcite/avatica/remote/JsonService.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/org/apache/calcite/avatica/remote/JsonService.java b/avatica/src/main/java/org/apache/calcite/avatica/remote/JsonService.java
index 3de4ef0..7e110ff 100644
--- a/avatica/src/main/java/org/apache/calcite/avatica/remote/JsonService.java
+++ b/avatica/src/main/java/org/apache/calcite/avatica/remote/JsonService.java
@@ -41,11 +41,14 @@ public abstract class JsonService implements Service {
* responses to and from the peer service. */
public abstract String apply(String request);
- private <T> T decode(String response, Class<T> valueType) throws IOException {
+ //@VisibleForTesting
+ protected static <T> T decode(String response, Class<T> valueType)
+ throws IOException {
return MAPPER.readValue(response, valueType);
}
- private <T> String encode(T request) throws IOException {
+ //@VisibleForTesting
+ protected static <T> String encode(T request) throws IOException {
final StringWriter w = new StringWriter();
MAPPER.writeValue(w, request);
return w.toString();
@@ -71,6 +74,14 @@ public abstract class JsonService implements Service {
}
}
+ public ResultSetResponse apply(TablesRequest request) {
+ try {
+ return decode(apply(encode(request)), ResultSetResponse.class);
+ } catch (IOException e) {
+ throw handle(e);
+ }
+ }
+
public PrepareResponse apply(PrepareRequest request) {
try {
return decode(apply(encode(request)), PrepareResponse.class);
@@ -87,6 +98,14 @@ public abstract class JsonService implements Service {
}
}
+ public FetchResponse apply(FetchRequest request) {
+ try {
+ return decode(apply(encode(request)), FetchResponse.class);
+ } catch (IOException e) {
+ throw handle(e);
+ }
+ }
+
public CreateStatementResponse apply(CreateStatementRequest request) {
try {
return decode(apply(encode(request)), CreateStatementResponse.class);
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/avatica/src/main/java/org/apache/calcite/avatica/remote/LocalService.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/org/apache/calcite/avatica/remote/LocalService.java b/avatica/src/main/java/org/apache/calcite/avatica/remote/LocalService.java
index 5ee3d16..faf60b8 100644
--- a/avatica/src/main/java/org/apache/calcite/avatica/remote/LocalService.java
+++ b/avatica/src/main/java/org/apache/calcite/avatica/remote/LocalService.java
@@ -16,10 +16,13 @@
*/
package org.apache.calcite.avatica.remote;
+import org.apache.calcite.avatica.ColumnMetaData;
import org.apache.calcite.avatica.Meta;
import org.apache.calcite.avatica.MetaImpl;
+import java.sql.Types;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
/**
@@ -27,6 +30,8 @@ import java.util.List;
*/
public class LocalService implements Service {
final Meta meta;
+ /** Whether output is going to JSON. */
+ private final boolean json = true;
public LocalService(Meta meta) {
this.meta = meta;
@@ -47,8 +52,8 @@ public class LocalService implements Service {
public ResultSetResponse toResponse(Meta.MetaResultSet resultSet) {
Meta.CursorFactory cursorFactory = resultSet.signature.cursorFactory;
final List<Object> list;
- if (resultSet.iterable != null) {
- list = list(resultSet.iterable);
+ if (resultSet.firstFrame != null) {
+ list = list(resultSet.firstFrame.rows);
switch (cursorFactory.style) {
case ARRAY:
cursorFactory = Meta.CursorFactory.LIST;
@@ -68,16 +73,16 @@ public class LocalService implements Service {
signature = signature.setCursorFactory(cursorFactory);
}
return new ResultSetResponse(resultSet.statementId, resultSet.ownStatement,
- signature, list);
+ signature, new Meta.Frame(0, true, list));
}
private List<List<Object>> list2(Meta.MetaResultSet resultSet) {
- List<List<Object>> list = new ArrayList<List<Object>>();
- return MetaImpl.collect(resultSet.signature.cursorFactory,
- meta.createIterable(new Meta.StatementHandle(resultSet.statementId),
- resultSet.signature,
- resultSet.iterable),
- list);
+ final Meta.StatementHandle h =
+ new Meta.StatementHandle(resultSet.statementId);
+ final Iterable<Object> iterable = meta.createIterable(h,
+ resultSet.signature, Collections.emptyList(), resultSet.firstFrame);
+ final List<List<Object>> list = new ArrayList<>();
+ return MetaImpl.collect(resultSet.signature.cursorFactory, iterable, list);
}
public ResultSetResponse apply(CatalogsRequest request) {
@@ -91,11 +96,43 @@ public class LocalService implements Service {
return toResponse(resultSet);
}
+ public ResultSetResponse apply(TablesRequest request) {
+ final Meta.MetaResultSet resultSet =
+ meta.getTables(request.catalog, Meta.Pat.of(request.schemaPattern),
+ Meta.Pat.of(request.tableNamePattern), request.typeList);
+ return toResponse(resultSet);
+ }
+
public PrepareResponse apply(PrepareRequest request) {
final Meta.StatementHandle h =
new Meta.StatementHandle(request.statementId);
- final Meta.Signature signature =
- meta.prepare(h, request.sql, request.maxRowCount);
+ Meta.Signature signature =
+ meta.prepare(h, request.sql, request.maxRowCount)
+ .setCursorFactory(Meta.CursorFactory.LIST);
+ if (json) {
+ final List<ColumnMetaData> columns = new ArrayList<>();
+ for (ColumnMetaData column : signature.columns) {
+ switch (column.type.rep) {
+ case BYTE:
+ case PRIMITIVE_BYTE:
+ case DOUBLE:
+ case PRIMITIVE_DOUBLE:
+ case FLOAT:
+ case PRIMITIVE_FLOAT:
+ case INTEGER:
+ case PRIMITIVE_INT:
+ case SHORT:
+ case PRIMITIVE_SHORT:
+ case LONG:
+ case PRIMITIVE_LONG:
+ column = column.setTypeId(Types.NUMERIC);
+ }
+ columns.add(column);
+ }
+ signature = new Meta.Signature(columns, signature.sql,
+ signature.parameters, signature.internalParameters,
+ signature.cursorFactory);
+ }
return new PrepareResponse(signature);
}
@@ -105,20 +142,29 @@ public class LocalService implements Service {
final Meta.MetaResultSet resultSet =
meta.prepareAndExecute(h, request.sql, request.maxRowCount,
new Meta.PrepareCallback() {
- public Object getMonitor() {
+ @Override public Object getMonitor() {
return LocalService.class;
}
- public void clear() {}
+ @Override public void clear() {}
- public void assign(Meta.Signature signature,
- Iterable<Object> iterable) {}
+ @Override public void assign(Meta.Signature signature,
+ Meta.Frame firstFrame) {}
- public void execute() {}
+ @Override public void execute() {}
});
return toResponse(resultSet);
}
+ public FetchResponse apply(FetchRequest request) {
+ final Meta.StatementHandle h =
+ new Meta.StatementHandle(request.statementId);
+ final Meta.Frame frame =
+ meta.fetch(h, request.parameterValues, request.offset,
+ request.fetchMaxRowCount);
+ return new FetchResponse(frame);
+ }
+
public CreateStatementResponse apply(CreateStatementRequest request) {
final Meta.StatementHandle h =
meta.createStatement(new Meta.ConnectionHandle(request.connectionId));
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/avatica/src/main/java/org/apache/calcite/avatica/remote/MockJsonService.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/org/apache/calcite/avatica/remote/MockJsonService.java b/avatica/src/main/java/org/apache/calcite/avatica/remote/MockJsonService.java
index 7fe7ea8..19e59e3 100644
--- a/avatica/src/main/java/org/apache/calcite/avatica/remote/MockJsonService.java
+++ b/avatica/src/main/java/org/apache/calcite/avatica/remote/MockJsonService.java
@@ -18,6 +18,8 @@ package org.apache.calcite.avatica.remote;
import org.apache.calcite.avatica.AvaticaConnection;
+import java.io.IOException;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@@ -44,10 +46,44 @@ public class MockJsonService extends JsonService {
/** Factory that creates a {@code MockJsonService}. */
public static class Factory implements Service.Factory {
public Service create(AvaticaConnection connection) {
- final Map<String, String> map1 = new HashMap<String, String>();
- map1.put(
- "{\"request\":\"getSchemas\",\"catalog\":null,\"schemaPattern\":{\"s\":null}}",
- "{\"response\":\"resultSet\", rows: []}");
+ final Map<String, String> map1 = new HashMap<>();
+ try {
+ map1.put(
+ "{\"request\":\"getSchemas\",\"catalog\":null,\"schemaPattern\":{\"s\":null}}",
+ "{\"response\":\"resultSet\", firstFrame: {offset: 0, done: true, rows: []}}");
+ map1.put(
+ JsonService.encode(new SchemasRequest(null, null)),
+ "{\"response\":\"resultSet\", firstFrame: {offset: 0, done: true, rows: []}}");
+ map1.put(
+ JsonService.encode(
+ new TablesRequest(null, null, null, Arrays.<String>asList())),
+ "{\"response\":\"resultSet\", firstFrame: {offset: 0, done: true, rows: []}}");
+ map1.put(
+ "{\"request\":\"createStatement\",\"connectionId\":0}",
+ "{\"response\":\"createStatement\",\"id\":0}");
+ map1.put(
+ "{\"request\":\"prepareAndExecute\",\"statementId\":0,"
+ + "\"sql\":\"select * from (\\n values (1, 'a'), (null, 'b'), (3, 'c')) as t (c1, c2)\",\"maxRowCount\":-1}",
+ "{\"response\":\"resultSet\",\"signature\": {\n"
+ + " \"columns\": [\n"
+ + " {\"columnName\": \"C1\", \"type\": {type: \"scalar\", id: 4, rep: \"INTEGER\"}},\n"
+ + " {\"columnName\": \"C2\", \"type\": {type: \"scalar\", id: 12, rep: \"STRING\"}}\n"
+ + " ], \"cursorFactory\": {\"style\": \"ARRAY\"}\n"
+ + "}, \"rows\": [[1, \"a\"], [null, \"b\"], [3, \"c\"]]}");
+ map1.put(
+ "{\"request\":\"prepare\",\"statementId\":0,"
+ + "\"sql\":\"select * from (\\n values (1, 'a'), (null, 'b'), (3, 'c')) as t (c1, c2)\",\"maxRowCount\":-1}",
+ "{\"response\":\"prepare\",\"signature\": {\n"
+ + " \"columns\": [\n"
+ + " {\"columnName\": \"C1\", \"type\": {type: \"scalar\", id: 4, rep: \"INTEGER\"}},\n"
+ + " {\"columnName\": \"C2\", \"type\": {type: \"scalar\", id: 12, rep: \"STRING\"}}\n"
+ + " ],\n"
+ + " \"parameters\": [],\n"
+ + " \"cursorFactory\": {\"style\": \"ARRAY\"}\n"
+ + "}}");
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
return new MockJsonService(map1);
}
}
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/avatica/src/main/java/org/apache/calcite/avatica/remote/RemoteMeta.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/org/apache/calcite/avatica/remote/RemoteMeta.java b/avatica/src/main/java/org/apache/calcite/avatica/remote/RemoteMeta.java
index 89ef490..83dd28c 100644
--- a/avatica/src/main/java/org/apache/calcite/avatica/remote/RemoteMeta.java
+++ b/avatica/src/main/java/org/apache/calcite/avatica/remote/RemoteMeta.java
@@ -17,10 +17,14 @@
package org.apache.calcite.avatica.remote;
import org.apache.calcite.avatica.AvaticaConnection;
+import org.apache.calcite.avatica.AvaticaParameter;
+import org.apache.calcite.avatica.ColumnMetaData;
import org.apache.calcite.avatica.Meta;
import org.apache.calcite.avatica.MetaImpl;
import java.sql.SQLException;
+import java.util.Collections;
+import java.util.List;
/**
* Implementation of {@link Meta} for the remote driver.
@@ -33,10 +37,19 @@ class RemoteMeta extends MetaImpl {
this.service = service;
}
- private MetaResultSet toResultSet(Service.ResultSetResponse response) {
- final Signature signature0 = response.signature;
+ private MetaResultSet toResultSet(Class clazz,
+ Service.ResultSetResponse response) {
+ Signature signature0 = response.signature;
+ if (signature0 == null) {
+ final List<ColumnMetaData> columns =
+ clazz == null
+ ? Collections.<ColumnMetaData>emptyList()
+ : fieldMetaData(clazz).columns;
+ signature0 = Signature.create(columns,
+ "?", Collections.<AvaticaParameter>emptyList(), CursorFactory.ARRAY);
+ }
return new MetaResultSet(response.statementId, response.ownStatement,
- signature0, response.rows);
+ signature0, response.firstFrame);
}
@Override public StatementHandle createStatement(ConnectionHandle ch) {
@@ -48,13 +61,22 @@ class RemoteMeta extends MetaImpl {
@Override public MetaResultSet getCatalogs() {
final Service.ResultSetResponse response =
service.apply(new Service.CatalogsRequest());
- return toResultSet(response);
+ return toResultSet(MetaCatalog.class, response);
}
@Override public MetaResultSet getSchemas(String catalog, Pat schemaPattern) {
final Service.ResultSetResponse response =
service.apply(new Service.SchemasRequest(catalog, schemaPattern.s));
- return toResultSet(response);
+ return toResultSet(MetaSchema.class, response);
+ }
+
+ @Override public MetaResultSet getTables(String catalog, Pat schemaPattern,
+ Pat tableNamePattern, List<String> typeList) {
+ final Service.ResultSetResponse response =
+ service.apply(
+ new Service.TablesRequest(catalog, schemaPattern.s,
+ tableNamePattern.s, typeList));
+ return toResultSet(MetaTable.class, response);
}
@Override public Signature prepare(StatementHandle h, String sql,
@@ -72,14 +94,23 @@ class RemoteMeta extends MetaImpl {
callback.clear();
response = service.apply(
new Service.PrepareAndExecuteRequest(h.id, sql, maxRowCount));
- callback.assign(response.signature, response.rows);
+ callback.assign(response.signature, response.firstFrame);
}
callback.execute();
- return toResultSet(response);
+ return toResultSet(null, response);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
+
+ @Override public Frame fetch(StatementHandle h, List<Object> parameterValues,
+ int offset, int fetchMaxRowCount) {
+ final Service.FetchResponse response =
+ service.apply(
+ new Service.FetchRequest(h.id, parameterValues, offset,
+ fetchMaxRowCount));
+ return response.frame;
+ }
}
// End RemoteMeta.java
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/avatica/src/main/java/org/apache/calcite/avatica/remote/Service.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/org/apache/calcite/avatica/remote/Service.java b/avatica/src/main/java/org/apache/calcite/avatica/remote/Service.java
index cad38dd..cf73b49 100644
--- a/avatica/src/main/java/org/apache/calcite/avatica/remote/Service.java
+++ b/avatica/src/main/java/org/apache/calcite/avatica/remote/Service.java
@@ -32,8 +32,10 @@ import java.util.List;
public interface Service {
ResultSetResponse apply(CatalogsRequest request);
ResultSetResponse apply(SchemasRequest request);
+ ResultSetResponse apply(TablesRequest request);
PrepareResponse apply(PrepareRequest request);
ResultSetResponse apply(PrepareAndExecuteRequest request);
+ FetchResponse apply(FetchRequest request);
CreateStatementResponse apply(CreateStatementRequest request);
/** Factory that creates a {@code Service}. */
@@ -49,9 +51,11 @@ public interface Service {
@JsonSubTypes({
@JsonSubTypes.Type(value = CatalogsRequest.class, name = "getCatalogs"),
@JsonSubTypes.Type(value = SchemasRequest.class, name = "getSchemas"),
+ @JsonSubTypes.Type(value = TablesRequest.class, name = "getTables"),
@JsonSubTypes.Type(value = PrepareRequest.class, name = "prepare"),
@JsonSubTypes.Type(value = PrepareAndExecuteRequest.class,
name = "prepareAndExecute"),
+ @JsonSubTypes.Type(value = FetchRequest.class, name = "fetch"),
@JsonSubTypes.Type(value = CreateStatementRequest.class,
name = "createStatement") })
abstract class Request {
@@ -66,6 +70,7 @@ public interface Service {
@JsonSubTypes({
@JsonSubTypes.Type(value = ResultSetResponse.class, name = "resultSet"),
@JsonSubTypes.Type(value = PrepareResponse.class, name = "prepare"),
+ @JsonSubTypes.Type(value = FetchResponse.class, name = "fetch"),
@JsonSubTypes.Type(value = CreateStatementResponse.class,
name = "createStatement") })
abstract class Response {
@@ -97,6 +102,31 @@ public interface Service {
}
}
+ /** Request for
+ * {@link Meta#getTables(String, org.apache.calcite.avatica.Meta.Pat, org.apache.calcite.avatica.Meta.Pat, java.util.List)}
+ */
+ class TablesRequest extends Request {
+ public final String catalog;
+ public final String schemaPattern;
+ public final String tableNamePattern;
+ public final List<String> typeList;
+
+ @JsonCreator
+ public TablesRequest(@JsonProperty("catalog") String catalog,
+ @JsonProperty("schemaPattern") String schemaPattern,
+ @JsonProperty("tableNamePattern") String tableNamePattern,
+ @JsonProperty("typeList") List<String> typeList) {
+ this.catalog = catalog;
+ this.schemaPattern = schemaPattern;
+ this.tableNamePattern = tableNamePattern;
+ this.typeList = typeList;
+ }
+
+ @Override Response accept(Service service) {
+ return service.apply(this);
+ }
+ }
+
/** Response that contains a result set.
*
* <p>Several types of request, including
@@ -107,17 +137,17 @@ public interface Service {
public final int statementId;
public final boolean ownStatement;
public final Meta.Signature signature;
- public final List<Object> rows;
+ public final Meta.Frame firstFrame;
@JsonCreator
public ResultSetResponse(@JsonProperty("statementId") int statementId,
@JsonProperty("ownStatement") boolean ownStatement,
@JsonProperty("signature") Meta.Signature signature,
- @JsonProperty("rows") List<Object> rows) {
+ @JsonProperty("firstFrame") Meta.Frame firstFrame) {
this.statementId = statementId;
this.ownStatement = ownStatement;
this.signature = signature;
- this.rows = rows;
+ this.firstFrame = firstFrame;
}
}
@@ -177,6 +207,45 @@ public interface Service {
}
/** Request for
+ * {@link org.apache.calcite.avatica.Meta#fetch(Meta.StatementHandle, List, int, int)}. */
+ class FetchRequest extends Request {
+ public final int statementId;
+ public final int offset;
+ /** Maximum number of rows to be returned in the frame. Negative means no
+ * limit. */
+ public final int fetchMaxRowCount;
+ /** A list of parameter values, if statement is to be executed; otherwise
+ * null. */
+ public final List<Object> parameterValues;
+
+ @JsonCreator
+ public FetchRequest(@JsonProperty("statementId") int statementId,
+ @JsonProperty("parameterValues") List<Object> parameterValues,
+ @JsonProperty("offset") int offset,
+ @JsonProperty("fetchMaxRowCount") int fetchMaxRowCount) {
+ this.statementId = statementId;
+ this.parameterValues = parameterValues;
+ this.offset = offset;
+ this.fetchMaxRowCount = fetchMaxRowCount;
+ }
+
+ @Override FetchResponse accept(Service service) {
+ return service.apply(this);
+ }
+ }
+
+ /** Response from
+ * {@link org.apache.calcite.avatica.remote.Service.FetchRequest}. */
+ class FetchResponse extends Response {
+ public final Meta.Frame frame;
+
+ @JsonCreator
+ public FetchResponse(@JsonProperty("frame") Meta.Frame frame) {
+ this.frame = frame;
+ }
+ }
+
+ /** Request for
* {@link org.apache.calcite.avatica.Meta#createStatement(org.apache.calcite.avatica.Meta.ConnectionHandle)}. */
class CreateStatementRequest extends Request {
public final int connectionId;
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/avatica/src/main/java/org/apache/calcite/avatica/util/AbstractCursor.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/org/apache/calcite/avatica/util/AbstractCursor.java b/avatica/src/main/java/org/apache/calcite/avatica/util/AbstractCursor.java
index 301352f..42731ba 100644
--- a/avatica/src/main/java/org/apache/calcite/avatica/util/AbstractCursor.java
+++ b/avatica/src/main/java/org/apache/calcite/avatica/util/AbstractCursor.java
@@ -22,6 +22,7 @@ import org.apache.calcite.avatica.ColumnMetaData;
import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
+import java.math.BigInteger;
import java.math.RoundingMode;
import java.net.URL;
import java.sql.Array;
@@ -71,12 +72,12 @@ public abstract class AbstractCursor implements Cursor {
return accessors;
}
- protected Accessor createAccessor(ColumnMetaData type, int ordinal,
+ protected Accessor createAccessor(ColumnMetaData columnMetaData, int ordinal,
Calendar localCalendar, ArrayImpl.Factory factory) {
// Create an accessor appropriate to the underlying type; the accessor
// can convert to any type in the same family.
Getter getter = createGetter(ordinal);
- switch (type.type.type) {
+ switch (columnMetaData.type.id) {
case Types.TINYINT:
return new ByteAccessor(getter);
case Types.SMALLINT:
@@ -92,15 +93,17 @@ public abstract class AbstractCursor implements Cursor {
return new FloatAccessor(getter);
case Types.DOUBLE:
return new DoubleAccessor(getter);
+ case Types.NUMERIC:
+ return new NumberAccessor(getter);
case Types.DECIMAL:
return new BigDecimalAccessor(getter);
case Types.CHAR:
- switch (type.type.representation) {
+ switch (columnMetaData.type.rep) {
case PRIMITIVE_CHAR:
case CHARACTER:
- return new StringFromCharAccessor(getter, type.displaySize);
+ return new StringFromCharAccessor(getter, columnMetaData.displaySize);
default:
- return new FixedStringAccessor(getter, type.displaySize);
+ return new FixedStringAccessor(getter, columnMetaData.displaySize);
}
case Types.VARCHAR:
return new StringAccessor(getter);
@@ -108,27 +111,27 @@ public abstract class AbstractCursor implements Cursor {
case Types.VARBINARY:
return new BinaryAccessor(getter);
case Types.DATE:
- switch (type.type.representation) {
+ switch (columnMetaData.type.rep) {
case PRIMITIVE_INT:
case INTEGER:
return new DateFromIntAccessor(getter, localCalendar);
case JAVA_SQL_DATE:
return new DateAccessor(getter, localCalendar);
default:
- throw new AssertionError("bad " + type.type.representation);
+ throw new AssertionError("bad " + columnMetaData.type.rep);
}
case Types.TIME:
- switch (type.type.representation) {
+ switch (columnMetaData.type.rep) {
case PRIMITIVE_INT:
case INTEGER:
return new TimeFromIntAccessor(getter, localCalendar);
case JAVA_SQL_TIME:
return new TimeAccessor(getter, localCalendar);
default:
- throw new AssertionError("bad " + type.type.representation);
+ throw new AssertionError("bad " + columnMetaData.type.rep);
}
case Types.TIMESTAMP:
- switch (type.type.representation) {
+ switch (columnMetaData.type.rep) {
case PRIMITIVE_LONG:
case LONG:
return new TimestampFromLongAccessor(getter, localCalendar);
@@ -137,31 +140,32 @@ public abstract class AbstractCursor implements Cursor {
case JAVA_UTIL_DATE:
return new TimestampFromUtilDateAccessor(getter, localCalendar);
default:
- throw new AssertionError("bad " + type.type.representation);
+ throw new AssertionError("bad " + columnMetaData.type.rep);
}
case Types.ARRAY:
return new ArrayAccessor(getter,
- ((ColumnMetaData.ArrayType) type.type).component, factory);
+ ((ColumnMetaData.ArrayType) columnMetaData.type).component, factory);
case Types.JAVA_OBJECT:
case Types.STRUCT:
case Types.OTHER: // e.g. map
- if (type.type.typeName.startsWith("INTERVAL_")) {
- int end = type.type.typeName.indexOf("(");
+ if (columnMetaData.type.name.startsWith("INTERVAL_")) {
+ int end = columnMetaData.type.name.indexOf("(");
if (end < 0) {
- end = type.type.typeName.length();
+ end = columnMetaData.type.name.length();
}
TimeUnitRange range =
TimeUnitRange.valueOf(
- type.type.typeName.substring("INTERVAL_".length(), end));
+ columnMetaData.type.name.substring("INTERVAL_".length(), end));
if (range.monthly()) {
return new IntervalYearMonthAccessor(getter, range);
} else {
- return new IntervalDayTimeAccessor(getter, range, type.scale);
+ return new IntervalDayTimeAccessor(getter, range,
+ columnMetaData.scale);
}
}
return new ObjectAccessor(getter);
default:
- throw new RuntimeException("unknown type " + type.type.type);
+ throw new RuntimeException("unknown type " + columnMetaData.type.id);
}
}
@@ -617,6 +621,41 @@ public abstract class AbstractCursor implements Cursor {
}
/**
+ * Accessor that assumes that the underlying value is a {@link Number};
+ * corresponds to {@link java.sql.Types#NUMERIC}.
+ *
+ * <p>This is useful when numbers have been translated over JSON. JSON
+ * converts a 0L (0 long) value to the string "0" and back to 0 (0 int).
+ * So you cannot be sure that the source and target type are the same.
+ */
+ private static class NumberAccessor extends BigNumberAccessor {
+ public NumberAccessor(Getter getter) {
+ super(getter);
+ }
+
+ protected Number getNumber() {
+ return (Number) getObject();
+ }
+
+ public BigDecimal getBigDecimal(int scale) {
+ return getBigDecimal();
+ }
+
+ public BigDecimal getBigDecimal() {
+ Number n = getNumber();
+ return n == null ? null
+ : n instanceof BigDecimal ? (BigDecimal) n
+ : n instanceof BigInteger ? new BigDecimal((BigInteger) n)
+ : n instanceof Long ? new BigDecimal((long) n)
+ : n instanceof Integer ? new BigDecimal((int) n)
+ : n instanceof Short ? new BigDecimal((short) n)
+ : n instanceof Byte ? new BigDecimal((byte) n)
+ : n instanceof Double ? new BigDecimal((double) n)
+ : new BigDecimal((float) n);
+ }
+ }
+
+ /**
* Accessor that assumes that the underlying value is a {@link String};
* corresponds to {@link java.sql.Types#CHAR}
* and {@link java.sql.Types#VARCHAR}.
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/4d2f647a/avatica/src/main/java/org/apache/calcite/avatica/util/ArrayImpl.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/org/apache/calcite/avatica/util/ArrayImpl.java b/avatica/src/main/java/org/apache/calcite/avatica/util/ArrayImpl.java
index e953e6a..385f733 100644
--- a/avatica/src/main/java/org/apache/calcite/avatica/util/ArrayImpl.java
+++ b/avatica/src/main/java/org/apache/calcite/avatica/util/ArrayImpl.java
@@ -39,11 +39,11 @@ public class ArrayImpl implements Array {
}
public String getBaseTypeName() throws SQLException {
- return elementType.typeName;
+ return elementType.name;
}
public int getBaseType() throws SQLException {
- return elementType.type;
+ return elementType.id;
}
public Object getArray() throws SQLException {
@@ -65,7 +65,7 @@ public class ArrayImpl implements Array {
@SuppressWarnings("unchecked")
protected Object getArray(List list) throws SQLException {
int i = 0;
- switch (elementType.representation) {
+ switch (elementType.rep) {
case PRIMITIVE_DOUBLE:
final double[] doubles = new double[list.size()];
for (double v : (List<Double>) list) {
@@ -118,7 +118,7 @@ public class ArrayImpl implements Array {
// fall through
}
final Object[] objects = list.toArray();
- switch (elementType.type) {
+ switch (elementType.id) {
case Types.ARRAY:
final ColumnMetaData.ArrayType arrayType =
(ColumnMetaData.ArrayType) elementType;
[8/9] incubator-calcite git commit: [CALCITE-592] Upgrade to Guava
14.0.1
Posted by jh...@apache.org.
[CALCITE-592] Upgrade to Guava 14.0.1
Project: http://git-wip-us.apache.org/repos/asf/incubator-calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-calcite/commit/0fe2637d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-calcite/tree/0fe2637d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-calcite/diff/0fe2637d
Branch: refs/heads/master
Commit: 0fe2637d66d3c263d507fc2ef98366238707dfea
Parents: 76a0665
Author: Julian Hyde <jh...@apache.org>
Authored: Mon Mar 23 02:18:37 2015 -0700
Committer: Julian Hyde <jh...@apache.org>
Committed: Mon Mar 23 02:18:37 2015 -0700
----------------------------------------------------------------------
core/pom.xml | 4 ++++
pom.xml | 9 +++++++--
2 files changed, 11 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/0fe2637d/core/pom.xml
----------------------------------------------------------------------
diff --git a/core/pom.xml b/core/pom.xml
index 34059f7..5533984 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -60,6 +60,10 @@ limitations under the License.
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
+ <groupId>com.google.code.findbugs</groupId>
+ <artifactId>jsr305</artifactId>
+ </dependency>
+ <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/0fe2637d/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 683f173..f870774 100644
--- a/pom.xml
+++ b/pom.xml
@@ -124,11 +124,16 @@ limitations under the License.
<version>2.1.1</version>
</dependency>
<dependency>
+ <groupId>com.google.code.findbugs</groupId>
+ <artifactId>jsr305</artifactId>
+ <version>1.3.9</version>
+ </dependency>
+ <dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
- <!-- We support versions as old as 11.0.2 (the version used by Hadoop)
+ <!-- We support versions as old as 14.0.1 (the version used by Hive)
but prefer more recent versions. -->
- <version>11.0.2</version>
+ <version>14.0.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
[5/9] incubator-calcite git commit: [CALCITE-630] Flesh out
AvaticaParameter#setObject (Nick Dimiduk)
Posted by jh...@apache.org.
[CALCITE-630] Flesh out AvaticaParameter#setObject (Nick Dimiduk)
Close apache/incubator-calcite#62
Project: http://git-wip-us.apache.org/repos/asf/incubator-calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-calcite/commit/8b9a5776
Tree: http://git-wip-us.apache.org/repos/asf/incubator-calcite/tree/8b9a5776
Diff: http://git-wip-us.apache.org/repos/asf/incubator-calcite/diff/8b9a5776
Branch: refs/heads/master
Commit: 8b9a57768fdd429b849fc1add1057a8b6399e15e
Parents: fe13dd3
Author: Julian Hyde <jh...@apache.org>
Authored: Sun Mar 22 23:00:53 2015 -0700
Committer: Julian Hyde <jh...@apache.org>
Committed: Mon Mar 23 01:45:01 2015 -0700
----------------------------------------------------------------------
.../calcite/avatica/AvaticaParameter.java | 228 +++++++++++++++++++
1 file changed, 228 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/8b9a5776/avatica/src/main/java/org/apache/calcite/avatica/AvaticaParameter.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/org/apache/calcite/avatica/AvaticaParameter.java b/avatica/src/main/java/org/apache/calcite/avatica/AvaticaParameter.java
index 03fa4dc..c2c0992 100644
--- a/avatica/src/main/java/org/apache/calcite/avatica/AvaticaParameter.java
+++ b/avatica/src/main/java/org/apache/calcite/avatica/AvaticaParameter.java
@@ -24,6 +24,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
+import java.math.BigInteger;
import java.net.URL;
import java.sql.Array;
import java.sql.Blob;
@@ -35,6 +36,7 @@ import java.sql.RowId;
import java.sql.SQLXML;
import java.sql.Time;
import java.sql.Timestamp;
+import java.sql.Types;
import java.util.Calendar;
/**
@@ -210,6 +212,99 @@ public class AvaticaParameter {
public void setObject(Object[] slots, int index, Object x,
int targetSqlType) {
+ if (x == null || Types.NULL == targetSqlType) {
+ setNull(slots, index, targetSqlType);
+ return;
+ }
+ switch (targetSqlType) {
+ case Types.CLOB:
+ case Types.DATALINK:
+ case Types.NCLOB:
+ case Types.OTHER:
+ case Types.REF:
+ case Types.SQLXML:
+ case Types.STRUCT:
+ throw notImplemented();
+ case Types.ARRAY:
+ setArray(slots, index, toArray(x));
+ break;
+ case Types.BIGINT:
+ setLong(slots, index, toLong(x));
+ break;
+ case Types.BINARY:
+ case Types.LONGVARBINARY:
+ case Types.VARBINARY:
+ setBytes(slots, index, toBytes(x));
+ break;
+ case Types.BIT:
+ case Types.BOOLEAN:
+ setBoolean(slots, index, toBoolean(x));
+ break;
+ case Types.BLOB:
+ if (x instanceof Blob) {
+ setBlob(slots, index, (Blob) x);
+ break;
+ } else if (x instanceof InputStream) {
+ setBlob(slots, index, (InputStream) x);
+ }
+ throw unsupportedCast(x.getClass(), Blob.class);
+ case Types.CHAR:
+ case Types.NCHAR:
+ String s = toString(x);
+ if (s.length() == 1) {
+ setChar(slots, index, s.charAt(0));
+ break;
+ }
+ throw unsupportedCast(x.getClass(), Character.TYPE);
+ case Types.DATE:
+ setDate(slots, index, toDate(x));
+ break;
+ case Types.DECIMAL:
+ case Types.NUMERIC:
+ setBigDecimal(slots, index, toBigDecimal(x));
+ break;
+ case Types.DISTINCT:
+ throw notImplemented();
+ case Types.DOUBLE:
+ case Types.FLOAT:
+ setDouble(slots, index, toDouble(x));
+ break;
+ case Types.INTEGER:
+ setInt(slots, index, toInt(x));
+ break;
+ case Types.JAVA_OBJECT:
+ setObject(slots, index, x);
+ break;
+ case Types.LONGNVARCHAR:
+ case Types.LONGVARCHAR:
+ case Types.NVARCHAR:
+ case Types.VARCHAR:
+ setString(slots, index, toString(x));
+ break;
+ case Types.REAL:
+ setFloat(slots, index, toFloat(x));
+ break;
+ case Types.ROWID:
+ if (x instanceof RowId) {
+ setRowId(slots, index, (RowId) x);
+ break;
+ }
+ throw unsupportedCast(x.getClass(), RowId.class);
+ case Types.SMALLINT:
+ setShort(slots, index, toShort(x));
+ break;
+ case Types.TIME:
+ setTime(slots, index, toTime(x));
+ break;
+ case Types.TIMESTAMP:
+ setTimestamp(slots, index, toTimestamp(x));
+ break;
+ case Types.TINYINT:
+ setByte(slots, index, toByte(x));
+ break;
+ default:
+ throw notImplemented();
+ }
}
public void setObject(Object[] slots, int index, Object x) {
@@ -249,6 +344,139 @@ public class AvaticaParameter {
int scaleOrLength) {
}
+ private static RuntimeException unsupportedCast(Class<?> from, Class<?> to) {
+ return new UnsupportedOperationException("Cannot convert from "
+ + from.getCanonicalName() + " to " + to.getCanonicalName());
+ }
+
+ private static RuntimeException notImplemented() {
+ return new RuntimeException("not implemented");
+ }
+
+ private static Array toArray(Object x) {
+ if (x instanceof Array) {
+ return (Array) x;
+ }
+ throw unsupportedCast(x.getClass(), Array.class);
+ }
+
+ private static BigDecimal toBigDecimal(Object x) {
+ if (x instanceof BigDecimal) {
+ return (BigDecimal) x;
+ } else if (x instanceof BigInteger) {
+ return new BigDecimal((BigInteger) x);
+ } else if (x instanceof Number) {
+ return new BigDecimal(x.toString());
+ } else if (x instanceof String) {
+ return new BigDecimal((String) x);
+ }
+ throw unsupportedCast(x.getClass(), BigDecimal.class);
+ }
+
+ private static boolean toBoolean(Object x) {
+ if (x instanceof Boolean) {
+ return (Boolean) x;
+ } else if (x instanceof Number) {
+ return ((Number) x).intValue() != 0;
+ } else if (x instanceof String) {
+ String s = (String) x;
+ if (s.equalsIgnoreCase("true") || s.equalsIgnoreCase("yes")) {
+ return true;
+ } else if (s.equalsIgnoreCase("false") || s.equalsIgnoreCase("no")) {
+ return false;
+ }
+ }
+ throw unsupportedCast(x.getClass(), Boolean.TYPE);
+ }
+
+ private static byte toByte(Object x) {
+ if (x instanceof Number) {
+ return ((Number) x).byteValue();
+ } else if (x instanceof String) {
+ return Byte.parseByte((String) x);
+ } else {
+ throw unsupportedCast(x.getClass(), Byte.TYPE);
+ }
+ }
+
+ private static byte[] toBytes(Object x) {
+ if (x instanceof byte[]) {
+ return (byte[]) x;
+ }
+ throw unsupportedCast(x.getClass(), byte[].class);
+ }
+
+ private static Date toDate(Object x) {
+ return new Date(toLong(x));
+ }
+
+ private static double toDouble(Object x) {
+ if (x instanceof Number) {
+ return ((Number) x).doubleValue();
+ } else if (x instanceof String) {
+ return Double.parseDouble((String) x);
+ } else {
+ throw unsupportedCast(x.getClass(), Double.TYPE);
+ }
+ }
+
+ private static float toFloat(Object x) {
+ if (x instanceof Number) {
+ return ((Number) x).floatValue();
+ } else if (x instanceof String) {
+ return Float.parseFloat((String) x);
+ } else {
+ throw unsupportedCast(x.getClass(), Float.TYPE);
+ }
+ }
+
+ private static int toInt(Object x) {
+ if (x instanceof Number) {
+ return ((Number) x).intValue();
+ } else if (x instanceof String) {
+ return Integer.parseInt((String) x);
+ } else {
+ throw unsupportedCast(x.getClass(), Integer.TYPE);
+ }
+ }
+
+ private static long toLong(Object x) {
+ if (x instanceof Number) {
+ return ((Number) x).longValue();
+ } else if (x instanceof String) {
+ return Long.parseLong((String) x);
+ } else {
+ throw unsupportedCast(x.getClass(), Long.TYPE);
+ }
+ }
+
+ private static short toShort(Object x) {
+ if (x instanceof Number) {
+ return ((Number) x).shortValue();
+ } else if (x instanceof String) {
+ return Short.parseShort((String) x);
+ } else {
+ throw unsupportedCast(x.getClass(), Short.TYPE);
+ }
+ }
+
+ private static String toString(Object x) {
+ if (x instanceof String) {
+ return (String) x;
+ } else if (x instanceof Character) {
+ return x.toString();
+ }
+ throw unsupportedCast(x.getClass(), String.class);
+ }
+
+ private static Time toTime(Object x) {
+ return new Time(toLong(x));
+ }
+
+ private static Timestamp toTimestamp(Object x) {
+ return new Timestamp(toLong(x));
+ }
+
/** Singleton value to denote parameters that have been set to null (as
* opposed to not set).
*