Repository: phoenix
Updated Branches:
  refs/heads/4.0 89262f2be -> e174793e9


PHOENIX-1253 Throw SQLException on prepared stmt

Throw an SQLException if a bind parameter with an invalid index
is set (via setXXX methods) on a PhoenixPreparedStatement.


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/e174793e
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/e174793e
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/e174793e

Branch: refs/heads/4.0
Commit: e174793e915de85e4784a6162898e3a5cc06ac10
Parents: 89262f2
Author: Gabriel Reid <gabri...@ngdata.com>
Authored: Tue Sep 16 10:04:59 2014 +0200
Committer: Gabriel Reid <gabri...@ngdata.com>
Committed: Wed Sep 17 09:28:50 2014 +0200

----------------------------------------------------------------------
 .../phoenix/jdbc/PhoenixPreparedStatement.java  | 79 +++++++++++++-------
 .../jdbc/PhoenixPreparedStatementTest.java      | 61 +++++++++++++++
 2 files changed, 112 insertions(+), 28 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/e174793e/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixPreparedStatement.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixPreparedStatement.java
 
b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixPreparedStatement.java
index 7eea568..09fcb98 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixPreparedStatement.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixPreparedStatement.java
@@ -66,11 +66,12 @@ import org.apache.phoenix.util.SQLCloseable;
  * {@link #setTime(int, Time, Calendar)} - {@link #setTimestamp(int, 
Timestamp)} -
  * {@link #setTimestamp(int, Timestamp, Calendar)} - {@link #setNull(int, 
int)} - {@link #setNull(int, int, String)} -
  * {@link #setBytes(int, byte[])} - {@link #clearParameters()} - {@link 
#getMetaData()}
- * 
- * 
+ *
+ *
  * @since 0.1
  */
 public class PhoenixPreparedStatement extends PhoenixStatement implements 
PreparedStatement, SQLCloseable {
+    private final int parameterCount;
     private final List<Object> parameters;
     private final CompilableStatement statement;
 
@@ -82,6 +83,7 @@ public class PhoenixPreparedStatement extends 
PhoenixStatement implements Prepar
         this.statement = parser.nextStatement(new ExecutableNodeFactory());
         if (this.statement == null) { throw new EOFException(); }
         this.query = null; // TODO: add toString on SQLStatement
+        this.parameterCount = statement.getBindCount();
         this.parameters = Arrays.asList(new Object[statement.getBindCount()]);
         Collections.fill(parameters, BindManager.UNBOUND_PARAMETER);
     }
@@ -90,6 +92,7 @@ public class PhoenixPreparedStatement extends 
PhoenixStatement implements Prepar
         super(connection);
         this.query = query;
         this.statement = parseStatement(query);
+        this.parameterCount = statement.getBindCount();
         this.parameters = Arrays.asList(new Object[statement.getBindCount()]);
         Collections.fill(parameters, BindManager.UNBOUND_PARAMETER);
     }
@@ -98,6 +101,7 @@ public class PhoenixPreparedStatement extends 
PhoenixStatement implements Prepar
         super(statement.connection);
         this.query = statement.query;
         this.statement = statement.statement;
+        this.parameterCount = statement.parameters.size();
         this.parameters = new ArrayList<Object>(statement.parameters);
     }
 
@@ -107,6 +111,27 @@ public class PhoenixPreparedStatement extends 
PhoenixStatement implements Prepar
         batch.add(new PhoenixPreparedStatement(this));
     }
 
+    /**
+     * Set a bind parameter's value.
+     * @param parameterIndex 1-based index of the bind parameter to be set
+     * @param value value to be set
+     * @throws SQLException if the bind parameter index is invalid
+     */
+    private void setParameter(int parameterIndex, Object value) throws 
SQLException {
+        if (parameterIndex < 1 || parameterIndex > parameterCount) {
+            throw new 
SQLExceptionInfo.Builder(SQLExceptionCode.PARAM_INDEX_OUT_OF_BOUND)
+                    .setMessage("Can't set parameter at index " + 
parameterIndex + ", " +
+                             parameterCount + " bind parameters are defined")
+                    .build().buildException();
+        }
+        if (parameterIndex < 1) {
+            throw new 
SQLExceptionInfo.Builder(SQLExceptionCode.PARAM_INDEX_OUT_OF_BOUND)
+                    .setMessage("Invalid bind parameter index " + 
parameterIndex)
+                    .build().buildException();
+        }
+        this.parameters.set(parameterIndex - 1, value);
+    }
+
 
     @Override
     public void clearParameters() throws SQLException {
@@ -128,8 +153,8 @@ public class PhoenixPreparedStatement extends 
PhoenixStatement implements Prepar
             i++;
         }
     }
-    
-    
+
+
     public QueryPlan compileQuery() throws SQLException {
         return compileQuery(statement, query);
     }
@@ -230,7 +255,7 @@ public class PhoenixPreparedStatement extends 
PhoenixStatement implements Prepar
 
     @Override
     public void setArray(int parameterIndex, Array x) throws SQLException {
-       parameters.set(parameterIndex - 1, x);
+        setParameter(parameterIndex, x);
     }
 
     @Override
@@ -250,12 +275,12 @@ public class PhoenixPreparedStatement extends 
PhoenixStatement implements Prepar
 
     @Override
     public void setBigDecimal(int parameterIndex, BigDecimal x) throws 
SQLException {
-        parameters.set(parameterIndex - 1, x);
+        setParameter(parameterIndex, x);
     }
 
     @Override
     public void setBytes(int parameterIndex, byte[] x) throws SQLException {
-        parameters.set(parameterIndex - 1, x);
+        setParameter(parameterIndex, x);
     }
 
     @Override
@@ -290,12 +315,12 @@ public class PhoenixPreparedStatement extends 
PhoenixStatement implements Prepar
 
     @Override
     public void setBoolean(int parameterIndex, boolean x) throws SQLException {
-        parameters.set(parameterIndex - 1, x);
+        setParameter(parameterIndex, x);
     }
 
     @Override
     public void setByte(int parameterIndex, byte x) throws SQLException {
-        parameters.set(parameterIndex - 1, x);
+        setParameter(parameterIndex, x);
     }
 
     @Override
@@ -330,35 +355,33 @@ public class PhoenixPreparedStatement extends 
PhoenixStatement implements Prepar
 
     @Override
     public void setDate(int parameterIndex, Date x) throws SQLException {
-        parameters.set(parameterIndex - 1, x);
+        setParameter(parameterIndex, x);
     }
 
     @Override
     public void setDate(int parameterIndex, Date x, Calendar cal) throws 
SQLException {
         cal.setTime(x);
-        parameters.set(parameterIndex - 1, new Date(cal.getTimeInMillis()));
+        setParameter(parameterIndex, new Date(cal.getTimeInMillis()));
     }
 
     @Override
     public void setDouble(int parameterIndex, double x) throws SQLException {
-//        parameters.set(parameterIndex - 1, BigDecimal.valueOf(x));
-        parameters.set(parameterIndex - 1, x);
+        setParameter(parameterIndex, x);
     }
 
     @Override
     public void setFloat(int parameterIndex, float x) throws SQLException {
-//        parameters.set(parameterIndex - 1, BigDecimal.valueOf(x));
-        parameters.set(parameterIndex - 1, x);
+        setParameter(parameterIndex, x);
     }
 
     @Override
     public void setInt(int parameterIndex, int x) throws SQLException {
-        parameters.set(parameterIndex - 1, x);
+        setParameter(parameterIndex, x);
     }
 
     @Override
     public void setLong(int parameterIndex, long x) throws SQLException {
-        parameters.set(parameterIndex - 1, x);
+        setParameter(parameterIndex, x);
     }
 
     @Override
@@ -393,17 +416,17 @@ public class PhoenixPreparedStatement extends 
PhoenixStatement implements Prepar
 
     @Override
     public void setNull(int parameterIndex, int sqlType) throws SQLException {
-        parameters.set(parameterIndex - 1, null);
+        setParameter(parameterIndex, null);
     }
 
     @Override
     public void setNull(int parameterIndex, int sqlType, String typeName) 
throws SQLException {
-        parameters.set(parameterIndex - 1, null);
+        setParameter(parameterIndex, null);
     }
 
     @Override
     public void setObject(int parameterIndex, Object o) throws SQLException {
-        parameters.set(parameterIndex - 1, o);
+        setParameter(parameterIndex, o);
     }
 
     @Override
@@ -411,7 +434,7 @@ public class PhoenixPreparedStatement extends 
PhoenixStatement implements Prepar
         PDataType targetType = PDataType.fromTypeId(targetSqlType);
         PDataType sourceType = PDataType.fromLiteral(o);
         o = targetType.toObject(o, sourceType);
-        parameters.set(parameterIndex - 1, o);
+        setParameter(parameterIndex, o);
     }
 
     @Override
@@ -436,39 +459,39 @@ public class PhoenixPreparedStatement extends 
PhoenixStatement implements Prepar
 
     @Override
     public void setShort(int parameterIndex, short x) throws SQLException {
-        parameters.set(parameterIndex - 1, x);
+        setParameter(parameterIndex, x);
     }
 
     @Override
     public void setString(int parameterIndex, String x) throws SQLException {
-        parameters.set(parameterIndex - 1, x);
+        setParameter(parameterIndex, x);
     }
 
     @Override
     public void setTime(int parameterIndex, Time x) throws SQLException {
-        parameters.set(parameterIndex - 1, x);
+        setParameter(parameterIndex, x);
     }
 
     @Override
     public void setTime(int parameterIndex, Time x, Calendar cal) throws 
SQLException {
         cal.setTime(x);
-        parameters.set(parameterIndex - 1, new Time(cal.getTimeInMillis()));
+        setParameter(parameterIndex, new Time(cal.getTimeInMillis()));
     }
 
     @Override
     public void setTimestamp(int parameterIndex, Timestamp x) throws 
SQLException {
-        parameters.set(parameterIndex - 1, x);
+        setParameter(parameterIndex, x);
     }
 
     @Override
     public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) 
throws SQLException {
         cal.setTime(x);
-        parameters.set(parameterIndex - 1,  
DateUtil.getTimestamp(cal.getTimeInMillis(), x.getNanos()));
+        setParameter(parameterIndex,  
DateUtil.getTimestamp(cal.getTimeInMillis(), x.getNanos()));
     }
 
     @Override
     public void setURL(int parameterIndex, URL x) throws SQLException {
-        parameters.set(parameterIndex - 1, x.toExternalForm()); // Just treat 
as String
+        setParameter(parameterIndex, x.toExternalForm()); // Just treat as 
String
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/phoenix/blob/e174793e/phoenix-core/src/test/java/org/apache/phoenix/jdbc/PhoenixPreparedStatementTest.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/test/java/org/apache/phoenix/jdbc/PhoenixPreparedStatementTest.java
 
b/phoenix-core/src/test/java/org/apache/phoenix/jdbc/PhoenixPreparedStatementTest.java
new file mode 100644
index 0000000..c2bbdfb
--- /dev/null
+++ 
b/phoenix-core/src/test/java/org/apache/phoenix/jdbc/PhoenixPreparedStatementTest.java
@@ -0,0 +1,61 @@
+/*
+ * 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.phoenix.jdbc;
+
+import org.apache.phoenix.query.BaseConnectionlessQueryTest;
+import org.junit.Test;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.Properties;
+
+import static org.junit.Assert.fail;
+
+public class PhoenixPreparedStatementTest extends BaseConnectionlessQueryTest {
+
+    @Test
+    public void testSetParameter_InvalidIndex() throws Exception {
+        Properties connectionProperties = new Properties();
+        Connection connection = DriverManager.getConnection(getUrl(), 
connectionProperties);
+
+        PreparedStatement stmt = connection.prepareStatement(
+                "UPSERT INTO " + ATABLE + " (organization_id, entity_id, 
a_integer) " +
+                        "VALUES (?,?,?)");
+
+        stmt.setString(1, "AAA");
+        stmt.setString(2, "BBB");
+        stmt.setInt(3, 1);
+
+        try {
+            stmt.setString(4, "Invalid bind column");
+            fail("Setting a value for a column that doesn't exist should throw 
SQLException");
+        } catch (SQLException e) {
+            // Expected exception
+        }
+
+        try {
+            stmt.setString(-1, "Invalid bind column");
+            fail("Setting a value for a column that doesn't exist should throw 
SQLException");
+        } catch (SQLException e) {
+            // Expected exception
+        }
+    }
+
+}

Reply via email to