35#include <com/sun/star/sdbc/DataType.hpp>
56OPreparedStatement::OPreparedStatement(
Connection* _pConnection,
63 SAL_INFO(
"connectivity.firebird",
"OPreparedStatement(). "
79 m_pInSqlda =
static_cast<XSQLDA*
>(calloc(1, XSQLDA_LENGTH(10)));
93 SAL_WARN(
"connectivity.firebird",
"isc_dsql_describe_bind failed");
99 m_pInSqlda =
static_cast<XSQLDA*
>(calloc(1, XSQLDA_LENGTH(nItems)));
106 SAL_WARN_IF(aErr,
"connectivity.firebird",
"isc_dsql_describe_bind failed");
145 ::osl::MutexGuard aGuard(
m_aMutex );
146 checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
159 checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
182 const OUString& sInput)
185 "setString(" << nParameterIndex <<
" , " << sInput <<
")");
188 checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
196 XSQLVAR* pVar =
m_pInSqlda->sqlvar + (nParameterIndex - 1);
198 int dtype = (pVar->sqltype & ~1);
200 if (str.getLength() > pVar->sqllen)
201 str = str.copy(0, pVar->sqllen);
206 const sal_Int32 max_varchar_len = 0xFFFF;
208 if (str.getLength() > max_varchar_len)
210 str = str.copy(0, max_varchar_len);
212 const sal_uInt16
nLength = str.getLength();
213 static_assert(
sizeof(
nLength) == 2,
"must match dest memcpy len");
214 memcpy(pVar->sqldata, &
nLength, 2);
216 memcpy(pVar->sqldata + 2, str.getStr(), str.getLength());
220 memcpy(pVar->sqldata, str.getStr(), str.getLength());
222 memset(pVar->sqldata + str.getLength(),
' ', pVar->sqllen - str.getLength());
226 setClob(nParameterIndex, sInput );
230 sal_Int32 int32Value = sInput.toInt32();
231 if ( (int32Value < std::numeric_limits<sal_Int16>::min()) ||
232 (int32Value > std::numeric_limits<sal_Int16>::max()) )
235 "Value out of range for SQL_SHORT type",
236 ::dbtools::StandardSQLState::INVALID_SQL_DATA_TYPE,
239 setShort(nParameterIndex, int32Value);
244 sal_Int32 int32Value = sInput.toInt32();
245 setInt(nParameterIndex, int32Value);
250 sal_Int64 int64Value = sInput.toInt64();
251 setLong(nParameterIndex, int64Value);
256 float floatValue = sInput.toFloat();
257 setFloat(nParameterIndex, floatValue);
262 bool boolValue = sInput.toBoolean();
269 pVar->sqldata =
nullptr;
274 "Incorrect type for setString",
275 ::dbtools::StandardSQLState::INVALID_SQL_DATA_TYPE,
283 checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
290 SAL_INFO(
"connectivity.firebird",
"executeQuery(). "
294 checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
315 u"isc_dsql_free_statement: close cursor");
316 SAL_WARN(
"connectivity.firebird", sErrMsg);
327 SAL_WARN(
"connectivity.firebird",
"isc_dsql_execute failed" );
333 uno::Reference< XInterface >(*
this),
360sal_Int64 toNumericWithoutDecimalPlace(
const OUString& sSource)
362 OUString sNumber(sSource);
365 (void)sSource.startsWith(
"0", &sNumber);
367 sal_Int32 nDotIndex = sNumber.indexOf(
'.');
371 return sNumber.toInt64();
376 OUStringBuffer sBuffer(15);
379 sBuffer.append(sNumber.subView(0, nDotIndex));
381 sBuffer.append(sNumber.subView(nDotIndex + 1));
392 checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
401 setValue< sal_Bool >(
nIndex, bValue, SQL_BOOLEAN);
408 checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
416 if ((pVar->sqltype & ~1) !=
nType)
419 "Incorrect type for setValue",
420 ::dbtools::StandardSQLState::INVALID_SQL_DATA_TYPE,
457 checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
461 short dType = (pVar->sqltype & ~1);
462 short dSubType = pVar->sqlsubtype;
464 if(dSubType < 0 || dSubType > 2)
467 "Incorrect number sub type",
468 ::dbtools::StandardSQLState::INVALID_SQL_DATA_TYPE,
473 static_cast<short>(-pVar->sqlscale) };
477 switch(columnType.getSdbcType())
479 case DataType::SMALLINT:
480 setValue< sal_Int16 >(
nIndex,
481 static_cast<sal_Int16
>(
nValue),
484 case DataType::INTEGER:
485 setValue< sal_Int32 >(
nIndex,
486 static_cast<sal_Int32
>(
nValue),
489 case DataType::BIGINT:
490 setValue< sal_Int64 >(
nIndex,
491 static_cast<sal_Int64
>(
nValue),
494 case DataType::NUMERIC:
495 case DataType::DECIMAL:
507 aCTime.tm_mday = rDate.Day;
508 aCTime.tm_mon = rDate.Month -1;
509 aCTime.tm_year = rDate.Year -1900;
512 isc_encode_sql_date(&aCTime, &aISCDate);
514 setValue< ISC_DATE >(nIndex, aISCDate, SQL_TYPE_DATE);
520 aCTime.tm_sec = rTime.Seconds;
521 aCTime.tm_min = rTime.Minutes;
522 aCTime.tm_hour = rTime.Hours;
525 isc_encode_sql_time(&aCTime, &aISCTime);
529 aISCTime += rTime.NanoSeconds / (1000000000 / ISC_TIME_SECONDS_PRECISION);
531 setValue< ISC_TIME >(
nIndex, aISCTime, SQL_TYPE_TIME);
537 aCTime.tm_sec = rTimestamp.Seconds;
538 aCTime.tm_min = rTimestamp.Minutes;
539 aCTime.tm_hour = rTimestamp.Hours;
540 aCTime.tm_mday = rTimestamp.Day;
541 aCTime.tm_mon = rTimestamp.Month - 1;
542 aCTime.tm_year = rTimestamp.Year - 1900;
544 ISC_TIMESTAMP aISCTimestamp;
545 isc_encode_timestamp(&aCTime, &aISCTimestamp);
548 aISCTimestamp.timestamp_time += rTimestamp.NanoSeconds / (1000000000 / ISC_TIME_SECONDS_PRECISION);
550 setValue< ISC_TIMESTAMP >(nIndex, aISCTimestamp, SQL_TIMESTAMP);
585 u"isc_close_blob failed",
593 ::osl::MutexGuard aGuard(
m_aMutex );
594 checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
596#if SAL_TYPES_SIZEOFPOINTER == 8
597 isc_blob_handle aBlobHandle = 0;
599 isc_blob_handle aBlobHandle =
nullptr;
609 sal_Int64 nCharWritten = 1;
611 sal_Int64 nLen = xClob->length();
612 while ( nLen >= nCharWritten )
614 sal_Int64 nCharRemain = nLen - nCharWritten + 1;
616 sal_uInt16 nWriteSize = std::min<sal_Int64>(nCharRemain, MAX_SIZE);
618 xClob->getSubString(nCharWritten, nWriteSize),
619 RTL_TEXTENCODING_UTF8);
624 nCharWritten += nWriteSize;
637 u
"isc_put_segment failed",
642 setValue< ISC_QUAD >(nParameterIndex, aBlobId, SQL_BLOB);
647 ::osl::MutexGuard aGuard(
m_aMutex );
648 checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
651#if SAL_TYPES_SIZEOFPOINTER == 8
652 isc_blob_handle aBlobHandle = 0;
654 isc_blob_handle aBlobHandle =
nullptr;
662 RTL_TEXTENCODING_UTF8);
663 size_t nDataSize = sData.getLength();
677 for (
size_t i = 0;
i < nNbEntireChunks; ++
i)
682 strCurrentChunk.getLength(),
683 strCurrentChunk.getStr() );
688 if (nRemainingBytes && !aErr)
691 OString strCurrentChunk = sData.copy(nNbEntireChunks *
MAX_SIZE_SEGMENT, nRemainingBytes);
694 strCurrentChunk.getLength(),
695 strCurrentChunk.getStr() );
706 u"isc_put_segment failed",
711 setValue< ISC_QUAD >(nParameterIndex, aBlobId, SQL_BLOB);
718 checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
721#if SAL_TYPES_SIZEOFPOINTER == 8
722 isc_blob_handle aBlobHandle = 0;
724 isc_blob_handle aBlobHandle =
nullptr;
731 const sal_Int64 nBlobLen = xBlob->length();
735 sal_uInt64 nDataWritten = 0;
736 while (sal::static_int_cast<sal_uInt64>(nBlobLen) > nDataWritten)
738 sal_uInt64 nDataRemaining = nBlobLen - nDataWritten;
739 sal_uInt16 nWriteSize = std::min(nDataRemaining, sal_uInt64(SAL_MAX_UINT16));
743 reinterpret_cast<const char*
>(xBlob->getBytes(nDataWritten, nWriteSize).getConstArray()));
744 nDataWritten += nWriteSize;
758 u
"isc_put_segment failed",
763 setValue< ISC_QUAD >(nParameterIndex, aBlobId, SQL_BLOB);
769 ::osl::MutexGuard aGuard(
m_aMutex );
770 checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
777 ::osl::MutexGuard aGuard(
m_aMutex );
778 checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
785 checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
786 ::osl::MutexGuard aGuard(
m_aMutex );
792 XSQLVAR* pVar =
m_pInSqlda->sqlvar + (parameterIndex - 1);
793 int dType = (pVar->sqltype & ~1);
795 if(sqlType == DataType::DECIMAL || sqlType == DataType::NUMERIC)
812 OUStringBuffer sBuffer(15);
813 sBuffer.append(sValue);
814 if(sValue.indexOf(
'.') != -1)
816 for(sal_Int32 i=sValue.subView(sValue.indexOf(
'.')+1).size(); i<
scale;i++)
823 for (sal_Int32 i=0;
i<
scale;
i++)
829 sValue = sBuffer.makeStringAndClear();
833 setValue< sal_Int16 >(parameterIndex,
834 static_cast<sal_Int16
>( toNumericWithoutDecimalPlace(sValue) ),
839 setValue< sal_Int32 >(parameterIndex,
840 static_cast<sal_Int32
>( toNumericWithoutDecimalPlace(sValue) ),
844 setValue< sal_Int64 >(parameterIndex,
845 toNumericWithoutDecimalPlace(sValue),
850 "No Firebird sql type found for numeric or decimal types");
864 ::osl::MutexGuard aGuard(
m_aMutex );
865 checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
872 ::osl::MutexGuard aGuard(
m_aMutex );
873 checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
881 checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
884 XSQLVAR* pVar =
m_pInSqlda->sqlvar + (nParameterIndex - 1);
885 int dType = (pVar->sqltype & ~1);
887 if( dType == SQL_BLOB )
889#if SAL_TYPES_SIZEOFPOINTER == 8
890 isc_blob_handle aBlobHandle = 0;
892 isc_blob_handle aBlobHandle =
nullptr;
899 const sal_Int32 nBytesLen = xBytes.getLength();
903 sal_uInt32 nDataWritten = 0;
904 while (sal::static_int_cast<sal_uInt32>(nBytesLen) > nDataWritten)
906 sal_uInt32 nDataRemaining = nBytesLen - nDataWritten;
907 sal_uInt16 nWriteSize = std::min(nDataRemaining, sal_uInt32(SAL_MAX_UINT16));
911 reinterpret_cast<const char*
>(xBytes.getConstArray()) + nDataWritten);
912 nDataWritten += nWriteSize;
926 u
"isc_put_segment failed",
931 setValue< ISC_QUAD >(nParameterIndex, aBlobId, SQL_BLOB);
933 else if( dType == SQL_VARYING )
936 const sal_Int32 nMaxSize = 0xFFFF;
938 if (xBytesCopy.getLength() > nMaxSize)
940 xBytesCopy.realloc( nMaxSize );
942 const sal_uInt16 nSize = xBytesCopy.getLength();
948 pVar->sqldata =
static_cast<char *
>(malloc(
sizeof(
char) * nSize + 2));
950 static_assert(
sizeof(nSize) == 2,
"must match dest memcpy len");
952 memcpy(pVar->sqldata, &nSize, 2);
954 memcpy(pVar->sqldata + 2, xBytesCopy.getConstArray(), nSize);
956 else if( dType == SQL_TEXT )
958 if (pVar->sqllen < xBytes.getLength())
962 memcpy(pVar->sqldata, xBytes.getConstArray(), xBytes.getLength() );
964 memset(pVar->sqldata + xBytes.getLength(), 0, pVar->sqllen - xBytes.getLength());
969 "Incorrect type for setBytes",
970 ::dbtools::StandardSQLState::INVALID_SQL_DATA_TYPE,
978 ::osl::MutexGuard aGuard(
m_aMutex );
979 checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
986 ::osl::MutexGuard aGuard(
m_aMutex );
987 checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
1033 if ((nParameterIndex == 0) || (nParameterIndex >
m_pInSqlda->sqld))
1036 "No column " + OUString::number(nParameterIndex),
1037 ::dbtools::StandardSQLState::COLUMN_NOT_FOUND,
1045 XSQLVAR* pVar =
m_pInSqlda->sqlvar + (nParameterIndex - 1);
virtual void SAL_CALL setDate(sal_Int32 parameterIndex, const css::util::Date &x) override
virtual void SAL_CALL setLong(sal_Int32 nIndex, sal_Int64 nValue) override
virtual void SAL_CALL release() noexcept override
virtual ~OPreparedStatement() override
virtual void SAL_CALL setCharacterStream(sal_Int32 parameterIndex, const css::uno::Reference< css::io::XInputStream > &x, sal_Int32 length) override
void setParameterNull(sal_Int32 nParameterIndex, bool bSetNull=true)
virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL executeQuery() override
css::uno::Reference< css::sdbc::XResultSetMetaData > m_xMetaData
virtual void SAL_CALL setObjectNull(sal_Int32 parameterIndex, sal_Int32 sqlType, const OUString &typeName) override
virtual void SAL_CALL setTime(sal_Int32 parameterIndex, const css::util::Time &x) override
virtual void SAL_CALL setBoolean(sal_Int32 nIndex, sal_Bool nValue) override
void openBlobForWriting(isc_blob_handle &rBlobHandle, ISC_QUAD &rBlobId)
Assumes that all necessary mutexes have been taken.
void setValue(sal_Int32 nIndex, const T &nValue, ISC_SHORT nType)
Set a numeric value in the input SQLDA.
virtual void SAL_CALL setObject(sal_Int32 parameterIndex, const css::uno::Any &x) override
virtual void SAL_CALL setBytes(sal_Int32 parameterIndex, const css::uno::Sequence< sal_Int8 > &x) override
virtual void SAL_CALL setDouble(sal_Int32 parameterIndex, double x) override
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType) override
virtual void SAL_CALL addBatch() override
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override
virtual void SAL_CALL setByte(sal_Int32 nIndex, sal_Int8 nValue) override
virtual void SAL_CALL setString(sal_Int32 parameterIndex, const OUString &x) override
virtual void SAL_CALL disposing() override
virtual void SAL_CALL setArray(sal_Int32 parameterIndex, const css::uno::Reference< css::sdbc::XArray > &x) override
virtual void SAL_CALL setObjectWithInfo(sal_Int32 parameterIndex, const css::uno::Any &x, sal_Int32 targetSqlType, sal_Int32 scale) 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 css::uno::Reference< css::sdbc::XConnection > SAL_CALL getConnection() 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 setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const css::uno::Any &rValue) override
void setClob(sal_Int32 nParamIndex, const OUString &rStr)
virtual void SAL_CALL setTimestamp(sal_Int32 parameterIndex, const css::util::DateTime &x) override
virtual void SAL_CALL setInt(sal_Int32 nIndex, sal_Int32 nValue) override
virtual css::uno::Reference< css::sdbc::XResultSetMetaData > SAL_CALL getMetaData() override
virtual void SAL_CALL setNull(sal_Int32 nIndex, sal_Int32 nValue) override
virtual sal_Bool SAL_CALL execute() override
virtual void SAL_CALL setRef(sal_Int32 parameterIndex, const css::uno::Reference< css::sdbc::XRef > &x) override
virtual void SAL_CALL clearParameters() override
virtual void SAL_CALL setBlob(sal_Int32 parameterIndex, const css::uno::Reference< css::sdbc::XBlob > &x) override
virtual void SAL_CALL setShort(sal_Int32 nIndex, sal_Int16 nValue) override
void closeBlobAfterWriting(isc_blob_handle &rBlobHandle)
Assumes that all necessary mutexes have been taken.
void checkParameterIndex(sal_Int32 nParameterIndex)
virtual void SAL_CALL close() override
virtual void SAL_CALL setFloat(sal_Int32 parameterIndex, float x) override
virtual void SAL_CALL acquire() noexcept override
This ResultSet does not deal with the management of the SQLDA it is supplied with.
virtual void SAL_CALL release() noexcept override
::rtl::Reference< Connection > m_pConnection
isc_stmt_handle m_aStatementHandle
css::uno::Reference< css::sdbc::XResultSet > m_xResultSet
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType) override
sal_Int32 getStatementChangeCount()
ISC_STATUS_ARRAY m_statusVector
void prepareAndDescribeStatement(std::u16string_view sqlIn, XSQLDA *&pOutSqlda)
virtual void SAL_CALL acquire() noexcept override
virtual void disposeResultSet()
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override
virtual void SAL_CALL close() override
virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const css::uno::Any &rValue) override
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
IMPLEMENT_SERVICE_INFO(OPreparedStatement,"com.sun.star.sdbcx.firebird.PreparedStatement","com.sun.star.sdbc.PreparedStatement")
constexpr size_t MAX_SIZE_SEGMENT
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
css::uno::Sequence< T > concatSequences(const css::uno::Sequence< T > &rS1, const Ss &... rSn)
void freeSQLVAR(XSQLDA *pSqlda)
void checkDisposed(bool _bThrow)
OUString StatusVectorToString(const ISC_STATUS_ARRAY &rStatusVector, std::u16string_view rCause)
sal_Int64 pow10Integer(int nDecimalCount)
void evaluateStatusVector(const ISC_STATUS_ARRAY &rStatusVector, std::u16string_view aCause, const css::uno::Reference< css::uno::XInterface > &_rxContext)
Evaluate a firebird status vector and throw exceptions as necessary.
void mallocSQLVAR(XSQLDA *pSqlda)
sal_Int64 toInt64(std::u16string_view str, sal_Int16 radix=10)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
#define PROPERTY_ID_RESULTSETTYPE
#define PROPERTY_ID_USEBOOKMARKS
#define PROPERTY_ID_RESULTSETCONCURRENCY
#define PROPERTY_ID_FETCHDIRECTION
TransliterationModules tm