Repository: drill Updated Branches: refs/heads/master 4baf9e70b -> 4e2df00e7
http://git-wip-us.apache.org/repos/asf/drill/blob/71082e6c/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillFactory.java ---------------------------------------------------------------------- diff --git a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillFactory.java b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillFactory.java new file mode 100644 index 0000000..033fbe7 --- /dev/null +++ b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillFactory.java @@ -0,0 +1,79 @@ +/** + * 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.drill.jdbc.impl; + +import java.sql.SQLException; +import java.util.Properties; + +import net.hydromatic.avatica.AvaticaConnection; +import net.hydromatic.avatica.AvaticaFactory; +import net.hydromatic.avatica.UnregisteredDriver; + + +/** + * Partial implementation of {@link net.hydromatic.avatica.AvaticaFactory} + * (factory for main JDBC objects) for Drill's JDBC driver. + * <p> + * Handles JDBC version number. + * </p> + */ +abstract class DrillFactory implements AvaticaFactory { + protected final int major; + protected final int minor; + + /** Creates a JDBC factory with given major/minor version number. */ + protected DrillFactory(int major, int minor) { + this.major = major; + this.minor = minor; + } + + @Override + public int getJdbcMajorVersion() { + return major; + } + + @Override + public int getJdbcMinorVersion() { + return minor; + } + + + /** + * Creates a Drill connection for Avatica (in terms of Avatica types). + * <p> + * This implementation delegates to + * {@link newDrillConnection(DriverImpl, DrillFactory, String, Properties)}. + * </p> + */ + @Override + public final AvaticaConnection newConnection(UnregisteredDriver driver, + AvaticaFactory factory, + String url, + Properties info) throws SQLException { + return newDrillConnection((DriverImpl) driver, (DrillFactory) factory, url, info); + } + + /** + * Creates a Drill connection (in terms of Drill-specific types). + */ + abstract DrillConnectionImpl newDrillConnection(DriverImpl driver, + DrillFactory factory, + String url, + Properties info) throws SQLException; +} http://git-wip-us.apache.org/repos/asf/drill/blob/71082e6c/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillHandler.java ---------------------------------------------------------------------- diff --git a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillHandler.java b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillHandler.java new file mode 100644 index 0000000..e6f4045 --- /dev/null +++ b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillHandler.java @@ -0,0 +1,48 @@ +/** + * 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.drill.jdbc.impl; + +import java.sql.SQLException; + +import net.hydromatic.avatica.AvaticaConnection; +import net.hydromatic.avatica.AvaticaStatement; +import net.hydromatic.avatica.Handler; + +class DrillHandler implements Handler { + static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(DrillHandler.class); + + @Override + public void onConnectionInit(AvaticaConnection c) throws SQLException { + } + + @Override + public void onConnectionClose(AvaticaConnection c) throws RuntimeException { + DrillConnectionImpl connection = (DrillConnectionImpl) c; + connection.cleanup(); + } + + @Override + public void onStatementExecute(AvaticaStatement statement, + ResultSink resultSink) throws RuntimeException { + } + + @Override + public void onStatementClose(AvaticaStatement statement) throws RuntimeException { + ((DrillRemoteStatement) statement).cleanUp(); + } +} http://git-wip-us.apache.org/repos/asf/drill/blob/71082e6c/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillJdbc40Factory.java ---------------------------------------------------------------------- diff --git a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillJdbc40Factory.java b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillJdbc40Factory.java new file mode 100644 index 0000000..fb140a3 --- /dev/null +++ b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillJdbc40Factory.java @@ -0,0 +1,34 @@ +/** + * 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.drill.jdbc.impl; + +/** + * Implementation of {@link net.hydromatic.avatica.AvaticaFactory} + * for Drill and JDBC 4.0 (corresponds to JDK 1.6). + */ +// Note: Must be public so net.hydromatic.avatica.UnregisteredDriver can +// (reflectively) call no-args constructor. +public class DrillJdbc40Factory extends DrillJdbc41Factory { + + /** Creates a factory for JDBC version 4.1. */ + // Note: Must be public so net.hydromatic.avatica.UnregisteredDriver can + // (reflectively) call this constructor. + public DrillJdbc40Factory() { + super(4, 0); + } +} http://git-wip-us.apache.org/repos/asf/drill/blob/71082e6c/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillJdbc41Factory.java ---------------------------------------------------------------------- diff --git a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillJdbc41Factory.java b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillJdbc41Factory.java new file mode 100644 index 0000000..3d02fac --- /dev/null +++ b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillJdbc41Factory.java @@ -0,0 +1,226 @@ +/** + * 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.drill.jdbc.impl; + +import java.io.InputStream; +import java.io.Reader; +import java.sql.NClob; +import java.sql.ResultSetMetaData; +import java.sql.RowId; +import java.sql.SQLException; +import java.sql.SQLXML; +import java.util.List; +import java.util.Properties; +import java.util.TimeZone; + +import net.hydromatic.avatica.AvaticaConnection; +import net.hydromatic.avatica.AvaticaPrepareResult; +import net.hydromatic.avatica.AvaticaPreparedStatement; +import net.hydromatic.avatica.AvaticaResultSetMetaData; +import net.hydromatic.avatica.AvaticaStatement; +import net.hydromatic.avatica.ColumnMetaData; + + +/** + * Implementation of {@link net.hydromatic.avatica.AvaticaFactory} for Drill and + * JDBC 4.1 (corresponds to JDK 1.7). + */ +// Note: Must be public so net.hydromatic.avatica.UnregisteredDriver can +// (reflectively) call no-args constructor. +public class DrillJdbc41Factory extends DrillFactory { + + /** Creates a factory for JDBC version 4.1. */ + // Note: Must be public so net.hydromatic.avatica.UnregisteredDriver can + // (reflectively) call this constructor. + public DrillJdbc41Factory() { + this(4, 1); + } + + /** Creates a JDBC factory with given major/minor version number. */ + protected DrillJdbc41Factory(int major, int minor) { + super(major, minor); + } + + + @Override + DrillConnectionImpl newDrillConnection(DriverImpl driver, + DrillFactory factory, + String url, + Properties info) throws SQLException { + return new DrillConnectionImpl(driver, factory, url, info); + } + + @Override + public DrillDatabaseMetaData newDatabaseMetaData(AvaticaConnection connection) { + return new DrillDatabaseMetaData((DrillConnectionImpl) connection); + } + + + @Override + public DrillStatementImpl newStatement(AvaticaConnection connection, + int resultSetType, + int resultSetConcurrency, + int resultSetHoldability) { + return new DrillStatementImpl((DrillConnectionImpl) connection, + resultSetType, + resultSetConcurrency, + resultSetHoldability); + } + + @Override + public DrillJdbc41PreparedStatement newPreparedStatement(AvaticaConnection connection, + AvaticaPrepareResult prepareResult, + int resultSetType, + int resultSetConcurrency, + int resultSetHoldability) + throws SQLException { + return new DrillJdbc41PreparedStatement((DrillConnectionImpl) connection, + (DrillPrepareResult) prepareResult, + resultSetType, + resultSetConcurrency, + resultSetHoldability); + } + + @Override + public DrillResultSetImpl newResultSet(AvaticaStatement statement, + AvaticaPrepareResult prepareResult, + TimeZone timeZone) { + final ResultSetMetaData metaData = + newResultSetMetaData(statement, prepareResult.getColumnList()); + return new DrillResultSetImpl( (DrillStatementImpl) statement, + (DrillPrepareResult) prepareResult, + metaData, timeZone); + } + + @Override + public ResultSetMetaData newResultSetMetaData(AvaticaStatement statement, + List<ColumnMetaData> columnMetaDataList) { + return new AvaticaResultSetMetaData(statement, null, columnMetaDataList); + } + + + /** + * JDBC 4.1 version of {@link DrillPreparedStatementImpl}. + */ + private static class DrillJdbc41PreparedStatement extends DrillPreparedStatementImpl { + + DrillJdbc41PreparedStatement(DrillConnectionImpl connection, + DrillPrepareResult prepareResult, + int resultSetType, + int resultSetConcurrency, + int resultSetHoldability) throws SQLException { + super(connection, prepareResult, + resultSetType, resultSetConcurrency, resultSetHoldability); + } + + @Override + public void setRowId(int parameterIndex, RowId x) throws SQLException { + getParameter(parameterIndex).setRowId(x); + } + + @Override + public void setNString(int parameterIndex, String value) throws SQLException { + getParameter(parameterIndex).setNString(value); + } + + @Override + public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException { + getParameter(parameterIndex).setNCharacterStream(value, length); + } + + @Override + public void setNClob(int parameterIndex, NClob value) throws SQLException { + getParameter(parameterIndex).setNClob(value); + } + + @Override + public void setClob(int parameterIndex, Reader reader, long length) throws SQLException { + getParameter(parameterIndex).setClob(reader, length); + } + + @Override + public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException { + getParameter(parameterIndex).setBlob(inputStream, length); + } + + @Override + public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException { + getParameter(parameterIndex).setNClob(reader, length); + } + + @Override + public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException { + getParameter(parameterIndex).setSQLXML(xmlObject); + } + + @Override + public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException { + getParameter(parameterIndex).setAsciiStream(x, length); + } + + @Override + public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException { + getParameter(parameterIndex).setBinaryStream(x, length); + } + + @Override + public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException { + getParameter(parameterIndex).setCharacterStream(reader, length); + } + + @Override + public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException { + getParameter(parameterIndex).setAsciiStream(x); + } + + @Override + public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException { + getParameter(parameterIndex).setBinaryStream(x); + } + + @Override + public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException { + getParameter(parameterIndex).setCharacterStream(reader); + } + + @Override + public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException { + getParameter(parameterIndex).setNCharacterStream(value); + } + + @Override + public void setClob(int parameterIndex, Reader reader) throws SQLException { + getParameter(parameterIndex).setClob(reader); + } + + @Override + public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException { + getParameter(parameterIndex).setBlob(inputStream); + } + + @Override + public void setNClob(int parameterIndex, Reader reader) throws SQLException { + getParameter(parameterIndex).setNClob(reader); + } + + } + +} + +// End DrillJdbc41Factory.java http://git-wip-us.apache.org/repos/asf/drill/blob/71082e6c/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillPrepareResult.java ---------------------------------------------------------------------- diff --git a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillPrepareResult.java b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillPrepareResult.java new file mode 100644 index 0000000..6870673 --- /dev/null +++ b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillPrepareResult.java @@ -0,0 +1,52 @@ +/** + * 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.drill.jdbc.impl; + +import java.util.Collections; +import java.util.List; + +import net.hydromatic.avatica.AvaticaParameter; +import net.hydromatic.avatica.AvaticaPrepareResult; +import net.hydromatic.avatica.ColumnMetaData; + +class DrillPrepareResult implements AvaticaPrepareResult{ + static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(DrillPrepareResult.class); + + final String sql; + final DrillColumnMetaDataList columns = new DrillColumnMetaDataList(); + + DrillPrepareResult(String sql) { + super(); + this.sql = sql; + } + + @Override + public List<ColumnMetaData> getColumnList() { + return columns; + } + + @Override + public String getSql() { + return sql; + } + + @Override + public List<AvaticaParameter> getParameterList() { + return Collections.emptyList(); + } +} http://git-wip-us.apache.org/repos/asf/drill/blob/71082e6c/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillPreparedStatementImpl.java ---------------------------------------------------------------------- diff --git a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillPreparedStatementImpl.java b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillPreparedStatementImpl.java new file mode 100644 index 0000000..5e9ec93 --- /dev/null +++ b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillPreparedStatementImpl.java @@ -0,0 +1,56 @@ +/** + * 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.drill.jdbc.impl; + +import java.sql.SQLException; + +import net.hydromatic.avatica.AvaticaPrepareResult; +import net.hydromatic.avatica.AvaticaPreparedStatement; + +/** + * Implementation of {@link java.sql.PreparedStatement} for Drill. + * + * <p> + * This class has sub-classes which implement JDBC 3.0 and JDBC 4.0 APIs; it is instantiated using + * {@link net.hydromatic.avatica.AvaticaFactory#newPreparedStatement}. + * </p> + */ +abstract class DrillPreparedStatementImpl extends AvaticaPreparedStatement + implements DrillRemoteStatement { + + protected DrillPreparedStatementImpl(DrillConnectionImpl connection, + AvaticaPrepareResult prepareResult, + int resultSetType, + int resultSetConcurrency, + int resultSetHoldability) throws SQLException { + super(connection, prepareResult, + resultSetType, resultSetConcurrency, resultSetHoldability); + connection.openStatementsRegistry.addStatement(this); + } + + @Override + public DrillConnectionImpl getConnection() { + return (DrillConnectionImpl) super.getConnection(); + } + + @Override + public void cleanUp() { + final DrillConnectionImpl connection1 = (DrillConnectionImpl) connection; + connection1.openStatementsRegistry.removeStatement(this); + } +} http://git-wip-us.apache.org/repos/asf/drill/blob/71082e6c/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillRemoteStatement.java ---------------------------------------------------------------------- diff --git a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillRemoteStatement.java b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillRemoteStatement.java new file mode 100644 index 0000000..9bd1b16 --- /dev/null +++ b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillRemoteStatement.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. + */ +package org.apache.drill.jdbc.impl; + +interface DrillRemoteStatement { + void cleanUp(); +} http://git-wip-us.apache.org/repos/asf/drill/blob/71082e6c/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillResultSetImpl.java ---------------------------------------------------------------------- diff --git a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillResultSetImpl.java b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillResultSetImpl.java index cb6bd1d..d7fafe9 100644 --- a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillResultSetImpl.java +++ b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillResultSetImpl.java @@ -43,8 +43,6 @@ import org.apache.drill.exec.rpc.user.QueryDataBatch; import org.apache.drill.exec.rpc.user.UserResultsListener; import org.apache.drill.jdbc.AlreadyClosedSqlException; import org.apache.drill.jdbc.DrillConnection; -import org.apache.drill.jdbc.DrillConnectionImpl; -import org.apache.drill.jdbc.DrillCursor; import org.apache.drill.jdbc.DrillResultSet; import org.apache.drill.jdbc.ExecutionCanceledSqlException; import org.apache.drill.jdbc.SchemaChangeListener; @@ -55,27 +53,27 @@ import org.slf4j.Logger; import com.google.common.collect.Queues; -public class DrillResultSetImpl extends AvaticaResultSet implements DrillResultSet { +/** + * Drill's implementation of {@link ResultSet}. + */ +class DrillResultSetImpl extends AvaticaResultSet implements DrillResultSet { @SuppressWarnings("unused") - private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(DrillResultSetImpl.class); + private static final org.slf4j.Logger logger = + org.slf4j.LoggerFactory.getLogger(DrillResultSetImpl.class); private final DrillStatementImpl statement; - // (Public until JDBC impl. classes moved out of published-intf. package. (DRILL-2089).) - public SchemaChangeListener changeListener; - // (Public until JDBC impl. classes moved out of published-intf. package. (DRILL-2089).) - public final ResultsListener resultsListener; + SchemaChangeListener changeListener; + final ResultsListener resultsListener; private final DrillClient client; - // (Public until JDBC impl. classes moved out of published-intf. package. (DRILL-2089).) // TODO: Resolve: Since is barely manipulated here in DrillResultSetImpl, // move down into DrillCursor and have this.clean() have cursor clean it. - public final RecordBatchLoader currentBatch; - // (Public until JDBC impl. classes moved out of published-intf. package. (DRILL-2089).) - public final DrillCursor cursor; - public boolean hasPendingCancelationNotification; + final RecordBatchLoader currentBatch; + final DrillCursor cursor; + boolean hasPendingCancelationNotification; - public DrillResultSetImpl(DrillStatementImpl statement, AvaticaPrepareResult prepareResult, - ResultSetMetaData resultSetMetaData, TimeZone timeZone) { + DrillResultSetImpl(DrillStatementImpl statement, AvaticaPrepareResult prepareResult, + ResultSetMetaData resultSetMetaData, TimeZone timeZone) { super(statement, prepareResult, resultSetMetaData, timeZone); this.statement = statement; final int batchQueueThrottlingThreshold = @@ -130,8 +128,7 @@ public class DrillResultSetImpl extends AvaticaResultSet implements DrillResultS close(); } - // (Public until JDBC impl. classes moved out of published-intf. package. (DRILL-2089).) - public synchronized void cleanup() { + synchronized void cleanup() { if (resultsListener.getQueryId() != null && ! resultsListener.completed) { client.cancelQuery(resultsListener.getQueryId()); } @@ -142,8 +139,15 @@ public class DrillResultSetImpl extends AvaticaResultSet implements DrillResultS @Override public boolean next() throws SQLException { checkNotClosed(); - // Next may be called after close has been called (for example after a user cancel) which in turn - // sets the cursor to null. So we must check before we call next. + // TODO: Resolve following comments (possibly obsolete because of later + // addition of preceding call to checkNotClosed. Also, NOTE that the + // following check, and maybe some checkNotClosed() calls, probably must + // synchronize on the statement, per the comment on AvaticaStatement's + // openResultSet: + + // Next may be called after close has been called (for example after a user + // cancellation) which in turn sets the cursor to null. So we must check + // before we call next. // TODO: handle next() after close is called in the Avatica code. if (super.cursor != null) { return super.next(); @@ -168,8 +172,9 @@ public class DrillResultSetImpl extends AvaticaResultSet implements DrillResultS // calling some wait method? resultsListener.latch.await(); } catch ( InterruptedException e ) { - // Preserve evidence that the interruption occurred so that code higher up on the call stack can learn of the - // interruption and respond to it if it wants to. + // Preserve evidence that the interruption occurred so that code higher up + // on the call stack can learn of the interruption and respond to it if it + // wants to. Thread.currentThread().interrupt(); // Not normally expected--Drill doesn't interrupt in this area (right?)-- @@ -189,8 +194,7 @@ public class DrillResultSetImpl extends AvaticaResultSet implements DrillResultS } } - // (Public until JDBC impl. classes moved out of published-intf. package. (DRILL-2089).) - public static class ResultsListener implements UserResultsListener { + static class ResultsListener implements UserResultsListener { private static final Logger logger = getLogger( ResultsListener.class ); private static volatile int nextInstanceId = 1; @@ -331,7 +335,7 @@ public class DrillResultSetImpl extends AvaticaResultSet implements DrillResultS completed = true; } - public QueryId getQueryId() { + QueryId getQueryId() { return queryId; } @@ -344,8 +348,7 @@ public class DrillResultSetImpl extends AvaticaResultSet implements DrillResultS * @throws InterruptedException * if waiting on the queue was interrupted */ - public QueryDataBatch getNext() throws UserException, - InterruptedException { + QueryDataBatch getNext() throws UserException, InterruptedException { while (true) { if (executionFailureException != null) { logger.debug( "[#{}] Dequeued query failure exception: {}.", http://git-wip-us.apache.org/repos/asf/drill/blob/71082e6c/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillStatementImpl.java ---------------------------------------------------------------------- diff --git a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillStatementImpl.java b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillStatementImpl.java index 6610f52..6cba58e 100644 --- a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillStatementImpl.java +++ b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillStatementImpl.java @@ -23,20 +23,24 @@ import java.sql.SQLFeatureNotSupportedException; import org.apache.drill.common.exceptions.DrillRuntimeException; import org.apache.drill.jdbc.AlreadyClosedSqlException; -import org.apache.drill.jdbc.DrillConnectionImpl; -import org.apache.drill.jdbc.DrillRemoteStatement; import org.apache.drill.jdbc.DrillStatement; import org.apache.drill.jdbc.InvalidParameterSqlException; import net.hydromatic.avatica.AvaticaStatement; -public abstract class DrillStatementImpl extends AvaticaStatement - implements DrillStatement, DrillRemoteStatement { +/** + * Drill's implementation of {@link Statement}. + */ +// (Was abstract to avoid errors _here_ if newer versions of JDBC added +// interface methods, but now newer versions would probably use Java 8's default +// methods for compatibility.) +class DrillStatementImpl extends AvaticaStatement implements DrillStatement, + DrillRemoteStatement { private final DrillConnectionImpl connection; - // (Public until JDBC impl. classes moved out of published-intf. package. (DRILL-2089).) - public DrillStatementImpl(DrillConnectionImpl connection, int resultSetType, int resultSetConcurrency, int resultSetHoldability) { + DrillStatementImpl(DrillConnectionImpl connection, int resultSetType, + int resultSetConcurrency, int resultSetHoldability) { super(connection, resultSetType, resultSetConcurrency, resultSetHoldability); this.connection = connection; connection.openStatementsRegistry.addStatement(this); @@ -120,7 +124,7 @@ public abstract class DrillStatementImpl extends AvaticaStatement } @Override - public void cleanup() { + public void cleanUp() { final DrillConnectionImpl connection1 = (DrillConnectionImpl) connection; connection1.openStatementsRegistry.removeStatement(this); } http://git-wip-us.apache.org/repos/asf/drill/blob/71082e6c/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillStatementRegistry.java ---------------------------------------------------------------------- diff --git a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillStatementRegistry.java b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillStatementRegistry.java new file mode 100644 index 0000000..722e268 --- /dev/null +++ b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillStatementRegistry.java @@ -0,0 +1,77 @@ +/** + * 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.drill.jdbc.impl; + +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; + +import org.slf4j.Logger; + +import static org.slf4j.LoggerFactory.getLogger; + +/** + * Registry of open statements (for a connection), for closing them when a + * connection is closed. + * <p> + * Concurrency: Not thread-safe. (Creating statements, closing statements, + * and closing connection cannot be concurrent (unless concurrency is + * coordinated elsewhere).) + * </p> + */ +class DrillStatementRegistry { + + private static final Logger logger = getLogger( DrillStatementRegistry.class ); + + /** ... (using as IdentityHash*Set*) */ + private final Map<Statement, Object> openStatements = new IdentityHashMap<>(); + + + void addStatement( Statement statement ) { + logger.debug( "Adding to open-statements registry: " + statement ); + openStatements.put( statement, statement ); + } + + void removeStatement( Statement statement ) { + logger.debug( "Removing from open-statements registry: " + statement ); + openStatements.remove( statement ); + } + + void close() { + // Note: Can't call close() on statement during iteration of map because + // close() calls our removeStatement(...), which modifies the map. + + // Copy set of open statements to other collection before closing: + final List<Statement> copiedList = new ArrayList<>( openStatements.keySet() ); + + for ( final Statement statement : copiedList ) { + try { + logger.debug( "Auto-closing (via open-statements registry): " + statement ); + statement.close(); + } + catch ( SQLException e ) { + logger.error( "Error auto-closing statement " + statement + ": " + e, e ); + // Otherwise ignore the error, to close which statements we can close. + } + } + openStatements.clear(); + } +} http://git-wip-us.apache.org/repos/asf/drill/blob/71082e6c/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DriverImpl.java ---------------------------------------------------------------------- diff --git a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DriverImpl.java b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DriverImpl.java new file mode 100644 index 0000000..9fa7ce4 --- /dev/null +++ b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DriverImpl.java @@ -0,0 +1,76 @@ +/** + * 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.drill.jdbc.impl; + +import net.hydromatic.avatica.DriverVersion; +import net.hydromatic.avatica.Handler; +import net.hydromatic.avatica.HandlerImpl; +import net.hydromatic.avatica.UnregisteredDriver; + +/** + * Optiq JDBC driver. + */ +public class DriverImpl extends UnregisteredDriver { + private static final String CONNECTION_STRING_PREFIX = "jdbc:drill:"; + private static final String METADATA_PROPERTIES_RESOURCE_PATH = + "apache-drill-jdbc.properties"; + + + public DriverImpl() { + super(); + } + + + @Override + protected String getConnectStringPrefix() { + return CONNECTION_STRING_PREFIX; + } + + @Override + protected String getFactoryClassName(JdbcVersion jdbcVersion) { + switch (jdbcVersion) { + case JDBC_30: + return "org.apache.drill.jdbc.impl.DrillJdbc3Factory"; + case JDBC_40: + return "org.apache.drill.jdbc.impl.DrillJdbc40Factory"; + case JDBC_41: + default: + return "org.apache.drill.jdbc.impl.DrillJdbc41Factory"; + } + } + + @Override + protected DriverVersion createDriverVersion() { + return DriverVersion.load( + this.getClass(), + METADATA_PROPERTIES_RESOURCE_PATH, + // Driver name and version: + "Apache Drill JDBC Driver", + "<Properties resource " + METADATA_PROPERTIES_RESOURCE_PATH + " not loaded>", + // Database product name and version: + "Apache Drill", + "<Properties resource " + METADATA_PROPERTIES_RESOURCE_PATH + " not loaded>"); + } + + + @Override + protected Handler createHandler() { + return new DrillHandler(); + } + +} http://git-wip-us.apache.org/repos/asf/drill/blob/71082e6c/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/GlobalServiceSetReference.java ---------------------------------------------------------------------- diff --git a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/GlobalServiceSetReference.java b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/GlobalServiceSetReference.java new file mode 100644 index 0000000..16e5a76 --- /dev/null +++ b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/GlobalServiceSetReference.java @@ -0,0 +1,27 @@ +/** + * 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.drill.jdbc.impl; + +import org.apache.drill.exec.server.RemoteServiceSet; + +class GlobalServiceSetReference { + static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(GlobalServiceSetReference.class); + + static final ThreadLocal<RemoteServiceSet> SETS = new ThreadLocal<RemoteServiceSet>(); + +} http://git-wip-us.apache.org/repos/asf/drill/blob/71082e6c/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/MetaImpl.java ---------------------------------------------------------------------- diff --git a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/MetaImpl.java b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/MetaImpl.java new file mode 100644 index 0000000..7e76ea9 --- /dev/null +++ b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/MetaImpl.java @@ -0,0 +1,666 @@ +/** + * 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.drill.jdbc.impl; + +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.sql.Types; +import java.util.List; + +import net.hydromatic.avatica.AvaticaPrepareResult; +import net.hydromatic.avatica.AvaticaResultSet; +import net.hydromatic.avatica.AvaticaStatement; +import net.hydromatic.avatica.Cursor; +import net.hydromatic.avatica.Meta; + +import org.apache.drill.common.exceptions.DrillRuntimeException; +import org.apache.drill.common.util.DrillStringUtils; + + +class MetaImpl implements Meta { + private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(MetaImpl.class); + + // TODO: Use more central version of these constants if availabe. + + /** Radix used to report precision and scale of integral exact numeric types. */ + private static final int RADIX_INTEGRAL = 10; + /** Radix used to report precision and scale of non-integral exact numeric + types (DECIMAL). */ + private static final int RADIX_DECIMAL = 10; + /** Radix used to report precision and scale of approximate numeric types + (FLOAT, etc.). */ + private static final int RADIX_APPROXIMATE = 10; + /** Radix used to report precisions of interval types. */ + private static final int RADIX_INTERVAL = 10; + + /** (Maximum) precision of TINYINT. */ + private static final int PREC_TINYINT = 3; + /** (Maximum) precision of SMALLINT. */ + private static final int PREC_SMALLINT = 5; + /** (Maximum) precision of INTEGER. */ + private static final int PREC_INTEGER = 10; + /** (Maximum) precision of BIGINT. */ + private static final int PREC_BIGINT = 19; + + /** Precision of FLOAT. */ + private static final int PREC_FLOAT = 7; + /** Precision of DOUBLE. */ + private static final int PREC_DOUBLE = 15; + /** Precision of REAL. */ + private static final int PREC_REAL = PREC_DOUBLE; + + /** Scale of INTEGER types. */ + private static final int SCALE_INTEGRAL = 0; + /** JDBC conventional(?) scale value for FLOAT. */ + private static final int SCALE_FLOAT = 7; + /** JDBC conventional(?) scale value for DOUBLE. */ + private static final int SCALE_DOUBLE = 15; + /** JDBC conventional(?) scale value for REAL. */ + private static final int SCALE_REAL = SCALE_DOUBLE; + + /** (Apparent) maximum precision for starting unit of INTERVAL type. */ + private static final int PREC_INTERVAL_LEAD_MAX = 10; + /** (Apparent) maximum fractional seconds precision for INTERVAL type. */ + private static final int PREC_INTERVAL_TRAIL_MAX = 9; + + + final DrillConnectionImpl connection; + + MetaImpl(DrillConnectionImpl connection) { + this.connection = connection; + } + + @Override + public String getSqlKeywords() { + return ""; + } + + @Override + public String getNumericFunctions() { + return ""; + } + + @Override + public String getStringFunctions() { + return ""; + } + + @Override + public String getSystemFunctions() { + return ""; + } + + @Override + public String getTimeDateFunctions() { + return ""; + } + + // TODO: BUG: null is not a proper empty result set. + private static ResultSet getEmptyResultSet() { + return null; + } + + private ResultSet s(String s) { + try { + logger.debug("Running {}", s); + AvaticaStatement statement = connection.createStatement(); + statement.execute(s); + return statement.getResultSet(); + + } catch (Exception e) { + throw new DrillRuntimeException("Failure while attempting to get DatabaseMetadata.", e); + } + + } + + @Override + public ResultSet getTables(String catalog, final Pat schemaPattern, final Pat tableNamePattern, + final List<String> typeList) { + StringBuilder sb = new StringBuilder(); + sb.append("select " + + "TABLE_CATALOG as TABLE_CAT, " + + "TABLE_SCHEMA as TABLE_SCHEM, " + + "TABLE_NAME, " + + "TABLE_TYPE, " + + "'' as REMARKS, " + + "'' as TYPE_CAT, " + + "'' as TYPE_SCHEM, " + + "'' as TYPE_NAME, " + + "'' as SELF_REFERENCING_COL_NAME, " + + "'' as REF_GENERATION " + + "FROM INFORMATION_SCHEMA.`TABLES` WHERE 1=1 "); + + if (catalog != null) { + sb.append(" AND TABLE_CATALOG = '" + DrillStringUtils.escapeSql(catalog) + "' "); + } + + if (schemaPattern.s != null) { + sb.append(" AND TABLE_SCHEMA like '" + DrillStringUtils.escapeSql(schemaPattern.s) + "'"); + } + + if (tableNamePattern.s != null) { + sb.append(" AND TABLE_NAME like '" + DrillStringUtils.escapeSql(tableNamePattern.s) + "'"); + } + + if (typeList != null && typeList.size() > 0) { + sb.append("AND ("); + for (int t = 0; t < typeList.size(); t++) { + if (t != 0) { + sb.append(" OR "); + } + sb.append(" TABLE_TYPE LIKE '" + DrillStringUtils.escapeSql(typeList.get(t)) + "' "); + } + sb.append(")"); + } + + sb.append(" ORDER BY TABLE_TYPE, TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME"); + + return s(sb.toString()); + } + + /** + * Implements {@link DatabaseMetaData#getColumns()}. + */ + @Override + public ResultSet getColumns(String catalog, Pat schemaPattern, + Pat tableNamePattern, Pat columnNamePattern) { + StringBuilder sb = new StringBuilder(); + // TODO: Resolve the various questions noted below. + sb.append( + "SELECT " + // getColumns INFORMATION_SCHEMA.COLUMNS getColumns() + // column source column or column name + // number expression + // ------- ------------------------ ------------- + + /* 1 */ "\n TABLE_CATALOG as TABLE_CAT, " + + /* 2 */ "\n TABLE_SCHEMA as TABLE_SCHEM, " + + /* 3 */ "\n TABLE_NAME as TABLE_NAME, " + + /* 4 */ "\n COLUMN_NAME as COLUMN_NAME, " + + /* 5 DATA_TYPE */ + // TODO: Resolve the various questions noted below for DATA_TYPE. + + "\n CASE DATA_TYPE " + // (All values in JDBC 4.0/Java 7 java.sql.Types except for types.NULL:) + + // Exact-match cases: + + "\n WHEN 'BIGINT' THEN " + Types.BIGINT + + "\n WHEN 'BINARY' THEN " + Types.BINARY + // Resolve: Not seen in Drill yet. Can it appear?: + + "\n WHEN 'BIT' THEN " + Types.BIT + // Resolve: Not seen in Drill yet. Can it appear?: + + "\n WHEN 'BLOB', 'BINARY LARGE OBJECT' THEN " + Types.BLOB + + "\n WHEN 'BOOLEAN' THEN " + Types.BOOLEAN + + + "\n WHEN 'CHAR', 'CHARACTER' THEN " + Types.CHAR + // Resolve: Not seen in Drill yet. Can it appear?: + + "\n WHEN 'CLOB', 'CHARACTER LARGE OBJECT' " + + "\n THEN " + Types.CLOB + + // Resolve: Not seen in Drill yet. Can it appear?: + + "\n WHEN 'DATALINK' THEN " + Types.DATALINK + + "\n WHEN 'DATE' THEN " + Types.DATE + + "\n WHEN 'DECIMAL' THEN " + Types.DECIMAL + // Resolve: Not seen in Drill yet. Can it appear?: + + "\n WHEN 'DISTINCT' THEN " + Types.DISTINCT + + "\n WHEN 'DOUBLE', 'DOUBLE PRECISION' THEN " + Types.DOUBLE + + + "\n WHEN 'FLOAT' THEN " + Types.FLOAT + + + "\n WHEN 'INTEGER' THEN " + Types.INTEGER + + // Drill's INFORMATION_SCHEMA's COLUMNS currently has + // "INTERVAL_YEAR_MONTH" and "INTERVAL_DAY_TIME" instead of SQL standard + // 'INTERVAL'. + + "\n WHEN 'INTERVAL', " + + "\n 'INTERVAL_YEAR_MONTH', " + + "\n 'INTERVAL_DAY_TIME' THEN " + Types.OTHER + + // Resolve: Not seen in Drill yet. Can it ever appear?: + + "\n WHEN 'JAVA_OBJECT' THEN " + Types.JAVA_OBJECT + + // Resolve: Not seen in Drill yet. Can it appear?: + + "\n WHEN 'LONGNVARCHAR' THEN " + Types.LONGNVARCHAR + // Resolve: Not seen in Drill yet. Can it appear?: + + "\n WHEN 'LONGVARBINARY' THEN " + Types.LONGVARBINARY + // Resolve: Not seen in Drill yet. Can it appear?: + + "\n WHEN 'LONGVARCHAR' THEN " + Types.LONGVARCHAR + + // Resolve: Not seen in Drill yet. Can it appear?: + + "\n WHEN 'NCHAR', 'NATIONAL CHARACTER' THEN " + Types.NCHAR + // Resolve: Not seen in Drill yet. Can it appear?: + + "\n WHEN 'NCLOB', 'NATIONAL CHARACTER LARGE OBJECT' " + + "\n THEN " + Types.NCLOB + // TODO: Resolve following about NULL (and then update comment and code): + // It is not clear whether Types.NULL can represent a type (perhaps the + // type of the literal NULL when no further type information is known?) or + // whether 'NULL' can appear in INFORMATION_SCHEMA.COLUMNS.DATA_TYPE. + // For now, since it shouldn't hurt, include 'NULL'/Types.NULL in mapping. + + "\n WHEN 'NULL' THEN " + Types.NULL + // (No NUMERIC--Drill seems to map any to DECIMAL currently.) + + "\n WHEN 'NUMERIC' THEN " + Types.NUMERIC + // Resolve: Not seen in Drill yet. Can it appear?: + + "\n WHEN 'NVARCHAR', 'NATIONAL CHARACTER VARYING' " + + "\n THEN " + Types.NVARCHAR + + // Resolve: Unexpectedly, has appeared in Drill. Should it? + + "\n WHEN 'OTHER' THEN " + Types.OTHER + + + "\n WHEN 'REAL' THEN " + Types.REAL + // SQL source syntax: + // <reference type> ::= + // REF <left paren> <referenced type> <right paren> [ <scope clause> ] + // Resolve: Not seen in Drill yet. Can it appear?: + + "\n WHEN 'REF' THEN " + Types.REF + // Resolve: Not seen in Drill yet. Can it appear?: + + "\n WHEN 'ROWID' THEN " + Types.ROWID + + + "\n WHEN 'SMALLINT' THEN " + Types.SMALLINT + // Resolve: Not seen in Drill yet. Can it appear?: + + "\n WHEN 'SQLXML' THEN " + Types.SQLXML + + + "\n WHEN 'TIME' THEN " + Types.TIME + + "\n WHEN 'TIMESTAMP' THEN " + Types.TIMESTAMP + + "\n WHEN 'TINYINT' THEN " + Types.TINYINT + + + "\n WHEN 'VARBINARY', 'BINARY VARYING' THEN " + Types.VARBINARY + + "\n WHEN 'VARCHAR', 'CHARACTER VARYING' " + + "\n THEN " + Types.VARCHAR + + + "\n ELSE" + // Pattern-match cases: + + "\n CASE " + + // TODO: RESOLVE: How does ARRAY appear in COLUMNS.DATA_TYPE? + // - Only at end (with no maximum size, as "VARCHAR(65535) ARRAY")? + // - Possibly with maximum size (as "... ARRAY[10]")? + // - Then, how should it appear in JDBC ("ARRAY"? "... ARRAY"?) + // (SQL source syntax: + // <array type> ::= + // <data type> ARRAY + // [ <left bracket or trigraph> <maximum cardinality> + // <right bracket or trigraph> ] + + "\n WHEN DATA_TYPE LIKE '% ARRAY' THEN " + Types.ARRAY + + // TODO: RESOLVE: How does MAP appear in COLUMNS.DATA_TYPE? + // - Only at end? + // - Otherwise? + // TODO: RESOLVE: Should it map to Types.OTHER or something else? + // Has appeared in Drill. Should it? + + "\n WHEN DATA_TYPE LIKE '% MAP' THEN " + Types.OTHER + + // TODO: RESOLVE: How does "STRUCT" appear? + // - Only at beginning (as "STRUCT(INTEGER sint, BOOLEAN sboolean")? + // - Otherwise too? + // - Then, how should it appear in JDBC ("STRUCT"? "STRUCT(...)"?) + + "\n WHEN DATA_TYPE LIKE 'STRUCT(%' THEN " + Types.STRUCT + + + "\n ELSE " + Types.OTHER + + "\n END " + + "\n END as DATA_TYPE, " + + /* 6 TYPE_NAME */ + // Map Drill's current info. schema values to what SQL standard + // specifies (for DATA_TYPE)--and assume that that's what JDBC wants. + + "\n CASE DATA_TYPE " + + "\n WHEN 'INTERVAL_YEAR_MONTH', " + + "\n 'INTERVAL_DAY_TIME' THEN 'INTERVAL'" + // TODO: Resolve how non-scalar types should appear in + // INFORMATION_SCHEMA.COLUMNS and here in JDBC: + // - "ARRAY" or "... ARRAY"? + // - "MAP" or "... MAP"? + // - "STRUCT" or "STRUCT(...)"? + + "\n ELSE DATA_TYPE " + + "\n END as TYPE_NAME, " + + /* 7 COLUMN_SIZE */ + /* "... COLUMN_SIZE .... + * For numeric data, this is the maximum precision. + * For character data, this is the length in characters. + * For datetime datatypes, this is the length in characters of the String + * representation (assuming the maximum allowed precision of the + * fractional seconds component). + * For binary data, this is the length in bytes. + * For the ROWID datatype, this is the length in bytes. + * Null is returned for data types where the column size is not applicable." + * + * Note: "Maximum precision" seems to mean the maximum number of + * significant decimal digits that can appear (not the number of digits + * that can be counted on, and not the maximum number of characters + * needed to display a value). + */ + + "\n CASE DATA_TYPE " + + // "For numeric data, ... the maximum precision": + // TODO: Change literals to references to declared constant fields: + // - exact numeric types: + // (in decimal digits, coordinated with NUM_PREC_RADIX = 10) + + "\n WHEN 'TINYINT' THEN " + PREC_TINYINT + + "\n WHEN 'SMALLINT' THEN " + PREC_SMALLINT + + "\n WHEN 'INTEGER' THEN " + PREC_INTEGER + + "\n WHEN 'BIGINT' THEN " + PREC_BIGINT + + "\n WHEN 'DECIMAL', 'NUMERIC' THEN NUMERIC_PRECISION " + // - approximate numeric types: + // (in decimal digits, coordinated with NUM_PREC_RADIX = 10) + // TODO: REVISIT: Should these be in bits or decimal digits (with + // NUM_PREC_RADIX coordinated)? INFORMATION_SCHEMA.COLUMNS's value + // are supposed to be in bits (per the SQL spec.). What does JDBC + // require and allow? + + "\n WHEN 'FLOAT' THEN " + PREC_FLOAT + + "\n WHEN 'DOUBLE' THEN " + PREC_DOUBLE + + "\n WHEN 'REAL' THEN " + PREC_REAL + + // "For character data, ... the length in characters": + // TODO: BUG: DRILL-2459: For CHARACTER / CHAR, length is not in + // CHARACTER_MAXIMUM_LENGTH but in NUMERIC_PRECISION. + // Workaround: + + "\n WHEN 'VARCHAR', 'CHARACTER VARYING' " + + "\n THEN CHARACTER_MAXIMUM_LENGTH " + + "\n WHEN 'CHAR', 'CHARACTER', " + + "\n 'NCHAR', 'NATIONAL CHAR', 'NATIONAL CHARACTER' " + + "\n THEN NUMERIC_PRECISION " + + // "For datetime datatypes ... length ... String representation + // (assuming the maximum ... precision of ... fractional seconds ...)": + + "\n WHEN 'DATE' THEN 10 " // YYYY-MM-DD + + "\n WHEN 'TIME' THEN " + + "\n CASE " + + "\n WHEN NUMERIC_PRECISION > 0 " // HH:MM:SS.sss + + "\n THEN 8 + 1 + NUMERIC_PRECISION" + + "\n ELSE 8" // HH:MM:SS + + "\n END " + + "\n WHEN 'TIMESTAMP' THEN " + + "\n CASE " // date + "T" + time (above) + + "\n WHEN NUMERIC_PRECISION > 0 " + + " THEN 10 + 1 + 8 + 1 + NUMERIC_PRECISION" + + "\n ELSE 10 + 1 + 8" + + "\n END " + + // TODO: DRILL-2531: When DRILL-2519 is fixed, use start and end unit + // and start-unit precision to implement maximum width more precisely + // (narrowly) than this workaround: + // For INTERVAL_YEAR_MONTH, maximum width is from "P1234567890Y12M" + // (5 + apparent maximum start unit precision of 10) + // unit precision): + + "\n WHEN 'INTERVAL_YEAR_MONTH' " + + "\n THEN 5 + " + + PREC_INTERVAL_LEAD_MAX + // For INTERVAL_DAY_TIME, maximum width is from + // "P1234567890D12H12M12.123456789S" (12 + apparent maximum start unit + // precision of 10 + apparent maximum seconds fractional precision of 9): + + "\n WHEN 'INTERVAL_DAY_TIME' " + + "\n THEN 12 + " + + ( PREC_INTERVAL_LEAD_MAX + + PREC_INTERVAL_TRAIL_MAX ) + + // "For binary data, ... the length in bytes": + // BUG: DRILL-2459: BINARY and BINARY VARYING / VARBINARY length is + // not in CHARACTER_MAXIMUM_LENGTH but in NUMERIC_PRECISION. + // Workaround: + + "\n WHEN 'VARBINARY', 'BINARY VARYING', " + + "\n 'BINARY' THEN NUMERIC_PRECISION " + + // "For ... ROWID datatype...": Not in Drill? + + // "Null ... for data types [for which] ... not applicable.": + + "\n ELSE NULL " + + "\n END as COLUMN_SIZE, " + + + /* 8 */ "\n CHARACTER_MAXIMUM_LENGTH as BUFFER_LENGTH, " + + /* 9 DECIMAL_DIGITS */ + + "\n CASE DATA_TYPE" + + "\n WHEN 'TINYINT', " + + "\n 'SMALLINT', " + + "\n 'INTEGER', " + + "\n 'BIGINT' THEN " + SCALE_INTEGRAL + + "\n WHEN 'DECIMAL', " + + "\n 'NUMERIC' THEN NUMERIC_SCALE " + + "\n WHEN 'FLOAT' THEN " + SCALE_FLOAT + + "\n WHEN 'DOUBLE' THEN " + SCALE_DOUBLE + + "\n WHEN 'REAL' THEN " + SCALE_REAL + + "\n WHEN 'INTERVAL' THEN NUMERIC_SCALE " + + "\n WHEN 'INTERVAL_YEAR_MONTH' THEN 0 " + + "\n WHEN 'INTERVAL_DAY_TIME' THEN NUMERIC_SCALE " + + "\n END as DECIMAL_DIGITS, " + + /* 10 NUM_PREC_RADIX */ + + "\n CASE DATA_TYPE " + + "\n WHEN 'TINYINT', " + + "\n 'SMALLINT', " + + "\n 'INTEGER', " + + "\n 'BIGINT' THEN " + RADIX_INTEGRAL + + "\n WHEN 'DECIMAL', " + + "\n 'NUMERIC' THEN " + RADIX_DECIMAL + + "\n WHEN 'FLOAT', " + + "\n 'DOUBLE', " + + "\n 'REAL' THEN " + RADIX_APPROXIMATE + + "\n WHEN 'INTERVAL_YEAR_MONTH', " + + "\n 'INTERVAL_DAY_TIME' THEN " + RADIX_INTERVAL + + "\n ELSE NULL" + + "\n END as NUM_PREC_RADIX, " + + /* 11 NULLABLE */ + + "\n CASE IS_NULLABLE " + + "\n WHEN 'YES' THEN " + DatabaseMetaData.columnNullable + + "\n WHEN 'NO' THEN " + DatabaseMetaData.columnNoNulls + + "\n WHEN '' THEN " + DatabaseMetaData.columnNullableUnknown + + "\n ELSE -1" + + "\n END as NULLABLE, " + + + /* 12 */ "\n CAST( NULL as VARCHAR ) as REMARKS, " + + /* 13 */ "\n CAST( NULL as VARCHAR ) as COLUMN_DEF, " + + /* 14 */ "\n 0 as SQL_DATA_TYPE, " + + /* 15 */ "\n 0 as SQL_DATETIME_SUB, " + + /* 16 CHAR_OCTET_LENGTH */ + + "\n CASE DATA_TYPE" + + "\n WHEN 'VARCHAR', 'CHARACTER VARYING' " + + "\n THEN 4 * CHARACTER_MAXIMUM_LENGTH " + + "\n WHEN 'CHAR', 'CHARACTER', " + + "\n 'NCHAR', 'NATIONAL CHAR', 'NATIONAL CHARACTER' " + // TODO: BUG: DRILL-2459: For CHARACTER / CHAR, length is not in + // CHARACTER_MAXIMUM_LENGTH but in NUMERIC_PRECISION. Workaround: + + "\n THEN 4 * NUMERIC_PRECISION " + + "\n ELSE NULL " + + "\n END as CHAR_OCTET_LENGTH, " + + + /* 17 */ "\n 1 + ORDINAL_POSITION as ORDINAL_POSITION, " + + /* 18 */ "\n IS_NULLABLE as IS_NULLABLE, " + + /* 19 */ "\n CAST( NULL as VARCHAR ) as SCOPE_CATALOG, " + + /* 20 */ "\n CAST( NULL as VARCHAR ) as SCOPE_SCHEMA, " + + /* 21 */ "\n CAST( NULL as VARCHAR ) as SCOPE_TABLE, " + // TODO: Change to SMALLINT when it's implemented (DRILL-2470): + + /* 22 */ "\n CAST( NULL as INTEGER ) as SOURCE_DATA_TYPE, " + + /* 23 */ "\n '' as IS_AUTOINCREMENT, " + + /* 24 */ "\n '' as IS_GENERATEDCOLUMN " + + + "\n FROM INFORMATION_SCHEMA.COLUMNS " + + "\n WHERE 1=1 "); + + if (catalog != null) { + sb.append("\n AND TABLE_CATALOG = '" + DrillStringUtils.escapeSql(catalog) + "'"); + } + if (schemaPattern.s != null) { + sb.append("\n AND TABLE_SCHEMA like '" + DrillStringUtils.escapeSql(schemaPattern.s) + "'"); + } + if (tableNamePattern.s != null) { + sb.append("\n AND TABLE_NAME like '" + DrillStringUtils.escapeSql(tableNamePattern.s) + "'"); + } + if (columnNamePattern.s != null) { + sb.append("\n AND COLUMN_NAME like '" + DrillStringUtils.escapeSql(columnNamePattern.s) + "'"); + } + + sb.append("\n ORDER BY TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME"); + + return s(sb.toString()); + } + + @Override + public ResultSet getSchemas(String catalog, Pat schemaPattern) { + StringBuilder sb = new StringBuilder(); + sb.append("select " + + "SCHEMA_NAME as TABLE_SCHEM, " + + "CATALOG_NAME as TABLE_CAT " + + " FROM INFORMATION_SCHEMA.SCHEMATA WHERE 1=1 "); + + if (catalog != null) { + sb.append(" AND CATALOG_NAME = '" + DrillStringUtils.escapeSql(catalog) + "' "); + } + if (schemaPattern.s != null) { + sb.append(" AND SCHEMA_NAME like '" + DrillStringUtils.escapeSql(schemaPattern.s) + "'"); + } + sb.append(" ORDER BY CATALOG_NAME, SCHEMA_NAME"); + + return s(sb.toString()); + } + + @Override + public ResultSet getCatalogs() { + StringBuilder sb = new StringBuilder(); + sb.append("select " + + "CATALOG_NAME as TABLE_CAT " + + " FROM INFORMATION_SCHEMA.CATALOGS "); + + sb.append(" ORDER BY CATALOG_NAME"); + + return s(sb.toString()); + } + + @Override + public ResultSet getTableTypes() { + return getEmptyResultSet(); + } + + @Override + public ResultSet getProcedures(String catalog, Pat schemaPattern, Pat procedureNamePattern) { + return getEmptyResultSet(); + } + + @Override + public ResultSet getProcedureColumns(String catalog, Pat schemaPattern, Pat procedureNamePattern, + Pat columnNamePattern) { + return getEmptyResultSet(); + } + + @Override + public ResultSet getColumnPrivileges(String catalog, String schema, String table, Pat columnNamePattern) { + return getEmptyResultSet(); + } + + @Override + public ResultSet getTablePrivileges(String catalog, Pat schemaPattern, Pat tableNamePattern) { + return getEmptyResultSet(); + } + + @Override + public ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable) { + return getEmptyResultSet(); + } + + @Override + public ResultSet getVersionColumns(String catalog, String schema, String table) { + return getEmptyResultSet(); + } + + @Override + public ResultSet getPrimaryKeys(String catalog, String schema, String table) { + return getEmptyResultSet(); + } + + @Override + public ResultSet getImportedKeys(String catalog, String schema, String table) { + return getEmptyResultSet(); + } + + @Override + public ResultSet getExportedKeys(String catalog, String schema, String table) { + return getEmptyResultSet(); + } + + @Override + public ResultSet getCrossReference(String parentCatalog, String parentSchema, String parentTable, + String foreignCatalog, String foreignSchema, String foreignTable) { + return getEmptyResultSet(); + } + + @Override + public ResultSet getTypeInfo() { + return getEmptyResultSet(); + } + + @Override + public ResultSet getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate) { + return getEmptyResultSet(); + } + + @Override + public ResultSet getUDTs(String catalog, Pat schemaPattern, Pat typeNamePattern, int[] types) { + return getEmptyResultSet(); + } + + @Override + public ResultSet getSuperTypes(String catalog, Pat schemaPattern, Pat typeNamePattern) { + return getEmptyResultSet(); + } + + @Override + public ResultSet getSuperTables(String catalog, Pat schemaPattern, Pat tableNamePattern) { + return getEmptyResultSet(); + } + + @Override + public ResultSet getAttributes(String catalog, Pat schemaPattern, Pat typeNamePattern, Pat attributeNamePattern) { + return getEmptyResultSet(); + } + + @Override + public ResultSet getClientInfoProperties() { + return getEmptyResultSet(); + } + + @Override + public ResultSet getFunctions(String catalog, Pat schemaPattern, Pat functionNamePattern) { + return getEmptyResultSet(); + } + + @Override + public ResultSet getFunctionColumns(String catalog, Pat schemaPattern, Pat functionNamePattern, Pat columnNamePattern) { + return getEmptyResultSet(); + } + + @Override + public ResultSet getPseudoColumns(String catalog, Pat schemaPattern, Pat tableNamePattern, Pat columnNamePattern) { + return getEmptyResultSet(); + } + + @Override + public Cursor createCursor(AvaticaResultSet resultSet_) { + return ((DrillResultSetImpl) resultSet_).cursor; + } + + @Override + public AvaticaPrepareResult prepare(AvaticaStatement statement_, String sql) { + //DrillStatement statement = (DrillStatement) statement_; + return new DrillPrepareResult(sql); + } + + interface Named { + String getName(); + } + +} http://git-wip-us.apache.org/repos/asf/drill/blob/71082e6c/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/TypeConvertingSqlAccessor.java ---------------------------------------------------------------------- diff --git a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/TypeConvertingSqlAccessor.java b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/TypeConvertingSqlAccessor.java index e095c42..b542f94 100644 --- a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/TypeConvertingSqlAccessor.java +++ b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/TypeConvertingSqlAccessor.java @@ -29,12 +29,11 @@ import org.apache.drill.exec.vector.accessor.InvalidAccessException; import org.apache.drill.exec.vector.accessor.SqlAccessor; import org.apache.drill.jdbc.SQLConversionOverflowException; -// (Public until JDBC impl. classes moved out of published-intf. package. (DRILL-2089).) /** * SQL accessor implementing data type conversion for JDBC * {@link ResultSet}.get<i>Type</i>(<i><column ID></i>) column accessor methods. */ -public class TypeConvertingSqlAccessor implements SqlAccessor { +class TypeConvertingSqlAccessor implements SqlAccessor { private final SqlAccessor innerAccessor; public TypeConvertingSqlAccessor( SqlAccessor innerAccessor ) { http://git-wip-us.apache.org/repos/asf/drill/blob/71082e6c/exec/jdbc/src/test/java/org/apache/drill/jdbc/ConnectionTest.java ---------------------------------------------------------------------- diff --git a/exec/jdbc/src/test/java/org/apache/drill/jdbc/ConnectionTest.java b/exec/jdbc/src/test/java/org/apache/drill/jdbc/ConnectionTest.java index 8a469c3..8735146 100644 --- a/exec/jdbc/src/test/java/org/apache/drill/jdbc/ConnectionTest.java +++ b/exec/jdbc/src/test/java/org/apache/drill/jdbc/ConnectionTest.java @@ -27,6 +27,7 @@ import org.junit.BeforeClass; import org.junit.Test; import java.sql.Connection; +import java.sql.DriverManager; import java.sql.SQLFeatureNotSupportedException; import java.sql.SQLException; import java.util.concurrent.ExecutorService; @@ -48,7 +49,8 @@ public class ConnectionTest extends JdbcTestBase { // (Note: Can't use JdbcTest's connect(...) because JdbcTest closes // Connection--and other JDBC objects--on test method failure, but this test // class uses some objects across methods.) - connection = new Driver().connect( "jdbc:drill:zk=local", null ); + Driver.load(); + connection = DriverManager.getConnection( "jdbc:drill:zk=local" ); executor = Executors.newSingleThreadExecutor(); } http://git-wip-us.apache.org/repos/asf/drill/blob/71082e6c/exec/jdbc/src/test/java/org/apache/drill/jdbc/DrillColumnMetaDataListTest.java ---------------------------------------------------------------------- diff --git a/exec/jdbc/src/test/java/org/apache/drill/jdbc/DrillColumnMetaDataListTest.java b/exec/jdbc/src/test/java/org/apache/drill/jdbc/DrillColumnMetaDataListTest.java index a6f2325..a4571c7 100644 --- a/exec/jdbc/src/test/java/org/apache/drill/jdbc/DrillColumnMetaDataListTest.java +++ b/exec/jdbc/src/test/java/org/apache/drill/jdbc/DrillColumnMetaDataListTest.java @@ -18,9 +18,11 @@ package org.apache.drill.jdbc; import net.hydromatic.avatica.ColumnMetaData; + import org.apache.drill.common.expression.SchemaPath; import org.apache.drill.exec.record.BatchSchema; import org.apache.drill.exec.record.MaterializedField; +import org.apache.drill.jdbc.impl.DrillColumnMetaDataList; import org.junit.After; import org.junit.Before; import org.junit.Test;
