src-main.org.awakefw.sql.jdbc.PreparedStatementHttp Maven / Gradle / Ivy
Show all versions of awake-sql Show documentation
/*
* This file is part of Awake SQL.
* Awake SQL: Remote JDBC access over HTTP.
* Copyright (C) 2013, KawanSoft SAS
* (http://www.kawansoft.com). All rights reserved.
*
* Awake SQL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Awake SQL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see .
*
* If you develop commercial activities using Awake SQL, you must:
* a) disclose and distribute all source code of your own product,
* b) license your own product under the GNU General Public License.
*
* You can be released from the requirements of the license by
* purchasing a commercial license. Buying such a license will allow you
* to ship Awake SQL with your closed source products without disclosing
* the source code.
*
* For more information, please contact KawanSoft SAS at this
* address: [email protected]
*
* Any modifications to this file must keep this entire header
* intact.
*/
package org.awakefw.sql.jdbc;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringReader;
import java.io.Writer;
import java.math.BigDecimal;
import java.net.URL;
import java.sql.Array;
import java.sql.BatchUpdateException;
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.Statement;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Calendar;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.awakefw.file.api.util.AwakeDebug;
import org.awakefw.file.api.util.HtmlConverter;
import org.awakefw.file.util.AwakeFileUtil;
import org.awakefw.file.util.Tag;
import org.awakefw.sql.jdbc.http.JdbcHttpBatchTransfer;
import org.awakefw.sql.jdbc.http.JdbcHttpExecuteRawTransfer;
import org.awakefw.sql.jdbc.http.JdbcHttpStatementTransfer;
import org.awakefw.sql.jdbc.util.AwakeAsciiStream;
import org.awakefw.sql.jdbc.util.AwakeInputStream;
import org.awakefw.sql.jdbc.util.AwakeReader;
import org.awakefw.sql.jdbc.util.ParametersUtil;
import org.awakefw.sql.json.IntArrayTransport;
import org.awakefw.sql.json.StatementHolder;
import org.awakefw.sql.transport.TransportConverter;
import org.awakefw.sql.util.FileNameFromBlobBuilder;
/**
* Creates and handle a Prepared Statement Http.
*/
public class PreparedStatementHttp extends StatementHttp implements
PreparedStatement {
/** Debug flag */
private static boolean DEBUG = AwakeDebug
.isSet(PreparedStatementHttp.class);
/**
* The holder that contains the sql order and the list if (parameter type,
* parameter value ) for prepared statements
**/
private StatementHolder statementHolder = null;
/** The statement to execute */
private String sql = null;
/**
* The update count returned by PreparedStatementHttp.getUpdateCount() after
* an execute()
*/
private int updateCount = 0;
/**
* Constructor
*
* @param connectionHttp
* The Http Connection
* @param sql
* the sql statement to use
* @param resultSetType
* The result set type
* @param resultSetConcurrency
* The result set concurrency
* @param resultSetHoldability
* The result set holdability
* @throws SQLException
*/
public PreparedStatementHttp(ConnectionHttp connectionHttp, String sql,
int resultSetType, int resultSetConcurrency,
int resultSetHoldability) throws SQLException {
super(connectionHttp, resultSetType, resultSetConcurrency,
resultSetHoldability);
if (sql == null) {
throw new SQLException("sql order is null!");
}
this.sql = sql.trim();
statementHolder = new StatementHolder(sql, resultSetType,
resultSetConcurrency, resultSetHoldability);
statementHolder.setPreparedStatement(true);
statementHolder.setHtmlEncodingOn(connectionHttp.isHtmlEncodingOn());
}
/**
* Constructor for auto-generated keys
*
* @param connectionHttp
* The Http Connection
* @param sql
* the sql statement to use
* @param autoGeneratedKeys
* a flag indicating whether auto-generated keys should be
* returned; one of Statement.RETURN_GENERATED_KEYS
* or Statement.NO_GENERATED_KEYS
*
* @throws SQLException
*/
public PreparedStatementHttp(ConnectionHttp connectionHttp, String sql,
int autoGeneratedKeys) throws SQLException {
super(connectionHttp, ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT);
if (sql == null) {
throw new SQLException("sql order is null!");
}
this.sql = sql.trim();
statementHolder = new StatementHolder(sql, autoGeneratedKeys);
statementHolder.setPreparedStatement(true);
statementHolder.setHtmlEncodingOn(connectionHttp.isHtmlEncodingOn());
}
/**
* Constructor for auto-generated keys
*
* @param connectionHttp
* The Http Connection
* @param sql
* the sql statement to use
* @param columnIndexes
* an array of column indexes indicating the columns that should
* be returned from the inserted row or rows
*
* @throws SQLException
*/
public PreparedStatementHttp(ConnectionHttp connectionHttp, String sql,
int[] columnIndexes) throws SQLException {
super(connectionHttp, ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT);
if (sql == null) {
throw new SQLException("sql order is null!");
}
this.sql = sql.trim();
statementHolder = new StatementHolder(sql, columnIndexes);
statementHolder.setPreparedStatement(true);
statementHolder.setHtmlEncodingOn(connectionHttp.isHtmlEncodingOn());
}
/**
* Constructor for auto-generated keys
*
* @param connectionHttp
* The Http Connection
* @param sql
* the sql statement to use
* @param columnNames
* an array of column names indicating the columns that should be
* returned from the inserted row or rows
*
* @throws SQLException
*/
public PreparedStatementHttp(ConnectionHttp connectionHttp, String sql,
String[] columnNames) throws SQLException {
super(connectionHttp, ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT);
if (sql == null) {
throw new SQLException("sql order is null!");
}
this.sql = sql.trim();
statementHolder = new StatementHolder(sql, columnNames);
statementHolder.setPreparedStatement(true);
statementHolder.setHtmlEncodingOn(connectionHttp.isHtmlEncodingOn());
}
/**
* @throws SQLException
* @see java.sql.Statement#close()
*/
@Override
public void close() throws SQLException {
super.close();
statementHolder = null;
}
/**
* Executes the SQL query in this PreparedStatement
object and
* returns the ResultSet
object generated by the query.
*
* @return a ResultSet
object that contains the data produced
* by the query; never null
* @exception SQLException
* if a database access error occurs or the SQL statement
* does not return a ResultSet
object
*/
@Override
public ResultSet executeQuery() throws SQLException {
testIfClosed();
if (connectionHttp.isStatelessMode()) {
if (!connectionHttp.getAutoCommit()) {
throw new IllegalStateException(
Tag.AWAKE
+ "executeQuery() can\'t be executed when auto commit is off.");
}
}
// Check that all parameters values are set
ParametersUtil.checkParameters(statementHolder);
statementHolder.setPreparedStatement(true);
statementHolder.setExecuteUpdate(false);
statementHolder.setFetchSize(fetchSize);
statementHolder.setMaxRows(maxRows);
statementHolder.setQueryTimeout(queryTimeout);
statementHolder.setEscapeProcessing(escapeProcessingInt);
// Send unique order to Server to SQL Executor
JdbcHttpStatementTransfer jdbcHttpStatementTransfer = new JdbcHttpStatementTransfer(
connectionHttp, connectionHttp.getAuthenticationToken());
File receiveFile = jdbcHttpStatementTransfer
.getFileFromExecuteQueryOnServer(statementHolder);
debug("getFileFromexecuteOnServer() : " + receiveFile);
ResultSet rs = new ResultSetHttp(connectionHttp, statementHolder, this,
receiveFile);
return rs;
}
/**
* Executes the SQL statement in this PreparedStatement
object,
* which must be an SQL INSERT
, UPDATE
or
* DELETE
statement; or an SQL statement that returns nothing,
* such as a DDL statement.
*
* @return either (1) the row count for INSERT
,
* UPDATE
, or DELETE
statements or (2) 0
* for SQL statements that return nothing
* @exception SQLException
* if a database access error occurs or the SQL statement
* returns a ResultSet
object
*/
@Override
public synchronized int executeUpdate() throws SQLException {
testIfClosed();
lastExecuteIsRaw = false;
// Check that all parameters values are set
ParametersUtil.checkParameters(statementHolder);
statementHolder.setPreparedStatement(true);
statementHolder.setExecuteUpdate(true);
// Add the statement to the statement list
connectionHttp.addStatementHolder(statementHolder);
int rc = 0;
// Execute
//if (connectionHttp.getAutoCommit()) {
if ((connectionHttp.isStatelessMode() && connectionHttp.getAutoCommit()
|| !connectionHttp.isStatelessMode())) {
try {
debug("before getStringFromExecuteUpdateListOnServer()");
// Send order to Server to SQL Executor
connectionHttp.receiveFromExecuteUpdate = connectionHttp
.getStringFromExecuteUpdateListOnServer();
debug("after getStringFromExecuteUpdateListOnServer()");
BufferedReader bufferedReader = new BufferedReader(
new StringReader(
connectionHttp.receiveFromExecuteUpdate));
String line1 = null;
try {
line1 = bufferedReader.readLine();
} catch (IOException e1) {
throw new SQLException(e1);
}
try {
rc = Integer.parseInt(line1);
} catch (NumberFormatException e) {
throw new SQLException(Tag.AWAKE_PRODUCT_FAIL
+ e.getMessage(),
new IOException(e.getMessage(), e));
}
} finally {
connectionHttp.resetStatementHolderList(); // Safety reset of
// list
}
}
return rc;
}
/**
* Executes the given SQL statement, which may return multiple results. In
* some (uncommon) situations, a single SQL statement may return multiple
* result sets and/or update counts. Normally you can ignore this unless you
* are (1) executing a stored procedure that you know may return multiple
* results or (2) you are dynamically executing an unknown SQL string.
*
* The execute
method executes an SQL statement and indicates
* the form of the first result. You must then use the methods
* getResultSet
or getUpdateCount
to retrieve the
* result, and getMoreResults
to move to any subsequent
* result(s).
*
* @param sql
* any SQL statement
* @return true
if the first result is a ResultSet
* object; false
if it is an update count or there are
* no results
* @exception SQLException
* if a database access error occurs
* @see #getResultSet
* @see #getUpdateCount
* @see #getMoreResults
*/
@Override
public boolean execute() throws SQLException {
testIfClosed();
if (connectionHttp.isStatelessMode()) {
if (!connectionHttp.getAutoCommit()) {
throw new IllegalStateException(Tag.AWAKE
+ "execute can\'t be executed when auto commit is off.");
}
}
lastExecuteIsRaw = true;
// Check that all parameters values are set
ParametersUtil.checkParameters(statementHolder);
statementHolder.setPreparedStatement(true);
statementHolder.setExecuteUpdate(false);
statementHolder.setFetchSize(fetchSize);
statementHolder.setMaxRows(maxRows);
statementHolder.setQueryTimeout(queryTimeout);
statementHolder.setEscapeProcessing(escapeProcessingInt);
// Reset the fields values
rsFromExecute = null;
updateCount = -1;
// Send order to Server to SQL Executor
JdbcHttpExecuteRawTransfer jdbcHttpExecuteRawTransfer = new JdbcHttpExecuteRawTransfer(
connectionHttp, connectionHttp.getAuthenticationToken());
receiveFileFromExecute = jdbcHttpExecuteRawTransfer
.getFileFromExecuteRaw(statementHolder);
localFiles.add(receiveFileFromExecute);
debug("getFileFromexecuteOnServer() : " + receiveFileFromExecute);
boolean fileResultSet = super.isFileResultSet(receiveFileFromExecute);
try {
if (DEBUG) {
String fileContent = FileUtils
.readFileToString(receiveFileFromExecute);
System.out.println(fileContent);
}
} catch (IOException e2) {
throw new SQLException(e2);
}
if (fileResultSet) {
// Transform the Result Set in String back to an Result Set
// (emulated)
rsFromExecute = new ResultSetHttp(connectionHttp, statementHolder,
this, receiveFileFromExecute);
return true;
} else {
BufferedReader bufferedReader = null;
String line1 = null;
try {
bufferedReader = new BufferedReader(new FileReader(
receiveFileFromExecute));
line1 = bufferedReader.readLine();
} catch (IOException e1) {
throw new SQLException(e1);
} finally {
IOUtils.closeQuietly(bufferedReader);
}
String updateCountStr = StringUtils.substringAfter(line1,
"getUpdateCount=");
try {
updateCount = Integer.parseInt(updateCountStr);
} catch (NumberFormatException e) {
throw new SQLException(Tag.AWAKE_PRODUCT_FAIL + e.getMessage(),
new IOException(e.getMessage(), e));
}
return false;
}
}
/*
* (non-Javadoc)
*
* @see org.awakefw.sql.jdbc.StatementHttp#getUpdateCount()
*/
@Override
public int getUpdateCount() throws SQLException {
return updateCount;
}
/**
* Moves to this Statement
object's next result, returns
* true
if it is a ResultSet
object, and
* implicitly closes any current ResultSet
object(s) obtained
* with the method getResultSet
.
*
*
* There are no more results when the following is true:
*
*
* (!getMoreResults() && (getUpdateCount() == -1)
*
*
* @return true
if the next result is a ResultSet
* object; false
if it is an update count or there are
* no more results
* @exception SQLException
* if a database access error occurs
* @see #execute
*/
public boolean getMoreResults() throws SQLException {
// always return false for now:
return false;
}
/**
* Sets the designated parameter to SQL NULL
.
*
*
* Note: You must specify the parameter's SQL type.
*
* @param parameterIndex
* the first parameter is 1, the second is 2, ...
* @param sqlType
* the SQL type code defined in java.sql.Types
* @exception SQLException
* if a database access error occurs
*/
public void setNull(int parameterIndex, int sqlType) throws SQLException {
testIfClosed();
statementHolder.setNullParameter(parameterIndex, sqlType);
}
/**
* Sets the designated parameter to the given Java boolean
* value. The driver converts this to an SQL BIT
value when it
* sends it to the database.
*
* @param parameterIndex
* the first parameter is 1, the second is 2, ...
* @param x
* the parameter value
* @exception SQLException
* if a database access error occurs
*/
@Override
public void setBoolean(int parameterIndex, boolean x) throws SQLException {
testIfClosed();
statementHolder.setParameter(parameterIndex, x);
}
/**
* Sets the designated parameter to the given Java short
value.
* The driver converts this to an SQL SMALLINT
value when it
* sends it to the database.
*
* @param parameterIndex
* the first parameter is 1, the second is 2, ...
* @param x
* the parameter value
* @exception SQLException
* if a database access error occurs
*/
@Override
public void setShort(int parameterIndex, short x) throws SQLException {
testIfClosed();
statementHolder.setParameter(parameterIndex, x);
}
/**
* Sets the designated parameter to the given Java int
value.
* The driver converts this to an SQL INTEGER
value when it
* sends it to the database.
*
* @param parameterIndex
* the first parameter is 1, the second is 2, ...
* @param x
* the parameter value
* @exception SQLException
* if a database access error occurs
*/
@Override
public void setInt(int parameterIndex, int x) throws SQLException {
testIfClosed();
statementHolder.setParameter(parameterIndex, x);
}
/**
* Sets the designated parameter to the given Java long
value.
* The driver converts this to an SQL BIGINT
value when it
* sends it to the database.
*
* @param parameterIndex
* the first parameter is 1, the second is 2, ...
* @param x
* the parameter value
* @exception SQLException
* if a database access error occurs
*/
@Override
public void setLong(int parameterIndex, long x) throws SQLException {
testIfClosed();
statementHolder.setParameter(parameterIndex, x);
}
/**
* Sets the designated parameter to the given Java float
value.
* The driver converts this to an SQL FLOAT
value when it sends
* it to the database.
*
* @param parameterIndex
* the first parameter is 1, the second is 2, ...
* @param x
* the parameter value
* @exception SQLException
* if a database access error occurs
*/
@Override
public void setFloat(int parameterIndex, float x) throws SQLException {
testIfClosed();
statementHolder.setParameter(parameterIndex, x);
}
/**
* Sets the designated parameter to the given Java double
* value. The driver converts this to an SQL DOUBLE
value when
* it sends it to the database.
*
* @param parameterIndex
* the first parameter is 1, the second is 2, ...
* @param x
* the parameter value
* @exception SQLException
* if a database access error occurs
*/
@Override
public void setDouble(int parameterIndex, double x) throws SQLException {
testIfClosed();
statementHolder.setParameter(parameterIndex, x);
}
/**
* Sets the designated parameter to the given
* java.math.BigDecimal
value. The driver converts this to an
* SQL NUMERIC
value when it sends it to the database.
*
* @param parameterIndex
* the first parameter is 1, the second is 2, ...
* @param x
* the parameter value
* @exception SQLException
* if parameterIndex does not correspond to a parameter
* marker in the SQL statement; if a database access error
* occurs or this method is called on a closed
* PreparedStatement
*/
@Override
public void setBigDecimal(int parameterIndex, BigDecimal x)
throws SQLException {
testIfClosed();
statementHolder.setParameter(parameterIndex, x);
}
/**
* Sets the designated parameter to the given Java String
* value. The driver converts this to an SQL VARCHAR
or
* LONGVARCHAR
value (depending on the argument's size relative
* to the driver's limits on VARCHAR
values) when it sends it
* to the database.
*
* @param parameterIndex
* the first parameter is 1, the second is 2, ...
* @param x
* the parameter value
* @exception SQLException
* if a database access error occurs
*/
@Override
public void setString(int parameterIndex, String x) throws SQLException {
testIfClosed();
// x = TransportConverter.toTransportFormat(x);
if (x != null && x.length() > connectionHttp.getMaxLengthForString()) {
throw new SQLException(
"String is too big for upload with Awake SQL: "
+ x.length()
+ " bytes. Maximum length authorized is: "
+ connectionHttp.getMaxLengthForString());
}
statementHolder.setParameter(parameterIndex, x);
}
/**
* Sets the designated parameter to the given String
object.
* The driver converts this to a SQL NCHAR
or
* NVARCHAR
or LONGNVARCHAR
value
* (depending on the argument's
* size relative to the driver's limits on NVARCHAR
values)
* when it sends it to the database.
*
* @param parameterIndex of the first parameter is 1, the second is 2, ...
* @param value the parameter value
* @throws SQLException if parameterIndex does not correspond to a parameter
* marker in the SQL statement; if the driver does not support national
* character sets; if the driver can detect that a data conversion
* error could occur; if a database access error occurs; or
* this method is called on a closed PreparedStatement
* @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
* @since 1.6
*/
@Override
public void setNString(int parameterIndex, String value)
throws SQLException {
testIfClosed();
// x = TransportConverter.toTransportFormat(x);
if (value != null && value.length() > connectionHttp.getMaxLengthForString()) {
throw new SQLException(
"String is too big for upload with Awake SQL: "
+ value.length()
+ " bytes. Maximum length authorized is: "
+ connectionHttp.getMaxLengthForString());
}
statementHolder.setParameter(parameterIndex, value, StatementHolder.SET_N_STRING);
}
/**
* Sets the designated parameter to the given Java byte
value.
* The driver converts this to an SQL TINYINT
value when it
* sends it to the database.
*
* @param parameterIndex
* the first parameter is 1, the second is 2, ...
* @param x
* the parameter value
* @exception SQLException
* if a database access error occurs
*/
@Override
public void setByte(int parameterIndex, byte x) throws SQLException {
testIfClosed();
byte[] theByte = new byte[1];
theByte[0] = x;
String encodedString = TransportConverter.toTransportFormat(theByte);
// parameterValues.put(parameterIndex, hexString);
statementHolder.setParameter(parameterIndex, encodedString);
}
/**
* Sets the designated parameter to the given Java array of bytes. The
* driver converts this to an SQL VARBINARY
or
* LONGVARBINARY
(depending on the argument's size relative to
* the driver's limits on VARBINARY
values) when it sends it to
* the database.
*
* @param parameterIndex
* the first parameter is 1, the second is 2, ...
* @param x
* the parameter value
* @exception SQLException
* if a database access error occurs
*/
@Override
public void setBytes(int parameterIndex, byte[] x) throws SQLException {
testIfClosed();
String encodedString = TransportConverter.toTransportFormat(x);
// parameterValues.put(parameterIndex, hexString);
statementHolder.setParameter(parameterIndex, encodedString);
}
/**
* Sets the designated parameter to the given java.sql.Date
* value. The driver converts this to an SQL DATE
value when it
* sends it to the database.
*
* @param parameterIndex
* the first parameter is 1, the second is 2, ...
* @param x
* the parameter value
* @exception SQLException
* if a database access error occurs
*/
@Override
public void setDate(int parameterIndex, java.sql.Date x)
throws SQLException {
testIfClosed();
statementHolder.setParameter(parameterIndex, x);
}
/**
* Sets the designated parameter to the given java.sql.Time
* value. The driver converts this to an SQL TIME
value when it
* sends it to the database.
*
* @param parameterIndex
* the first parameter is 1, the second is 2, ...
* @param x
* the parameter value
* @exception SQLException
* if a database access error occurs
*/
public void setTime(int parameterIndex, java.sql.Time x)
throws SQLException {
testIfClosed();
statementHolder.setParameter(parameterIndex, x);
}
/**
* Sets the designated parameter to the given
* java.sql.Timestamp
value. The driver converts this to an SQL
* TIMESTAMP
value when it sends it to the database.
*
* @param parameterIndex
* the first parameter is 1, the second is 2, ...
* @param x
* the parameter value
* @exception SQLException
* if a database access error occurs
*/
@Override
public void setTimestamp(int parameterIndex, java.sql.Timestamp x)
throws SQLException {
testIfClosed();
statementHolder.setParameter(parameterIndex, x);
}
/**
*
* Sets the value of the designated parameter using the given object. The
* second parameter must be of type Object
; therefore, the
* java.lang
equivalent objects should be used for built-in
* types.
*
*
* The JDBC specification specifies a standard mapping from Java
* Object
types to SQL types. The given argument will be
* converted to the corresponding SQL type before being sent to the
* database.
*
*
* Note that this method may be used to pass datatabase- specific abstract
* data types, by using a driver-specific Java type.
*
* If the object is of a class implementing the interface
* SQLData
, the JDBC driver should call the method
* SQLData.writeSQL
to write it to the SQL data stream. If, on
* the other hand, the object is of a class implementing Ref
,
* Blob
, Clob
, Struct
, or
* Array
, the driver should pass it to the database as a value
* of the corresponding SQL type.
*
* This method throws an exception if there is an ambiguity, for example, if
* the object is of a class implementing more than one of the interfaces
* named above.
*
* @param parameterIndex
* the first parameter is 1, the second is 2, ...
* @param x
* the object containing the input parameter value
* @exception SQLException
* if a database access error occurs or the type of the given
* object is ambiguous
*/
@Override
public void setObject(int parameterIndex, Object x) throws SQLException {
testIfClosed();
if (x != null
&& x.toString().length() > connectionHttp
.getMaxLengthForString()) {
throw new SQLException(
"Object is too big for upload with Awake SQL: "
+ x.toString().length()
+ " bytes. Maximum length authorized is: "
+ connectionHttp.getMaxLengthForString());
}
statementHolder.setParameter(parameterIndex, x);
}
/**
* Sets the designated parameter to the given input stream. When a very
* large binary value is input to a LONGVARBINARY
parameter, it
* may be more practical to send it via a java.io.InputStream
* object. The data will be read from the stream as needed until end-of-file
* is reached.
*
*
* Note: This stream object can either be a standard Java stream
* object or your own subclass that implements the standard interface.
*
* Note: Consult your JDBC driver documentation to determine if it
* might be more efficient to use a version of setBinaryStream
* which takes a length parameter.
*
* @param parameterIndex
* the first parameter is 1, the second is 2, ...
* @param x
* the java input stream which contains the binary parameter
* value
* @exception SQLException
* if parameterIndex does not correspond to a parameter
* marker in the SQL statement; if a database access error
* occurs or this method is called on a closed
* PreparedStatement
* @throws SQLFeatureNotSupportedException
* if the JDBC driver does not support this method
* @since 1.6
*/
@Override
public void setBinaryStream(int parameterIndex, java.io.InputStream x)
throws SQLException {
testIfClosed();
// Create the file from the input Stream, naming it on the table name
FileNameFromBlobBuilder fileNameFromBlobBuilder = new FileNameFromBlobBuilder(
sql, parameterIndex, false);
String rawRemoteFileName = fileNameFromBlobBuilder.getFileName();
String dir = AwakeFileUtil.getAwakeTempDir();
File blobFile = new File(dir + rawRemoteFileName);
debug("rawRemoteFileName: " + rawRemoteFileName);
debug("blobFile : " + blobFile);
OutputStream out = null;
try {
out = new BufferedOutputStream(new FileOutputStream(blobFile));
IOUtils.copy(x, out);
} catch (IOException e) {
throw new SQLException(e.getMessage());
} finally {
IOUtils.closeQuietly(x);
IOUtils.closeQuietly(out);
}
connectionHttp.addLocalFile(blobFile);
connectionHttp.addRemoteFile(rawRemoteFileName);
// Ok. File is successfully uploaded!
// Set the parameter using the file name
InputStream inputStream = new AwakeInputStream(rawRemoteFileName);
// parameterValues.put(parameterIndex, inputStream);
statementHolder.setParameter(parameterIndex, inputStream);
}
/**
* Sets the designated parameter to the given input stream, which will have
* the specified number of bytes. When a very large binary value is input to
* a LONGVARBINARY
parameter, it may be more practical to send
* it via a java.io.InputStream
object. The data will be read
* from the stream as needed until end-of-file is reached.
*
*
* Note: This stream object can either be a standard Java stream
* object or your own subclass that implements the standard interface.
*
* @param parameterIndex
* the first parameter is 1, the second is 2, ...
* @param x
* the java input stream which contains the binary parameter
* value
* @param length
* the number of bytes in the stream
* @exception SQLException
* if parameterIndex does not correspond to a parameter
* marker in the SQL statement; if a database access error
* occurs or this method is called on a closed
* PreparedStatement
*/
@Override
public void setBinaryStream(int parameterIndex, java.io.InputStream x,
int length) throws SQLException {
testIfClosed();
this.setBinaryStream(parameterIndex, x);
}
/**
* Sets the designated parameter to the given input stream, which will have
* the specified number of bytes. When a very large binary value is input to
* a LONGVARBINARY
parameter, it may be more practical to send
* it via a java.io.InputStream
object. The data will be read
* from the stream as needed until end-of-file is reached.
*
*
* Note: This stream object can either be a standard Java stream
* object or your own subclass that implements the standard interface.
*
* @param parameterIndex
* the first parameter is 1, the second is 2, ...
* @param x
* the java input stream which contains the binary parameter
* value
* @param length
* the number of bytes in the stream
* @exception SQLException
* if parameterIndex does not correspond to a parameter
* marker in the SQL statement; if a database access error
* occurs or this method is called on a closed
* PreparedStatement
* @since 1.6
*/
@Override
public void setBinaryStream(int parameterIndex, java.io.InputStream x,
long length) throws SQLException {
testIfClosed();
this.setBinaryStream(parameterIndex, x);
}
@Override
public void setBlob(int parameterIndex, Blob x) throws SQLException {
testIfClosed();
if (x instanceof BlobHttp) {
BlobHttp blobHttp = (BlobHttp)x;
// Close the underlying output stream, cleaner:
blobHttp.close();
// Create the file from the input Stream, naming it on the table
// name
FileNameFromBlobBuilder fileNameFromBlobBuilder = new FileNameFromBlobBuilder(
sql, parameterIndex, false);
String rawRemoteFileName = fileNameFromBlobBuilder.getFileName();
debug("blobHttp.getFile(): " + blobHttp.getFile());
debug("rawRemoteFileName : " + rawRemoteFileName);
connectionHttp.addLocalFile(blobHttp.getFile());
connectionHttp.addRemoteFile(rawRemoteFileName);
// Ok. File is successfully uploaded!
// Set the parameter using the file name
InputStream inputStream = new AwakeInputStream(rawRemoteFileName);
// parameterValues.put(parameterIndex, inputStream);
statementHolder.setParameter(parameterIndex, inputStream);
} else {
InputStream in = x.getBinaryStream();
setBinaryStream(parameterIndex, in);
}
}
@Override
public void setBlob(int parameterIndex, InputStream inputStream)
throws SQLException {
testIfClosed();
setBinaryStream(parameterIndex, inputStream);
}
@Override
public void setBlob(int parameterIndex, InputStream inputStream, long length)
throws SQLException {
testIfClosed();
setBinaryStream(parameterIndex, inputStream);
}
@Override
public void setAsciiStream(int parameterIndex, InputStream x, int length)
throws SQLException {
setAsciiStream(parameterIndex, x);
}
@Override
public void setAsciiStream(int parameterIndex, InputStream x, long length)
throws SQLException {
setAsciiStream(parameterIndex, x);
}
@Override
public void setAsciiStream(int parameterIndex, InputStream x)
throws SQLException {
testIfClosed();
// Create the file from the input Stream, naming it on the table name
FileNameFromBlobBuilder fileNameFromBlobBuilder = new FileNameFromBlobBuilder(
sql, parameterIndex, true);
String rawRemoteFileName = fileNameFromBlobBuilder.getFileName();
String dir = AwakeFileUtil.getAwakeTempDir();
File clobFile = new File(dir + rawRemoteFileName);
debug("rawRemoteFileName: " + rawRemoteFileName);
debug("blobFile : " + clobFile);
Writer writer = null;
try {
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(x));
writer = new BufferedWriter(new FileWriter(clobFile));
String line = null;
while ((line = bufferedReader.readLine()) != null) {
if (connectionHttp.isHtmlEncodingOn()) {
line = HtmlConverter.toHtml(line);
}
writer.write(line + CR_LF);
}
} catch (IOException e) {
throw new SQLException(e.getMessage());
} finally {
IOUtils.closeQuietly(x);
IOUtils.closeQuietly(writer);
}
connectionHttp.addLocalFile(clobFile);
connectionHttp.addRemoteFile(rawRemoteFileName);
// Ok. File is successfully uploaded!
// Set the parameter using the file name
AwakeAsciiStream awakeAsciiStream = new AwakeAsciiStream(
rawRemoteFileName);
// parameterValues.put(parameterIndex, inputStream);
statementHolder.setParameter(parameterIndex, awakeAsciiStream);
}
/**
* Sets the designated parameter to the given Reader
object.
* When a very large UNICODE value is input to a LONGVARCHAR
* parameter, it may be more practical to send it via a
* java.io.Reader
object. The data will be read from the stream
* as needed until end-of-file is reached. The JDBC driver will do any
* necessary conversion from UNICODE to the database char format.
*
*
* Note: This stream object can either be a standard Java stream
* object or your own subclass that implements the standard interface.
*
* Note: Consult your JDBC driver documentation to determine if it
* might be more efficient to use a version of
* setCharacterStream
which takes a length parameter.
*
* @param parameterIndex
* the first parameter is 1, the second is 2, ...
* @param reader
* the java.io.Reader
object that contains the
* Unicode data
* @exception SQLException
* if parameterIndex does not correspond to a parameter
* marker in the SQL statement; if a database access error
* occurs or this method is called on a closed
* PreparedStatement
* @throws SQLFeatureNotSupportedException
* if the JDBC driver does not support this method
* @since 1.6
*/
@Override
public void setCharacterStream(int parameterIndex, java.io.Reader reader)
throws SQLException {
testIfClosed();
// Create the file from the input Stream, naming it on the table name
FileNameFromBlobBuilder fileNameFromBlobBuilder = new FileNameFromBlobBuilder(
sql, parameterIndex, true);
String rawRemoteFileName = fileNameFromBlobBuilder.getFileName();
String dir = AwakeFileUtil.getAwakeTempDir();
File clobFile = new File(dir + rawRemoteFileName);
debug("rawFileName: " + rawRemoteFileName);
debug("clobFile : " + clobFile);
BufferedReader bufferedReader = null;
Writer writer = null;
try {
bufferedReader = new BufferedReader(reader);
writer = new BufferedWriter(new FileWriter(clobFile));
String line = null;
while ((line = bufferedReader.readLine()) != null) {
if (connectionHttp.isHtmlEncodingOn()) {
line = HtmlConverter.toHtml(line);
}
writer.write(line + CR_LF);
}
} catch (IOException e) {
throw new SQLException(e.getMessage());
} finally {
IOUtils.closeQuietly(reader);
IOUtils.closeQuietly(writer);
}
connectionHttp.addLocalFile(clobFile);
connectionHttp.addRemoteFile(rawRemoteFileName);
// Ok. File is successfully uploaded!
// Set the parameter using the file name
Reader awakeReader = new AwakeReader(rawRemoteFileName);
// parameterValues.put(parameterIndex, awakeReader);
statementHolder.setParameter(parameterIndex, awakeReader);
}
/**
* Sets the designated parameter to the given Reader
object,
* which is the given number of characters long. When a very large UNICODE
* value is input to a LONGVARCHAR
parameter, it may be more
* practical to send it via a java.io.Reader
object. The data
* will be read from the stream as needed until end-of-file is reached. The
* JDBC driver will do any necessary conversion from UNICODE to the database
* char format.
*
*
* Note: This stream object can either be a standard Java stream
* object or your own subclass that implements the standard interface.
*
* @param parameterIndex
* the first parameter is 1, the second is 2, ...
* @param reader
* the java.io.Reader
object that contains the
* Unicode data
* @param length
* the number of characters in the stream
* @exception SQLException
* if parameterIndex does not correspond to a parameter
* marker in the SQL statement; if a database access error
* occurs or this method is called on a closed
* PreparedStatement
* @since 1.2
*/
@Override
public void setCharacterStream(int parameterIndex, java.io.Reader reader,
int length) throws SQLException {
testIfClosed();
this.setCharacterStream(parameterIndex, reader);
}
/**
* Sets the designated parameter to the given Reader
object,
* which is the given number of characters long. When a very large UNICODE
* value is input to a LONGVARCHAR
parameter, it may be more
* practical to send it via a java.io.Reader
object. The data
* will be read from the stream as needed until end-of-file is reached. The
* JDBC driver will do any necessary conversion from UNICODE to the database
* char format.
*
*
* Note: This stream object can either be a standard Java stream
* object or your own subclass that implements the standard interface.
*
* @param parameterIndex
* the first parameter is 1, the second is 2, ...
* @param reader
* the java.io.Reader
object that contains the
* Unicode data
* @param length
* the number of characters in the stream
* @exception SQLException
* if parameterIndex does not correspond to a parameter
* marker in the SQL statement; if a database access error
* occurs or this method is called on a closed
* PreparedStatement
* @since 1.6
*/
@Override
public void setCharacterStream(int parameterIndex, java.io.Reader reader,
long length) throws SQLException {
testIfClosed();
this.setCharacterStream(parameterIndex, reader);
}
@Override
public void setClob(int parameterIndex, Clob x) throws SQLException {
testIfClosed();
// Clob creation is not optimized (other file creation) , because if htmlEncoding is on we must rewrite the file
Reader reader = x.getCharacterStream();
setCharacterStream(parameterIndex, reader);
}
@Override
public void setClob(int parameterIndex, Reader reader, long length)
throws SQLException {
testIfClosed();
setCharacterStream(parameterIndex, reader, length);
}
@Override
public void setClob(int parameterIndex, Reader reader) throws SQLException {
testIfClosed();
setCharacterStream(parameterIndex, reader);
}
/**
* Clears the current parameter values immediately.
*
* In general, parameter values remain in force for repeated use of a
* statement. Setting a parameter value automatically clears its previous
* value. However, in some cases it is useful to immediately release the
* resources used by the current parameter values; this can be done by
* calling the method clearParameters
.
*
* @exception SQLException
* if a database access error occurs
*/
@Override
public void clearParameters() throws SQLException {
statementHolder.clearParameters();
}
// --------------------------JDBC 2.0-----------------------------
/**
* Adds a set of parameters to this PreparedStatement
object's
* batch of commands.
*
* @exception SQLException
* if a database access error occurs
* @see Statement#addBatch
* @since 1.2
*/
@Override
public void addBatch() throws SQLException {
// Check that all parameters values are set
ParametersUtil.checkParameters(statementHolder);
// Create a StatementHolder that contains only the parameter
// and add it to the batchHolderList field:
StatementHolder batchHolder = new StatementHolder(
statementHolder.getParameterTypes(),
statementHolder.getParameterStringValues(),
statementHolder.isHtmlEncodingOn());
batchHolder.setPreparedStatement(true);
batchHolder.setExecuteUpdate(true);
batchHolderFileList.add(batchHolder);
debug("batchHolder: " + batchHolder);
}
/**
* Submits a batch of commands to the database for execution and if all
* commands execute successfully, returns an array of update counts. The
* int
elements of the array that is returned are ordered to
* correspond to the commands in the batch, which are ordered according to
* the order in which they were added to the batch. The elements in the
* array returned by the method executeBatch
may be one of the
* following:
*
* - A number greater than or equal to zero -- indicates that the command
* was processed successfully and is an update count giving the number of
* rows in the database that were affected by the command's execution
*
- A value of
SUCCESS_NO_INFO
-- indicates that the command
* was processed successfully but that the number of rows affected is
* unknown
*
* If one of the commands in a batch update fails to execute properly, this
* method throws a BatchUpdateException
, and a JDBC driver may
* or may not continue to process the remaining commands in the batch.
* However, the driver's behavior must be consistent with a particular DBMS,
* either always continuing to process commands or never continuing to
* process commands. If the driver continues processing after a failure, the
* array returned by the method
* BatchUpdateException.getUpdateCounts
will contain as many
* elements as there are commands in the batch, and at least one of the
* elements will be the following:
*
*
- A value of
EXECUTE_FAILED
-- indicates that the command
* failed to execute successfully and occurs only if a driver continues to
* process commands after a command fails
*
*
* A driver is not required to implement this method. The possible
* implementations and return values have been modified in the Java 2 SDK,
* Standard Edition, version 1.3 to accommodate the option of continuing to
* proccess commands in a batch update after a
* BatchUpdateException
obejct has been thrown.
*
* @return an array of update counts containing one element for each command
* in the batch. The elements of the array are ordered according to
* the order in which commands were added to the batch.
* @exception SQLException
* if a database access error occurs or the driver does not
* support batch statements. Throws
* {@link BatchUpdateException} (a subclass of
* SQLException
) if one of the commands sent to
* the database fails to execute properly or attempts to
* return a result set.
* @since 1.3
*/
@Override
public int[] executeBatch() throws SQLException {
int updateCounts[] = new int[batchHolderFileList.size()];
if (batchHolderFileList.size() == 0) {
return updateCounts;
}
JdbcHttpBatchTransfer jdbcHttpBatchTransfer = new JdbcHttpBatchTransfer(
connectionHttp, connectionHttp.getAuthenticationToken());
String updateCountsStr = jdbcHttpBatchTransfer
.getStringFromExecutePrepStatementBatchOnServer(
statementHolder, batchHolderFileList);
updateCounts = IntArrayTransport.fromJson(updateCountsStr);
clearBatch();
return updateCounts;
}
/**
* Sets the designated parameter to the given java.net.URL
value.
* The driver converts this to an SQL DATALINK
value
* when it sends it to the database.
*
* @param parameterIndex the first parameter is 1, the second is 2, ...
* @param x the java.net.URL
object to be set
* @exception SQLException if parameterIndex does not correspond to a parameter
* marker in the SQL statement; if a database access error occurs or
* this method is called on a closed PreparedStatement
* @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
* @since 1.4
*/
@Override
public void setURL(int parameterIndex, URL x) throws SQLException {
if (x == null) {
throw new IllegalArgumentException("URL can not be null!");
}
statementHolder.setParameter(parameterIndex, x);
}
/**
* Sets the designated parameter to the given java.sql.Array
object.
* The driver converts this to an SQL ARRAY
value when it
* sends it to the database.
*
* @param parameterIndex the first parameter is 1, the second is 2, ...
* @param x an Array
object that maps an SQL ARRAY
value
* @exception SQLException if parameterIndex does not correspond to a parameter
* marker in the SQL statement; if a database access error occurs or
* this method is called on a closed PreparedStatement
* @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
* @since 1.2
*/
public void setArray (int parameterIndex, Array x) throws SQLException {
if (connectionHttp.isStatelessMode()) {
throw new SQLException(ConnectionHttp.FEATURE_NOT_SUPPORTED_IN_STATELESS_MODE);
}
if (x == null) {
throw new IllegalArgumentException("Array can not be null!");
}
statementHolder.setParameter(parameterIndex, x);
}
/**
* Sets the designated parameter to the given java.sql.RowId
object. The
* driver converts this to a SQL ROWID
value when it sends it
* to the database
*
* @param parameterIndex the first parameter is 1, the second is 2, ...
* @param x the parameter value
* @throws SQLException if parameterIndex does not correspond to a parameter
* marker in the SQL statement; if a database access error occurs or
* this method is called on a closed PreparedStatement
* @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
*
* @since 1.6
*/
@Override
public void setRowId(int parameterIndex, RowId x) throws SQLException {
if (connectionHttp.isStatelessMode()) {
throw new SQLException(
ConnectionHttp.FEATURE_NOT_SUPPORTED_IN_STATELESS_MODE);
}
if (x == null) {
throw new IllegalArgumentException("RowId can not be null!");
}
statementHolder.setParameter(parameterIndex, x);
}
//
// Not (yet) implemented methods
//
@Override
public void setUnicodeStream(int parameterIndex, InputStream x, int length)
throws SQLException {
throw new SQLFeatureNotSupportedException(ConnectionHttp.AWAKE_NOT_SUPPORTED_METHOD);
}
@Override
public void setObject(int parameterIndex, Object x, int targetSqlType)
throws SQLException {
throw new SQLFeatureNotSupportedException(ConnectionHttp.AWAKE_NOT_SUPPORTED_METHOD);
}
@Override
public void setRef(int parameterIndex, Ref x) throws SQLException {
throw new SQLFeatureNotSupportedException(ConnectionHttp.AWAKE_NOT_SUPPORTED_METHOD);
}
@Override
public ResultSetMetaData getMetaData() throws SQLException {
throw new SQLFeatureNotSupportedException(ConnectionHttp.AWAKE_NOT_SUPPORTED_METHOD);
}
@Override
public void setDate(int parameterIndex, Date x, Calendar cal)
throws SQLException {
throw new SQLFeatureNotSupportedException(ConnectionHttp.AWAKE_NOT_SUPPORTED_METHOD);
}
@Override
public void setTime(int parameterIndex, Time x, Calendar cal)
throws SQLException {
throw new SQLFeatureNotSupportedException(ConnectionHttp.AWAKE_NOT_SUPPORTED_METHOD);
}
@Override
public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal)
throws SQLException {
throw new SQLFeatureNotSupportedException(ConnectionHttp.AWAKE_NOT_SUPPORTED_METHOD);
}
@Override
public void setNull(int parameterIndex, int sqlType, String typeName)
throws SQLException {
throw new SQLFeatureNotSupportedException(ConnectionHttp.AWAKE_NOT_SUPPORTED_METHOD);
}
@Override
public ParameterMetaData getParameterMetaData() throws SQLException {
throw new SQLFeatureNotSupportedException(ConnectionHttp.AWAKE_NOT_SUPPORTED_METHOD);
}
@Override
public void setNCharacterStream(int parameterIndex, Reader value,
long length) throws SQLException {
throw new SQLFeatureNotSupportedException(ConnectionHttp.AWAKE_NOT_SUPPORTED_METHOD);
}
@Override
public void setNClob(int parameterIndex, NClob value) throws SQLException {
throw new SQLFeatureNotSupportedException(ConnectionHttp.AWAKE_NOT_SUPPORTED_METHOD);
}
@Override
public void setNClob(int parameterIndex, Reader reader, long length)
throws SQLException {
throw new SQLFeatureNotSupportedException(ConnectionHttp.AWAKE_NOT_SUPPORTED_METHOD);
}
@Override
public void setSQLXML(int parameterIndex, SQLXML xmlObject)
throws SQLException {
throw new SQLFeatureNotSupportedException(ConnectionHttp.AWAKE_NOT_SUPPORTED_METHOD);
}
@Override
public void setObject(int parameterIndex, Object x, int targetSqlType,
int scaleOrLength) throws SQLException {
throw new SQLFeatureNotSupportedException(ConnectionHttp.AWAKE_NOT_SUPPORTED_METHOD);
}
@Override
public void setNCharacterStream(int parameterIndex, Reader value)
throws SQLException {
throw new SQLFeatureNotSupportedException(ConnectionHttp.AWAKE_NOT_SUPPORTED_METHOD);
}
@Override
public void setNClob(int parameterIndex, Reader reader) throws SQLException {
throw new SQLFeatureNotSupportedException(ConnectionHttp.AWAKE_NOT_SUPPORTED_METHOD);
}
private static void debug(String s) {
if (DEBUG)
System.out.println(s);
}
}