From 91596e7080bfed7ebbaa3908a14f498af333e2b9 Mon Sep 17 00:00:00 2001 From: Vishnu Prasad V S Date: Fri, 10 May 2024 14:31:18 +0530 Subject: [PATCH] Branch cut for release 4b.2 (#158) * Removing support for PreparedStatement as prepared statements (#157) * Updating version for next release (#159) --- pom.xml | 2 +- .../core/QueryServiceConnection.java | 5 +- .../core/QueryServicePreparedStatement.java | 559 ------------------ .../core/QueryServiceConnectionTest.java | 43 ++ .../QueryServicePreparedStatementTest.java | 74 --- 5 files changed, 46 insertions(+), 637 deletions(-) delete mode 100644 src/main/java/com/salesforce/cdp/queryservice/core/QueryServicePreparedStatement.java delete mode 100644 src/test/java/com/salesforce/cdp/queryservice/core/QueryServicePreparedStatementTest.java diff --git a/pom.xml b/pom.xml index 9f6183c..5d6aa59 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.queryService Salesforce-CDP-jdbc - 1.19.4 + 1.19.5 UTF-8 diff --git a/src/main/java/com/salesforce/cdp/queryservice/core/QueryServiceConnection.java b/src/main/java/com/salesforce/cdp/queryservice/core/QueryServiceConnection.java index 3c08855..4396ffb 100644 --- a/src/main/java/com/salesforce/cdp/queryservice/core/QueryServiceConnection.java +++ b/src/main/java/com/salesforce/cdp/queryservice/core/QueryServiceConnection.java @@ -144,8 +144,7 @@ public Statement createStatement() throws SQLException { @Override public PreparedStatement prepareStatement(String sql) throws SQLException { - return new QueryServicePreparedStatement(this, sql, - ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); + throw new SQLFeatureNotSupportedException("PreparedStatement is not supported"); } @Override @@ -241,7 +240,7 @@ public Statement createStatement(int resultSetType, int resultSetConcurrency) th @Override public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { - return new QueryServicePreparedStatement(this, sql, resultSetType, resultSetConcurrency); + throw new SQLFeatureNotSupportedException("PreparedStatement is not supported"); } @Override diff --git a/src/main/java/com/salesforce/cdp/queryservice/core/QueryServicePreparedStatement.java b/src/main/java/com/salesforce/cdp/queryservice/core/QueryServicePreparedStatement.java deleted file mode 100644 index 4a629a7..0000000 --- a/src/main/java/com/salesforce/cdp/queryservice/core/QueryServicePreparedStatement.java +++ /dev/null @@ -1,559 +0,0 @@ -/* - * Copyright (c) 2021, salesforce.com, inc. - * - * Licensed 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 com.salesforce.cdp.queryservice.core; - -import com.google.common.annotations.VisibleForTesting; -import lombok.extern.slf4j.Slf4j; - -import java.io.InputStream; -import java.io.Reader; -import java.math.BigDecimal; -import java.net.URL; -import java.sql.*; -import java.util.Calendar; -import java.util.HashMap; -import java.util.Map; - -@Slf4j -public class QueryServicePreparedStatement extends QueryServiceAbstractStatement implements PreparedStatement { - private String sql; - - private Map parameters = new HashMap<>(); - - public QueryServicePreparedStatement(QueryServiceConnection queryServiceConnection, String sql, - int resultSetType, int resultSetConcurrency) { - super(queryServiceConnection, resultSetType, resultSetConcurrency); - this.sql = sql; - } - - @Override - public ResultSet executeQuery() throws SQLException { - String fullSql = createSqlQuery(); - resultSet = super.executeQuery(fullSql); - return resultSet; - } - - @Override - public int executeUpdate() throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void setNull(int parameterIndex, int sqlType) throws SQLException { - parameters.put(parameterIndex, null); - } - - @Override - public void setBoolean(int parameterIndex, boolean x) throws SQLException { - parameters.put(parameterIndex, x); - } - - @Override - public void setByte(int parameterIndex, byte x) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void setShort(int parameterIndex, short x) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void setInt(int parameterIndex, int x) throws SQLException { - parameters.put(parameterIndex, x); - } - - @Override - public void setLong(int parameterIndex, long x) throws SQLException { - parameters.put(parameterIndex, x); - } - - @Override - public void setFloat(int parameterIndex, float x) throws SQLException { - parameters.put(parameterIndex, x); - } - - @Override - public void setDouble(int parameterIndex, double x) throws SQLException { - parameters.put(parameterIndex, x); - } - - @Override - public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException { - parameters.put(parameterIndex, x); - } - - @Override - public void setString(int parameterIndex, String x) throws SQLException { - parameters.put(parameterIndex, "'" + x + "'"); - } - - @Override - public void setBytes(int parameterIndex, byte[] x) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void setDate(int parameterIndex, Date x) throws SQLException { - parameters.put(parameterIndex, x); - } - - @Override - public void setTime(int parameterIndex, Time x) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void clearParameters() throws SQLException { - parameters.clear(); - } - - @Override - public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void setObject(int parameterIndex, Object x) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public boolean execute() throws SQLException { - String fullSql = createSqlQuery(); - resultSet = super.executeQuery(fullSql); - return true; - } - - @Override - public void addBatch() throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void setRef(int parameterIndex, Ref x) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void setBlob(int parameterIndex, Blob x) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void setClob(int parameterIndex, Clob x) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void setArray(int parameterIndex, Array x) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public ResultSetMetaData getMetaData() throws SQLException { - return null; - } - - @Override - public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException { - //NOOP - } - - @Override - public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException { - //NOOP - } - - @Override - public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException { - //NOOP - } - - @Override - public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException { - //NOOP - } - - @Override - public void setURL(int parameterIndex, URL x) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public ParameterMetaData getParameterMetaData() throws SQLException { - return null; - } - - @Override - public void setRowId(int parameterIndex, RowId x) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void setNString(int parameterIndex, String value) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void setNClob(int parameterIndex, NClob value) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void setClob(int parameterIndex, Reader reader, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void setClob(int parameterIndex, Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void setNClob(int parameterIndex, Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public ResultSet executeQuery(String sql) throws SQLException { - resultSet = super.executeQuery(sql); - return resultSet; - } - - @Override - public int executeUpdate(String sql) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void close() throws SQLException { - - } - - @Override - public int getMaxFieldSize() throws SQLException { - return 0; - } - - @Override - public void setMaxFieldSize(int max) throws SQLException { - - } - - @Override - public int getMaxRows() throws SQLException { - return 0; - } - - @Override - public void setMaxRows(int max) throws SQLException { - - } - - @Override - public void setEscapeProcessing(boolean enable) throws SQLException { - - } - - @Override - public int getQueryTimeout() throws SQLException { - return 0; - } - - @Override - public void setQueryTimeout(int seconds) throws SQLException { - //TODO: Check if this needs to be set to execute with http client. - } - - @Override - public void cancel() throws SQLException { - // TODO: Check if request can be cancelled. - } - - @Override - public SQLWarning getWarnings() throws SQLException { - return null; - } - - @Override - public void clearWarnings() throws SQLException { - - } - - @Override - public void setCursorName(String name) throws SQLException { - - } - - @Override - public boolean execute(String sql) throws SQLException { - resultSet = super.executeQuery(sql); - return true; - } - - @Override - public ResultSet getResultSet() throws SQLException { - return resultSet; - } - - @Override - public int getUpdateCount() throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public boolean getMoreResults() throws SQLException { - return false; - } - - @Override - public void setFetchDirection(int direction) throws SQLException { - //NOOP - } - - @Override - public int getFetchDirection() throws SQLException { - return 0; - } - - @Override - public void setFetchSize(int rows) throws SQLException { - //NOOP - } - - @Override - public int getFetchSize() throws SQLException { - return 0; - } - - @Override - public int getResultSetConcurrency() throws SQLException { - return 0; - } - - @Override - public int getResultSetType() throws SQLException { - return 0; - } - - @Override - public void addBatch(String sql) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public void clearBatch() throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public int[] executeBatch() throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public Connection getConnection() throws SQLException { - return connection; - } - - @Override - public boolean getMoreResults(int current) throws SQLException { - return false; - } - - @Override - public ResultSet getGeneratedKeys() throws SQLException { - return null; - } - - @Override - public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public int executeUpdate(String sql, String[] columnNames) throws SQLException { - throw new SQLFeatureNotSupportedException("Not supported"); - } - - @Override - public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { - return false; - } - - @Override - public boolean execute(String sql, int[] columnIndexes) throws SQLException { - return false; - } - - @Override - public boolean execute(String sql, String[] columnNames) throws SQLException { - return false; - } - - @Override - public int getResultSetHoldability() throws SQLException { - return 0; - } - - @Override - public boolean isClosed() throws SQLException { - return false; - } - - @Override - public void setPoolable(boolean poolable) throws SQLException { - - } - - @Override - public boolean isPoolable() throws SQLException { - return false; - } - - @Override - public void closeOnCompletion() throws SQLException { - - } - - @Override - public boolean isCloseOnCompletion() throws SQLException { - return false; - } - - @Override - public T unwrap(Class iface) throws SQLException { - return null; - } - - @Override - public boolean isWrapperFor(Class iface) throws SQLException { - return false; - } - - // Replaces ? in sql query with parameters - @VisibleForTesting - String createSqlQuery() throws SQLException { - String sqlQuery = sql; - int parameterIndex = 0; - while(sqlQuery.contains("?")) { - if (parameterIndex == parameters.size()) { - log.error("Not enough parameters to replace placeholders in query."); - throw new SQLException("Not enough parameters"); - } - Object parameter = parameters.get(parameterIndex++); - sqlQuery = sqlQuery.replaceFirst("\\?", parameter == null ? "null" : parameter.toString()); - } - return sqlQuery; - } -} diff --git a/src/test/java/com/salesforce/cdp/queryservice/core/QueryServiceConnectionTest.java b/src/test/java/com/salesforce/cdp/queryservice/core/QueryServiceConnectionTest.java index 57c6820..8ac10b6 100644 --- a/src/test/java/com/salesforce/cdp/queryservice/core/QueryServiceConnectionTest.java +++ b/src/test/java/com/salesforce/cdp/queryservice/core/QueryServiceConnectionTest.java @@ -19,6 +19,7 @@ import com.salesforce.cdp.queryservice.enums.QueryEngineEnum; import com.salesforce.cdp.queryservice.model.QueryConfigResponse; import com.salesforce.cdp.queryservice.util.Constants; +import org.assertj.core.api.Assertions; import org.junit.Test; import org.junit.jupiter.api.DisplayName; import org.junit.runner.RunWith; @@ -28,7 +29,10 @@ import org.powermock.modules.junit4.PowerMockRunner; import org.powermock.reflect.Whitebox; +import java.sql.PreparedStatement; +import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; import java.util.Properties; import static org.assertj.core.api.Assertions.assertThat; @@ -168,6 +172,45 @@ public void testGrpcIsValid() throws SQLException { assertThat(connection.isValid(10)).isFalse(); } + @Test + @DisplayName("Verify PreparedStatement creation is not supported") + public void testPreparedStatementsFail() throws SQLException { + replace(MemberMatcher.method(QueryServiceConnection.class, "isValid")) + .with((o, m, args) -> {return true;}); + + String serverUrl = "jdbc:queryService-jdbc:mysample://something.my.salesforce.com/"; + Properties properties = new Properties(); + properties.put(Constants.USER_NAME, "test-user"); + properties.put(Constants.USER, "test-user-12"); + properties.put(Constants.ENABLE_STREAM_FLOW, "true"); + + QueryServiceConnection connection = spy(new QueryServiceConnection(serverUrl, properties)); + + Assertions.assertThatThrownBy(() -> connection.prepareStatement("select * from individual__dlm")) + .hasMessage("PreparedStatement is not supported") + .isInstanceOf(SQLFeatureNotSupportedException.class); + + Assertions.assertThatThrownBy(() -> connection.prepareStatement("select * from individual__dlm", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) + .hasMessage("PreparedStatement is not supported") + .isInstanceOf(SQLFeatureNotSupportedException.class); + + Assertions.assertThatThrownBy(() -> connection.prepareStatement("select * from individual__dlm", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT)) + .hasMessage("Setting holdability is not supported") + .isInstanceOf(SQLFeatureNotSupportedException.class); + + Assertions.assertThatThrownBy(() -> connection.prepareStatement("select * from individual__dlm", 1)) + .hasMessage("Autogenerated keys not supported") + .isInstanceOf(SQLFeatureNotSupportedException.class); + + Assertions.assertThatThrownBy(() -> connection.prepareStatement("select * from individual__dlm", new int[] {1})) + .hasMessage("column Indexes not supported") + .isInstanceOf(SQLFeatureNotSupportedException.class); + + Assertions.assertThatThrownBy(() -> connection.prepareStatement("select * from individual__dlm", new String[] {"column__c"})) + .hasMessage("column Name not supported") + .isInstanceOf(SQLFeatureNotSupportedException.class); + } + private QueryConfigResponse getQueryConfigResponseTrino() { return getQueryConfigResponse(QueryEngineEnum.TRINO); } diff --git a/src/test/java/com/salesforce/cdp/queryservice/core/QueryServicePreparedStatementTest.java b/src/test/java/com/salesforce/cdp/queryservice/core/QueryServicePreparedStatementTest.java deleted file mode 100644 index 33543b9..0000000 --- a/src/test/java/com/salesforce/cdp/queryservice/core/QueryServicePreparedStatementTest.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2021, salesforce.com, inc. - * - * Licensed 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 com.salesforce.cdp.queryservice.core; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; - -import java.sql.Date; -import java.sql.ResultSet; -import java.sql.SQLException; - -@RunWith(MockitoJUnitRunner.class) -public class QueryServicePreparedStatementTest { - - @Rule - public ExpectedException exceptionRule = ExpectedException.none(); - - private QueryServicePreparedStatement preparedStatement; - - @Mock - private QueryServiceConnection connection; - - @Before - public void init() { - preparedStatement = new QueryServicePreparedStatement(connection, "select FirstName__c, BirthDate__c, YearlyIncome__c from Individual__dlm where FirstName__c = ? and YearlyIncome__c > ?", ResultSet.TYPE_FORWARD_ONLY, - ResultSet.CONCUR_READ_ONLY); - } - - @Test - public void testWildCardReplacementForPreparedStatement() throws SQLException { - preparedStatement.setString(0, "Angella"); - preparedStatement.setInt(1, 1000); - String sql = preparedStatement.createSqlQuery(); - Assert.assertEquals(sql, "select FirstName__c, BirthDate__c, YearlyIncome__c from Individual__dlm where FirstName__c = 'Angella' and YearlyIncome__c > 1000"); - } - - @Test - public void testSqlWithoutEnoughParameters() throws SQLException { - preparedStatement.setString(0, "Angella"); - exceptionRule.expect(SQLException.class); - exceptionRule.expectMessage("Not enough parameters"); - preparedStatement.createSqlQuery(); - } - - @Test - public void testSqlWithDateParameter() throws SQLException { - Date date = new Date(System.currentTimeMillis()); - preparedStatement = new QueryServicePreparedStatement(connection, "select FirstName__c, BirthDate__c from Individual__dlm where BirthDate__c > ?", ResultSet.TYPE_FORWARD_ONLY, - ResultSet.CONCUR_READ_ONLY); - preparedStatement.setDate(0, date); - String sql = preparedStatement.createSqlQuery(); - Assert.assertEquals(sql, "select FirstName__c, BirthDate__c from Individual__dlm where BirthDate__c > " + date.toString()); - } -}