You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by jh...@apache.org on 2015/04/03 15:02:39 UTC

[06/10] incubator-calcite git commit: [CALCITE-654] Tighten up AvaticaStatement#execute semantics (Nick Dimiduk)

[CALCITE-654] Tighten up AvaticaStatement#execute semantics (Nick Dimiduk)


Project: http://git-wip-us.apache.org/repos/asf/incubator-calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-calcite/commit/0ea085b7
Tree: http://git-wip-us.apache.org/repos/asf/incubator-calcite/tree/0ea085b7
Diff: http://git-wip-us.apache.org/repos/asf/incubator-calcite/diff/0ea085b7

Branch: refs/heads/master
Commit: 0ea085b7858cbf0e8b250ac238d4f1def1ff20f5
Parents: ba07b09
Author: Nick Dimiduk <nd...@gmail.com>
Authored: Mon Mar 30 17:42:26 2015 -0700
Committer: Julian Hyde <jh...@apache.org>
Committed: Fri Apr 3 01:10:05 2015 -0700

----------------------------------------------------------------------
 .../apache/calcite/avatica/jdbc/JdbcMeta.java   | 21 +++++++++--
 .../calcite/avatica/RemoteDriverTest.java       | 26 ++++++++++++--
 .../calcite/avatica/AvaticaStatement.java       | 37 +++++++++++++-------
 3 files changed, 66 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/0ea085b7/avatica-server/src/main/java/org/apache/calcite/avatica/jdbc/JdbcMeta.java
----------------------------------------------------------------------
diff --git a/avatica-server/src/main/java/org/apache/calcite/avatica/jdbc/JdbcMeta.java b/avatica-server/src/main/java/org/apache/calcite/avatica/jdbc/JdbcMeta.java
index 90e8c2a..b5fb561 100644
--- a/avatica-server/src/main/java/org/apache/calcite/avatica/jdbc/JdbcMeta.java
+++ b/avatica-server/src/main/java/org/apache/calcite/avatica/jdbc/JdbcMeta.java
@@ -708,13 +708,28 @@ public class JdbcMeta implements Meta {
       final PreparedStatement statement = connection.prepareStatement(sql);
       final int id = System.identityHashCode(statement);
       final StatementInfo info = new StatementInfo(statement);
-      statementCache.put(id, info);
-      info.resultSet = statement.executeQuery();
-      MetaResultSet mrs = JdbcResultSet.create(ch.id, id, info.resultSet);
+      statementCache.put(id, info); // TODO: must we retain a statement in all cases?
+      boolean ret = statement.execute();
+      info.resultSet = statement.getResultSet();
+      assert ret || info.resultSet == null;
+      final MetaResultSet mrs;
+      if (info.resultSet == null) {
+        // build a non-JDBC result that contains the update count
+        int updateCount = statement.getUpdateCount();
+        List<ColumnMetaData> columns = new ArrayList<>(1);
+        columns.add(UPDATE_COL);
+        List<Object> val = new ArrayList<>();
+        val.add(new Object[] { updateCount });
+        mrs = new MetaResultSet(ch.id, id, true, new Signature(columns, sql, null, null,
+            CursorFactory.ARRAY), new Frame(0, true, val));
+      } else {
+        mrs = JdbcResultSet.create(ch.id, id, info.resultSet);
+      }
       if (LOG.isTraceEnabled()) {
         StatementHandle h = new StatementHandle(ch.id, id, null);
         LOG.trace("prepAndExec statement " + h);
       }
+      // TODO: review client to ensure statementId is updated when appropriate
       return mrs;
     } catch (SQLException e) {
       throw propagate(e);

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/0ea085b7/avatica-server/src/test/java/org/apache/calcite/avatica/RemoteDriverTest.java
----------------------------------------------------------------------
diff --git a/avatica-server/src/test/java/org/apache/calcite/avatica/RemoteDriverTest.java b/avatica-server/src/test/java/org/apache/calcite/avatica/RemoteDriverTest.java
index a2ab87a..2b9c111 100644
--- a/avatica-server/src/test/java/org/apache/calcite/avatica/RemoteDriverTest.java
+++ b/avatica-server/src/test/java/org/apache/calcite/avatica/RemoteDriverTest.java
@@ -152,7 +152,6 @@ public class RemoteDriverTest {
     checkStatementExecuteQuery(mjs(), false);
   }
 
-  @Ignore
   @Test public void testPrepareExecuteQueryLocal() throws Exception {
     checkStatementExecuteQuery(ljs(), true);
   }
@@ -180,7 +179,7 @@ public class RemoteDriverTest {
       resultSet = statement.executeQuery(sql);
     }
     if (parameterMetaData != null) {
-      assertThat(parameterMetaData.getParameterCount(), equalTo(2));
+      assertThat(parameterMetaData.getParameterCount(), equalTo(0));
     }
     final ResultSetMetaData metaData = resultSet.getMetaData();
     assertEquals(2, metaData.getColumnCount());
@@ -195,6 +194,27 @@ public class RemoteDriverTest {
     connection.close();
   }
 
+  @Test public void testCreateInsertUpdateDrop() throws Exception {
+    final String drop = "drop table TEST_TABLE if exists";
+    final String create = "create table TEST_TABLE("
+        + "id int not null, "
+        + "msg varchar(3) not null)";
+    final String insert = "insert into TEST_TABLE values(1, 'foo')";
+    final String update = "update TEST_TABLE set msg='bar' where id=1";
+    try (Connection connection = ljs();
+        Statement statement = connection.createStatement()) {
+      boolean ret;
+      assertFalse(statement.execute(drop));
+      assertEquals(0, statement.getUpdateCount());
+      assertFalse(statement.execute(create));
+      assertEquals(0, statement.getUpdateCount());
+      assertFalse(statement.execute(insert));
+      assertEquals(1, statement.getUpdateCount());
+      assertFalse(statement.execute(update));
+      assertEquals(0, statement.executeUpdate(drop));
+    }
+  }
+
   @Test public void testStatementLifecycle() throws Exception {
     try (AvaticaConnection connection = (AvaticaConnection) ljs()) {
       Map<Integer, AvaticaStatement> clientMap = connection.statementMap;
@@ -312,6 +332,8 @@ public class RemoteDriverTest {
     connection.close();
   }
 
+
+
   /**
    * Factory that creates a service based on a local JDBC connection.
    */

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/0ea085b7/avatica/src/main/java/org/apache/calcite/avatica/AvaticaStatement.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/org/apache/calcite/avatica/AvaticaStatement.java b/avatica/src/main/java/org/apache/calcite/avatica/AvaticaStatement.java
index 8276b07..1a7e5ec 100644
--- a/avatica/src/main/java/org/apache/calcite/avatica/AvaticaStatement.java
+++ b/avatica/src/main/java/org/apache/calcite/avatica/AvaticaStatement.java
@@ -17,6 +17,7 @@
 package org.apache.calcite.avatica;
 
 import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
 import java.sql.SQLWarning;
 import java.sql.Statement;
@@ -55,6 +56,7 @@ public abstract class AvaticaStatement
   private int fetchSize;
   private int fetchDirection;
   protected int maxRowCount = 0;
+  private int updateCount = -1;
 
   /**
    * Creates an AvaticaStatement.
@@ -89,21 +91,30 @@ public abstract class AvaticaStatement
   // implement Statement
 
   public boolean execute(String sql) throws SQLException {
-    try {
-      // In JDBC, maxRowCount = 0 means no limit; in prepare it means LIMIT 0
-      final int maxRowCount1 = maxRowCount <= 0 ? -1 : maxRowCount;
-      ResultSet resultSet =
-          connection.prepareAndExecuteInternal(this, sql, maxRowCount1);
-      if (resultSet.isClosed()) {
-        return false;
+    ResultSet resultSet = executeQuery(sql);
+    ResultSetMetaData md = resultSet.getMetaData();
+    // hackish, but be sure we're looking at an update count result, not user data
+    if (md.getCatalogName(1).equalsIgnoreCase("avatica_internal")
+        && md.getTableName(1).equalsIgnoreCase("update_result")
+        && md.getColumnCount() == 1
+        && md.getColumnName(1).equalsIgnoreCase("u")) {
+      if (!resultSet.next()) {
+        throw new SQLException("expected one row, got zero");
       }
-      return true;
-    } catch (RuntimeException e) {
-      throw connection.helper.createException("while executing SQL: " + sql, e);
+      this.updateCount = resultSet.getInt(1);
+      if (resultSet.next()) {
+        throw new SQLException("expected one row, got two or more");
+      }
+      resultSet.close();
+      return false;
+    } else {
+      return !resultSet.isClosed();
     }
   }
 
   public ResultSet executeQuery(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 int maxRowCount1 = maxRowCount <= 0 ? -1 : maxRowCount;
@@ -122,12 +133,12 @@ public abstract class AvaticaStatement
     if (!resultSet.next()) {
       throw new SQLException("expected one row, got zero");
     }
-    int result = resultSet.getInt(1);
+    this.updateCount = resultSet.getInt(1);
     if (resultSet.next()) {
       throw new SQLException("expected one row, got two or more");
     }
     resultSet.close();
-    return result;
+    return this.updateCount;
   }
 
   public synchronized void close() throws SQLException {
@@ -240,7 +251,7 @@ public abstract class AvaticaStatement
   }
 
   public int getUpdateCount() throws SQLException {
-    return -1;
+    return updateCount;
   }
 
   public boolean getMoreResults() throws SQLException {