You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by el...@apache.org on 2016/03/07 19:28:22 UTC
[44/59] [partial] calcite git commit: [CALCITE-1078] Detach avatica
from the core calcite Maven project
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaResultSet.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaResultSet.java b/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaResultSet.java
new file mode 100644
index 0000000..478723f
--- /dev/null
+++ b/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaResultSet.java
@@ -0,0 +1,1046 @@
+/*
+ * 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 org.apache.calcite.avatica.remote.TypedValue;
+import org.apache.calcite.avatica.util.ArrayImpl;
+import org.apache.calcite.avatica.util.Cursor;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URL;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Date;
+import java.sql.NClob;
+import java.sql.Ref;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.RowId;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.SQLXML;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+import java.util.List;
+import java.util.Map;
+import java.util.TimeZone;
+
+/**
+ * Implementation of {@link java.sql.ResultSet}
+ * for the Avatica engine.
+ */
+public class AvaticaResultSet implements ResultSet, ArrayImpl.Factory {
+ protected final AvaticaStatement statement;
+ protected final QueryState state;
+ protected final Meta.Signature signature;
+ protected final Meta.Frame firstFrame;
+ protected final List<ColumnMetaData> columnMetaDataList;
+ protected final ResultSetMetaData resultSetMetaData;
+ protected final Calendar localCalendar;
+
+ protected Cursor cursor;
+ protected List<Cursor.Accessor> accessorList;
+ private int row;
+ private boolean afterLast;
+ private int fetchDirection;
+ private int fetchSize;
+ private int type;
+ private int concurrency;
+ private int holdability;
+ private boolean closed;
+ private long timeoutMillis;
+ private Cursor timeoutCursor;
+
+ public AvaticaResultSet(AvaticaStatement statement,
+ QueryState state,
+ Meta.Signature signature,
+ ResultSetMetaData resultSetMetaData,
+ TimeZone timeZone,
+ Meta.Frame firstFrame) {
+ this.statement = statement;
+ this.state = state;
+ this.signature = signature;
+ this.firstFrame = firstFrame;
+ this.columnMetaDataList = signature.columns;
+ this.type = statement.resultSetType;
+ this.concurrency = statement.resultSetConcurrency;
+ this.holdability = statement.resultSetHoldability;
+ this.fetchSize = statement.getFetchSize();
+ this.fetchDirection = statement.getFetchDirection();
+ this.resultSetMetaData = resultSetMetaData;
+ this.localCalendar = Calendar.getInstance(timeZone);
+ }
+
+ private int findColumn0(String columnLabel) throws SQLException {
+ for (ColumnMetaData columnMetaData : columnMetaDataList) {
+ // Per JDBC 3.0 specification, match is case-insensitive and if there is
+ // more than one column with a particular name, take the first.
+ if (columnMetaData.label.equalsIgnoreCase(columnLabel)) {
+ return columnMetaData.ordinal; // 0-based
+ }
+ }
+ throw new SQLException("column '" + columnLabel + "' not found");
+ }
+
+ /**
+ * Returns the accessor for column with a given index.
+ *
+ * @param columnIndex 1-based column index
+ * @return Accessor
+ * @throws SQLException if index is not valid
+ */
+ private Cursor.Accessor getAccessor(int columnIndex) throws SQLException {
+ try {
+ return accessorList.get(columnIndex - 1);
+ } catch (IndexOutOfBoundsException e) {
+ throw new SQLException("invalid column ordinal: " + columnIndex);
+ }
+ }
+
+ /**
+ * Returns the accessor for column with a given label.
+ *
+ * @param columnLabel Column label
+ * @return Accessor
+ * @throws SQLException if there is no column with that label
+ */
+ private Cursor.Accessor getAccessor(String columnLabel) throws SQLException {
+ return accessorList.get(findColumn0(columnLabel));
+ }
+
+ public void close() {
+ closed = true;
+ final Cursor cursor = this.cursor;
+ if (cursor != null) {
+ this.cursor = null;
+ cursor.close();
+ }
+ statement.onResultSetClose(this);
+ // TODO: for timeout, see IteratorResultSet.close
+/*
+ if (timeoutCursor != null) {
+ final long noTimeout = 0;
+ timeoutCursor.close(noTimeout);
+ timeoutCursor = null;
+ }
+*/
+ }
+
+ /**
+ * Sets the timeout that this result set will wait for a row from the
+ * underlying iterator.
+ *
+ * <p>Not a JDBC method.</p>
+ *
+ * @param timeoutMillis Timeout in milliseconds. Must be greater than zero.
+ */
+ void setTimeout(long timeoutMillis) {
+ assert timeoutMillis > 0;
+ assert this.timeoutMillis == 0;
+ this.timeoutMillis = timeoutMillis;
+ assert timeoutCursor == null;
+ timeoutCursor = cursor;
+
+ // TODO: for timeout, see IteratorResultSet.setTimeout
+/*
+ timeoutCursor = new TimeoutCursor(timeoutMillis);
+ timeoutCursor.start();
+*/
+ }
+
+ // not JDBC
+ protected void cancel() {
+ throw new UnsupportedOperationException(); // TODO:
+ }
+
+ /**
+ * Executes this result set. (Not a JDBC method.)
+ *
+ * <p>Note that execute cannot occur in the constructor, because the
+ * constructor occurs while the statement is locked, to make sure that
+ * execute/cancel don't happen at the same time.</p>
+ *
+ * @see org.apache.calcite.avatica.AvaticaConnection.Trojan#execute(AvaticaResultSet)
+ *
+ * @throws SQLException if execute fails for some reason.
+ */
+ protected AvaticaResultSet execute() throws SQLException {
+ final List<TypedValue> parameterValues = statement.getBoundParameterValues();
+ final Iterable<Object> iterable1 =
+ statement.connection.meta.createIterable(statement.handle, state, signature,
+ parameterValues, firstFrame);
+ this.cursor = MetaImpl.createCursor(signature.cursorFactory, iterable1);
+ this.accessorList =
+ cursor.createAccessors(columnMetaDataList, localCalendar, this);
+ this.row = -1;
+ this.afterLast = false;
+ return this;
+ }
+
+ protected AvaticaResultSet execute2(Cursor cursor,
+ List<ColumnMetaData> columnMetaDataList) {
+ this.cursor = cursor;
+ this.accessorList =
+ cursor.createAccessors(columnMetaDataList, localCalendar, this);
+ this.row = -1;
+ this.afterLast = false;
+ return this;
+ }
+
+ public ResultSet create(ColumnMetaData.AvaticaType elementType,
+ Iterable<Object> iterable) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean next() throws SQLException {
+ // TODO: for timeout, see IteratorResultSet.next
+ if (isClosed()) {
+ throw new SQLException("next() called on closed cursor");
+ }
+ if (cursor.next()) {
+ ++row;
+ return true;
+ } else {
+ afterLast = true;
+ return false;
+ }
+ }
+
+ public int findColumn(String columnLabel) throws SQLException {
+ return findColumn0(columnLabel) + 1;
+ }
+
+ public boolean wasNull() throws SQLException {
+ return cursor.wasNull();
+ }
+
+ public String getString(int columnIndex) throws SQLException {
+ return getAccessor(columnIndex).getString();
+ }
+
+ public boolean getBoolean(int columnIndex) throws SQLException {
+ return getAccessor(columnIndex).getBoolean();
+ }
+
+ public byte getByte(int columnIndex) throws SQLException {
+ return getAccessor(columnIndex).getByte();
+ }
+
+ public short getShort(int columnIndex) throws SQLException {
+ return getAccessor(columnIndex).getShort();
+ }
+
+ public int getInt(int columnIndex) throws SQLException {
+ return getAccessor(columnIndex).getInt();
+ }
+
+ public long getLong(int columnIndex) throws SQLException {
+ return getAccessor(columnIndex).getLong();
+ }
+
+ public float getFloat(int columnIndex) throws SQLException {
+ return getAccessor(columnIndex).getFloat();
+ }
+
+ public double getDouble(int columnIndex) throws SQLException {
+ return getAccessor(columnIndex).getDouble();
+ }
+
+ public BigDecimal getBigDecimal(
+ int columnIndex, int scale) throws SQLException {
+ return getAccessor(columnIndex).getBigDecimal(scale);
+ }
+
+ public byte[] getBytes(int columnIndex) throws SQLException {
+ return getAccessor(columnIndex).getBytes();
+ }
+
+ public Date getDate(int columnIndex) throws SQLException {
+ return getAccessor(columnIndex).getDate(localCalendar);
+ }
+
+ public Time getTime(int columnIndex) throws SQLException {
+ return getAccessor(columnIndex).getTime(localCalendar);
+ }
+
+ public Timestamp getTimestamp(int columnIndex) throws SQLException {
+ return getAccessor(columnIndex).getTimestamp(localCalendar);
+ }
+
+ public InputStream getAsciiStream(int columnIndex) throws SQLException {
+ return getAccessor(columnIndex).getAsciiStream();
+ }
+
+ public InputStream getUnicodeStream(int columnIndex) throws SQLException {
+ return getAccessor(columnIndex).getUnicodeStream();
+ }
+
+ public InputStream getBinaryStream(int columnIndex) throws SQLException {
+ return getAccessor(columnIndex).getBinaryStream();
+ }
+
+ public String getString(String columnLabel) throws SQLException {
+ return getAccessor(columnLabel).getString();
+ }
+
+ public boolean getBoolean(String columnLabel) throws SQLException {
+ return getAccessor(columnLabel).getBoolean();
+ }
+
+ public byte getByte(String columnLabel) throws SQLException {
+ return getAccessor(columnLabel).getByte();
+ }
+
+ public short getShort(String columnLabel) throws SQLException {
+ return getAccessor(columnLabel).getShort();
+ }
+
+ public int getInt(String columnLabel) throws SQLException {
+ return getAccessor(columnLabel).getInt();
+ }
+
+ public long getLong(String columnLabel) throws SQLException {
+ return getAccessor(columnLabel).getLong();
+ }
+
+ public float getFloat(String columnLabel) throws SQLException {
+ return getAccessor(columnLabel).getFloat();
+ }
+
+ public double getDouble(String columnLabel) throws SQLException {
+ return getAccessor(columnLabel).getDouble();
+ }
+
+ public BigDecimal getBigDecimal(
+ String columnLabel, int scale) throws SQLException {
+ return getAccessor(columnLabel).getBigDecimal(scale);
+ }
+
+ public byte[] getBytes(String columnLabel) throws SQLException {
+ return getAccessor(columnLabel).getBytes();
+ }
+
+ public Date getDate(String columnLabel) throws SQLException {
+ return getAccessor(columnLabel).getDate(localCalendar);
+ }
+
+ public Time getTime(String columnLabel) throws SQLException {
+ return getAccessor(columnLabel).getTime(localCalendar);
+ }
+
+ public Timestamp getTimestamp(String columnLabel) throws SQLException {
+ return getAccessor(columnLabel).getTimestamp(localCalendar);
+ }
+
+ public InputStream getAsciiStream(String columnLabel) throws SQLException {
+ return getAccessor(columnLabel).getAsciiStream();
+ }
+
+ public InputStream getUnicodeStream(String columnLabel) throws SQLException {
+ return getAccessor(columnLabel).getUnicodeStream();
+ }
+
+ public InputStream getBinaryStream(String columnLabel) throws SQLException {
+ return getAccessor(columnLabel).getBinaryStream();
+ }
+
+ public SQLWarning getWarnings() throws SQLException {
+ return null; // no warnings, since warnings are not supported
+ }
+
+ public void clearWarnings() throws SQLException {
+ // no-op since warnings are not supported
+ }
+
+ public String getCursorName() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public ResultSetMetaData getMetaData() throws SQLException {
+ return resultSetMetaData;
+ }
+
+ public Object getObject(int columnIndex) throws SQLException {
+ final Cursor.Accessor accessor = getAccessor(columnIndex);
+ final ColumnMetaData metaData = columnMetaDataList.get(columnIndex - 1);
+ return AvaticaSite.get(accessor, metaData.type.id, localCalendar);
+ }
+
+ public Object getObject(String columnLabel) throws SQLException {
+ return getAccessor(columnLabel).getObject();
+ }
+
+ public Reader getCharacterStream(int columnIndex) throws SQLException {
+ return getAccessor(columnIndex).getCharacterStream();
+ }
+
+ public Reader getCharacterStream(String columnLabel) throws SQLException {
+ return getAccessor(columnLabel).getCharacterStream();
+ }
+
+ public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
+ return getAccessor(columnIndex).getBigDecimal();
+ }
+
+ public BigDecimal getBigDecimal(String columnLabel) throws SQLException {
+ return getAccessor(columnLabel).getBigDecimal();
+ }
+
+ public boolean isBeforeFirst() throws SQLException {
+ return row < 0;
+ }
+
+ public boolean isAfterLast() throws SQLException {
+ return afterLast;
+ }
+
+ public boolean isFirst() throws SQLException {
+ return row == 0;
+ }
+
+ public boolean isLast() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void beforeFirst() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void afterLast() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean first() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean last() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public int getRow() throws SQLException {
+ return row;
+ }
+
+ public boolean absolute(int row) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean relative(int rows) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean previous() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setFetchDirection(int direction) throws SQLException {
+ this.fetchDirection = direction;
+ }
+
+ public int getFetchDirection() throws SQLException {
+ return fetchDirection;
+ }
+
+ public void setFetchSize(int fetchSize) throws SQLException {
+ this.fetchSize = fetchSize;
+ }
+
+ public int getFetchSize() throws SQLException {
+ return fetchSize;
+ }
+
+ public int getType() throws SQLException {
+ return type;
+ }
+
+ public int getConcurrency() throws SQLException {
+ return concurrency;
+ }
+
+ public boolean rowUpdated() throws SQLException {
+ return false;
+ }
+
+ public boolean rowInserted() throws SQLException {
+ return false;
+ }
+
+ public boolean rowDeleted() throws SQLException {
+ return false;
+ }
+
+ public void updateNull(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateBoolean(int columnIndex, boolean x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateByte(int columnIndex, byte x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateShort(int columnIndex, short x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateInt(int columnIndex, int x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateLong(int columnIndex, long x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateFloat(int columnIndex, float x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateDouble(int columnIndex, double x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateBigDecimal(
+ int columnIndex, BigDecimal x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateString(int columnIndex, String x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateBytes(int columnIndex, byte[] x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateDate(int columnIndex, Date x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateTime(int columnIndex, Time x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateTimestamp(
+ int columnIndex, Timestamp x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateAsciiStream(
+ int columnIndex, InputStream x, int length) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateBinaryStream(
+ int columnIndex, InputStream x, int length) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateCharacterStream(
+ int columnIndex, Reader x, int length) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateObject(
+ int columnIndex, Object x, int scaleOrLength) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateObject(int columnIndex, Object x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateNull(String columnLabel) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateBoolean(
+ String columnLabel, boolean x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateByte(String columnLabel, byte x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateShort(String columnLabel, short x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateInt(String columnLabel, int x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateLong(String columnLabel, long x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateFloat(String columnLabel, float x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateDouble(String columnLabel, double x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateBigDecimal(
+ String columnLabel, BigDecimal x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateString(String columnLabel, String x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateBytes(String columnLabel, byte[] x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateDate(String columnLabel, Date x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateTime(String columnLabel, Time x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateTimestamp(
+ String columnLabel, Timestamp x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateAsciiStream(
+ String columnLabel, InputStream x, int length) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateBinaryStream(
+ String columnLabel, InputStream x, int length) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateCharacterStream(
+ String columnLabel, Reader reader, int length) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateObject(
+ String columnLabel, Object x, int scaleOrLength) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateObject(String columnLabel, Object x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void insertRow() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateRow() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void deleteRow() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void refreshRow() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void cancelRowUpdates() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void moveToInsertRow() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void moveToCurrentRow() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public AvaticaStatement getStatement() {
+ return statement;
+ }
+
+ public Object getObject(
+ int columnIndex, Map<String, Class<?>> map) throws SQLException {
+ return getAccessor(columnIndex).getObject(map);
+ }
+
+ public Ref getRef(int columnIndex) throws SQLException {
+ return getAccessor(columnIndex).getRef();
+ }
+
+ public Blob getBlob(int columnIndex) throws SQLException {
+ return getAccessor(columnIndex).getBlob();
+ }
+
+ public Clob getClob(int columnIndex) throws SQLException {
+ return getAccessor(columnIndex).getClob();
+ }
+
+ public Array getArray(int columnIndex) throws SQLException {
+ return getAccessor(columnIndex).getArray();
+ }
+
+ public Object getObject(
+ String columnLabel, Map<String, Class<?>> map) throws SQLException {
+ return getAccessor(columnLabel).getObject(map);
+ }
+
+ public Ref getRef(String columnLabel) throws SQLException {
+ return getAccessor(columnLabel).getRef();
+ }
+
+ public Blob getBlob(String columnLabel) throws SQLException {
+ return getAccessor(columnLabel).getBlob();
+ }
+
+ public Clob getClob(String columnLabel) throws SQLException {
+ return getAccessor(columnLabel).getClob();
+ }
+
+ public Array getArray(String columnLabel) throws SQLException {
+ return getAccessor(columnLabel).getArray();
+ }
+
+ public Date getDate(int columnIndex, Calendar cal) throws SQLException {
+ return getAccessor(columnIndex).getDate(cal);
+ }
+
+ public Date getDate(String columnLabel, Calendar cal) throws SQLException {
+ return getAccessor(columnLabel).getDate(cal);
+ }
+
+ public Time getTime(int columnIndex, Calendar cal) throws SQLException {
+ return getAccessor(columnIndex).getTime(cal);
+ }
+
+ public Time getTime(String columnLabel, Calendar cal) throws SQLException {
+ return getAccessor(columnLabel).getTime(cal);
+ }
+
+ public Timestamp getTimestamp(
+ int columnIndex, Calendar cal) throws SQLException {
+ return getAccessor(columnIndex).getTimestamp(cal);
+ }
+
+ public Timestamp getTimestamp(
+ String columnLabel, Calendar cal) throws SQLException {
+ return getAccessor(columnLabel).getTimestamp(cal);
+ }
+
+ public URL getURL(int columnIndex) throws SQLException {
+ return getAccessor(columnIndex).getURL();
+ }
+
+ public URL getURL(String columnLabel) throws SQLException {
+ return getAccessor(columnLabel).getURL();
+ }
+
+ public void updateRef(int columnIndex, Ref x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateRef(String columnLabel, Ref x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateBlob(int columnIndex, Blob x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateBlob(String columnLabel, Blob x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateClob(int columnIndex, Clob x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateClob(String columnLabel, Clob x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateArray(int columnIndex, Array x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateArray(String columnLabel, Array x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public RowId getRowId(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public RowId getRowId(String columnLabel) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateRowId(int columnIndex, RowId x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateRowId(String columnLabel, RowId x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public int getHoldability() throws SQLException {
+ return holdability;
+ }
+
+ public boolean isClosed() throws SQLException {
+ return closed;
+ }
+
+ public void updateNString(
+ int columnIndex, String nString) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateNString(
+ String columnLabel, String nString) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateNClob(int columnIndex, NClob nClob) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateNClob(
+ String columnLabel, NClob nClob) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public NClob getNClob(int columnIndex) throws SQLException {
+ return getAccessor(columnIndex).getNClob();
+ }
+
+ public NClob getNClob(String columnLabel) throws SQLException {
+ return getAccessor(columnLabel).getNClob();
+ }
+
+ public SQLXML getSQLXML(int columnIndex) throws SQLException {
+ return getAccessor(columnIndex).getSQLXML();
+ }
+
+ public SQLXML getSQLXML(String columnLabel) throws SQLException {
+ return getAccessor(columnLabel).getSQLXML();
+ }
+
+ public void updateSQLXML(
+ int columnIndex, SQLXML xmlObject) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateSQLXML(
+ String columnLabel, SQLXML xmlObject) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public String getNString(int columnIndex) throws SQLException {
+ return getAccessor(columnIndex).getNString();
+ }
+
+ public String getNString(String columnLabel) throws SQLException {
+ return getAccessor(columnLabel).getNString();
+ }
+
+ public Reader getNCharacterStream(int columnIndex) throws SQLException {
+ return getAccessor(columnIndex).getNCharacterStream();
+ }
+
+ public Reader getNCharacterStream(String columnLabel) throws SQLException {
+ return getAccessor(columnLabel).getNCharacterStream();
+ }
+
+ public void updateNCharacterStream(
+ int columnIndex, Reader x, long length) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateNCharacterStream(
+ String columnLabel, Reader reader, long length) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateAsciiStream(
+ int columnIndex, InputStream x, long length) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateBinaryStream(
+ int columnIndex, InputStream x, long length) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateCharacterStream(
+ int columnIndex, Reader x, long length) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateAsciiStream(
+ String columnLabel, InputStream x, long length) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateBinaryStream(
+ String columnLabel, InputStream x, long length) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateCharacterStream(
+ String columnLabel, Reader reader, long length) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateBlob(
+ int columnIndex,
+ InputStream inputStream,
+ long length) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateBlob(
+ String columnLabel,
+ InputStream inputStream,
+ long length) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateClob(
+ int columnIndex, Reader reader, long length) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateClob(
+ String columnLabel, Reader reader, long length) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateNClob(
+ int columnIndex, Reader reader, long length) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateNClob(
+ String columnLabel, Reader reader, long length) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateNCharacterStream(
+ int columnIndex, Reader x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateNCharacterStream(
+ String columnLabel, Reader reader) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateAsciiStream(
+ int columnIndex, InputStream x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateBinaryStream(
+ int columnIndex, InputStream x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateCharacterStream(
+ int columnIndex, Reader x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateAsciiStream(
+ String columnLabel, InputStream x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateBinaryStream(
+ String columnLabel, InputStream x) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateCharacterStream(
+ String columnLabel, Reader reader) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateBlob(
+ int columnIndex, InputStream inputStream) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateBlob(
+ String columnLabel, InputStream inputStream) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateClob(int columnIndex, Reader reader) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateClob(
+ String columnLabel, Reader reader) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateNClob(
+ int columnIndex, Reader reader) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void updateNClob(
+ String columnLabel, Reader reader) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public <T> T getObject(int columnIndex, Class<T> type) throws SQLException {
+ return getAccessor(columnIndex).getObject(type);
+ }
+
+ public <T> T getObject(
+ String columnLabel, Class<T> type) throws SQLException {
+ return getAccessor(columnLabel).getObject(type);
+ }
+
+ public <T> T unwrap(Class<T> iface) throws SQLException {
+ if (iface.isInstance(this)) {
+ return iface.cast(this);
+ }
+ throw statement.connection.helper.createException(
+ "does not implement '" + iface + "'");
+ }
+
+ public boolean isWrapperFor(Class<?> iface) throws SQLException {
+ return iface.isInstance(this);
+ }
+}
+
+// End AvaticaResultSet.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaResultSetMetaData.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaResultSetMetaData.java b/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaResultSetMetaData.java
new file mode 100644
index 0000000..b4e8892
--- /dev/null
+++ b/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaResultSetMetaData.java
@@ -0,0 +1,145 @@
+/*
+ * 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.sql.ResultSetMetaData;
+import java.sql.SQLException;
+
+/**
+ * Implementation of {@link ResultSetMetaData}
+ * for the Avatica framework.
+ */
+public class AvaticaResultSetMetaData implements ResultSetMetaData {
+ final AvaticaStatement statement;
+ final Object query; // reserved for future use
+ final Meta.Signature signature;
+
+ public AvaticaResultSetMetaData(
+ AvaticaStatement statement,
+ Object query,
+ Meta.Signature signature) {
+ this.statement = statement;
+ this.query = query;
+ this.signature = signature;
+ }
+
+ private ColumnMetaData getColumnMetaData(int column) {
+ return signature.columns.get(column - 1);
+ }
+
+ // implement ResultSetMetaData
+
+ public int getColumnCount() throws SQLException {
+ return signature.columns.size();
+ }
+
+ public boolean isAutoIncrement(int column) throws SQLException {
+ return getColumnMetaData(column).autoIncrement;
+ }
+
+ public boolean isCaseSensitive(int column) throws SQLException {
+ return getColumnMetaData(column).caseSensitive;
+ }
+
+ public boolean isSearchable(int column) throws SQLException {
+ return getColumnMetaData(column).searchable;
+ }
+
+ public boolean isCurrency(int column) throws SQLException {
+ return getColumnMetaData(column).currency;
+ }
+
+ public int isNullable(int column) throws SQLException {
+ return getColumnMetaData(column).nullable;
+ }
+
+ public boolean isSigned(int column) throws SQLException {
+ return getColumnMetaData(column).signed;
+ }
+
+ public int getColumnDisplaySize(int column) throws SQLException {
+ return getColumnMetaData(column).displaySize;
+ }
+
+ public String getColumnLabel(int column) throws SQLException {
+ return getColumnMetaData(column).label;
+ }
+
+ public String getColumnName(int column) throws SQLException {
+ return getColumnMetaData(column).columnName;
+ }
+
+ public String getSchemaName(int column) throws SQLException {
+ return getColumnMetaData(column).schemaName;
+ }
+
+ public int getPrecision(int column) throws SQLException {
+ return getColumnMetaData(column).precision;
+ }
+
+ public int getScale(int column) throws SQLException {
+ return getColumnMetaData(column).scale;
+ }
+
+ public String getTableName(int column) throws SQLException {
+ return getColumnMetaData(column).tableName;
+ }
+
+ public String getCatalogName(int column) throws SQLException {
+ return getColumnMetaData(column).catalogName;
+ }
+
+ public int getColumnType(int column) throws SQLException {
+ return getColumnMetaData(column).type.id;
+ }
+
+ public String getColumnTypeName(int column) throws SQLException {
+ return getColumnMetaData(column).type.name;
+ }
+
+ public boolean isReadOnly(int column) throws SQLException {
+ return getColumnMetaData(column).readOnly;
+ }
+
+ public boolean isWritable(int column) throws SQLException {
+ return getColumnMetaData(column).writable;
+ }
+
+ public boolean isDefinitelyWritable(int column) throws SQLException {
+ return getColumnMetaData(column).definitelyWritable;
+ }
+
+ public String getColumnClassName(int column) throws SQLException {
+ return getColumnMetaData(column).columnClassName;
+ }
+
+ // implement Wrapper
+
+ public <T> T unwrap(Class<T> iface) throws SQLException {
+ if (iface.isInstance(this)) {
+ return iface.cast(this);
+ }
+ throw statement.connection.helper.createException(
+ "does not implement '" + iface + "'");
+ }
+
+ public boolean isWrapperFor(Class<?> iface) throws SQLException {
+ return iface.isInstance(this);
+ }
+}
+
+// End AvaticaResultSetMetaData.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaSeverity.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaSeverity.java b/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaSeverity.java
new file mode 100644
index 0000000..675c8af
--- /dev/null
+++ b/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaSeverity.java
@@ -0,0 +1,90 @@
+/*
+ * 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 org.apache.calcite.avatica.proto.Common;
+
+import java.util.Objects;
+
+/**
+ * An enumeration that denotes the severity of a given unexpected state.
+ */
+public enum AvaticaSeverity {
+ /**
+ * The severity of the outcome of some unexpected state is unknown.
+ */
+ UNKNOWN(0),
+
+ /**
+ * The system has been left in an unrecoverable state as a result of an operation.
+ */
+ FATAL(1),
+
+ /**
+ * The result of an action resulted in an error which the current operation cannot recover
+ * from. Clients can attempt to execute the operation again.
+ */
+ ERROR(2),
+
+ /**
+ * The operation completed successfully but a message was generated to warn the client about
+ * some unexpected state or action.
+ */
+ WARNING(3);
+
+ private final int value;
+
+ AvaticaSeverity(int value) {
+ this.value = value;
+ }
+
+ public int getValue() {
+ return value;
+ }
+
+ public Common.Severity toProto() {
+ switch (this) {
+ case UNKNOWN:
+ return Common.Severity.UNKNOWN_SEVERITY;
+ case FATAL:
+ return Common.Severity.FATAL_SEVERITY;
+ case ERROR:
+ return Common.Severity.ERROR_SEVERITY;
+ case WARNING:
+ return Common.Severity.WARNING_SEVERITY;
+ default:
+ throw new RuntimeException("Unhandled Severity level: " + this);
+ }
+ }
+
+ public static AvaticaSeverity fromProto(Common.Severity proto) {
+ switch (Objects.requireNonNull(proto)) {
+ case UNKNOWN_SEVERITY:
+ return AvaticaSeverity.UNKNOWN;
+ case FATAL_SEVERITY:
+ return AvaticaSeverity.FATAL;
+ case ERROR_SEVERITY:
+ return AvaticaSeverity.ERROR;
+ case WARNING_SEVERITY:
+ return AvaticaSeverity.WARNING;
+ default:
+ throw new RuntimeException("Unhandled protobuf Severity level: " + proto);
+ }
+ }
+}
+
+// End AvaticaSeverity.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaSite.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaSite.java b/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaSite.java
new file mode 100644
index 0000000..7fd6947
--- /dev/null
+++ b/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaSite.java
@@ -0,0 +1,587 @@
+/*
+ * 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 org.apache.calcite.avatica.remote.TypedValue;
+import org.apache.calcite.avatica.util.Cursor;
+
+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;
+import java.sql.Clob;
+import java.sql.Date;
+import java.sql.NClob;
+import java.sql.Ref;
+import java.sql.RowId;
+import java.sql.SQLException;
+import java.sql.SQLXML;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.sql.Types;
+import java.util.Calendar;
+
+/**
+ * A location that a value can be written to or read from.
+ */
+public class AvaticaSite {
+ final AvaticaParameter parameter;
+
+ /** Calendar is not thread-safe. But calendar is only used from within one
+ * thread, and we have to trust that clients are not modifying calendars
+ * that they pass to us in a method such as
+ * {@link java.sql.PreparedStatement#setTime(int, Time, Calendar)}, so we do
+ * not need to synchronize access. */
+ final Calendar calendar;
+ private final int index;
+ final TypedValue[] slots;
+
+ /** Value that means the parameter has been set to null.
+ * If value is null, parameter has not been set. */
+ public static final Object DUMMY_VALUE = Dummy.INSTANCE;
+
+ public AvaticaSite(AvaticaParameter parameter, Calendar calendar, int index,
+ TypedValue[] slots) {
+ assert calendar != null;
+ assert parameter != null;
+ assert slots != null;
+ this.parameter = parameter;
+ this.calendar = calendar;
+ this.index = index;
+ this.slots = slots;
+ }
+
+ private TypedValue wrap(ColumnMetaData.Rep rep, Object o,
+ Calendar calendar) {
+ return TypedValue.ofJdbc(rep, o, calendar);
+ }
+
+ private TypedValue wrap(ColumnMetaData.Rep rep, Object o) {
+ return TypedValue.ofJdbc(rep, o, calendar);
+ }
+
+ public boolean isSet(int index) {
+ return slots[index] != null;
+ }
+
+ public void setByte(byte o) {
+ slots[index] = wrap(ColumnMetaData.Rep.BYTE, o);
+ }
+
+ public void setChar(char o) {
+ slots[index] = wrap(ColumnMetaData.Rep.CHARACTER, o);
+ }
+
+ public void setShort(short o) {
+ slots[index] = wrap(ColumnMetaData.Rep.SHORT, o);
+ }
+
+ public void setInt(int o) {
+ slots[index] = wrap(ColumnMetaData.Rep.INTEGER, o);
+ }
+
+ public void setLong(long o) {
+ slots[index] = wrap(ColumnMetaData.Rep.LONG, o);
+ }
+
+ public void setBoolean(boolean o) {
+ slots[index] = wrap(ColumnMetaData.Rep.BOOLEAN, o);
+ }
+
+ public void setRowId(RowId x) {
+ slots[index] = wrap(ColumnMetaData.Rep.OBJECT, x);
+ }
+
+ public void setNString(String o) {
+ slots[index] = wrap(ColumnMetaData.Rep.STRING, o);
+ }
+
+ public void setNCharacterStream(Reader value, long length) {
+ }
+
+ public void setNClob(NClob value) {
+ slots[index] = wrap(ColumnMetaData.Rep.OBJECT, value);
+ }
+
+ public void setClob(Reader reader, long length) {
+ }
+
+ public void setBlob(InputStream inputStream, long length) {
+ }
+
+ public void setNClob(Reader reader, long length) {
+ }
+
+ public void setSQLXML(SQLXML xmlObject) {
+ slots[index] = wrap(ColumnMetaData.Rep.OBJECT, xmlObject);
+ }
+
+ public void setAsciiStream(InputStream x, long length) {
+ }
+
+ public void setBinaryStream(InputStream x, long length) {
+ }
+
+ public void setCharacterStream(Reader reader, long length) {
+ }
+
+ public void setAsciiStream(InputStream x) {
+ }
+
+ public void setBinaryStream(InputStream x) {
+ }
+
+ public void setCharacterStream(Reader reader) {
+ }
+
+ public void setNCharacterStream(Reader value) {
+ }
+
+ public void setClob(Reader reader) {
+ }
+
+ public void setBlob(InputStream inputStream) {
+ }
+
+ public void setNClob(Reader reader) {
+ }
+
+ public void setUnicodeStream(InputStream x, int length) {
+ }
+
+ public void setFloat(float x) {
+ slots[index] = wrap(ColumnMetaData.Rep.FLOAT, x);
+ }
+
+ public void setDouble(double x) {
+ slots[index] = wrap(ColumnMetaData.Rep.DOUBLE, x);
+ }
+
+ public void setBigDecimal(BigDecimal x) {
+ slots[index] = wrap(ColumnMetaData.Rep.NUMBER, x);
+ }
+
+ public void setString(String x) {
+ slots[index] = wrap(ColumnMetaData.Rep.STRING, x);
+ }
+
+ public void setBytes(byte[] x) {
+ slots[index] = wrap(ColumnMetaData.Rep.BYTE_STRING, x);
+ }
+
+ public void setTimestamp(Timestamp x, Calendar calendar) {
+ slots[index] = wrap(ColumnMetaData.Rep.JAVA_SQL_TIMESTAMP, x, calendar);
+ }
+
+ public void setTime(Time x, Calendar calendar) {
+ slots[index] = wrap(ColumnMetaData.Rep.JAVA_SQL_TIME, x, calendar);
+ }
+
+ public void setDate(Date x, Calendar cal) {
+ slots[index] = wrap(ColumnMetaData.Rep.JAVA_SQL_DATE, x, calendar);
+ }
+
+ public void setObject(Object x, int targetSqlType) {
+ if (x == null || Types.NULL == targetSqlType) {
+ setNull(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(toArray(x));
+ break;
+ case Types.BIGINT:
+ setLong(toLong(x));
+ break;
+ case Types.BINARY:
+ case Types.LONGVARBINARY:
+ case Types.VARBINARY:
+ setBytes(toBytes(x));
+ break;
+ case Types.BIT:
+ case Types.BOOLEAN:
+ setBoolean(toBoolean(x));
+ break;
+ case Types.BLOB:
+ if (x instanceof Blob) {
+ setBlob((Blob) x);
+ break;
+ } else if (x instanceof InputStream) {
+ setBlob((InputStream) x);
+ }
+ throw unsupportedCast(x.getClass(), Blob.class);
+ case Types.DATE:
+ setDate(toDate(x), calendar);
+ break;
+ case Types.DECIMAL:
+ case Types.NUMERIC:
+ setBigDecimal(toBigDecimal(x));
+ break;
+ case Types.DISTINCT:
+ throw notImplemented();
+ case Types.DOUBLE:
+ case Types.FLOAT: // yes really; SQL FLOAT is up to 8 bytes
+ setDouble(toDouble(x));
+ break;
+ case Types.INTEGER:
+ setInt(toInt(x));
+ break;
+ case Types.JAVA_OBJECT:
+ setObject(x);
+ break;
+ case Types.LONGNVARCHAR:
+ case Types.LONGVARCHAR:
+ case Types.NVARCHAR:
+ case Types.VARCHAR:
+ case Types.CHAR:
+ case Types.NCHAR:
+ setString(toString(x));
+ break;
+ case Types.REAL:
+ setFloat(toFloat(x));
+ break;
+ case Types.ROWID:
+ if (x instanceof RowId) {
+ setRowId((RowId) x);
+ break;
+ }
+ throw unsupportedCast(x.getClass(), RowId.class);
+ case Types.SMALLINT:
+ setShort(toShort(x));
+ break;
+ case Types.TIME:
+ setTime(toTime(x), calendar);
+ break;
+ case Types.TIMESTAMP:
+ setTimestamp(toTimestamp(x), calendar);
+ break;
+ case Types.TINYINT:
+ setByte(toByte(x));
+ break;
+ default:
+ throw notImplemented();
+ }
+ }
+
+ /** Similar logic to {@link #setObject}. */
+ public static Object get(Cursor.Accessor accessor, int targetSqlType,
+ Calendar localCalendar) throws SQLException {
+ switch (targetSqlType) {
+ case Types.CLOB:
+ case Types.DATALINK:
+ case Types.NCLOB:
+ case Types.REF:
+ case Types.SQLXML:
+ case Types.STRUCT:
+ throw notImplemented();
+ case Types.ARRAY:
+ return accessor.getArray();
+ case Types.BIGINT:
+ final long aLong = accessor.getLong();
+ if (aLong == 0 && accessor.wasNull()) {
+ return null;
+ }
+ return aLong;
+ case Types.BINARY:
+ case Types.LONGVARBINARY:
+ case Types.VARBINARY:
+ return accessor.getBytes();
+ case Types.BIT:
+ case Types.BOOLEAN:
+ final boolean aBoolean = accessor.getBoolean();
+ if (!aBoolean && accessor.wasNull()) {
+ return null;
+ }
+ return aBoolean;
+ case Types.BLOB:
+ return accessor.getBlob();
+ case Types.DATE:
+ return accessor.getDate(localCalendar);
+ case Types.DECIMAL:
+ case Types.NUMERIC:
+ return accessor.getBigDecimal();
+ case Types.DISTINCT:
+ throw notImplemented();
+ case Types.DOUBLE:
+ case Types.FLOAT: // yes really; SQL FLOAT is up to 8 bytes
+ final double aDouble = accessor.getDouble();
+ if (aDouble == 0 && accessor.wasNull()) {
+ return null;
+ }
+ return aDouble;
+ case Types.INTEGER:
+ final int anInt = accessor.getInt();
+ if (anInt == 0 && accessor.wasNull()) {
+ return null;
+ }
+ return anInt;
+ case Types.JAVA_OBJECT:
+ case Types.OTHER:
+ return accessor.getObject();
+ case Types.LONGNVARCHAR:
+ case Types.LONGVARCHAR:
+ case Types.NVARCHAR:
+ case Types.VARCHAR:
+ case Types.CHAR:
+ case Types.NCHAR:
+ return accessor.getString();
+ case Types.REAL:
+ final float aFloat = accessor.getFloat();
+ if (aFloat == 0 && accessor.wasNull()) {
+ return null;
+ }
+ return aFloat;
+ case Types.ROWID:
+ throw notImplemented();
+ case Types.SMALLINT:
+ final short aShort = accessor.getShort();
+ if (aShort == 0 && accessor.wasNull()) {
+ return null;
+ }
+ return aShort;
+ case Types.TIME:
+ return accessor.getTime(localCalendar);
+ case Types.TIMESTAMP:
+ return accessor.getTimestamp(localCalendar);
+ case Types.TINYINT:
+ final byte aByte = accessor.getByte();
+ if (aByte == 0 && accessor.wasNull()) {
+ return null;
+ }
+ return aByte;
+ default:
+ throw notImplemented();
+ }
+ }
+
+ public void setObject(Object x) {
+ slots[index] = TypedValue.ofJdbc(x, calendar);
+ }
+
+ public void setNull(int sqlType) {
+ slots[index] = wrap(ColumnMetaData.Rep.OBJECT, null);
+ }
+
+ public void setRef(Ref x) {
+ }
+
+ public void setBlob(Blob x) {
+ }
+
+ public void setClob(Clob x) {
+ }
+
+ public void setArray(Array x) {
+ }
+
+ public void setNull(int sqlType, String typeName) {
+ }
+
+ public void setURL(URL x) {
+ }
+
+ public void setObject(Object x, int targetSqlType,
+ 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);
+ }
+
+ public 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) {
+ 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);
+ }
+ 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 Boolean) {
+ return (Boolean) x ? (byte) 1 : (byte) 0;
+ } 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;
+ }
+ 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 {
+ throw unsupportedCast(x.getClass(), Double.TYPE);
+ }
+ }
+
+ 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 {
+ throw unsupportedCast(x.getClass(), Float.TYPE);
+ }
+ }
+
+ 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 {
+ throw unsupportedCast(x.getClass(), Integer.TYPE);
+ }
+ }
+
+ 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 {
+ throw unsupportedCast(x.getClass(), Long.TYPE);
+ }
+ }
+
+ 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 {
+ throw unsupportedCast(x.getClass(), Short.TYPE);
+ }
+ }
+
+ private static String toString(Object x) {
+ if (x instanceof String) {
+ return (String) x;
+ } else if (x instanceof Character
+ || x instanceof Boolean) {
+ return x.toString();
+ }
+ throw unsupportedCast(x.getClass(), String.class);
+ }
+
+ /** Singleton value to denote parameters that have been set to null (as
+ * opposed to not set).
+ *
+ * <p>Not a valid value for a parameter.
+ *
+ * <p>As an enum, it is serializable by Jackson. */
+ private enum Dummy {
+ INSTANCE
+ }
+}
+
+// End AvaticaSite.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaSqlException.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaSqlException.java b/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaSqlException.java
new file mode 100644
index 0000000..9408a7b
--- /dev/null
+++ b/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaSqlException.java
@@ -0,0 +1,138 @@
+/*
+ * 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.io.PrintStream;
+import java.io.PrintWriter;
+import java.sql.SQLException;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A client-facing {@link SQLException} which encapsulates errors from the remote Avatica server.
+ */
+public class AvaticaSqlException extends SQLException {
+
+ private static final long serialVersionUID = 1L;
+
+ private final String errorMessage;
+ private final List<String> stackTraces;
+ private final String remoteServer;
+
+ /**
+ * Construct the Exception with information from the server.
+ *
+ * @param errorMessage A human-readable error message.
+ * @param errorCode An integer corresponding to a known error.
+ * @param stackTraces Server-side stacktrace.
+ * @param remoteServer The host:port where the Avatica server is located
+ */
+ public AvaticaSqlException(String errorMessage, String sqlState, int errorCode,
+ List<String> stackTraces, String remoteServer) {
+ super("Error " + errorCode + " (" + sqlState + ") : " + errorMessage, sqlState, errorCode);
+ this.errorMessage = errorMessage;
+ this.stackTraces = Objects.requireNonNull(stackTraces);
+ this.remoteServer = remoteServer;
+ }
+
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ /**
+ * @return The stacktraces for exceptions thrown on the Avatica server.
+ */
+ public List<String> getStackTraces() {
+ return stackTraces;
+ }
+
+ /**
+ * @return The host:port for the remote Avatica server. May be null.
+ */
+ public String getRemoteServer() {
+ return remoteServer;
+ }
+
+ // printStackTrace() will get redirected to printStackTrace(PrintStream), don't need to override.
+
+ @Override public void printStackTrace(PrintStream stream) {
+ super.printStackTrace(stream);
+ stream.flush();
+ printServerStackTrace(new PrintStreamOrWriter(stream));
+ }
+
+ @Override public void printStackTrace(PrintWriter writer) {
+ super.printStackTrace(writer);
+ writer.flush();
+ printServerStackTrace(new PrintStreamOrWriter(writer));
+ }
+
+ void printServerStackTrace(PrintStreamOrWriter streamOrWriter) {
+ for (String serverStackTrace : this.stackTraces) {
+ streamOrWriter.println(serverStackTrace);
+ }
+ }
+
+ /**
+ * A class that encapsulates either a PrintStream or a PrintWriter.
+ */
+ private static class PrintStreamOrWriter {
+ /**
+ * Enumeration to differentiate between a PrintStream and a PrintWriter.
+ */
+ private enum Type {
+ STREAM,
+ WRITER
+ }
+
+ private PrintStream stream;
+ private PrintWriter writer;
+ private final Type type;
+
+ public PrintStreamOrWriter(PrintStream stream) {
+ this.stream = stream;
+ type = Type.STREAM;
+ }
+
+ public PrintStreamOrWriter(PrintWriter writer) {
+ this.writer = writer;
+ type = Type.WRITER;
+ }
+
+ /**
+ * Prints the given string to the the provided stream or writer.
+ *
+ * @param string The string to print
+ */
+ public void println(String string) {
+ switch (type) {
+ case STREAM:
+ stream.println(string);
+ stream.flush();
+ return;
+ case WRITER:
+ writer.println(string);
+ writer.flush();
+ return;
+ default:
+ throw new IllegalStateException();
+ }
+ }
+ }
+}
+
+// End AvaticaSqlException.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaStatement.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaStatement.java b/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaStatement.java
new file mode 100644
index 0000000..cfd1d45
--- /dev/null
+++ b/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaStatement.java
@@ -0,0 +1,527 @@
+/*
+ * 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 org.apache.calcite.avatica.remote.TypedValue;
+
+import java.sql.CallableStatement;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.Statement;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Implementation of {@link java.sql.Statement}
+ * for the Avatica engine.
+ */
+public abstract class AvaticaStatement
+ implements Statement {
+ /** The default value for {@link Statement#getFetchSize()}. */
+ public static final int DEFAULT_FETCH_SIZE = 100;
+
+ public final AvaticaConnection connection;
+ /** Statement id; unique within connection. */
+ public Meta.StatementHandle handle;
+ protected boolean closed;
+
+ /**
+ * Support for {@link #closeOnCompletion()} method.
+ */
+ protected boolean closeOnCompletion;
+
+ /**
+ * Current result set, or null if the statement is not executing anything.
+ * Any method which modifies this member must synchronize
+ * on the AvaticaStatement.
+ */
+ protected AvaticaResultSet openResultSet;
+
+ /** Current update count. Same lifecycle as {@link #openResultSet}. */
+ protected long updateCount;
+
+ private int queryTimeoutMillis;
+ final int resultSetType;
+ final int resultSetConcurrency;
+ final int resultSetHoldability;
+ private int fetchSize = DEFAULT_FETCH_SIZE;
+ private int fetchDirection;
+ protected long maxRowCount = 0;
+
+ private Meta.Signature signature;
+
+ protected void setSignature(Meta.Signature signature) {
+ this.signature = signature;
+ }
+
+ protected Meta.Signature getSignature() {
+ return signature;
+ }
+
+ public Meta.StatementType getStatementType() {
+ return signature.statementType;
+ }
+
+ /**
+ * Creates an AvaticaStatement.
+ *
+ * @param connection Connection
+ * @param h Statement handle
+ * @param resultSetType Result set type
+ * @param resultSetConcurrency Result set concurrency
+ * @param resultSetHoldability Result set holdability
+ */
+ protected AvaticaStatement(AvaticaConnection connection,
+ Meta.StatementHandle h, int resultSetType, int resultSetConcurrency,
+ int resultSetHoldability) {
+ this(connection, h, resultSetType, resultSetConcurrency, resultSetHoldability, null);
+ }
+
+ protected AvaticaStatement(AvaticaConnection connection,
+ Meta.StatementHandle h, int resultSetType, int resultSetConcurrency,
+ int resultSetHoldability, Meta.Signature signature) {
+ this.connection = Objects.requireNonNull(connection);
+ this.resultSetType = resultSetType;
+ this.resultSetConcurrency = resultSetConcurrency;
+ this.resultSetHoldability = resultSetHoldability;
+ this.signature = signature;
+ this.closed = false;
+ if (h == null) {
+ final Meta.ConnectionHandle ch = connection.handle;
+ h = connection.meta.createStatement(ch);
+ }
+ connection.statementMap.put(h.id, this);
+ this.handle = h;
+ }
+
+ /** Returns the identifier of the statement, unique within its connection. */
+ public int getId() {
+ return handle.id;
+ }
+
+ private void checkNotPreparedOrCallable(String s) throws SQLException {
+ if (this instanceof PreparedStatement
+ || this instanceof CallableStatement) {
+ throw connection.helper.createException("Cannot call " + s
+ + " on prepared or callable statement");
+ }
+ }
+
+ protected void executeInternal(String sql) throws SQLException {
+ // reset previous state before moving forward.
+ this.updateCount = -1;
+ try {
+ // In JDBC, maxRowCount = 0 means no limit; in prepare it means LIMIT 0
+ final long maxRowCount1 = maxRowCount <= 0 ? -1 : maxRowCount;
+ for (int i = 0; i < connection.maxRetriesPerExecute; i++) {
+ try {
+ Meta.ExecuteResult x =
+ connection.prepareAndExecuteInternal(this, sql, maxRowCount1);
+ return;
+ } catch (NoSuchStatementException e) {
+ resetStatement();
+ }
+ }
+ } catch (RuntimeException e) {
+ throw connection.helper.createException("Error while executing SQL \"" + sql + "\": "
+ + e.getMessage(), e);
+ }
+
+ throw new RuntimeException("Failed to successfully execute query after "
+ + connection.maxRetriesPerExecute + " attempts.");
+ }
+
+ protected void resetStatement() {
+ // Invalidate the old statement
+ connection.statementMap.remove(handle.id);
+ // Get a new one
+ final Meta.ConnectionHandle ch = new Meta.ConnectionHandle(connection.id);
+ Meta.StatementHandle h = connection.meta.createStatement(ch);
+ // Cache it in the connection
+ connection.statementMap.put(h.id, this);
+ // Update the local state and try again
+ this.handle = h;
+ }
+
+ /**
+ * Re-initialize the ResultSet on the server with the given state.
+ * @param state The ResultSet's state.
+ * @param offset Offset into the desired ResultSet
+ * @return True if the ResultSet has more results, false if there are no more results.
+ */
+ protected boolean syncResults(QueryState state, long offset) throws NoSuchStatementException {
+ return connection.meta.syncResults(handle, state, offset);
+ }
+
+ // implement Statement
+
+ public boolean execute(String sql) throws SQLException {
+ checkNotPreparedOrCallable("execute(String)");
+ executeInternal(sql);
+ // Result set is null for DML or DDL.
+ // Result set is closed if user cancelled the query.
+ return openResultSet != null && !openResultSet.isClosed();
+ }
+
+ public ResultSet executeQuery(String sql) throws SQLException {
+ checkNotPreparedOrCallable("executeQuery(String)");
+ try {
+ executeInternal(sql);
+ if (openResultSet == null) {
+ throw connection.helper.createException(
+ "Statement did not return a result set");
+ }
+ return openResultSet;
+ } catch (RuntimeException e) {
+ throw connection.helper.createException("Error while executing SQL \"" + sql + "\": "
+ + e.getMessage(), e);
+ }
+ }
+
+ public final int executeUpdate(String sql) throws SQLException {
+ return (int) executeLargeUpdate(sql);
+ }
+
+ public long executeLargeUpdate(String sql) throws SQLException {
+ checkNotPreparedOrCallable("executeUpdate(String)");
+ executeInternal(sql);
+ return updateCount;
+ }
+
+ public synchronized void close() throws SQLException {
+ try {
+ close_();
+ } catch (RuntimeException e) {
+ throw connection.helper.createException("While closing statement", e);
+ }
+ }
+
+ protected void close_() {
+ if (!closed) {
+ closed = true;
+ if (openResultSet != null) {
+ AvaticaResultSet c = openResultSet;
+ openResultSet = null;
+ c.close();
+ }
+ try {
+ // inform the server to close the resource
+ connection.meta.closeStatement(handle);
+ } finally {
+ // make sure we don't leak on our side
+ connection.statementMap.remove(handle.id);
+ }
+ // If onStatementClose throws, this method will throw an exception (later
+ // converted to SQLException), but this statement still gets closed.
+ connection.driver.handler.onStatementClose(this);
+ }
+ }
+
+ public int getMaxFieldSize() throws SQLException {
+ throw connection.helper.unsupported();
+ }
+
+ public void setMaxFieldSize(int max) throws SQLException {
+ throw connection.helper.unsupported();
+ }
+
+ public final int getMaxRows() {
+ return (int) getLargeMaxRows();
+ }
+
+ public long getLargeMaxRows() {
+ return maxRowCount;
+ }
+
+ public final void setMaxRows(int maxRowCount) throws SQLException {
+ setLargeMaxRows(maxRowCount);
+ }
+
+ public void setLargeMaxRows(long maxRowCount) throws SQLException {
+ if (maxRowCount < 0) {
+ throw connection.helper.createException(
+ "illegal maxRows value: " + maxRowCount);
+ }
+ this.maxRowCount = maxRowCount;
+ }
+
+ public void setEscapeProcessing(boolean enable) throws SQLException {
+ throw connection.helper.unsupported();
+ }
+
+ public int getQueryTimeout() throws SQLException {
+ long timeoutSeconds = getQueryTimeoutMillis() / 1000;
+ if (timeoutSeconds > Integer.MAX_VALUE) {
+ return Integer.MAX_VALUE;
+ }
+ if (timeoutSeconds == 0 && getQueryTimeoutMillis() > 0) {
+ // Don't return timeout=0 if e.g. timeoutMillis=500. 0 is special.
+ return 1;
+ }
+ return (int) timeoutSeconds;
+ }
+
+ int getQueryTimeoutMillis() {
+ return queryTimeoutMillis;
+ }
+
+ public void setQueryTimeout(int seconds) throws SQLException {
+ if (seconds < 0) {
+ throw connection.helper.createException(
+ "illegal timeout value " + seconds);
+ }
+ setQueryTimeoutMillis(seconds * 1000);
+ }
+
+ void setQueryTimeoutMillis(int millis) {
+ this.queryTimeoutMillis = millis;
+ }
+
+ public synchronized void cancel() throws SQLException {
+ if (openResultSet != null) {
+ openResultSet.cancel();
+ }
+ }
+
+ public SQLWarning getWarnings() throws SQLException {
+ return null; // no warnings, since warnings are not supported
+ }
+
+ public void clearWarnings() throws SQLException {
+ // no-op since warnings are not supported
+ }
+
+ public void setCursorName(String name) throws SQLException {
+ throw connection.helper.unsupported();
+ }
+
+ public ResultSet getResultSet() throws SQLException {
+ // NOTE: result set becomes visible in this member while
+ // executeQueryInternal is still in progress, and before it has
+ // finished executing. Its internal state may not be ready for API
+ // calls. JDBC never claims to be thread-safe! (Except for calls to the
+ // cancel method.) It is not possible to synchronize, because it would
+ // block 'cancel'.
+ return openResultSet;
+ }
+
+ public int getUpdateCount() throws SQLException {
+ return (int) updateCount;
+ }
+
+ public long getLargeUpdateCount() throws SQLException {
+ return updateCount;
+ }
+
+ public boolean getMoreResults() throws SQLException {
+ throw connection.helper.unsupported();
+ }
+
+ public void setFetchDirection(int direction) throws SQLException {
+ this.fetchDirection = direction;
+ }
+
+ public int getFetchDirection() {
+ return fetchDirection;
+ }
+
+ public void setFetchSize(int rows) throws SQLException {
+ this.fetchSize = rows;
+ }
+
+ public int getFetchSize() {
+ return fetchSize;
+ }
+
+ public int getResultSetConcurrency() throws SQLException {
+ throw connection.helper.unsupported();
+ }
+
+ public int getResultSetType() throws SQLException {
+ throw connection.helper.unsupported();
+ }
+
+ public void addBatch(String sql) throws SQLException {
+ throw connection.helper.unsupported();
+ }
+
+ public void clearBatch() throws SQLException {
+ throw connection.helper.unsupported();
+ }
+
+ public int[] executeBatch() throws SQLException {
+ throw connection.helper.unsupported();
+ }
+
+ public AvaticaConnection getConnection() {
+ return connection;
+ }
+
+ public boolean getMoreResults(int current) throws SQLException {
+ throw connection.helper.unsupported();
+ }
+
+ public ResultSet getGeneratedKeys() throws SQLException {
+ throw connection.helper.unsupported();
+ }
+
+ public int executeUpdate(
+ String sql, int autoGeneratedKeys) throws SQLException {
+ throw connection.helper.unsupported();
+ }
+
+ public int executeUpdate(
+ String sql, int[] columnIndexes) throws SQLException {
+ throw connection.helper.unsupported();
+ }
+
+ public int executeUpdate(
+ String sql, String[] columnNames) throws SQLException {
+ throw connection.helper.unsupported();
+ }
+
+ public boolean execute(
+ String sql, int autoGeneratedKeys) throws SQLException {
+ throw connection.helper.unsupported();
+ }
+
+ public boolean execute(
+ String sql, int[] columnIndexes) throws SQLException {
+ throw connection.helper.unsupported();
+ }
+
+ public boolean execute(
+ String sql, String[] columnNames) throws SQLException {
+ throw connection.helper.unsupported();
+ }
+
+ public int getResultSetHoldability() throws SQLException {
+ throw connection.helper.unsupported();
+ }
+
+ public boolean isClosed() throws SQLException {
+ return closed;
+ }
+
+ public void setPoolable(boolean poolable) throws SQLException {
+ throw connection.helper.unsupported();
+ }
+
+ public boolean isPoolable() throws SQLException {
+ throw connection.helper.unsupported();
+ }
+
+ // implements java.sql.Statement.closeOnCompletion (added in JDK 1.7)
+ public void closeOnCompletion() throws SQLException {
+ closeOnCompletion = true;
+ }
+
+ // implements java.sql.Statement.isCloseOnCompletion (added in JDK 1.7)
+ public boolean isCloseOnCompletion() throws SQLException {
+ return closeOnCompletion;
+ }
+
+ // implement Wrapper
+
+ public <T> T unwrap(Class<T> iface) throws SQLException {
+ if (iface.isInstance(this)) {
+ return iface.cast(this);
+ }
+ throw connection.helper.createException(
+ "does not implement '" + iface + "'");
+ }
+
+ public boolean isWrapperFor(Class<?> iface) throws SQLException {
+ return iface.isInstance(this);
+ }
+
+ /**
+ * Executes a prepared statement.
+ *
+ * @param signature Parsed statement
+ * @param isUpdate if the execute is for an update
+ *
+ * @return as specified by {@link java.sql.Statement#execute(String)}
+ * @throws java.sql.SQLException if a database error occurs
+ */
+ protected boolean executeInternal(Meta.Signature signature, boolean isUpdate)
+ throws SQLException {
+ ResultSet resultSet = executeQueryInternal(signature, isUpdate);
+ // user may have cancelled the query
+ if (resultSet.isClosed()) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Executes a prepared query, closing any previously open result set.
+ *
+ * @param signature Parsed query
+ * @param isUpdate If the execute is for an update
+ * @return Result set
+ * @throws java.sql.SQLException if a database error occurs
+ */
+ protected ResultSet executeQueryInternal(Meta.Signature signature, boolean isUpdate)
+ throws SQLException {
+ return connection.executeQueryInternal(this, signature, null, null, isUpdate);
+ }
+
+ /**
+ * Called by each child result set when it is closed.
+ *
+ * @param resultSet Result set or cell set
+ */
+ void onResultSetClose(ResultSet resultSet) {
+ if (closeOnCompletion) {
+ close_();
+ }
+ }
+
+ /** Returns the list of values of this statement's parameters.
+ *
+ * <p>Called at execute time. Not a public API.</p>
+ *
+ * <p>The default implementation returns the empty list, because non-prepared
+ * statements have no parameters.</p>
+ *
+ * @see org.apache.calcite.avatica.AvaticaConnection.Trojan#getParameterValues(AvaticaStatement)
+ */
+ protected List<TypedValue> 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<TypedValue> getBoundParameterValues() throws SQLException {
+ final List<TypedValue> parameterValues = getParameterValues();
+ for (Object parameterValue : parameterValues) {
+ if (parameterValue == null) {
+ throw new SQLException("unbound parameter");
+ }
+ }
+ return parameterValues;
+ }
+}
+
+// End AvaticaStatement.java