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