Repository: phoenix Updated Branches: refs/heads/3.0 12494b7bf -> 963ea0f91
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/963ea0f9 Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/963ea0f9 Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/963ea0f9 Branch: refs/heads/3.0 Commit: 963ea0f9140244dc969da627f191d882cf2fd2f2 Parents: 12494b7 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:55 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/963ea0f9/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/963ea0f9/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 + } + } + +}