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*)¶mIndex);
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*)¶mIndex);
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