/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /************************************************************************* * * The Contents of this file are made available subject to the terms of * the BSD license. * * Copyright 2000, 2010 Oracle and/or its affiliates. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *************************************************************************/ #include #include #include "FPreparedStatement.hxx" #include #include "FResultSetMetaData.hxx" #include "FResultSet.hxx" #include #include #include "propertyids.hxx" using namespace connectivity::firebird; using namespace com::sun::star::uno; using namespace com::sun::star::lang; using namespace com::sun::star::beans; using namespace com::sun::star::sdbc; using namespace com::sun::star::container; using namespace com::sun::star::io; using namespace com::sun::star::util; typedef struct vary { short vary_length; char vary_string[1]; } VARY; IMPLEMENT_SERVICE_INFO(OPreparedStatement,"com.sun.star.sdbcx.firebird.PreparedStatement","com.sun.star.sdbc.PreparedStatement"); /* * Print the status, the SQLCODE, and exit. * Also, indicate which operation the error occured on. */ static int pr_error (long* status, char* operation) { printf("[\n"); printf("PROBLEM ON \"%s\".\n", operation); isc_print_status(status); printf("SQLCODE:%d\n", isc_sqlcode(status)); printf("]\n"); return 1; } OPreparedStatement::OPreparedStatement( OConnection* _pConnection,const TTypeInfoVector& _TypeInfo,const ::rtl::OUString& sql) :OStatement_BASE2(_pConnection) ,m_aTypeInfo(_TypeInfo) ,m_bPrepared(sal_False) ,m_sSqlStatement(sql) ,m_nNumParams(0) { ISC_STATUS_ARRAY status; // status vector isc_db_handle db = _pConnection->getDBHandler(); // database handle // enabling the XSQLDA to accommodate up to 10 select-list items (DEFAULT) m_OUTsqlda = (XSQLDA *)malloc(XSQLDA_LENGTH(10)); m_OUTsqlda->version = SQLDA_VERSION1; m_OUTsqlda->sqln = 10; // enabling the XSQLDA to accommodate up to 10 parameter items (DEFAULT) m_INsqlda = (XSQLDA *)malloc(XSQLDA_LENGTH(10)); m_INsqlda->version = SQLDA_VERSION1; m_INsqlda->sqln = 10; m_STMTHandler = NULL; // Set handle to NULL before allocation. if (isc_dsql_allocate_statement(status, &db, &m_STMTHandler)) if (pr_error(status, "allocate statement")) return; m_TRANSHandler = 0L; // transaction handle if (isc_start_transaction(status, &m_TRANSHandler, 1, &db, 0, NULL)) if (pr_error(status, "start transaction")) return; // sets the statement handle (stmt) to refer to the parsed format. char *sqlStr = strdup(OUStringToOString( m_sSqlStatement, RTL_TEXTENCODING_UTF8 ).getStr()); if (isc_dsql_prepare(status, &m_TRANSHandler, &m_STMTHandler, 0, sqlStr, 1, m_OUTsqlda)) if (pr_error(status, "prepare statement")) return; free(sqlStr); // fill the input XSQLDA with information about the parameters if (isc_dsql_describe_bind(status, &m_STMTHandler, 1, m_INsqlda)) if (pr_error(status, "bind statement")) return; XSQLVAR *var = NULL; int i, dtype; // determine if the input descriptor can accommodate the number of parameters // contained in the statement. if (0 == m_INsqlda->sqld) { free(m_INsqlda); m_INsqlda = NULL; } else { if (m_INsqlda->sqld > m_INsqlda->sqln) { int n = m_INsqlda->sqld; free(m_INsqlda); m_INsqlda = (XSQLDA *)malloc(XSQLDA_LENGTH(n)); m_INsqlda->sqln = n; m_INsqlda->version = SQLDA_VERSION1; if (isc_dsql_describe_bind(status, &m_STMTHandler, 1, m_INsqlda)) if (pr_error(status, "bind statement 2")) return; } } // fill the output XSQLDA with information about the select-list items. if (isc_dsql_describe(status, &m_STMTHandler, 1, m_OUTsqlda)) if (pr_error(status, "describe statement")) return; // determine if the output descriptor can accommodate the number of select-list // items specified in the statement. if (m_OUTsqlda->sqld > m_OUTsqlda->sqln) { int n = m_OUTsqlda->sqld; free(m_OUTsqlda); m_OUTsqlda = (XSQLDA *)malloc(XSQLDA_LENGTH(n)); m_OUTsqlda->sqln = n; m_OUTsqlda->version = SQLDA_VERSION1; if (isc_dsql_describe(status, &m_STMTHandler, 1, m_OUTsqlda)) if (pr_error(status, "describe statement 2")) return; } // Process each XSQLVAR parameter structure in the output XSQLDA for (i=0, var = m_OUTsqlda->sqlvar; i < m_OUTsqlda->sqld; i++, var++) { dtype = (var->sqltype & ~1); /* drop flag bit for now */ switch(dtype) { case SQL_VARYING: var->sqltype = SQL_TEXT; var->sqldata = (char *)malloc(sizeof(char)*var->sqllen + 2); break; case SQL_TEXT: var->sqldata = (char *)malloc(sizeof(char)*var->sqllen); break; case SQL_LONG: var->sqldata = (char *)malloc(sizeof(long)); break; case SQL_SHORT: var->sqldata = (char *)malloc(sizeof(char)*var->sqllen); break; case SQL_FLOAT: var->sqldata = (char *)malloc(sizeof(double)); break; case SQL_DOUBLE: var->sqldata = (char *)malloc(sizeof(double)); break; case SQL_D_FLOAT: var->sqldata = (char *)malloc(sizeof(double)); break; case SQL_TIMESTAMP: var->sqldata = (char *)malloc(sizeof(time_t)); break; case SQL_INT64: var->sqldata = (char *)malloc(sizeof(int)); break; /* process remaining types */ default: OSL_ASSERT( false ); break; } if (var->sqltype & 1) { /* allocate variable to hold NULL status */ var->sqlind = (short *)malloc(sizeof(short)); } } } // ----------------------------------------------------------------------------- OPreparedStatement::~OPreparedStatement() { } // ----------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::acquire() throw() { OStatement_BASE2::acquire(); } // ----------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::release() throw() { OStatement_BASE2::release(); } // ----------------------------------------------------------------------------- Any SAL_CALL OPreparedStatement::queryInterface( const Type & rType ) throw(RuntimeException) { Any aRet = OStatement_BASE2::queryInterface(rType); if(!aRet.hasValue()) aRet = OPreparedStatement_BASE::queryInterface(rType); return aRet; } // ------------------------------------------------------------------------- ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL OPreparedStatement::getTypes( ) throw(::com::sun::star::uno::RuntimeException) { return concatSequences(OPreparedStatement_BASE::getTypes(),OStatement_BASE2::getTypes()); } // ------------------------------------------------------------------------- Reference< XResultSetMetaData > SAL_CALL OPreparedStatement::getMetaData( ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); if(!m_xMetaData.is()) m_xMetaData = new OResultSetMetaData(getOwnConnection()); return m_xMetaData; } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::close( ) throw(SQLException, RuntimeException) { printf("DEBUG !!! connectivity.firebird => OPreparedStatement::close() \n"); ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); // Reset last warning message try { clearWarnings (); OStatement_BASE2::close(); } catch (SQLException &) { // If we get an error, ignore } // Remove this Statement object from the Connection object's // list } // ------------------------------------------------------------------------- sal_Bool SAL_CALL OPreparedStatement::execute( ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); // same as in statement with the difference that this statement also can contain parameter return sal_False; } // ------------------------------------------------------------------------- sal_Int32 SAL_CALL OPreparedStatement::executeUpdate( ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); // same as in statement with the difference that this statement also can contain parameter return 0; } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setString( sal_Int32 parameterIndex, const ::rtl::OUString& x ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); if (NULL == m_INsqlda) { printf ("DEBUG !!! OPreparedStatement::setString => The query has not input parameters \n."); return; } OString str = OUStringToOString(x , RTL_TEXTENCODING_UTF8 ); printf ("DEBUG !!! OPreparedStatement::setString => Setting parameter %i as: %s \n.", parameterIndex, str.getStr()); XSQLVAR *var = m_INsqlda->sqlvar + (parameterIndex - 1); int dtype = (var->sqltype & ~1); // drop flag bit for now switch(dtype) { case SQL_VARYING: var->sqltype = SQL_TEXT; case SQL_TEXT: var->sqllen = str.getLength(); var->sqldata = (char *)malloc(sizeof(char)*var->sqllen); sprintf(var->sqldata , "%s", str.getStr()); break; default: OSL_ASSERT( false ); } sprintf(var->sqldata , "%s", OUStringToOString(x , RTL_TEXTENCODING_UTF8 ).getStr()); } // ------------------------------------------------------------------------- Reference< XConnection > SAL_CALL OPreparedStatement::getConnection( ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); return (Reference< XConnection >)m_pConnection; } // ------------------------------------------------------------------------- Reference< XResultSet > SAL_CALL OPreparedStatement::executeQuery( ) throw(SQLException, RuntimeException) { char *sqlStr = strdup(OUStringToOString( m_sSqlStatement, RTL_TEXTENCODING_ASCII_US ).getStr()); printf("DEBUG !!! connectivity.firebird => OPreparedStatement::executeQuery() got called with sql: %s \n", sqlStr); free(sqlStr); ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); ISC_STATUS_ARRAY status; /* status vector */ if (NULL != m_INsqlda) { if (isc_dsql_execute2(status, &m_TRANSHandler, &m_STMTHandler, 1, m_INsqlda, NULL)) if (pr_error(status, "execute2 query")) return NULL; } else { if (isc_dsql_execute(status, &m_TRANSHandler, &m_STMTHandler, 1, NULL)) if (pr_error(status, "execute query")) return NULL; } Reference< OResultSet > pResult( new OResultSet( this) ); //initializeResultSet( pResult.get() ); Reference< XResultSet > xRS = pResult.get(); if (isc_commit_transaction(status, &m_TRANSHandler)) if (pr_error(status, "start transaction")) return NULL; printf("DEBUG !!! connectivity.firebird => OPreparedStatement::executeQuery() Query executed.\n"); return xRS; } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setBoolean( sal_Int32 parameterIndex, sal_Bool x ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setByte( sal_Int32 parameterIndex, sal_Int8 x ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setDate( sal_Int32 parameterIndex, const Date& aData ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setTime( sal_Int32 parameterIndex, const Time& aVal ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setTimestamp( sal_Int32 parameterIndex, const DateTime& aVal ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setDouble( sal_Int32 parameterIndex, double x ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setFloat( sal_Int32 parameterIndex, float x ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setInt( sal_Int32 parameterIndex, sal_Int32 x ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setLong( sal_Int32 parameterIndex, sal_Int64 aVal ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setNull( sal_Int32 parameterIndex, sal_Int32 sqlType ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setClob( sal_Int32 parameterIndex, const Reference< XClob >& x ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setBlob( sal_Int32 parameterIndex, const Reference< XBlob >& x ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setArray( sal_Int32 parameterIndex, const Reference< XArray >& x ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setRef( sal_Int32 parameterIndex, const Reference< XRef >& x ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex, const Any& x, sal_Int32 sqlType, sal_Int32 scale ) throw(SQLException, RuntimeException) { checkDisposed(OStatement_BASE::rBHelper.bDisposed); ::osl::MutexGuard aGuard( m_aMutex ); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& typeName ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setObject( sal_Int32 parameterIndex, const Any& x ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setShort( sal_Int32 parameterIndex, sal_Int16 x ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setBytes( sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setCharacterStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setBinaryStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::clearParameters( ) throw(SQLException, RuntimeException) { } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::clearBatch( ) throw(SQLException, RuntimeException) { } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::addBatch( ) throw(SQLException, RuntimeException) { } // ------------------------------------------------------------------------- Sequence< sal_Int32 > SAL_CALL OPreparedStatement::executeBatch( ) throw(SQLException, RuntimeException) { return Sequence< sal_Int32 > (); } // ------------------------------------------------------------------------- void OPreparedStatement::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue) throw (Exception) { switch(nHandle) { case PROPERTY_ID_RESULTSETCONCURRENCY: break; case PROPERTY_ID_RESULTSETTYPE: break; case PROPERTY_ID_FETCHDIRECTION: break; case PROPERTY_ID_USEBOOKMARKS: break; default: OStatement_Base::setFastPropertyValue_NoBroadcast(nHandle,rValue); } } // ----------------------------------------------------------------------------- void OPreparedStatement::checkParameterIndex(sal_Int32 _parameterIndex) { if( !_parameterIndex || _parameterIndex > m_nNumParams) throw SQLException(); } // ----------------------------------------------------------------------------- /* vim:set shiftwidth=4 softtabstop=4 expandtab: */