All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.snowflake.client.jdbc.SnowflakePreparedStatementV1 Maven / Gradle / Ivy

/*
 * Copyright (c) 2012-2019 Snowflake Computing Inc. All rights reserved.
 */

package net.snowflake.client.jdbc;

import net.snowflake.client.core.ParameterBindingDTO;
import net.snowflake.client.core.ResultUtil;
import net.snowflake.client.core.SFException;
import net.snowflake.client.core.SFStatementMetaData;
import net.snowflake.client.core.StmtUtil;
import net.snowflake.client.log.SFLogger;
import net.snowflake.client.log.SFLoggerFactory;
import net.snowflake.common.core.SFBinary;
import net.snowflake.common.core.SqlState;
import net.snowflake.client.jdbc.SnowflakeType;

import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
import java.net.URL;
import java.sql.Array;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Date;
import java.sql.NClob;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
import java.sql.Ref;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.RowId;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.SQLXML;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;

class SnowflakePreparedStatementV1 extends SnowflakeStatementV1
    implements PreparedStatement, SnowflakePreparedStatement
{
  static final SFLogger logger = SFLoggerFactory.getLogger(
      SnowflakePreparedStatementV1.class);
  /**
   * Error code returned when describing a statement that is binding table name
   */
  private static final Integer ERROR_CODE_TABLE_BIND_VARIABLE_NOT_SET = 2128;
  /**
   * Error code when preparing statement with binding object names
   */
  private static final Integer ERROR_CODE_OBJECT_BIND_NOT_SET = 2129;
  /**
   * Error code returned when describing a ddl command
   */
  private static final Integer ERROR_CODE_STATEMENT_CANNOT_BE_PREPARED = 7;
  /**
   * snow-44393 Workaround for compiler cannot prepare to_timestamp(?, 3)
   */
  private static final Integer ERROR_CODE_FORMAT_ARGUMENT_NOT_STRING = 1026;
  /**
   * A hash set that contains the error code that will not lead to exception
   * in describe mode
   */
  private static final Set errorCodesIgnoredInDescribeMode
      = new HashSet<>(Arrays.asList(
      ERROR_CODE_TABLE_BIND_VARIABLE_NOT_SET,
      ERROR_CODE_STATEMENT_CANNOT_BE_PREPARED,
      ERROR_CODE_OBJECT_BIND_NOT_SET,
      ERROR_CODE_FORMAT_ARGUMENT_NOT_STRING));

  private final String sql;
  /**
   * statement and result metadata from describe phase
   */
  private SFStatementMetaData statementMetaData;
  /**
   * map of bind name to bind values for single query execution
   * 

* Currently, bind name is just value index */ private Map parameterBindings = new HashMap<>(); /** * map of bind values for batch query executions */ private Map batchParameterBindings = new HashMap<>(); private Map wasPrevValueNull = new HashMap<>(); /** * Counter for batch size if we are executing a statement with array bind * supported */ private int batchSize = 0; private boolean alreadyDescribed = false; /** * Construct SnowflakePreparedStatementV1 * * @param connection connection object * @param sql sql * @param skipParsing true if the applications want to skip parsing * to get metadata. false by default. * @param resultSetType result set type: ResultSet.TYPE_FORWARD_ONLY. * @param resultSetConcurrency result set conconcurrency: ResultSet.CONCUR_READ_ONLY. * @param resultSetHoldability result set holdability: ResultSet.CLOSE_CURSORS_AT_COMMIT * @throws SQLException if any SQL error occurs. */ SnowflakePreparedStatementV1( SnowflakeConnectionV1 connection, String sql, boolean skipParsing, int resultSetType, int resultSetConcurrency, int resultSetHoldability ) throws SQLException { super(connection, resultSetType, resultSetConcurrency, resultSetHoldability); this.sql = sql; this.statementMetaData = SFStatementMetaData.emptyMetaData(); } /** * This method will check alreadyDescribed flag. And if it is false, it will * try to issue a describe request to server. If true, it will skip * describe request. * @throws SQLException */ private void describeSqlIfNotTried() throws SQLException { if (!alreadyDescribed) { try { this.statementMetaData = sfStatement.describe(sql); } catch (SFException e) { throw new SnowflakeSQLException(e); } catch (SnowflakeSQLException e) { if (!errorCodesIgnoredInDescribeMode.contains(e.getErrorCode())) { throw e; } else { statementMetaData = SFStatementMetaData.emptyMetaData(); } } alreadyDescribed = true; } } @Override public ResultSet executeQuery() throws SQLException { logger.debug("executeQuery()"); return executeQueryInternal(sql, parameterBindings); } @Override public long executeLargeUpdate() throws SQLException { logger.debug("executeLargeUpdate()"); return executeUpdateInternal(sql, parameterBindings, true); } @Override public int executeUpdate() throws SQLException { logger.debug("executeUpdate()"); return (int) executeLargeUpdate(); } @Override public void setNull(int parameterIndex, int sqlType) throws SQLException { logger.debug("setNull(parameterIndex: {}, sqlType: {})", parameterIndex, SnowflakeType.JavaSQLType.find(sqlType)); raiseSQLExceptionIfStatementIsClosed(); ParameterBindingDTO binding = new ParameterBindingDTO( SnowflakeType.ANY.toString(), null); parameterBindings.put(String.valueOf(parameterIndex), binding); } @Override public void setBoolean(int parameterIndex, boolean x) throws SQLException { logger.debug( "setBoolean(parameterIndex: {}, boolean x)", parameterIndex); ParameterBindingDTO binding = new ParameterBindingDTO( SnowflakeUtil.javaTypeToSFTypeString(Types.BOOLEAN), String.valueOf(x)); parameterBindings.put(String.valueOf(parameterIndex), binding); } @Override public void setByte(int parameterIndex, byte x) throws SQLException { logger.debug("setByte(parameterIndex: {}, byte x)", parameterIndex); ParameterBindingDTO binding = new ParameterBindingDTO( SnowflakeUtil.javaTypeToSFTypeString(Types.TINYINT), String.valueOf(x)); parameterBindings.put(String.valueOf(parameterIndex), binding); } @Override public void setShort(int parameterIndex, short x) throws SQLException { logger.debug("setShort(parameterIndex: {}, short x)", parameterIndex); ParameterBindingDTO binding = new ParameterBindingDTO(SnowflakeUtil .javaTypeToSFTypeString(Types.SMALLINT), String.valueOf(x)); parameterBindings.put(String.valueOf(parameterIndex), binding); } @Override public void setInt(int parameterIndex, int x) throws SQLException { logger.debug("setInt(parameterIndex: {}, int x)", parameterIndex); ParameterBindingDTO binding = new ParameterBindingDTO(SnowflakeUtil .javaTypeToSFTypeString(Types.INTEGER), String.valueOf(x)); parameterBindings.put(String.valueOf(parameterIndex), binding); } @Override public void setLong(int parameterIndex, long x) throws SQLException { logger.debug("setLong(parameterIndex: {}, long x)", parameterIndex); ParameterBindingDTO binding = new ParameterBindingDTO( SnowflakeUtil.javaTypeToSFTypeString(Types.BIGINT), String.valueOf(x)); parameterBindings.put(String.valueOf(parameterIndex), binding); } @Override public void setFloat(int parameterIndex, float x) throws SQLException { logger.debug("setFloat(parameterIndex: {}, float x)", parameterIndex); ParameterBindingDTO binding = new ParameterBindingDTO( SnowflakeUtil.javaTypeToSFTypeString(Types.FLOAT), String.valueOf(x)); parameterBindings.put(String.valueOf(parameterIndex), binding); } @Override public void setDouble(int parameterIndex, double x) throws SQLException { logger.debug("setDouble(parameterIndex: {}, double x)", parameterIndex); ParameterBindingDTO binding = new ParameterBindingDTO( SnowflakeUtil.javaTypeToSFTypeString(Types.DOUBLE), String.valueOf(x)); parameterBindings.put(String.valueOf(parameterIndex), binding); } @Override public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException { logger.debug("setBigDecimal(parameterIndex: {}, BigDecimal x)", parameterIndex); if (x == null) { setNull(parameterIndex, Types.DECIMAL); } else { ParameterBindingDTO binding = new ParameterBindingDTO( SnowflakeUtil.javaTypeToSFTypeString(Types.DECIMAL), String.valueOf(x)); parameterBindings.put(String.valueOf(parameterIndex), binding); } } @Override public void setString(int parameterIndex, String x) throws SQLException { logger.debug("setString(parameterIndex: {}, String x)", parameterIndex); ParameterBindingDTO binding = new ParameterBindingDTO( SnowflakeUtil.javaTypeToSFTypeString(Types.VARCHAR), x); parameterBindings.put(String.valueOf(parameterIndex), binding); } @Override public void setBytes(int parameterIndex, byte[] x) throws SQLException { logger.debug("setBytes(parameterIndex: {}, byte[] x)", parameterIndex); ParameterBindingDTO binding = new ParameterBindingDTO(SnowflakeUtil .javaTypeToSFTypeString(Types.BINARY), new SFBinary(x).toHex()); parameterBindings.put(String.valueOf(parameterIndex), binding); } @Override public void setDate(int parameterIndex, Date x) throws SQLException { logger.debug("setDate(parameterIndex: {}, Date x)", parameterIndex); if (x == null) { setNull(parameterIndex, Types.DATE); } else { ParameterBindingDTO binding = new ParameterBindingDTO( SnowflakeUtil.javaTypeToSFTypeString(Types.DATE), String.valueOf(x.getTime() + TimeZone.getDefault().getOffset(x.getTime()) - ResultUtil.msDiffJulianToGregorian(x))); parameterBindings.put(String.valueOf(parameterIndex), binding); } } @Override public void setTime(int parameterIndex, Time x) throws SQLException { logger.debug("setTime(parameterIndex: {}, Time x)", parameterIndex); if (x == null) { setNull(parameterIndex, Types.TIME); } else { // Convert to nanoseconds since midnight using the input time mod 24 hours. final long MS_IN_DAY = 86400 * 1000; long msSinceEpoch = x.getTime(); // Use % + % instead of just % to get the nonnegative remainder. // TODO(mkember): Change to use Math.floorMod when Client is on Java 8. long msSinceMidnight = (msSinceEpoch % MS_IN_DAY + MS_IN_DAY) % MS_IN_DAY; long nanosSinceMidnight = msSinceMidnight * 1000 * 1000; ParameterBindingDTO binding = new ParameterBindingDTO( SnowflakeUtil.javaTypeToSFTypeString(Types.TIME), String.valueOf(nanosSinceMidnight)); parameterBindings.put(String.valueOf(parameterIndex), binding); sfStatement.setHasUnsupportedStageBind(true); } } @Override public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException { logger.debug("setTimestamp(parameterIndex: {}, Timestamp x)", parameterIndex); // convert the timestamp from being in local time zone to be in UTC timezone String value = x == null ? null : String.valueOf( BigDecimal.valueOf((x.getTime() - ResultUtil.msDiffJulianToGregorian(x)) / 1000). scaleByPowerOfTen(9).add(BigDecimal.valueOf(x.getNanos()))); SnowflakeType sfType = SnowflakeUtil.javaTypeToSFType(Types.TIMESTAMP); if (sfType == SnowflakeType.TIMESTAMP) { sfType = connection.getSfSession().getTimestampMappedType(); } ParameterBindingDTO binding = new ParameterBindingDTO(sfType.name(), value); parameterBindings.put(String.valueOf(parameterIndex), binding); } @Override public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override @Deprecated public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public void clearParameters() throws SQLException { parameterBindings.clear(); if (batchParameterBindings.isEmpty()) { sfStatement.setHasUnsupportedStageBind(false); } } @Override public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException { if (x == null) { setNull(parameterIndex, targetSqlType); } else if (targetSqlType == Types.DATE) { setDate(parameterIndex, (Date) x); } else if (targetSqlType == Types.TIME) { setTime(parameterIndex, (Time) x); } else if (targetSqlType == Types.TIMESTAMP) { setTimestamp(parameterIndex, (Timestamp) x); } else { logger.debug("setObject(parameterIndex: {}, Object x, sqlType: {})", parameterIndex, SnowflakeType.JavaSQLType.find(targetSqlType)); ParameterBindingDTO binding = new ParameterBindingDTO( SnowflakeUtil.javaTypeToSFTypeString(targetSqlType), String.valueOf(x)); parameterBindings.put(String.valueOf(parameterIndex), binding); } } @Override public void setObject(int parameterIndex, Object x) throws SQLException { if (x == null) { setNull(parameterIndex, Types.NULL); } else if (x instanceof String) { setString(parameterIndex, (String) x); } else if (x instanceof BigDecimal) { setBigDecimal(parameterIndex, (BigDecimal) x); } else if (x instanceof Short) { setShort(parameterIndex, (Short) x); } else if (x instanceof Integer) { setInt(parameterIndex, (Integer) x); } else if (x instanceof Long) { setLong(parameterIndex, (Long) x); } else if (x instanceof Float) { setFloat(parameterIndex, (Float) x); } else if (x instanceof Double) { setDouble(parameterIndex, (Double) x); } else if (x instanceof Date) { setDate(parameterIndex, (Date) x); } else if (x instanceof Time) { setTime(parameterIndex, (Time) x); } else if (x instanceof Timestamp) { setTimestamp(parameterIndex, (Timestamp) x); } else if (x instanceof Boolean) { setBoolean(parameterIndex, (Boolean) x); } else { throw new SnowflakeSQLException(SqlState.FEATURE_NOT_SUPPORTED, ErrorCode.DATA_TYPE_NOT_SUPPORTED.getMessageCode(), "Object type: " + x.getClass()); } } @Override public boolean execute() throws SQLException { logger.debug("execute: {}", sql); return executeInternal(sql, parameterBindings); } @Override public void addBatch() throws SQLException { logger.debug("addBatch()"); raiseSQLExceptionIfStatementIsClosed(); describeSqlIfNotTried(); if (statementMetaData.isArrayBindSupported()) { for (Map.Entry binding : parameterBindings.entrySet()) { // get the entry for the bind variable in the batch binding map ParameterBindingDTO bindingValueAndType = batchParameterBindings.get(binding.getKey()); List values; Object newValue = binding.getValue().getValue(); // create binding value and type for the first time if (bindingValueAndType == null) { // create the value list values = new ArrayList<>(); bindingValueAndType = new ParameterBindingDTO( binding.getValue().getType(), values); // put the new map into the batch batchParameterBindings.put(binding.getKey(), bindingValueAndType); wasPrevValueNull.put( binding.getKey(), binding.getValue().getValue() == null); } else { // make sure type matches except for null values String prevType = bindingValueAndType.getType(); String newType = binding.getValue().getType(); if (wasPrevValueNull.get(binding.getKey()) && newValue != null) { // if previous value is null and the current value is not null // override the data type. bindingValueAndType = batchParameterBindings.remove( binding.getKey()); bindingValueAndType.setType(newType); batchParameterBindings.put(binding.getKey(), bindingValueAndType); prevType = newType; wasPrevValueNull.put(binding.getKey(), false); } // if previous type is null, replace it with new type if (SnowflakeType.ANY.name().equalsIgnoreCase(prevType) && !SnowflakeType.ANY.name().equalsIgnoreCase(newType)) { bindingValueAndType.setType(newType); } else if (binding.getValue().getValue() != null && !prevType.equalsIgnoreCase(newType)) { String row = "Unknown"; if (bindingValueAndType.getValue() instanceof Collection) { final List typeCheckedList = new ArrayList<>(); for (Object e : (List) bindingValueAndType.getValue()) { typeCheckedList.add((String) e); } values = typeCheckedList; row = Integer.toString(values.size() + 1); } throw new SnowflakeSQLException(SqlState.FEATURE_NOT_SUPPORTED, ErrorCode.ARRAY_BIND_MIXED_TYPES_NOT_SUPPORTED.getMessageCode(), SnowflakeType.getJavaType(SnowflakeType.fromString(prevType)).name(), SnowflakeType.getJavaType(SnowflakeType.fromString(newType)).name(), binding.getKey(), row); } // found the existing map so just get the value list final List typeCheckedList = new ArrayList<>(); for (Object e : (List) bindingValueAndType.getValue()) { typeCheckedList.add((String) e); } values = typeCheckedList; } // add the value to the list of values in batch binding map values.add((String) newValue); bindingValueAndType.setValue(values); } batchSize++; } else { batch.add(new BatchEntry(this.sql, parameterBindings)); parameterBindings = new HashMap<>(); } } @Override public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public void setRef(int parameterIndex, Ref x) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public void setBlob(int parameterIndex, Blob x) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public void setClob(int parameterIndex, Clob x) throws SQLException { setString(parameterIndex, x.toString()); } @Override public void setArray(int parameterIndex, Array x) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public ResultSetMetaData getMetaData() throws SQLException { logger.debug("getMetaData()"); raiseSQLExceptionIfStatementIsClosed(); describeSqlIfNotTried(); return new SnowflakeResultSetMetaDataV1( this.statementMetaData.getResultSetMetaData()); } @Override public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException { logger.debug("setDate(int parameterIndex, Date x, Calendar cal)"); raiseSQLExceptionIfStatementIsClosed(); if (x == null) { setNull(parameterIndex, Types.DATE); } else { // convert the date from to be in local time zone to be in UTC String value = String.valueOf(x.getTime() + cal.getTimeZone().getOffset(x.getTime()) - ResultUtil.msDiffJulianToGregorian(x)); ParameterBindingDTO binding = new ParameterBindingDTO( SnowflakeUtil.javaTypeToSFTypeString(Types.DATE), value); parameterBindings.put(String.valueOf(parameterIndex), binding); } } @Override public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException { logger.debug("setTime(int parameterIndex, Time x, Calendar cal)"); raiseSQLExceptionIfStatementIsClosed(); setTime(parameterIndex, x); } @Override public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException { logger.debug("setTimestamp(int parameterIndex, Timestamp x, Calendar cal)"); raiseSQLExceptionIfStatementIsClosed(); // convert the time from being in UTC to be in local time zone String value = null; if (x != null) { long milliSecSinceEpoch = x.getTime(); milliSecSinceEpoch = milliSecSinceEpoch + cal.getTimeZone().getOffset(milliSecSinceEpoch); value = String.valueOf( BigDecimal.valueOf(milliSecSinceEpoch / 1000). scaleByPowerOfTen(9).add(BigDecimal.valueOf(x.getNanos()))); } SnowflakeType sfType = SnowflakeUtil.javaTypeToSFType(Types.TIMESTAMP); if (sfType == SnowflakeType.TIMESTAMP) { sfType = connection.getSfSession().getTimestampMappedType(); } ParameterBindingDTO binding = new ParameterBindingDTO(sfType.name(), value); parameterBindings.put(String.valueOf(parameterIndex), binding); } @Override public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException { logger.debug("setNull(int parameterIndex, int sqlType, String typeName)"); setNull(parameterIndex, sqlType); } @Override public void setURL(int parameterIndex, URL x) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public ParameterMetaData getParameterMetaData() throws SQLException { describeSqlIfNotTried(); return new SnowflakeParameterMetadata(statementMetaData); } @Override public void setRowId(int parameterIndex, RowId x) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public void setNString(int parameterIndex, String value) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public void setNClob(int parameterIndex, NClob value) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public void setClob(int parameterIndex, Reader reader, long length) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException { logger.debug( "setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength)"); raiseSQLExceptionIfStatementIsClosed(); if (x == null) { setNull(parameterIndex, targetSqlType); } else if (targetSqlType == Types.DECIMAL || targetSqlType == Types.NUMERIC) { BigDecimal decimalObj = new BigDecimal(String.valueOf(x)); decimalObj.setScale(scaleOrLength); setBigDecimal(parameterIndex, decimalObj); } else { setObject(parameterIndex, x, targetSqlType); } } @Override public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public void setClob(int parameterIndex, Reader reader) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public void setNClob(int parameterIndex, Reader reader) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public ResultSet executeQuery(String sql) throws SQLException { logger.debug("executeQuery(String sql)"); throw new SnowflakeSQLException( ErrorCode.UNSUPPORTED_STATEMENT_TYPE_IN_EXECUTION_API, StmtUtil.truncateSQL(sql)); } @Override public int executeUpdate(String sql) throws SQLException { logger.debug("executeUpdate(String sql)"); throw new SnowflakeSQLException( ErrorCode.UNSUPPORTED_STATEMENT_TYPE_IN_EXECUTION_API, StmtUtil.truncateSQL(sql)); } @Override public boolean execute(String sql) throws SQLException { logger.debug("execute(String sql)"); throw new SnowflakeSQLException( ErrorCode.UNSUPPORTED_STATEMENT_TYPE_IN_EXECUTION_API, StmtUtil.truncateSQL(sql)); } @Override public void addBatch(String sql) throws SQLException { throw new SnowflakeSQLException( ErrorCode.UNSUPPORTED_STATEMENT_TYPE_IN_EXECUTION_API, StmtUtil.truncateSQL(sql)); } @Override public void clearBatch() throws SQLException { super.clearBatch(); batchParameterBindings.clear(); parameterBindings.clear(); wasPrevValueNull.clear(); batchSize = 0; sfStatement.setHasUnsupportedStageBind(false); } @Override public int[] executeBatch() throws SQLException { logger.debug("executeBatch()"); raiseSQLExceptionIfStatementIsClosed(); describeSqlIfNotTried(); if (this.statementMetaData.getStatementType().isGenerateResultSet()) { throw new SnowflakeSQLException( ErrorCode.UNSUPPORTED_STATEMENT_TYPE_IN_EXECUTION_API, StmtUtil.truncateSQL(sql)); } int[] updateCounts = null; try { if (this.statementMetaData.isArrayBindSupported()) { int updateCount = (int) executeUpdateInternal( this.sql, batchParameterBindings, false); // when update count is the same as the number of bindings in the batch, // expand the update count into an array (SNOW-14034) if (updateCount == batchSize) { updateCounts = new int[updateCount]; for (int idx = 0; idx < updateCount; idx++) updateCounts[idx] = 1; } else { updateCounts = new int[]{updateCount}; } } else { updateCounts = executeBatchInternal(false).intArr; } } finally { this.clearBatch(); } return updateCounts; } @Override public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public int executeUpdate(String sql, String[] columnNames) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public boolean execute(String sql, int[] columnIndexes) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public boolean execute(String sql, String[] columnNames) throws SQLException { throw new SQLFeatureNotSupportedException(); } // For testing use only Map getBatchParameterBindings() { return batchParameterBindings; } // package private for testing purpose only Map getParameterBindings() { return parameterBindings; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy