LibreOffice Module connectivity (master) 1
OPreparedStatement.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20
21#include <string.h>
22#include <osl/diagnose.h>
24#include <odbc/OBoundParam.hxx>
25#include <com/sun/star/io/IOException.hpp>
26#include <com/sun/star/sdbc/DataType.hpp>
27#include <odbc/OTools.hxx>
28#include <odbc/OResultSet.hxx>
32#include <comphelper/types.hxx>
34#include <strings.hrc>
35#include <memory>
36#include <type_traits>
37
38using namespace ::comphelper;
39using namespace connectivity;
40using namespace connectivity::odbc;
41using namespace com::sun::star::uno;
42using namespace com::sun::star::lang;
43using namespace com::sun::star::beans;
44using namespace com::sun::star::sdbc;
45using namespace com::sun::star::sdbcx;
46using namespace com::sun::star::container;
47using namespace com::sun::star::io;
48using namespace com::sun::star::util;
49
50IMPLEMENT_SERVICE_INFO(OPreparedStatement,"com.sun.star.sdbcx.OPreparedStatement","com.sun.star.sdbc.PreparedStatement");
51
52namespace
53{
54 // for now, never use wchar,
55 // but most of code is prepared to handle it
56 // in case we make this configurable
57 const bool bUseWChar = false;
58}
59
60OPreparedStatement::OPreparedStatement( OConnection* _pConnection,const OUString& sql)
61 :OStatement_BASE2(_pConnection)
62 ,numParams(0)
63 ,m_bPrepared(false)
64{
66}
67
69{
70}
71
72void SAL_CALL OPreparedStatement::acquire() noexcept
73{
75}
76
77void SAL_CALL OPreparedStatement::release() noexcept
78{
80}
81
82Any SAL_CALL OPreparedStatement::queryInterface( const Type & rType )
83{
85 return aRet.hasValue() ? aRet : OPreparedStatement_BASE::queryInterface(rType);
86}
87
88css::uno::Sequence< css::uno::Type > SAL_CALL OPreparedStatement::getTypes( )
89{
90 return ::comphelper::concatSequences(OPreparedStatement_BASE::getTypes(),OStatement_BASE2::getTypes());
91}
92
93
95{
96 ::osl::MutexGuard aGuard( m_aMutex );
97 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
98
99
101 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
102 if(!m_xMetaData.is())
104 return m_xMetaData;
105}
106
107
109{
110 ::osl::MutexGuard aGuard( m_aMutex );
111 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
112
113
114 // Close/clear our result set
116
117 // Reset last warning message
118
119 try {
120 clearWarnings ();
122 FreeParams();
123 }
124 catch (SQLException &) {
125 // If we get an error, ignore
126 }
127
128 // Remove this Statement object from the Connection object's
129 // list
130}
131
132
134{
135 ::osl::MutexGuard aGuard( m_aMutex );
136 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
137
138 // Reset warnings
139
140 clearWarnings ();
141
142 // Reset the statement handle, warning and saved Resultset
143
144 reset();
145
146 // Call SQLExecute
148
149 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
150 try
151 {
152 SQLRETURN nReturn = N3SQLExecute(m_aStatementHandle);
153
154 OTools::ThrowException(m_pConnection.get(),nReturn,m_aStatementHandle,SQL_HANDLE_STMT,*this);
155 bool needData = nReturn == SQL_NEED_DATA;
156
157 // Now loop while more data is needed (i.e. a data-at-
158 // execution parameter was given). For each parameter
159 // that needs data, put the data from the input stream.
160
161 while (needData) {
162
163 // Get the parameter number that requires data
164
165 sal_Int32* paramIndex = nullptr;
166 N3SQLParamData(m_aStatementHandle, reinterpret_cast<SQLPOINTER*>(&paramIndex));
167
168 // If the parameter index is -1, there is no
169 // more data required
170
171 if ( !paramIndex || ( *paramIndex == -1 ) )
172 needData = false;
173 else
174 {
175 // Now we have the proper parameter
176 // index, get the data from the input
177 // stream and do a SQLPutData
178 putParamData (*paramIndex);
179 }
180 }
181
182 }
183 catch (const SQLWarning&)
184 {
185 }
186
187 // Now determine if there is a result set associated with
188 // the SQL statement that was executed. Get the column
189 // count, and if it is not zero, there is a result set.
190
191
192 return getColumnCount() > 0;
193}
194
195
197{
198 ::osl::MutexGuard aGuard( m_aMutex );
199 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
200
201 sal_Int32 numRows = -1;
202
204 // Execute the statement. If execute returns sal_False, a
205 // row count exists.
206
207 if (!execute())
208 numRows = getUpdateCount ();
209 else
210 {
211 // No update count was produced (a ResultSet was). Raise
212 // an exception
213 m_pConnection->throwGenericSQLException(STR_NO_ROWCOUNT,*this);
214 }
215 return numRows;
216}
217
218
219void SAL_CALL OPreparedStatement::setString( sal_Int32 parameterIndex, const OUString& x )
220{
221 setParameter(parameterIndex, DataType::CHAR, invalid_scale, x);
222}
223
224
226{
227 ::osl::MutexGuard aGuard( m_aMutex );
228 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
229
230 return m_pConnection;
231}
232
233
235{
236 ::osl::MutexGuard aGuard( m_aMutex );
237 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
238
240
242
243 if (execute())
244 rs = getResultSet(false);
245 else
246 {
247 // No ResultSet was produced. Raise an exception
248 m_pConnection->throwGenericSQLException(STR_NO_RESULTSET,*this);
249 }
250 return rs;
251}
252
253
254void SAL_CALL OPreparedStatement::setBoolean( sal_Int32 parameterIndex, sal_Bool x )
255{
256 // Set the parameter as if it were an integer
257 setInt (parameterIndex, x ? 1 : 0 );
258}
259
260// The MutexGuard must _already_ be taken!
261void OPreparedStatement::setParameterPre(sal_Int32 parameterIndex)
262{
263 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
265 checkParameterIndex(parameterIndex);
266 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
267}
268
269
270template <typename T> void OPreparedStatement::setScalarParameter(const sal_Int32 parameterIndex, const sal_Int32 i_nType, const SQLULEN i_nColSize, const T i_Value)
271{
272 setScalarParameter(parameterIndex, i_nType, i_nColSize, invalid_scale, i_Value);
273}
274
275
276template <typename T> void OPreparedStatement::setScalarParameter(const sal_Int32 parameterIndex, const sal_Int32 i_nType, const SQLULEN i_nColSize, sal_Int32 i_nScale, const T i_Value)
277{
278 ::osl::MutexGuard aGuard( m_aMutex );
279 setParameterPre(parameterIndex);
280
281 typedef typename std::remove_reference<T>::type TnoRef;
282
283 TnoRef *bindBuf = static_cast< TnoRef* >( allocBindBuf(parameterIndex, sizeof(i_Value)) );
284 *bindBuf = i_Value;
285
286 setParameter(parameterIndex, i_nType, i_nColSize, i_nScale, bindBuf, sizeof(i_Value), sizeof(i_Value));
287}
288
289
290void OPreparedStatement::setParameter(const sal_Int32 parameterIndex, const sal_Int32 _nType, const sal_Int16 _nScale, const OUString &_sData)
291{
292 ::osl::MutexGuard aGuard( m_aMutex );
293 setParameterPre(parameterIndex);
294
295 assert (_nType == DataType::VARCHAR || _nType == DataType::CHAR || _nType == DataType::DECIMAL || _nType == DataType::NUMERIC);
296
297 sal_Int32 nCharLen;
298 sal_Int32 nByteLen;
299 void *pData;
300 if (bUseWChar)
301 {
302 /*
303 * On Windows, wchar is 16 bits (UTF-16 encoding), the ODBC "W" variants functions take UTF-16 encoded strings
304 * and character lengths are number of UTF-16 codepoints.
305 * Reference: http://msdn.microsoft.com/en-us/library/windows/desktop/ms716246%28v=vs.85%29.aspx
306 * ODBC Programmer's reference > Developing Applications > Programming Considerations > Unicode > Unicode Function Arguments
307 * http://support.microsoft.com/kb/294169
308 *
309 * UnixODBC can be configured at compile-time so that the "W" variants expect
310 * UTF-16 or UTF-32 encoded strings, and character lengths are number of codepoints.
311 * However, UTF-16 is the default, what all/most distributions do
312 * and the established API that most drivers implement.
313 * As wchar is often 32 bits, this differs from C-style strings of wchar!
314 *
315 * On MacOS X, the "W" variants use wchar_t, which is UCS4
316 *
317 * Our internal OUString storage is always UTF-16, so no conversion to do here.
318 */
319 static_assert(sizeof (SQLWCHAR) == 2 || sizeof (SQLWCHAR) == 4, "must be 2 or 4");
320 if (sizeof (SQLWCHAR) == 2)
321 {
322 nCharLen = _sData.getLength();
323 nByteLen = 2 * nCharLen;
324 pData = allocBindBuf(parameterIndex, nByteLen);
325 memcpy(pData, _sData.getStr(), nByteLen);
326 }
327 else
328 {
329 pData = allocBindBuf(parameterIndex, _sData.getLength() * 4);
330 sal_uInt32* pCursor = static_cast<sal_uInt32*>(pData);
331 nCharLen = 0;
332 for (sal_Int32 i = 0; i != _sData.getLength();)
333 {
334 *pCursor++ = _sData.iterateCodePoints(&i);
335 nCharLen += 1;
336 }
337 nByteLen = 4 * nCharLen;
338 }
339 }
340 else
341 {
342 assert(getOwnConnection()->getTextEncoding() != RTL_TEXTENCODING_UCS2 &&
343 getOwnConnection()->getTextEncoding() != RTL_TEXTENCODING_UCS4);
344 OString sOData(
345 OUStringToOString(_sData, getOwnConnection()->getTextEncoding()));
346 nCharLen = nByteLen = sOData.getLength();
347 pData = allocBindBuf(parameterIndex, nByteLen);
348 memcpy(pData, sOData.getStr(), nByteLen);
349 }
350
351 setParameter( parameterIndex, _nType, nCharLen, _nScale, pData, nByteLen, nByteLen );
352}
353
354void OPreparedStatement::setParameter(const sal_Int32 parameterIndex, const sal_Int32 _nType, const Sequence< sal_Int8 > &x)
355{
356 ::osl::MutexGuard aGuard( m_aMutex );
357 setParameterPre(parameterIndex);
358
359 assert(_nType == DataType::BINARY || _nType == DataType::VARBINARY);
360
361 // don't copy the sequence, just point the ODBC directly at the sequence's storage array
362 // Why BINARY/Sequence is treated differently than strings (which are copied), I'm not sure
363 OSL_VERIFY(allocBindBuf(parameterIndex, 0) == nullptr);
364 boundParams[parameterIndex-1].setSequence(x); // this ensures that the sequence stays alive
365
366 setParameter( parameterIndex, _nType, x.getLength(), invalid_scale, x.getConstArray(), x.getLength(), x.getLength() );
367}
368
369void OPreparedStatement::setParameter(const sal_Int32 parameterIndex, const sal_Int32 _nType, const SQLULEN _nColumnSize, const sal_Int32 _nScale, const void* const _pData, const SQLULEN _nDataLen, const SQLLEN _nDataAllocLen)
370{
371 SQLSMALLINT fCType, fSqlType;
372 OTools::getBindTypes(bUseWChar, m_pConnection->useOldDateFormat(), OTools::jdbcTypeToOdbc(_nType), fCType, fSqlType);
373
374 SQLLEN& rDataLen = boundParams[parameterIndex-1].getBindLengthBuffer();
375 rDataLen = _nDataLen;
376
377 SQLRETURN nRetcode;
378 nRetcode = (*reinterpret_cast<T3SQLBindParameter>(m_pConnection->getOdbcFunction(ODBC3SQLFunctionId::BindParameter)))(
380 // checkParameterIndex guarantees this is safe
381 static_cast<SQLUSMALLINT>(parameterIndex),
382 SQL_PARAM_INPUT,
383 fCType,
384 fSqlType,
385 _nColumnSize,
386 _nScale,
387 // we trust the ODBC driver not to touch it because SQL_PARAM_INPUT
388 const_cast<void*>(_pData),
389 _nDataAllocLen,
390 &rDataLen);
391
392 OTools::ThrowException(m_pConnection.get(), nRetcode, m_aStatementHandle, SQL_HANDLE_STMT, *this);
393}
394
395void SAL_CALL OPreparedStatement::setByte( const sal_Int32 parameterIndex, const sal_Int8 x )
396{
397 setScalarParameter(parameterIndex, DataType::TINYINT, 3, 0, x);
398}
399
400void SAL_CALL OPreparedStatement::setDate( sal_Int32 parameterIndex, const Date& aData )
401{
402 DATE_STRUCT x(OTools::DateToOdbcDate(aData));
403 setScalarParameter<DATE_STRUCT&>(parameterIndex, DataType::DATE, 10, x);
404}
405
406void SAL_CALL OPreparedStatement::setTime( sal_Int32 parameterIndex, const css::util::Time& aVal )
407{
408 SQLULEN nColSize;
409 if(aVal.NanoSeconds == 0)
410 nColSize = 8;
411 else if(aVal.NanoSeconds % 100000000 == 0)
412 nColSize = 10;
413 else if(aVal.NanoSeconds % 10000000 == 0)
414 nColSize = 11;
415 else if(aVal.NanoSeconds % 1000000 == 0)
416 nColSize = 12;
417 else if(aVal.NanoSeconds % 100000 == 0)
418 nColSize = 13;
419 else if(aVal.NanoSeconds % 10000 == 0)
420 nColSize = 14;
421 else if(aVal.NanoSeconds % 1000 == 0)
422 nColSize = 15;
423 else if(aVal.NanoSeconds % 100 == 0)
424 nColSize = 16;
425 else if(aVal.NanoSeconds % 10 == 0)
426 nColSize = 17;
427 else
428 nColSize = 18;
429 TIME_STRUCT x(OTools::TimeToOdbcTime(aVal));
430 setScalarParameter<TIME_STRUCT&>(parameterIndex, DataType::TIME, nColSize, (nColSize == 8)? 0 : nColSize-9, x);
431}
432
433
434void SAL_CALL OPreparedStatement::setTimestamp( sal_Int32 parameterIndex, const DateTime& aVal )
435{
436 SQLULEN nColSize;
437 if(aVal.NanoSeconds == 0)
438 {
439 if (aVal.Seconds == 0)
440 nColSize=16;
441 else
442 nColSize=19;
443 }
444 else if(aVal.NanoSeconds % 100000000 == 0)
445 nColSize = 21;
446 else if(aVal.NanoSeconds % 10000000 == 0)
447 nColSize = 22;
448 else if(aVal.NanoSeconds % 1000000 == 0)
449 nColSize = 23;
450 else if(aVal.NanoSeconds % 100000 == 0)
451 nColSize = 24;
452 else if(aVal.NanoSeconds % 10000 == 0)
453 nColSize = 25;
454 else if(aVal.NanoSeconds % 1000 == 0)
455 nColSize = 26;
456 else if(aVal.NanoSeconds % 100 == 0)
457 nColSize = 27;
458 else if(aVal.NanoSeconds % 10 == 0)
459 nColSize = 28;
460 else
461 nColSize = 29;
462
463 TIMESTAMP_STRUCT x(OTools::DateTimeToTimestamp(aVal));
464 setScalarParameter<TIMESTAMP_STRUCT&>(parameterIndex, DataType::TIMESTAMP, nColSize, (nColSize <= 19)? 0 : nColSize-20, x);
465}
466
467
468void SAL_CALL OPreparedStatement::setDouble( sal_Int32 parameterIndex, double x )
469{
470 setScalarParameter(parameterIndex, DataType::DOUBLE, 15, x);
471}
472
473
474void SAL_CALL OPreparedStatement::setFloat( sal_Int32 parameterIndex, float x )
475{
476 setScalarParameter(parameterIndex, DataType::FLOAT, 15, x);
477}
478
479
480void SAL_CALL OPreparedStatement::setInt( sal_Int32 parameterIndex, sal_Int32 x )
481{
482 setScalarParameter(parameterIndex, DataType::INTEGER, 10, 0, x);
483}
484
485
486void SAL_CALL OPreparedStatement::setLong( sal_Int32 parameterIndex, sal_Int64 x )
487{
488 try
489 {
490 setScalarParameter(parameterIndex, DataType::BIGINT, 19, 0, x);
491 }
492 catch(SQLException&)
493 {
494 setString(parameterIndex, ORowSetValue(x).getString());
495 }
496}
497
498
499void SAL_CALL OPreparedStatement::setNull( sal_Int32 parameterIndex, const sal_Int32 _nType )
500{
501 ::osl::MutexGuard aGuard( m_aMutex );
502 setParameterPre(parameterIndex);
503
504 OSL_VERIFY(allocBindBuf(parameterIndex, 0) == nullptr);
505 SQLLEN * const lenBuf = getLengthBuf (parameterIndex);
506 *lenBuf = SQL_NULL_DATA;
507
508
509 SQLSMALLINT fCType;
510 SQLSMALLINT fSqlType;
511
512 OTools::getBindTypes( bUseWChar,
513 m_pConnection->useOldDateFormat(),
515 fCType,
516 fSqlType);
517
518 SQLRETURN nReturn = N3SQLBindParameter( m_aStatementHandle,
519 static_cast<SQLUSMALLINT>(parameterIndex),
520 SQL_PARAM_INPUT,
521 fCType,
522 fSqlType,
523 0,
524 0,
525 nullptr,
526 0,
527 lenBuf
528 );
529 OTools::ThrowException(m_pConnection.get(),nReturn,m_aStatementHandle,SQL_HANDLE_STMT,*this);
530}
531
532
533void SAL_CALL OPreparedStatement::setClob( sal_Int32 parameterIndex, const Reference< XClob >& x )
534{
535 if ( x.is() )
536 setStream(parameterIndex, x->getCharacterStream(), x->length(), DataType::LONGVARCHAR);
537}
538
539
540void SAL_CALL OPreparedStatement::setBlob( sal_Int32 parameterIndex, const Reference< XBlob >& x )
541{
542 if ( x.is() )
543 setStream(parameterIndex, x->getBinaryStream(), x->length(), DataType::LONGVARBINARY);
544}
545
546
547void SAL_CALL OPreparedStatement::setArray( sal_Int32 /*parameterIndex*/, const Reference< XArray >& /*x*/ )
548{
549 ::dbtools::throwFunctionNotSupportedSQLException( "XParameters::setArray", *this );
550}
551
552
553void SAL_CALL OPreparedStatement::setRef( sal_Int32 /*parameterIndex*/, const Reference< XRef >& /*x*/ )
554{
555 ::dbtools::throwFunctionNotSupportedSQLException( "XParameters::setRef", *this );
556}
557
558void SAL_CALL OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex, const Any& x, sal_Int32 sqlType, sal_Int32 scale )
559{
560 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
561 ::osl::MutexGuard aGuard( m_aMutex );
562
564 // For each known SQL Type, call the appropriate
565 // set routine
566
567 switch (sqlType)
568 {
569 case DataType::CHAR:
570 case DataType::VARCHAR:
571 case DataType::LONGVARCHAR:
572 if(x.hasValue())
573 {
574 OUString sStr;
575 x >>= sStr;
576 setParameter(parameterIndex, sqlType, scale, sStr);
577 }
578 else
579 setNull(parameterIndex,sqlType);
580 break;
581 case DataType::DECIMAL:
582 case DataType::NUMERIC:
583 if(x.hasValue())
584 {
585 ORowSetValue aValue;
586 aValue.fill(x);
587 setParameter(parameterIndex, sqlType, scale, aValue.getString());
588 }
589 else
590 setNull(parameterIndex,sqlType);
591 break;
592 default:
593 ::dbtools::setObjectWithInfo(this,parameterIndex,x,sqlType,scale);
594 }
595}
596
597
598void SAL_CALL OPreparedStatement::setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const OUString& /*typeName*/ )
599{
600 setNull(parameterIndex,sqlType);
601}
602
603
604void SAL_CALL OPreparedStatement::setObject( sal_Int32 parameterIndex, const Any& x )
605{
606 if (!::dbtools::implSetObject(this, parameterIndex, x))
607 { // there is no other setXXX call which can handle the value in x
608 throw SQLException();
609 }
610}
611
612
613void SAL_CALL OPreparedStatement::setShort( sal_Int32 parameterIndex, sal_Int16 x )
614{
615 setScalarParameter(parameterIndex, DataType::SMALLINT, 5, 0, x);
616}
617
618
619void SAL_CALL OPreparedStatement::setBytes( sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x )
620{
621 setParameter(parameterIndex, DataType::BINARY, x);
622}
623
624
625void SAL_CALL OPreparedStatement::setCharacterStream( sal_Int32 parameterIndex, const Reference< css::io::XInputStream >& x, sal_Int32 length )
626{
627 // LEM: It is quite unclear to me what the interface here is.
628 // The XInputStream provides *bytes*, not characters.
629 setStream(parameterIndex, x, length, DataType::LONGVARCHAR);
630}
631
632
633void SAL_CALL OPreparedStatement::setBinaryStream( sal_Int32 parameterIndex, const Reference< css::io::XInputStream >& x, sal_Int32 length )
634{
635 setStream(parameterIndex, x, length, DataType::LONGVARBINARY);
636}
637
638
640{
641 ::osl::MutexGuard aGuard( m_aMutex );
643 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
644 N3SQLFreeStmt (m_aStatementHandle, SQL_RESET_PARAMS);
645 N3SQLFreeStmt (m_aStatementHandle, SQL_UNBIND);
646}
647
649{
650 ::dbtools::throwFunctionNotSupportedSQLException( "XPreparedBatchExecution::clearBatch", *this );
651 // clearParameters( );
652 // m_aBatchVector.erase();
653}
654
655
657{
658 ::dbtools::throwFunctionNotSupportedSQLException( "XPreparedBatchExecution::addBatch", *this );
659}
660
661
663{
664 ::dbtools::throwFunctionNotSupportedSQLException( "XPreparedBatchExecution::executeBatch", *this );
665 // not reached, but keep -Werror happy
666 return Sequence< sal_Int32 > ();
667}
668
669
670// methods
671
672
673// initBoundParam
674// Initialize the bound parameter objects
675
676
678{
679 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
680 // Get the number of parameters
681 numParams = 0;
683
684 // There are parameter markers, allocate the bound
685 // parameter objects
686
687 if (numParams > 0)
688 {
690 }
691}
692
693
694// allocBindBuf
695// Allocate storage for the permanent data buffer for the bound
696// parameter.
697
698
699void* OPreparedStatement::allocBindBuf( sal_Int32 index,sal_Int32 bufLen)
700{
701 void* b = nullptr;
702
703 // Sanity check the parameter number
704
705 if ((index >= 1) && (index <= numParams))
706 {
707 b = boundParams[index - 1].allocBindDataBuffer(bufLen);
708 }
709
710 return b;
711}
712
713
714// getLengthBuf
715// Gets the length buffer for the given parameter index
716
717
718SQLLEN* OPreparedStatement::getLengthBuf (sal_Int32 index)
719{
720 SQLLEN* b = nullptr;
721
722 // Sanity check the parameter number
723
724 if ((index >= 1) &&
725 (index <= numParams))
726 {
727 b = &boundParams[index - 1].getBindLengthBuffer ();
728 }
729
730 return b;
731}
732
733
734// putParamData
735// Puts parameter data from a previously bound input stream. The
736// input stream was bound using SQL_LEN_DATA_AT_EXEC.
738{
739 // Sanity check the parameter index
740 if ((index < 1) ||
741 (index > numParams))
742 {
743 return;
744 }
745
746 // We'll transfer up to MAX_PUT_DATA_LENGTH at a time
748
749 // Get the information about the input stream
750
751 Reference< XInputStream> inputStream = boundParams[index - 1].getInputStream ();
752 if ( !inputStream.is() )
753 {
755 const OUString sError( aResources.getResourceString(STR_NO_INPUTSTREAM));
756 throw SQLException (sError, *this,OUString(),0,Any());
757 }
758
759 sal_Int32 maxBytesLeft = boundParams[index - 1].getInputStreamLen ();
760
761 // Loop while more data from the input stream
762 sal_Int32 haveRead = 0;
763 try
764 {
765
766 do
767 {
768 sal_Int32 toReadThisRound = std::min( MAX_PUT_DATA_LENGTH, maxBytesLeft );
769
770 // Read some data from the input stream
771 haveRead = inputStream->readBytes( buf, toReadThisRound );
772 OSL_ENSURE( haveRead == buf.getLength(), "OPreparedStatement::putParamData: inconsistency!" );
773
774 if ( !haveRead )
775 // no more data in the stream - the given stream length was a maximum which could not be
776 // fulfilled by the stream
777 break;
778
779 // Put the data
780 OSL_ENSURE( m_aStatementHandle, "OPreparedStatement::putParamData: StatementHandle is null!" );
781 N3SQLPutData ( m_aStatementHandle, buf.getArray(), buf.getLength() );
782
783 // decrement the number of bytes still needed
784 maxBytesLeft -= haveRead;
785 }
786 while ( maxBytesLeft > 0 );
787 }
788 catch (const IOException& ex)
789 {
790
791 // If an I/O exception was generated, turn
792 // it into a SQLException
793
794 throw SQLException(ex.Message,*this,OUString(),0,Any());
795 }
796}
797
798// setStream
799// Sets an input stream as a parameter, using the given SQL type
801 sal_Int32 ParameterIndex,
803 SQLLEN length,
804 sal_Int32 _nType)
805{
806 ::osl::MutexGuard aGuard( m_aMutex );
807 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
808
809
811
812 checkParameterIndex(ParameterIndex);
813 // Get the buffer needed for the length
814
815 SQLLEN * const lenBuf = getLengthBuf(ParameterIndex);
816
817 // Allocate a new buffer for the parameter data. This buffer
818 // will be returned by SQLParamData (it is set to the parameter
819 // number, a sal_Int32)
820
821 sal_Int32* dataBuf = static_cast<sal_Int32*>( allocBindBuf(ParameterIndex, sizeof(ParameterIndex)) );
822 *dataBuf = ParameterIndex;
823
824 // Bind the parameter with SQL_LEN_DATA_AT_EXEC
825 *lenBuf = SQL_LEN_DATA_AT_EXEC (length);
826
827 SQLSMALLINT fCType, fSqlType;
828 OTools::getBindTypes(bUseWChar, m_pConnection->useOldDateFormat(), OTools::jdbcTypeToOdbc(_nType), fCType, fSqlType);
829
830
831 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
833 static_cast<SQLUSMALLINT>(ParameterIndex),
834 SQL_PARAM_INPUT,
835 fCType,
836 fSqlType,
837 length,
839 dataBuf,
840 sizeof(ParameterIndex),
841 lenBuf);
842
843 // Save the input stream
844 boundParams[ParameterIndex - 1].setInputStream (x, length);
845}
846
847
849{
850 numParams = 0;
851 boundParams.reset();
852}
853
854void OPreparedStatement::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue)
855{
856 try
857 {
858 switch(nHandle)
859 {
861 if(!isPrepared())
863 break;
865 if(!isPrepared())
867 break;
869 if(!isPrepared())
871 break;
873 if(!isPrepared())
875 break;
876 default:
878 }
879 }
880 catch(const SQLException&)
881 {
882 // throw Exception(e.Message,*this);
883 }
884}
885
887{
888 if(!isPrepared())
889 {
890 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
891 OString aSql(OUStringToOString(m_sSqlStatement,getOwnConnection()->getTextEncoding()));
892 SQLRETURN nReturn = N3SQLPrepare(m_aStatementHandle, reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(aSql.getStr())), aSql.getLength());
893 OTools::ThrowException(m_pConnection.get(),nReturn,m_aStatementHandle,SQL_HANDLE_STMT,*this);
894 m_bPrepared = true;
896 }
897}
898
899void OPreparedStatement::checkParameterIndex(sal_Int32 _parameterIndex)
900{
901 if( _parameterIndex > numParams ||
902 _parameterIndex < 1 ||
903 _parameterIndex > std::numeric_limits<SQLUSMALLINT>::max() )
904 {
906 const OUString sError( aResources.getResourceStringWithSubstitution(STR_WRONG_PARAM_INDEX,
907 "$pos$", OUString::number(_parameterIndex),
908 "$count$", OUString::number(numParams)
909 ));
910 SQLException aNext(sError,*this, OUString(),0,Any());
911
913 }
914}
915
917{
919 pReturn->setMetaData(getMetaData());
920 return pReturn;
921}
922
923
924/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
#define N3SQLNumParams(a, b)
Definition: OFunctions.hxx:257
#define N3SQLBindParameter(a, b, c, d, e, f, g, h, i, j)
Definition: OFunctions.hxx:218
#define N3SQLExecute(a)
Definition: OFunctions.hxx:237
#define N3SQLPutData(a, b, c)
Definition: OFunctions.hxx:268
#define N3SQLParamData(a, b)
Definition: OFunctions.hxx:262
#define N3SQLPrepare(a, b, c)
Definition: OFunctions.hxx:205
#define N3SQLFreeStmt(a, b)
Definition: OFunctions.hxx:493
IMPLEMENT_SERVICE_INFO(OPreparedStatement,"com.sun.star.sdbcx.OPreparedStatement","com.sun.star.sdbc.PreparedStatement")
OUString getString() const
Definition: FValue.cxx:933
void fill(sal_Int32 _nPos, sal_Int32 _nType, const css::uno::Reference< css::sdbc::XRow > &_xRow)
fetches a single value out of the row
Definition: FValue.cxx:2215
helper class for accessing resources shared by different libraries in the connectivity module
OUString getResourceString(TranslateId pResId) const
loads a string from the shared resource file
OUString getResourceStringWithSubstitution(TranslateId pResId, const char *_pAsciiPatternToReplace, const OUString &_rStringToSubstitute) const
loads a string from the shared resource file, and replaces a given ASCII pattern with a given string
void setParameter(sal_Int32 parameterIndex, sal_Int32 _nType, SQLULEN _nColumnSize, sal_Int32 _nScale, const void *_pData, SQLULEN _nDataLen, SQLLEN _nDataAllocLen)
virtual void SAL_CALL release() noexcept override
virtual void SAL_CALL setDate(sal_Int32 parameterIndex, const css::util::Date &x) override
virtual rtl::Reference< OResultSet > createResultSet() override
creates the driver specific resultset (factory)
void * allocBindBuf(sal_Int32 index, sal_Int32 bufLen)
void setParameterPre(sal_Int32 parameterIndex)
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType) override
virtual void SAL_CALL setTimestamp(sal_Int32 parameterIndex, const css::util::DateTime &x) override
virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL executeQuery() override
virtual void SAL_CALL setNull(sal_Int32 parameterIndex, sal_Int32 sqlType) override
virtual void SAL_CALL setObjectNull(sal_Int32 parameterIndex, sal_Int32 sqlType, const OUString &typeName) override
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override
virtual void SAL_CALL setByte(sal_Int32 parameterIndex, sal_Int8 x) override
virtual void SAL_CALL setTime(sal_Int32 parameterIndex, const css::util::Time &x) override
virtual void SAL_CALL setBlob(sal_Int32 parameterIndex, const css::uno::Reference< css::sdbc::XBlob > &x) override
virtual void SAL_CALL setRef(sal_Int32 parameterIndex, const css::uno::Reference< css::sdbc::XRef > &x) override
virtual void SAL_CALL setCharacterStream(sal_Int32 parameterIndex, const css::uno::Reference< css::io::XInputStream > &x, sal_Int32 length) override
virtual void SAL_CALL setBoolean(sal_Int32 parameterIndex, sal_Bool x) override
virtual void SAL_CALL setClob(sal_Int32 parameterIndex, const css::uno::Reference< css::sdbc::XClob > &x) override
virtual void SAL_CALL setDouble(sal_Int32 parameterIndex, double x) override
virtual void SAL_CALL setShort(sal_Int32 parameterIndex, sal_Int16 x) override
virtual void SAL_CALL addBatch() override
virtual void SAL_CALL setString(sal_Int32 parameterIndex, const OUString &x) override
virtual void SAL_CALL setBinaryStream(sal_Int32 parameterIndex, const css::uno::Reference< css::io::XInputStream > &x, sal_Int32 length) override
virtual void SAL_CALL setInt(sal_Int32 parameterIndex, sal_Int32 x) override
virtual css::uno::Sequence< sal_Int32 > SAL_CALL executeBatch() override
virtual sal_Int32 SAL_CALL executeUpdate() override
virtual void SAL_CALL clearBatch() override
virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const css::uno::Any &rValue) override
virtual void SAL_CALL setArray(sal_Int32 parameterIndex, const css::uno::Reference< css::sdbc::XArray > &x) override
virtual css::uno::Reference< css::sdbc::XConnection > SAL_CALL getConnection() override
css::uno::Reference< css::sdbc::XResultSetMetaData > m_xMetaData
void setScalarParameter(sal_Int32 parameterIndex, sal_Int32 _nType, SQLULEN _nColumnSize, const T i_Value)
std::unique_ptr< OBoundParam[]> boundParams
virtual css::uno::Reference< css::sdbc::XResultSetMetaData > SAL_CALL getMetaData() override
virtual sal_Bool SAL_CALL execute() override
virtual void SAL_CALL clearParameters() override
virtual void SAL_CALL setObjectWithInfo(sal_Int32 parameterIndex, const css::uno::Any &x, sal_Int32 targetSqlType, sal_Int32 scale) override
virtual void SAL_CALL setObject(sal_Int32 parameterIndex, const css::uno::Any &x) override
void setStream(sal_Int32 ParameterIndex, const css::uno::Reference< css::io::XInputStream > &x, SQLLEN length, sal_Int32 SQLtype)
virtual void SAL_CALL setBytes(sal_Int32 parameterIndex, const css::uno::Sequence< sal_Int8 > &x) override
virtual void SAL_CALL close() override
virtual void SAL_CALL setFloat(sal_Int32 parameterIndex, float x) override
virtual void SAL_CALL setLong(sal_Int32 parameterIndex, sal_Int64 x) override
void checkParameterIndex(sal_Int32 _parameterIndex)
virtual void SAL_CALL acquire() noexcept override
void setUsingBookmarks(bool _bUseBookmark)
Definition: OStatement.cxx:853
virtual void SAL_CALL acquire() noexcept override
void setResultSetType(sal_Int32 _par0)
Definition: OStatement.cxx:737
virtual sal_Int32 SAL_CALL getUpdateCount() override
Definition: OStatement.cxx:543
void setResultSetConcurrency(sal_Int32 _par0)
Definition: OStatement.cxx:725
virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const css::uno::Any &rValue) override
virtual void SAL_CALL close() override
Definition: OStatement.cxx:170
virtual void SAL_CALL clearWarnings() override
Definition: OStatement.cxx:622
void setFetchDirection(sal_Int32 _par0)
Definition: OStatement.cxx:801
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override
Definition: OStatement.cxx:126
virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getResultSet() override
Definition: OStatement.cxx:532
rtl::Reference< OConnection > m_pConnection
Definition: OStatement.hxx:71
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType) override
OConnection * getOwnConnection() const
Definition: OStatement.hxx:198
virtual void SAL_CALL release() noexcept override
static SQLSMALLINT jdbcTypeToOdbc(sal_Int32 jdbcType)
Definition: OTools.cxx:656
static DATE_STRUCT DateToOdbcDate(const css::util::Date &x)
Definition: OTools.hxx:143
static void ThrowException(const OConnection *_pConnection, SQLRETURN _rRetCode, SQLHANDLE _pContext, SQLSMALLINT _nHandleType, const css::uno::Reference< css::uno::XInterface > &_xInterface, bool _bNoFound=true)
Definition: OTools.cxx:302
static TIME_STRUCT TimeToOdbcTime(const css::util::Time &x)
Definition: OTools.hxx:151
static void getBindTypes(bool _bUseWChar, bool _bUseOldTimeDate, SQLSMALLINT _nOdbcType, SQLSMALLINT &fCType, SQLSMALLINT &fSqlType)
getBindTypes set the ODBC type for C
Definition: OTools.cxx:686
static TIMESTAMP_STRUCT DateTimeToTimestamp(const css::util::DateTime &x)
Definition: OTools.hxx:159
mutable::osl::Mutex m_aMutex
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() SAL_OVERRIDE
virtual css::uno::Any SAL_CALL queryInterface(css::uno::Type const &rType) SAL_OVERRIDE
float x
std::unique_ptr< sal_Int32[]> pData
bool getBOOL(const Any &_rAny)
sal_Int32 getINT32(const Any &_rAny)
OUString getString(const Any &_rAny)
Type
const sal_Int32 MAX_PUT_DATA_LENGTH
Definition: OTools.hxx:94
SQLRETURN(SQL_API * T3SQLBindParameter)(SQLHSTMT StatementHandle, SQLUSMALLINT ParameterNumber, SQLSMALLINT InputOutputType, SQLSMALLINT ValueType, SQLSMALLINT ParameterType, SQLULEN ColumnSize, SQLSMALLINT DecimalDigits, SQLPOINTER ParameterValuePtr, SQLLEN BufferLength, SQLLEN *StrLen_or_IndPtr)
Definition: OFunctions.hxx:207
void checkDisposed(bool _bThrow)
Definition: dbtools.cxx:1951
void throwInvalidIndexException(const css::uno::Reference< css::uno::XInterface > &Context, const css::uno::Any &Next)
throw an invalid index sqlexception
bool implSetObject(const Reference< XParameters > &_rxParameters, const sal_Int32 _nColumnIndex, const Any &_rValue)
Definition: dbtools.cxx:1516
void throwFunctionNotSupportedSQLException(const OUString &_rFunctionName, const css::uno::Reference< css::uno::XInterface > &_rxContext)
throws an exception with SQL state IM001, saying that a certain function is not supported
void setObjectWithInfo(const Reference< XParameters > &_xParams, sal_Int32 parameterIndex, const Any &x, sal_Int32 sqlType, sal_Int32 scale)
Definition: dbtools.cxx:1765
int i
index
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
Definition: pq_tools.cxx:100
#define SDB_ODBC_CHAR
Definition: odbc.hxx:68
sal_Int32 scale
Definition: pq_statics.cxx:62
sal_Int32 type
Definition: pq_statics.cxx:60
#define PROPERTY_ID_RESULTSETTYPE
Definition: propertyids.hxx:44
#define PROPERTY_ID_USEBOOKMARKS
Definition: propertyids.hxx:48
#define PROPERTY_ID_RESULTSETCONCURRENCY
Definition: propertyids.hxx:43
#define PROPERTY_ID_FETCHDIRECTION
Definition: propertyids.hxx:45
unsigned char sal_Bool
signed char sal_Int8