xref: /AOO41X/main/connectivity/source/drivers/odbcbase/OPreparedStatement.cxx (revision 9b5730f6ddef7eb82608ca4d31dc0d7678e652cf)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_connectivity.hxx"
26 
27 #include <stdio.h>
28 #include <string.h>
29 #include <osl/diagnose.h>
30 #include "odbc/OPreparedStatement.hxx"
31 #include "odbc/OBoundParam.hxx"
32 #include <com/sun/star/sdbc/DataType.hpp>
33 #include "odbc/OTools.hxx"
34 #include "odbc/ODriver.hxx"
35 #include "odbc/OResultSet.hxx"
36 #include "odbc/OResultSetMetaData.hxx"
37 #include <cppuhelper/typeprovider.hxx>
38 #include <comphelper/sequence.hxx>
39 #include <com/sun/star/lang/DisposedException.hpp>
40 #include "connectivity/dbtools.hxx"
41 #include <comphelper/types.hxx>
42 #include "connectivity/FValue.hxx"
43 #include "resource/common_res.hrc"
44 #include "connectivity/sqlparse.hxx"
45 
46 using namespace ::comphelper;
47 using namespace connectivity;
48 using namespace connectivity::odbc;
49 using namespace com::sun::star::uno;
50 using namespace com::sun::star::lang;
51 using namespace com::sun::star::beans;
52 using namespace com::sun::star::sdbc;
53 using namespace com::sun::star::sdbcx;
54 using namespace com::sun::star::container;
55 using namespace com::sun::star::io;
56 using namespace com::sun::star::util;
57 
58 IMPLEMENT_SERVICE_INFO(OPreparedStatement,"com.sun.star.sdbcx.OPreparedStatement","com.sun.star.sdbc.PreparedStatement");
59 
60 
OPreparedStatement(OConnection * _pConnection,const::rtl::OUString & sql)61 OPreparedStatement::OPreparedStatement( OConnection* _pConnection,const ::rtl::OUString& sql)
62     :OStatement_BASE2(_pConnection)
63     ,numParams(0)
64     ,boundParams(NULL)
65     ,m_bPrepared(sal_False)
66 {
67     m_sSqlStatement = sql;
68     try
69     {
70         if(_pConnection->isParameterSubstitutionEnabled())
71         {
72             OSQLParser aParser(_pConnection->getDriver()->getORB());
73             ::rtl::OUString sErrorMessage;
74             ::rtl::OUString sNewSql;
75             ::std::auto_ptr<OSQLParseNode> pNode( aParser.parseTree(sErrorMessage,sql) );
76             if ( pNode.get() )
77             {   // special handling for parameters
78                 OSQLParseNode::substituteParameterNames(pNode.get());
79                 pNode->parseNodeToStr( sNewSql, _pConnection );
80                 m_sSqlStatement = sNewSql;
81             }
82         }
83     }
84     catch(Exception&)
85     {
86     }
87 }
88 // -----------------------------------------------------------------------------
acquire()89 void SAL_CALL OPreparedStatement::acquire() throw()
90 {
91     OStatement_BASE2::acquire();
92 }
93 // -----------------------------------------------------------------------------
release()94 void SAL_CALL OPreparedStatement::release() throw()
95 {
96     OStatement_BASE2::release();
97 }
98 // -----------------------------------------------------------------------------
queryInterface(const Type & rType)99 Any SAL_CALL OPreparedStatement::queryInterface( const Type & rType ) throw(RuntimeException)
100 {
101     Any aRet = OStatement_BASE2::queryInterface(rType);
102     return aRet.hasValue() ? aRet : OPreparedStatement_BASE::queryInterface(rType);
103 }
104 // -------------------------------------------------------------------------
getTypes()105 ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL OPreparedStatement::getTypes(  ) throw(::com::sun::star::uno::RuntimeException)
106 {
107     return ::comphelper::concatSequences(OPreparedStatement_BASE::getTypes(),OStatement_BASE2::getTypes());
108 }
109 // -------------------------------------------------------------------------
110 
getMetaData()111 Reference< XResultSetMetaData > SAL_CALL OPreparedStatement::getMetaData(  ) throw(SQLException, RuntimeException)
112 {
113     ::osl::MutexGuard aGuard( m_aMutex );
114     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
115 
116 
117     prepareStatement();
118     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
119     if(!m_xMetaData.is())
120         m_xMetaData = new OResultSetMetaData(getOwnConnection(),m_aStatementHandle);
121     return m_xMetaData;
122 }
123 // -------------------------------------------------------------------------
124 
close()125 void SAL_CALL OPreparedStatement::close(  ) throw(SQLException, RuntimeException)
126 {
127     ::osl::MutexGuard aGuard( m_aMutex );
128     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
129 
130 
131     // Close/clear our result set
132     clearMyResultSet ();
133 
134     // Reset last warning message
135 
136     try {
137         clearWarnings ();
138         OStatement_BASE2::close();
139         FreeParams();
140     }
141     catch (SQLException &) {
142         // If we get an error, ignore
143     }
144 
145     // Remove this Statement object from the Connection object's
146     // list
147 }
148 // -------------------------------------------------------------------------
149 
execute()150 sal_Bool SAL_CALL OPreparedStatement::execute(  ) throw(SQLException, RuntimeException)
151 {
152     ::osl::MutexGuard aGuard( m_aMutex );
153     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
154 
155 
156     sal_Bool needData = sal_False;
157 
158     // Reset warnings
159 
160     clearWarnings ();
161 
162     // Reset the statement handle, warning and saved Resultset
163 
164     reset();
165 
166     // Call SQLExecute
167     prepareStatement();
168 
169     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
170     try
171     {
172         SQLRETURN nReturn = N3SQLExecute(m_aStatementHandle);
173 
174         OTools::ThrowException(m_pConnection,nReturn,m_aStatementHandle,SQL_HANDLE_STMT,*this);
175         needData = nReturn == SQL_NEED_DATA;
176 
177         // Now loop while more data is needed (i.e. a data-at-
178         // execution parameter was given).  For each parameter
179         // that needs data, put the data from the input stream.
180 
181         while (needData) {
182 
183             // Get the parameter number that requires data
184 
185             sal_Int32* paramIndex = 0;
186             nReturn = N3SQLParamData(m_aStatementHandle,(SQLPOINTER*)&paramIndex);
187 
188             // If the parameter index is -1, there is no
189             // more data required
190 
191             if ( !paramIndex || ( *paramIndex == -1 ) )
192                 needData = sal_False;
193             else
194             {
195                 // Now we have the proper parameter
196                 // index, get the data from the input
197                 // stream and do a SQLPutData
198                 putParamData (*paramIndex);
199             }
200         }
201 
202     }
203     catch (const SQLWarning&)
204     {
205     }
206 
207     // Now loop while more data is needed (i.e. a data-at-
208     // execution parameter was given).  For each parameter
209     // that needs data, put the data from the input stream.
210 
211     while (needData) {
212 
213         // Get the parameter number that requires data
214 
215         sal_Int32* paramIndex = 0;
216         N3SQLParamData (m_aStatementHandle,(SQLPOINTER*)&paramIndex);
217 
218         // If the parameter index is -1, there is no more
219         // data required
220 
221         if (*paramIndex == -1) {
222             needData = sal_False;
223         }
224         else {
225             // Now we have the proper parameter index,
226             // get the data from the input stream
227             // and do a SQLPutData
228             putParamData(*paramIndex);
229         }
230     }
231 
232     // Now determine if there is a result set associated with
233     // the SQL statement that was executed.  Get the column
234     // count, and if it is not zero, there is a result set.
235 
236 
237     return getColumnCount() > 0;
238 }
239 // -------------------------------------------------------------------------
240 
executeUpdate()241 sal_Int32 SAL_CALL OPreparedStatement::executeUpdate(  ) throw(SQLException, RuntimeException)
242 {
243     ::osl::MutexGuard aGuard( m_aMutex );
244     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
245 
246     sal_Int32 numRows = -1;
247 
248     prepareStatement();
249     // Execute the statement.  If execute returns sal_False, a
250     // row count exists.
251 
252     if (!execute())
253         numRows = getUpdateCount ();
254     else
255     {
256         // No update count was produced (a ResultSet was).  Raise
257         // an exception
258         m_pConnection->throwGenericSQLException(STR_NO_ROWCOUNT,*this);
259     }
260     return numRows;
261 }
262 // -------------------------------------------------------------------------
263 
setString(sal_Int32 parameterIndex,const::rtl::OUString & x)264 void SAL_CALL OPreparedStatement::setString( sal_Int32 parameterIndex, const ::rtl::OUString& x ) throw(SQLException, RuntimeException)
265 {
266     ::rtl::OString aString(::rtl::OUStringToOString(x,getOwnConnection()->getTextEncoding()));
267     setParameter(parameterIndex,DataType::CHAR,aString.getLength(),(void*)&x);
268 }
269 // -------------------------------------------------------------------------
270 
getConnection()271 Reference< XConnection > SAL_CALL OPreparedStatement::getConnection(  ) throw(SQLException, RuntimeException)
272 {
273     ::osl::MutexGuard aGuard( m_aMutex );
274     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
275 
276     return (Reference< XConnection >)m_pConnection;
277 }
278 // -------------------------------------------------------------------------
279 
executeQuery()280 Reference< XResultSet > SAL_CALL OPreparedStatement::executeQuery(  ) throw(SQLException, RuntimeException)
281 {
282     ::osl::MutexGuard aGuard( m_aMutex );
283     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
284 
285     Reference< XResultSet > rs = NULL;
286 
287     prepareStatement();
288 
289     if (execute())
290         rs = getResultSet(sal_False);
291     else
292     {
293         // No ResultSet was produced.  Raise an exception
294         m_pConnection->throwGenericSQLException(STR_NO_RESULTSET,*this);
295     }
296     return rs;
297 }
298 // -------------------------------------------------------------------------
299 
setBoolean(sal_Int32 parameterIndex,sal_Bool x)300 void SAL_CALL OPreparedStatement::setBoolean( sal_Int32 parameterIndex, sal_Bool x ) throw(SQLException, RuntimeException)
301 {
302     ::osl::MutexGuard aGuard( m_aMutex );
303     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
304 
305 
306     sal_Int32 value = 0;
307 
308     // If the parameter is sal_True, set the value to 1
309     if (x) {
310         value = 1;
311     }
312 
313     // Set the parameter as if it were an integer
314     setInt (parameterIndex, value);
315 }
316 // -------------------------------------------------------------------------
setParameter(sal_Int32 parameterIndex,sal_Int32 _nType,sal_Int32 _nSize,void * _pData)317 void OPreparedStatement::setParameter(sal_Int32 parameterIndex,sal_Int32 _nType,sal_Int32 _nSize,void* _pData)
318 {
319     ::osl::MutexGuard aGuard( m_aMutex );
320     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
321 
322     prepareStatement();
323     // Allocate a buffer to be used in binding.  This will be
324         // a 'permanent' buffer that the bridge will fill in with
325         // the bound data in native format.
326 
327 
328     checkParameterIndex(parameterIndex);
329     sal_Int32 nRealSize = _nSize;
330     SQLSMALLINT fSqlType = static_cast<SQLSMALLINT>(OTools::jdbcTypeToOdbc(_nType));
331     switch(fSqlType)
332     {
333         case SQL_CHAR:
334         case SQL_VARCHAR:
335         case SQL_DECIMAL:
336         case SQL_NUMERIC:
337             ++nRealSize;
338             break;
339         case SQL_BINARY:
340         case SQL_VARBINARY:
341             nRealSize=1;    //dummy buffer, binary data isn't copied
342             break;
343         default:
344             break;
345     }
346 
347     sal_Int8* bindBuf = allocBindBuf(parameterIndex, nRealSize);
348 
349     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
350     OTools::bindParameter(  m_pConnection,
351                             m_aStatementHandle,
352                             parameterIndex,
353                             bindBuf,
354                             getLengthBuf(parameterIndex),
355                             fSqlType,
356                             sal_False,
357                             m_pConnection->useOldDateFormat(),
358                             _pData,
359                             (Reference <XInterface>)*this,
360                             getOwnConnection()->getTextEncoding());
361 }
362 // -----------------------------------------------------------------------------
setByte(sal_Int32 parameterIndex,sal_Int8 x)363 void SAL_CALL OPreparedStatement::setByte( sal_Int32 parameterIndex, sal_Int8 x ) throw(SQLException, RuntimeException)
364 {
365     setParameter(parameterIndex,DataType::TINYINT,sizeof(sal_Int8),&x);
366 }
367 // -------------------------------------------------------------------------
368 
setDate(sal_Int32 parameterIndex,const Date & aData)369 void SAL_CALL OPreparedStatement::setDate( sal_Int32 parameterIndex, const Date& aData ) throw(SQLException, RuntimeException)
370 {
371     DATE_STRUCT x = OTools::DateToOdbcDate(aData);
372     setParameter(parameterIndex,DataType::DATE,sizeof(DATE_STRUCT),&x);
373 }
374 // -------------------------------------------------------------------------
375 
376 
setTime(sal_Int32 parameterIndex,const Time & aVal)377 void SAL_CALL OPreparedStatement::setTime( sal_Int32 parameterIndex, const Time& aVal ) throw(SQLException, RuntimeException)
378 {
379     TIME_STRUCT x = OTools::TimeToOdbcTime(aVal);
380     setParameter(parameterIndex,DataType::TIME,sizeof(TIME_STRUCT),&x);
381 }
382 // -------------------------------------------------------------------------
383 
setTimestamp(sal_Int32 parameterIndex,const DateTime & aVal)384 void SAL_CALL OPreparedStatement::setTimestamp( sal_Int32 parameterIndex, const DateTime& aVal ) throw(SQLException, RuntimeException)
385 {
386     TIMESTAMP_STRUCT x = OTools::DateTimeToTimestamp(aVal);
387     setParameter(parameterIndex,DataType::TIMESTAMP,sizeof(TIMESTAMP_STRUCT),&x);
388 }
389 // -------------------------------------------------------------------------
390 
setDouble(sal_Int32 parameterIndex,double x)391 void SAL_CALL OPreparedStatement::setDouble( sal_Int32 parameterIndex, double x ) throw(SQLException, RuntimeException)
392 {
393     setParameter(parameterIndex,DataType::DOUBLE,sizeof(double),&x);
394 }
395 
396 // -------------------------------------------------------------------------
397 
setFloat(sal_Int32 parameterIndex,float x)398 void SAL_CALL OPreparedStatement::setFloat( sal_Int32 parameterIndex, float x ) throw(SQLException, RuntimeException)
399 {
400     setParameter(parameterIndex,DataType::FLOAT,sizeof(float),&x);
401 }
402 // -------------------------------------------------------------------------
403 
setInt(sal_Int32 parameterIndex,sal_Int32 x)404 void SAL_CALL OPreparedStatement::setInt( sal_Int32 parameterIndex, sal_Int32 x ) throw(SQLException, RuntimeException)
405 {
406     setParameter(parameterIndex,DataType::INTEGER,sizeof(sal_Int32),&x);
407 }
408 // -------------------------------------------------------------------------
409 
setLong(sal_Int32 parameterIndex,sal_Int64 x)410 void SAL_CALL OPreparedStatement::setLong( sal_Int32 parameterIndex, sal_Int64 x ) throw(SQLException, RuntimeException)
411 {
412     try
413     {
414         setParameter(parameterIndex,DataType::BIGINT,sizeof(sal_Int64),&x);
415     }
416     catch(SQLException&)
417     {
418         setString(parameterIndex,ORowSetValue(x));
419     }
420 }
421 // -------------------------------------------------------------------------
422 
setNull(sal_Int32 parameterIndex,sal_Int32 sqlType)423 void SAL_CALL OPreparedStatement::setNull( sal_Int32 parameterIndex, sal_Int32 sqlType ) throw(SQLException, RuntimeException)
424 {
425     ::osl::MutexGuard aGuard( m_aMutex );
426     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
427 
428 
429     prepareStatement();
430     // Get the buffer needed for the length
431     checkParameterIndex(parameterIndex);
432 
433     sal_Int8* lenBuf = getLengthBuf (parameterIndex);
434     *(SQLLEN*)lenBuf = SQL_NULL_DATA;
435 
436 
437     SQLLEN prec = 0;
438     SQLULEN nColumnSize = 0;
439     if (sqlType == SQL_CHAR || sqlType == SQL_VARCHAR || sqlType == SQL_LONGVARCHAR)
440     {
441         prec = 1;
442         nColumnSize = 1;
443     }
444 
445     SQLSMALLINT fCType = 0;
446     SQLSMALLINT fSqlType = 0;
447 
448     SQLSMALLINT nDecimalDigits = 0;
449     OTools::getBindTypes(   sal_False,
450                             m_pConnection->useOldDateFormat(),
451                             (SQLSMALLINT)sqlType,
452                             fCType,
453                             fSqlType);
454 
455     SQLRETURN nReturn = N3SQLBindParameter( m_aStatementHandle,
456                                             (SQLUSMALLINT)parameterIndex,
457                                             (SQLSMALLINT)SQL_PARAM_INPUT,
458                                             fCType,
459                                             fSqlType,
460                                             nColumnSize,
461                                             nDecimalDigits,
462                                             NULL,
463                                             prec,
464                                             (SQLLEN*)lenBuf
465                                             );
466     OTools::ThrowException(m_pConnection,nReturn,m_aStatementHandle,SQL_HANDLE_STMT,*this);
467 }
468 // -------------------------------------------------------------------------
469 
setClob(sal_Int32 parameterIndex,const Reference<XClob> & x)470 void SAL_CALL OPreparedStatement::setClob( sal_Int32 parameterIndex, const Reference< XClob >& x ) throw(SQLException, RuntimeException)
471 {
472     if ( x.is() )
473         setStream(parameterIndex, x->getCharacterStream(), (SQLLEN)x->length(), DataType::LONGVARCHAR);
474 }
475 // -------------------------------------------------------------------------
476 
setBlob(sal_Int32 parameterIndex,const Reference<XBlob> & x)477 void SAL_CALL OPreparedStatement::setBlob( sal_Int32 parameterIndex, const Reference< XBlob >& x ) throw(SQLException, RuntimeException)
478 {
479     if ( x.is() )
480         setStream(parameterIndex, x->getBinaryStream(), (SQLLEN)x->length(), DataType::LONGVARCHAR);
481 }
482 // -------------------------------------------------------------------------
483 
setArray(sal_Int32,const Reference<XArray> &)484 void SAL_CALL OPreparedStatement::setArray( sal_Int32 /*parameterIndex*/, const Reference< XArray >& /*x*/ ) throw(SQLException, RuntimeException)
485 {
486     ::dbtools::throwFunctionNotSupportedException( "XParameters::setArray", *this );
487 }
488 // -------------------------------------------------------------------------
489 
setRef(sal_Int32,const Reference<XRef> &)490 void SAL_CALL OPreparedStatement::setRef( sal_Int32 /*parameterIndex*/, const Reference< XRef >& /*x*/ ) throw(SQLException, RuntimeException)
491 {
492     ::dbtools::throwFunctionNotSupportedException( "XParameters::setRef", *this );
493 }
494 // -------------------------------------------------------------------------
setDecimal(sal_Int32 parameterIndex,const::rtl::OUString & x)495 void OPreparedStatement::setDecimal( sal_Int32 parameterIndex, const ::rtl::OUString& x )
496 {
497     ::rtl::OString aString(::rtl::OUStringToOString(x,getOwnConnection()->getTextEncoding()));
498     setParameter(parameterIndex,DataType::DECIMAL,aString.getLength(),(void*)&x);
499 }
500 // -------------------------------------------------------------------------
setObjectWithInfo(sal_Int32 parameterIndex,const Any & x,sal_Int32 sqlType,sal_Int32 scale)501 void SAL_CALL OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex, const Any& x, sal_Int32 sqlType, sal_Int32 scale ) throw(SQLException, RuntimeException)
502 {
503     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
504     ::osl::MutexGuard aGuard( m_aMutex );
505 
506     prepareStatement();
507     // For each known SQL Type, call the appropriate
508         // set routine
509 
510     switch (sqlType)
511     {
512         case DataType::VARCHAR:
513         case DataType::LONGVARCHAR:
514             if(x.hasValue())
515             {
516                 ::rtl::OUString sStr;
517                 x >>= sStr;
518                 ::rtl::OString aString(::rtl::OUStringToOString(sStr,getOwnConnection()->getTextEncoding()));
519                 setParameter(parameterIndex,sqlType,aString.getLength(),&aString);
520             }
521             else
522                 setNull(parameterIndex,sqlType);
523             break;
524         case DataType::DECIMAL:
525             {
526                 ORowSetValue aValue;
527                 aValue.fill(x);
528                 setDecimal(parameterIndex,aValue);
529             }
530             break;
531         case DataType::NUMERIC:
532             {
533                 ORowSetValue aValue;
534                 aValue.fill(x);
535                 setString(parameterIndex,aValue);
536             }
537             break;
538         default:
539             ::dbtools::setObjectWithInfo(this,parameterIndex,x,sqlType,scale);
540         }
541 }
542 // -------------------------------------------------------------------------
543 
setObjectNull(sal_Int32 parameterIndex,sal_Int32 sqlType,const::rtl::OUString &)544 void SAL_CALL OPreparedStatement::setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& /*typeName*/ ) throw(SQLException, RuntimeException)
545 {
546     ::osl::MutexGuard aGuard( m_aMutex );
547     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
548 
549     setNull(parameterIndex,sqlType);
550 }
551 // -------------------------------------------------------------------------
552 
setObject(sal_Int32 parameterIndex,const Any & x)553 void SAL_CALL OPreparedStatement::setObject( sal_Int32 parameterIndex, const Any& x ) throw(SQLException, RuntimeException)
554 {
555     if (!::dbtools::implSetObject(this, parameterIndex, x))
556     {   // there is no other setXXX call which can handle the value in x
557         throw SQLException();
558     }
559 }
560 // -------------------------------------------------------------------------
561 
setShort(sal_Int32 parameterIndex,sal_Int16 x)562 void SAL_CALL OPreparedStatement::setShort( sal_Int32 parameterIndex, sal_Int16 x ) throw(SQLException, RuntimeException)
563 {
564     setParameter(parameterIndex,DataType::SMALLINT,sizeof(sal_Int16),&x);
565 }
566 // -------------------------------------------------------------------------
567 
setBytes(sal_Int32 parameterIndex,const Sequence<sal_Int8> & x)568 void SAL_CALL OPreparedStatement::setBytes( sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x ) throw(SQLException, RuntimeException)
569 {
570     setParameter(parameterIndex,DataType::BINARY,x.getLength(),(void*)&x);
571     boundParams[parameterIndex-1].setSequence(x); // this assures that the sequence stays alive
572 }
573 // -------------------------------------------------------------------------
574 
575 
setCharacterStream(sal_Int32 parameterIndex,const Reference<::com::sun::star::io::XInputStream> & x,sal_Int32 length)576 void SAL_CALL OPreparedStatement::setCharacterStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException)
577 {
578     setStream(parameterIndex, x, length, DataType::LONGVARCHAR);
579 }
580 // -------------------------------------------------------------------------
581 
setBinaryStream(sal_Int32 parameterIndex,const Reference<::com::sun::star::io::XInputStream> & x,sal_Int32 length)582 void SAL_CALL OPreparedStatement::setBinaryStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException)
583 {
584     setStream(parameterIndex, x, length, DataType::LONGVARBINARY);
585 }
586 // -------------------------------------------------------------------------
587 
clearParameters()588 void SAL_CALL OPreparedStatement::clearParameters(  ) throw(SQLException, RuntimeException)
589 {
590     prepareStatement();
591     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
592     SQLRETURN nRet = N3SQLFreeStmt (m_aStatementHandle, SQL_RESET_PARAMS);
593     nRet = N3SQLFreeStmt (m_aStatementHandle, SQL_UNBIND);
594 }
595 // -------------------------------------------------------------------------
clearBatch()596 void SAL_CALL OPreparedStatement::clearBatch(  ) throw(SQLException, RuntimeException)
597 {
598     //  clearParameters(  );
599     //  m_aBatchList.erase();
600 }
601 // -------------------------------------------------------------------------
602 
addBatch()603 void SAL_CALL OPreparedStatement::addBatch( ) throw(SQLException, RuntimeException)
604 {
605 }
606 // -------------------------------------------------------------------------
607 
executeBatch()608 Sequence< sal_Int32 > SAL_CALL OPreparedStatement::executeBatch(  ) throw(SQLException, RuntimeException)
609 {
610     return Sequence< sal_Int32 > ();
611 }
612 // -------------------------------------------------------------------------
613 
614 //====================================================================
615 // methods
616 //====================================================================
617 
618 //--------------------------------------------------------------------
619 // initBoundParam
620 // Initialize the bound parameter objects
621 //--------------------------------------------------------------------
622 
initBoundParam()623 void OPreparedStatement::initBoundParam () throw(SQLException)
624 {
625     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
626     // Get the number of parameters
627     numParams = 0;
628     N3SQLNumParams (m_aStatementHandle,&numParams);
629 
630     // There are parameter markers, allocate the bound
631     // parameter objects
632 
633     if (numParams > 0)
634     {
635         // Allocate an array of bound parameter objects
636 
637         boundParams = new OBoundParam[numParams];
638 
639         // Allocate and initialize each bound parameter
640 
641         for (sal_Int32 i = 0; i < numParams; i++)
642         {
643             boundParams[i] = OBoundParam();
644             boundParams[i].initialize ();
645         }
646     }
647 }
648 // -------------------------------------------------------------------------
649 
650 //--------------------------------------------------------------------
651 // allocBindBuf
652 // Allocate storage for the permanent data buffer for the bound
653 // parameter.
654 //--------------------------------------------------------------------
655 
allocBindBuf(sal_Int32 index,sal_Int32 bufLen)656 sal_Int8* OPreparedStatement::allocBindBuf( sal_Int32 index,sal_Int32 bufLen)
657 {
658     sal_Int8* b = NULL;
659 
660     // Sanity check the parameter number
661 
662     if ((index >= 1) &&
663         (index <= numParams) && bufLen > 0 )
664     {
665         b = boundParams[index - 1].allocBindDataBuffer(bufLen);
666     }
667 
668     return b;
669 }
670 // -------------------------------------------------------------------------
671 
672 //--------------------------------------------------------------------
673 // getDataBuf
674 // Gets the data buffer for the given parameter index
675 //--------------------------------------------------------------------
676 
getDataBuf(sal_Int32 index)677 sal_Int8* OPreparedStatement::getDataBuf (sal_Int32 index)
678 {
679     sal_Int8* b = NULL;
680 
681     // Sanity check the parameter number
682 
683     if ((index >= 1) &&
684         (index <= numParams))
685     {
686         b = boundParams[index - 1].getBindDataBuffer ();
687     }
688 
689     return b;
690 }
691 // -------------------------------------------------------------------------
692 
693 //--------------------------------------------------------------------
694 // getLengthBuf
695 // Gets the length buffer for the given parameter index
696 //--------------------------------------------------------------------
697 
getLengthBuf(sal_Int32 index)698 sal_Int8* OPreparedStatement::getLengthBuf (sal_Int32 index)
699 {
700     sal_Int8* b = NULL;
701 
702     // Sanity check the parameter number
703 
704     if ((index >= 1) &&
705         (index <= numParams))
706     {
707         b = boundParams[index - 1].getBindLengthBuffer ();
708     }
709 
710     return b;
711 }
712 // -------------------------------------------------------------------------
713 
714 //--------------------------------------------------------------------
715 // getParamLength
716 // Returns the length of the given parameter number.  When each
717 // parameter was bound, a 4-sal_Int8 buffer was given to hold the
718 // length (stored in native format).  Get the buffer, convert the
719 // buffer from native format, and return it.  If the length is -1,
720 // the column is considered to be NULL.
721 //--------------------------------------------------------------------
722 
getParamLength(sal_Int32 index)723 sal_Int32 OPreparedStatement::getParamLength (  sal_Int32 index)
724 {
725     sal_Int32 paramLen = SQL_NULL_DATA;
726 
727     // Sanity check the parameter number
728 
729     if ((index >= 1) &&
730         (index <= numParams)) {
731 
732         // Now get the length of the parameter from the
733         // bound param array.  -1 is returned if it is NULL.
734         long n = 0;
735         memcpy (&n, boundParams[index -1].getBindLengthBuffer (), sizeof (n));
736         paramLen = n;
737     }
738     return paramLen;
739 }
740 // -------------------------------------------------------------------------
741 
742 //--------------------------------------------------------------------
743 // putParamData
744 // Puts parameter data from a previously bound input stream.  The
745 // input stream was bound using SQL_LEN_DATA_AT_EXEC.
746 //--------------------------------------------------------------------
747 
putParamData(sal_Int32 index)748 void OPreparedStatement::putParamData (sal_Int32 index) throw(SQLException)
749 {
750     // Sanity check the parameter index
751     if ((index < 1) ||
752         (index > numParams))
753     {
754         return;
755     }
756 
757     // We'll transfer up to MAX_PUT_DATA_LENGTH at a time
758     Sequence< sal_Int8 > buf( MAX_PUT_DATA_LENGTH );
759 
760     // Get the information about the input stream
761 
762     Reference< XInputStream> inputStream =  boundParams[index - 1].getInputStream ();
763     if ( !inputStream.is() )
764     {
765         ::connectivity::SharedResources aResources;
766         const ::rtl::OUString sError( aResources.getResourceString(STR_NO_INPUTSTREAM));
767         throw SQLException (sError, *this,::rtl::OUString(),0,Any());
768     }
769 
770     sal_Int32 maxBytesLeft = boundParams[index - 1].getInputStreamLen ();
771 
772     // Loop while more data from the input stream
773     sal_Int32 haveRead = 0;
774     try
775     {
776 
777         do
778         {
779             sal_Int32 toReadThisRound = ::std::min( MAX_PUT_DATA_LENGTH, maxBytesLeft );
780 
781             // Read some data from the input stream
782             haveRead = inputStream->readBytes( buf, toReadThisRound );
783             OSL_ENSURE( haveRead == buf.getLength(), "OPreparedStatement::putParamData: inconsistency!" );
784 
785             if ( !haveRead )
786                 // no more data in the stream - the given stream length was a maximum which could not be
787                 // fulfilled by the stream
788                 break;
789 
790             // Put the data
791             OSL_ENSURE( m_aStatementHandle, "OPreparedStatement::putParamData: StatementHandle is null!" );
792             N3SQLPutData ( m_aStatementHandle, buf.getArray(), buf.getLength() );
793 
794             // decrement the number of bytes still needed
795             maxBytesLeft -= haveRead;
796         }
797         while ( maxBytesLeft > 0 );
798     }
799     catch (const IOException& ex)
800     {
801 
802         // If an I/O exception was generated, turn
803         // it into a SQLException
804 
805         throw SQLException(ex.Message,*this,::rtl::OUString(),0,Any());
806     }
807 }
808 // -------------------------------------------------------------------------
809 //--------------------------------------------------------------------
810 // getPrecision
811 // Given a SQL type, return the maximum precision for the column.
812 // Returns -1 if not known
813 //--------------------------------------------------------------------
814 
getPrecision(sal_Int32 sqlType)815 sal_Int32 OPreparedStatement::getPrecision ( sal_Int32 sqlType)
816 {
817     ::osl::MutexGuard aGuard( m_aMutex );
818     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
819 
820     sal_Int32 prec = -1;
821     const TTypeInfoVector& rTypeInfo = m_pConnection->getTypeInfo();
822     if ( !rTypeInfo.empty() )
823     {
824         m_pConnection->buildTypeInfo();
825     }
826 
827     if ( !rTypeInfo.empty() )
828     {
829         OTypeInfo aInfo;
830         aInfo.nType = (sal_Int16)sqlType;
831         TTypeInfoVector::const_iterator aIter = ::std::find(rTypeInfo.begin(),rTypeInfo.end(),aInfo);
832         if(aIter != rTypeInfo.end())
833             prec = (*aIter).nPrecision;
834     }
835     return prec;
836 }
837 
838 //--------------------------------------------------------------------
839 // setStream
840 // Sets an input stream as a parameter, using the given SQL type
841 //--------------------------------------------------------------------
842 
setStream(sal_Int32 ParameterIndex,const Reference<XInputStream> & x,SQLLEN length,sal_Int32 SQLtype)843 void OPreparedStatement::setStream(
844                                     sal_Int32 ParameterIndex,
845                                     const Reference< XInputStream>& x,
846                                     SQLLEN length,
847                                     sal_Int32 SQLtype)
848                                     throw(SQLException)
849 {
850     ::osl::MutexGuard aGuard( m_aMutex );
851     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
852 
853 
854     prepareStatement();
855 
856     checkParameterIndex(ParameterIndex);
857     // Get the buffer needed for the length
858 
859     sal_Int8* lenBuf = getLengthBuf(ParameterIndex);
860 
861     // Allocate a new buffer for the parameter data.  This buffer
862     // will be returned by SQLParamData (it is set to the parameter
863     // number, a 4-sal_Int8 integer)
864 
865     sal_Int8* dataBuf = allocBindBuf (ParameterIndex, 4);
866 
867     // Bind the parameter with SQL_LEN_DATA_AT_EXEC
868     SQLSMALLINT   Ctype = SQL_C_CHAR;
869     SQLLEN  atExec = SQL_LEN_DATA_AT_EXEC (length);
870     memcpy (dataBuf, &ParameterIndex, sizeof(ParameterIndex));
871     memcpy (lenBuf, &atExec, sizeof (atExec));
872 
873     if ((SQLtype == SQL_BINARY) || (SQLtype == SQL_VARBINARY) || (SQLtype == SQL_LONGVARBINARY))
874         Ctype = SQL_C_BINARY;
875 
876 
877     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
878     N3SQLBindParameter(m_aStatementHandle,
879                         (SQLUSMALLINT)ParameterIndex,
880                         (SQLUSMALLINT)SQL_PARAM_INPUT,
881                         Ctype,
882                         (SQLSMALLINT)SQLtype,
883                         (SQLULEN)length,
884                         0,
885                         dataBuf,
886                         sizeof(ParameterIndex),
887                         (SQLLEN*)lenBuf);
888 
889     // Save the input stream
890     boundParams[ParameterIndex - 1].setInputStream (x, length);
891 }
892 // -------------------------------------------------------------------------
893 
894 // -------------------------------------------------------------------------
895 
FreeParams()896 void OPreparedStatement::FreeParams()
897 {
898     numParams = 0;
899     delete [] boundParams;
900     boundParams = NULL;
901 }
902 // -------------------------------------------------------------------------
setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any & rValue)903 void OPreparedStatement::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue) throw (Exception)
904 {
905     try
906     {
907         switch(nHandle)
908         {
909             case PROPERTY_ID_RESULTSETCONCURRENCY:
910                 if(!isPrepared())
911                     setResultSetConcurrency(comphelper::getINT32(rValue));
912                 break;
913             case PROPERTY_ID_RESULTSETTYPE:
914                 if(!isPrepared())
915                     setResultSetType(comphelper::getINT32(rValue));
916                 break;
917             case PROPERTY_ID_FETCHDIRECTION:
918                 if(!isPrepared())
919                     setFetchDirection(comphelper::getINT32(rValue));
920                 break;
921             case PROPERTY_ID_USEBOOKMARKS:
922                 if(!isPrepared())
923                     setUsingBookmarks(comphelper::getBOOL(rValue));
924                 break;
925             default:
926                 OStatement_Base::setFastPropertyValue_NoBroadcast(nHandle,rValue);
927         }
928     }
929     catch(const SQLException&)
930     {
931         //  throw Exception(e.Message,*this);
932     }
933 }
934 // -----------------------------------------------------------------------------
prepareStatement()935 void OPreparedStatement::prepareStatement()
936 {
937     if(!isPrepared())
938     {
939         OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
940         ::rtl::OString aSql(::rtl::OUStringToOString(m_sSqlStatement,getOwnConnection()->getTextEncoding()));
941         SQLRETURN nReturn = N3SQLPrepare(m_aStatementHandle,(SDB_ODBC_CHAR *) aSql.getStr(),aSql.getLength());
942         OTools::ThrowException(m_pConnection,nReturn,m_aStatementHandle,SQL_HANDLE_STMT,*this);
943         m_bPrepared = sal_True;
944         initBoundParam();
945     }
946 }
947 // -----------------------------------------------------------------------------
checkParameterIndex(sal_Int32 _parameterIndex)948 void OPreparedStatement::checkParameterIndex(sal_Int32 _parameterIndex)
949 {
950     if( !_parameterIndex || _parameterIndex > numParams)
951     {
952         ::connectivity::SharedResources aResources;
953         const ::rtl::OUString sError( aResources.getResourceStringWithSubstitution(STR_WRONG_PARAM_INDEX,
954             "$pos$", ::rtl::OUString::valueOf(_parameterIndex),
955             "$count$", ::rtl::OUString::valueOf((sal_Int32)numParams)
956             ));
957         SQLException aNext(sError,*this, ::rtl::OUString(),0,Any());
958 
959         ::dbtools::throwInvalidIndexException(*this,makeAny(aNext));
960     }
961 }
962 // -----------------------------------------------------------------------------
createResulSet()963 OResultSet* OPreparedStatement::createResulSet()
964 {
965     OResultSet* pReturn = new OResultSet(m_aStatementHandle,this);
966     pReturn->setMetaData(getMetaData());
967     return pReturn;
968 }
969 // -----------------------------------------------------------------------------
970