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

src-main.org.awakefw.sql.jdbc.PreparedStatementHttp Maven / Gradle / Ivy

Go to download

Awake SQL is an open source framework that allows remote and secure JDBC access through HTTP.

The newest version!
/*
 * 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: *

    *
  1. 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 *
  2. 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: *

    *

  3. 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); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy