tdf#68676, tdf#131238: implement and use Unicode ODBC functions on Windows

It also prepares for using it on other platforms as well; the code is
generic, and should work with 32-bit SQLWCHAR, too. But I can't test
it, so it is not enabled on other platforms for now (see bUseWChar,
which was moved to connectivity/source/inc/odbc/OTools.hxx).

Change-Id: I29fe117910bbab62aba37e85dd27d65a742d28c7
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171081
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
This commit is contained in:
Mike Kaganski 2024-07-23 16:40:19 +05:00
parent abb0ec365b
commit 5ed1415d1c
13 changed files with 1450 additions and 792 deletions

View file

@ -90,11 +90,6 @@ SQLRETURN OConnection::OpenConnection(const OUString& aConnectStr, sal_Int32 nTi
return -1;
SQLRETURN nSQLRETURN = 0;
SDB_ODBC_CHAR szConnStrOut[4096] = {};
SDB_ODBC_CHAR szConnStrIn[2048] = {};
SQLSMALLINT cbConnStrOut;
OString aConStr(OUStringToOString(aConnectStr,getTextEncoding()));
memcpy(szConnStrIn, aConStr.getStr(), std::min<sal_Int32>(sal_Int32(2048),aConStr.getLength()));
#ifndef MACOSX
functions().SetConnectAttr(m_aConnectionHandle,SQL_ATTR_LOGIN_TIMEOUT,reinterpret_cast<SQLPOINTER>(static_cast<sal_IntPtr>(nTimeOut)),SQL_IS_UINTEGER);
@ -103,35 +98,47 @@ SQLRETURN OConnection::OpenConnection(const OUString& aConnectStr, sal_Int32 nTi
#endif
#ifdef LINUX
(void) bSilent;
nSQLRETURN = functions().DriverConnect(m_aConnectionHandle,
nullptr,
szConnStrIn,
static_cast<SQLSMALLINT>(std::min(sal_Int32(2048),aConStr.getLength())),
szConnStrOut,
SQLSMALLINT(sizeof(szConnStrOut)/sizeof(SDB_ODBC_CHAR)) -1,
&cbConnStrOut,
SQL_DRIVER_NOPROMPT);
if (nSQLRETURN == SQL_ERROR || nSQLRETURN == SQL_NO_DATA || SQL_SUCCESS_WITH_INFO == nSQLRETURN)
return nSQLRETURN;
#else
bSilent = true;
#endif //LINUX
SQLUSMALLINT nSilent = bSilent ? SQL_DRIVER_NOPROMPT : SQL_DRIVER_COMPLETE;
nSQLRETURN = functions().DriverConnect(m_aConnectionHandle,
nullptr,
szConnStrIn,
static_cast<SQLSMALLINT>(std::min<sal_Int32>(sal_Int32(2048),aConStr.getLength())),
szConnStrOut,
SQLSMALLINT(sizeof szConnStrOut),
&cbConnStrOut,
nSilent);
if (bUseWChar && functions().has(ODBC3SQLFunctionId::DriverConnectW))
{
SQLWChars sqlConnectStr(aConnectStr);
SQLWCHAR szConnStrOut[4096] = {};
SQLSMALLINT cchConnStrOut;
nSQLRETURN = functions().DriverConnectW(m_aConnectionHandle,
nullptr,
sqlConnectStr.get(),
sqlConnectStr.cch(),
szConnStrOut,
std::size(szConnStrOut) - 1,
&cchConnStrOut,
nSilent);
}
else
{
SQLChars sqlConnectStr(aConnectStr, getTextEncoding());
SQLCHAR szConnStrOut[4096] = {};
SQLSMALLINT cbConnStrOut;
nSQLRETURN = functions().DriverConnect(m_aConnectionHandle,
nullptr,
sqlConnectStr.get(),
sqlConnectStr.cch(),
szConnStrOut,
std::size(szConnStrOut) - 1,
&cbConnStrOut,
nSilent);
}
#ifdef LINUX
if (nSQLRETURN == SQL_ERROR || nSQLRETURN == SQL_NO_DATA || SQL_SUCCESS_WITH_INFO == nSQLRETURN)
#else
if (nSQLRETURN == SQL_ERROR || nSQLRETURN == SQL_NO_DATA)
#endif
return nSQLRETURN;
m_bClosed = false;
#endif //LINUX
try
{
OUString aVal;
@ -298,11 +305,27 @@ OUString SAL_CALL OConnection::nativeSQL( const OUString& sql )
{
::osl::MutexGuard aGuard( m_aMutex );
OString aSql(OUStringToOString(sql,getTextEncoding()));
char pOut[2048];
SQLINTEGER nOutLen;
OTools::ThrowException(this,functions().NativeSql(m_aConnectionHandle,reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(aSql.getStr())),aSql.getLength(),reinterpret_cast<SDB_ODBC_CHAR*>(pOut),sizeof pOut - 1,&nOutLen),m_aConnectionHandle,SQL_HANDLE_DBC,*this);
return OUString(pOut,nOutLen,getTextEncoding());
if (bUseWChar && functions().has(ODBC3SQLFunctionId::NativeSqlW))
{
SQLWChars nativeSQL(sql);
SQLWCHAR pOut[2048];
SQLRETURN ret = functions().NativeSqlW(m_aConnectionHandle,
nativeSQL.get(), nativeSQL.cch(),
pOut, std::size(pOut) - 1, &nOutLen);
OTools::ThrowException(this, ret, m_aConnectionHandle, SQL_HANDLE_DBC, *this);
return toUString(pOut, nOutLen);
}
else
{
SQLChars nativeSQL(sql, getTextEncoding());
SQLCHAR pOut[2048];
SQLRETURN ret = functions().NativeSql(m_aConnectionHandle,
nativeSQL.get(), nativeSQL.cch(),
pOut, std::size(pOut) - 1, &nOutLen);
OTools::ThrowException(this, ret, m_aConnectionHandle, SQL_HANDLE_DBC, *this);
return toUString(pOut, nOutLen, getTextEncoding());
}
}
void SAL_CALL OConnection::setAutoCommit( sal_Bool autoCommit )
@ -391,11 +414,20 @@ void SAL_CALL OConnection::setCatalog( const OUString& catalog )
::osl::MutexGuard aGuard( m_aMutex );
checkDisposed(OConnection_BASE::rBHelper.bDisposed);
OString aCat(OUStringToOString(catalog,getTextEncoding()));
OTools::ThrowException(this,
functions().SetConnectAttr(m_aConnectionHandle,SQL_ATTR_CURRENT_CATALOG,const_cast<char *>(aCat.getStr()),SQL_NTS),
m_aConnectionHandle,SQL_HANDLE_DBC,*this);
if (bUseWChar && functions().has(ODBC3SQLFunctionId::SetConnectAttrW))
{
SQLWChars sqlCatalog(catalog);
OTools::ThrowException(this,
functions().SetConnectAttrW(m_aConnectionHandle, SQL_ATTR_CURRENT_CATALOG, sqlCatalog.get(), SQL_NTSL),
m_aConnectionHandle,SQL_HANDLE_DBC,*this);
}
else
{
SQLChars sqlCatalog(catalog, getTextEncoding());
OTools::ThrowException(this,
functions().SetConnectAttr(m_aConnectionHandle,SQL_ATTR_CURRENT_CATALOG,sqlCatalog.get(),SQL_NTS),
m_aConnectionHandle,SQL_HANDLE_DBC,*this);
}
}
OUString SAL_CALL OConnection::getCatalog( )
@ -403,14 +435,25 @@ OUString SAL_CALL OConnection::getCatalog( )
::osl::MutexGuard aGuard( m_aMutex );
checkDisposed(OConnection_BASE::rBHelper.bDisposed);
SQLINTEGER nValueLen;
char pCat[1024];
OTools::ThrowException(this,
functions().GetConnectAttr(m_aConnectionHandle,SQL_ATTR_CURRENT_CATALOG,pCat,(sizeof pCat)-1,&nValueLen),
m_aConnectionHandle,SQL_HANDLE_DBC,*this);
if (bUseWChar && functions().has(ODBC3SQLFunctionId::GetConnectAttrW))
{
SQLWCHAR pCat[1024];
// SQLGetConnectAttrW gets/returns count of bytes, not characters
OTools::ThrowException(this,
functions().GetConnectAttrW(m_aConnectionHandle,SQL_ATTR_CURRENT_CATALOG,pCat,sizeof(pCat)-sizeof(SQLWCHAR),&nValueLen),
m_aConnectionHandle,SQL_HANDLE_DBC,*this);
return toUString(pCat, nValueLen / sizeof(SQLWCHAR));
}
else
{
SQLCHAR pCat[1024];
OTools::ThrowException(this,
functions().GetConnectAttr(m_aConnectionHandle,SQL_ATTR_CURRENT_CATALOG,pCat,sizeof(pCat)-1,&nValueLen),
m_aConnectionHandle,SQL_HANDLE_DBC,*this);
return OUString(pCat,nValueLen,getTextEncoding());
return toUString(pCat, nValueLen, getTextEncoding());
}
}
void SAL_CALL OConnection::setTransactionIsolation( sal_Int32 level )

View file

@ -24,6 +24,7 @@
#include <comphelper/property.hxx>
#include <cppuhelper/typeprovider.hxx>
#include <comphelper/sequence.hxx>
#include <comphelper/stl_types.hxx>
#include <odbc/OResultSetMetaData.hxx>
#include <odbc/OTools.hxx>
#include <comphelper/types.hxx>
@ -831,48 +832,52 @@ void ODatabaseMetaDataResultSet::openTypeInfo()
}
void ODatabaseMetaDataResultSet::openTables(const Any& catalog, const OUString& schemaPattern,
std::u16string_view tableNamePattern,
const OUString& tableNamePattern,
const Sequence< OUString >& types )
{
OString aPKQ,aPKO,aPKN,aCOL;
const OUString *pSchemaPat = nullptr;
if(schemaPattern != "%")
pSchemaPat = &schemaPattern;
else
pSchemaPat = nullptr;
if ( catalog.hasValue() )
aPKQ = OUStringToOString(comphelper::getString(catalog),m_nTextEncoding);
aPKO = OUStringToOString(schemaPattern,m_nTextEncoding);
aPKN = OUStringToOString(tableNamePattern,m_nTextEncoding);
const char *pPKQ = catalog.hasValue() && !aPKQ.isEmpty() ? aPKQ.getStr() : nullptr,
*pPKO = pSchemaPat && !pSchemaPat->isEmpty() && !aPKO.isEmpty() ? aPKO.getStr() : nullptr,
*pPKN = aPKN.getStr();
const char *pCOL = nullptr;
const char* const pComma = ",";
const OUString* pBegin = types.getConstArray();
const OUString* pEnd = pBegin + types.getLength();
for(;pBegin != pEnd;++pBegin)
OUString uPKQ;
catalog >>= uPKQ;
OUStringBuffer uCOL;
comphelper::intersperse(types.begin(), types.end(), comphelper::OUStringBufferAppender(uCOL), u",");
SQLRETURN nRetcode;
if (bUseWChar && functions().has(ODBC3SQLFunctionId::TablesW))
{
aCOL += OUStringToOString(*pBegin,m_nTextEncoding) + pComma;
}
if ( !aCOL.isEmpty() )
{
aCOL = aCOL.replaceAt(aCOL.getLength()-1,1,pComma);
pCOL = aCOL.getStr();
SQLWChars aPKQ, aPKO;
if (!uPKQ.isEmpty())
aPKQ = SQLWChars(uPKQ);
if (!schemaPattern.isEmpty() && schemaPattern != "%")
aPKO = SQLWChars(schemaPattern);
SQLWChars aPKN(tableNamePattern);
SQLWChars aCOL = !uCOL.isEmpty() ? SQLWChars(uCOL.makeStringAndClear()) : SQLWChars(u"" SQL_ALL_TABLE_TYPES ""_ustr);
auto pPKQ = !aPKQ.empty() ? aPKQ.get() : nullptr,
pPKO = !aPKO.empty() ? aPKO.get() : nullptr;
nRetcode = functions().TablesW(m_aStatementHandle,
pPKQ, pPKQ ? SQL_NTSL : 0,
pPKO, pPKO ? SQL_NTSL : 0,
aPKN.get(), SQL_NTSL,
aCOL.get(), SQL_NTSL);
}
else
pCOL = SQL_ALL_TABLE_TYPES;
{
SQLChars aPKQ, aPKO;
if (!uPKQ.isEmpty())
aPKQ = SQLChars(uPKQ, m_nTextEncoding);
if (!schemaPattern.isEmpty() && schemaPattern != "%")
aPKO = SQLChars(schemaPattern, m_nTextEncoding);
SQLChars aPKN(tableNamePattern, m_nTextEncoding);
SQLChars aCOL = !uCOL.isEmpty() ? SQLChars(uCOL, m_nTextEncoding) : SQLChars(SQL_ALL_TABLE_TYPES ""_ostr);
SQLRETURN nRetcode = functions().Tables(m_aStatementHandle,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pPKQ)), (catalog.hasValue() && !aPKQ.isEmpty()) ? SQL_NTS : 0,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pPKO)), pPKO ? SQL_NTS : 0,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pPKN)), SQL_NTS,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pCOL)), pCOL ? SQL_NTS : 0);
auto pPKQ = !aPKQ.empty() ? aPKQ.get() : nullptr,
pPKO = !aPKO.empty() ? aPKO.get() : nullptr;
nRetcode = functions().Tables(m_aStatementHandle,
pPKQ, pPKQ ? SQL_NTS : 0,
pPKO, pPKO ? SQL_NTS : 0,
aPKN.get(), SQL_NTS,
aCOL.get(), SQL_NTS);
}
OTools::ThrowException(m_pConnection.get(),nRetcode,m_aStatementHandle,SQL_HANDLE_STMT,*this);
checkColumnCount();
@ -880,11 +885,23 @@ void ODatabaseMetaDataResultSet::openTables(const Any& catalog, const OUString&
void ODatabaseMetaDataResultSet::openTablesTypes( )
{
SQLRETURN nRetcode = functions().Tables(m_aStatementHandle,
nullptr,0,
nullptr,0,
nullptr,0,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(SQL_ALL_TABLE_TYPES)),SQL_NTS);
SQLRETURN nRetcode;
if (bUseWChar && functions().has(ODBC3SQLFunctionId::TablesW))
{
nRetcode = functions().TablesW(m_aStatementHandle,
nullptr, 0,
nullptr, 0,
nullptr, 0,
SQLWChars(u"" SQL_ALL_TABLE_TYPES ""_ustr).get(), SQL_NTSL);
}
else
{
nRetcode = functions().Tables(m_aStatementHandle,
nullptr,0,
nullptr,0,
nullptr,0,
SQLChars(SQL_ALL_TABLE_TYPES ""_ostr).get(), SQL_NTS);
}
OTools::ThrowException(m_pConnection.get(),nRetcode,m_aStatementHandle,SQL_HANDLE_STMT,*this);
m_aColMapping.clear();
@ -896,12 +913,23 @@ void ODatabaseMetaDataResultSet::openTablesTypes( )
void ODatabaseMetaDataResultSet::openCatalogs()
{
SQLRETURN nRetcode = functions().Tables(m_aStatementHandle,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(SQL_ALL_CATALOGS)),SQL_NTS,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>("")),SQL_NTS,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>("")),SQL_NTS,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>("")),SQL_NTS);
SQLRETURN nRetcode;
if (bUseWChar && functions().has(ODBC3SQLFunctionId::TablesW))
{
nRetcode = functions().TablesW(m_aStatementHandle,
SQLWChars(u"" SQL_ALL_CATALOGS ""_ustr).get(), SQL_NTSL,
SQLWChars(u""_ustr).get(), SQL_NTSL,
SQLWChars(u""_ustr).get(), SQL_NTSL,
SQLWChars(u""_ustr).get(), SQL_NTSL);
}
else
{
nRetcode = functions().Tables(m_aStatementHandle,
SQLChars(SQL_ALL_CATALOGS ""_ostr).get(), SQL_NTS,
SQLChars(""_ostr).get(), SQL_NTS,
SQLChars(""_ostr).get(), SQL_NTS,
SQLChars(""_ostr).get(), SQL_NTS);
}
OTools::ThrowException(m_pConnection.get(),nRetcode,m_aStatementHandle,SQL_HANDLE_STMT,*this);
m_aColMapping.clear();
@ -913,11 +941,23 @@ void ODatabaseMetaDataResultSet::openCatalogs()
void ODatabaseMetaDataResultSet::openSchemas()
{
SQLRETURN nRetcode = functions().Tables(m_aStatementHandle,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>("")),SQL_NTS,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(SQL_ALL_SCHEMAS)),SQL_NTS,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>("")),SQL_NTS,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>("")),SQL_NTS);
SQLRETURN nRetcode;
if (bUseWChar && functions().has(ODBC3SQLFunctionId::TablesW))
{
nRetcode = functions().TablesW(m_aStatementHandle,
SQLWChars(u""_ustr).get(), SQL_NTSL,
SQLWChars(u"" SQL_ALL_SCHEMAS ""_ustr).get(), SQL_NTSL,
SQLWChars(u""_ustr).get(),SQL_NTSL,
SQLWChars(u""_ustr).get(),SQL_NTSL);
}
else
{
nRetcode = functions().Tables(m_aStatementHandle,
SQLChars(""_ostr).get(), SQL_NTS,
SQLChars(SQL_ALL_SCHEMAS ""_ostr).get(), SQL_NTS,
SQLChars(""_ostr).get(), SQL_NTS,
SQLChars(""_ostr).get(), SQL_NTS);
}
OTools::ThrowException(m_pConnection.get(),nRetcode,m_aStatementHandle,SQL_HANDLE_STMT,*this);
m_aColMapping.clear();
@ -928,69 +968,99 @@ void ODatabaseMetaDataResultSet::openSchemas()
}
void ODatabaseMetaDataResultSet::openColumnPrivileges( const Any& catalog, const OUString& schema,
std::u16string_view table,
std::u16string_view columnNamePattern )
const OUString& table,
const OUString& columnNamePattern )
{
const OUString *pSchemaPat = nullptr;
OUString uPKQ;
catalog >>= uPKQ;
SQLRETURN nRetcode;
if (bUseWChar && functions().has(ODBC3SQLFunctionId::ColumnPrivilegesW))
{
SQLWChars aPKQ, aPKO;
if (!uPKQ.isEmpty())
aPKQ = SQLWChars(uPKQ);
if (!schema.isEmpty() && schema != "%")
aPKO = SQLWChars(schema);
SQLWChars aPKN(table);
SQLWChars aCOL(columnNamePattern);
if(schema != "%")
pSchemaPat = &schema;
auto pPKQ = !aPKQ.empty() ? aPKQ.get() : nullptr,
pPKO = !aPKO.empty() ? aPKO.get() : nullptr;
nRetcode = functions().ColumnPrivilegesW(m_aStatementHandle,
pPKQ, pPKQ ? SQL_NTSL : 0,
pPKO, pPKO ? SQL_NTSL : 0,
aPKN.get(), SQL_NTSL,
aCOL.get(), SQL_NTSL);
}
else
pSchemaPat = nullptr;
{
SQLChars aPKQ, aPKO;
if (!uPKQ.isEmpty())
aPKQ = SQLChars(uPKQ, m_nTextEncoding);
if (!schema.isEmpty() && schema != "%")
aPKO = SQLChars(schema, m_nTextEncoding);
SQLChars aPKN(table, m_nTextEncoding);
SQLChars aCOL(columnNamePattern, m_nTextEncoding);
OString aPKQ,aPKO,aPKN,aCOL;
auto pPKQ = !aPKQ.empty() ? aPKQ.get() : nullptr,
pPKO = !aPKO.empty() ? aPKO.get() : nullptr;
if ( catalog.hasValue() )
aPKQ = OUStringToOString(comphelper::getString(catalog),m_nTextEncoding);
aPKO = OUStringToOString(schema,m_nTextEncoding);
aPKN = OUStringToOString(table,m_nTextEncoding);
aCOL = OUStringToOString(columnNamePattern,m_nTextEncoding);
const char *pPKQ = catalog.hasValue() && !aPKQ.isEmpty() ? aPKQ.getStr() : nullptr,
*pPKO = pSchemaPat && !pSchemaPat->isEmpty() && !aPKO.isEmpty() ? aPKO.getStr() : nullptr,
*pPKN = aPKN.getStr(),
*pCOL = aCOL.getStr();
SQLRETURN nRetcode = functions().ColumnPrivileges(m_aStatementHandle,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pPKQ)), (catalog.hasValue() && !aPKQ.isEmpty()) ? SQL_NTS : 0,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pPKO)), pPKO ? SQL_NTS : 0 ,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pPKN)), SQL_NTS,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pCOL)), SQL_NTS);
nRetcode = functions().ColumnPrivileges(m_aStatementHandle,
pPKQ, pPKQ ? SQL_NTS : 0,
pPKO, pPKO ? SQL_NTS : 0,
aPKN.get(), SQL_NTS,
aCOL.get(), SQL_NTS);
}
OTools::ThrowException(m_pConnection.get(),nRetcode,m_aStatementHandle,SQL_HANDLE_STMT,*this);
checkColumnCount();
}
void ODatabaseMetaDataResultSet::openColumns( const Any& catalog, const OUString& schemaPattern,
std::u16string_view tableNamePattern, std::u16string_view columnNamePattern )
const OUString& tableNamePattern, const OUString& columnNamePattern )
{
const OUString *pSchemaPat = nullptr;
OUString uPKQ;
catalog >>= uPKQ;
SQLRETURN nRetcode;
if (bUseWChar && functions().has(ODBC3SQLFunctionId::ColumnsW))
{
SQLWChars aPKQ, aPKO;
if (!uPKQ.isEmpty())
aPKQ = SQLWChars(uPKQ);
if (!schemaPattern.isEmpty() && schemaPattern != "%")
aPKO = SQLWChars(schemaPattern);
SQLWChars aPKN(tableNamePattern);
SQLWChars aCOL(columnNamePattern);
if(schemaPattern != "%")
pSchemaPat = &schemaPattern;
auto pPKQ = !aPKQ.empty() ? aPKQ.get() : nullptr,
pPKO = !aPKO.empty() ? aPKO.get() : nullptr;
nRetcode = functions().ColumnsW(m_aStatementHandle,
pPKQ, pPKQ ? SQL_NTSL : 0,
pPKO, pPKO ? SQL_NTSL : 0,
aPKN.get(), SQL_NTSL,
aCOL.get(), SQL_NTSL);
}
else
pSchemaPat = nullptr;
{
SQLChars aPKQ, aPKO;
if (!uPKQ.isEmpty())
aPKQ = SQLChars(uPKQ, m_nTextEncoding);
if (!schemaPattern.isEmpty() && schemaPattern != "%")
aPKO = SQLChars(schemaPattern, m_nTextEncoding);
SQLChars aPKN(tableNamePattern, m_nTextEncoding);
SQLChars aCOL(columnNamePattern, m_nTextEncoding);
OString aPKQ,aPKO,aPKN,aCOL;
if ( catalog.hasValue() )
aPKQ = OUStringToOString(comphelper::getString(catalog),m_nTextEncoding);
aPKO = OUStringToOString(schemaPattern,m_nTextEncoding);
aPKN = OUStringToOString(tableNamePattern,m_nTextEncoding);
aCOL = OUStringToOString(columnNamePattern,m_nTextEncoding);
const char *pPKQ = catalog.hasValue() && !aPKQ.isEmpty() ? aPKQ.getStr() : nullptr,
*pPKO = pSchemaPat && !pSchemaPat->isEmpty() && !aPKO.isEmpty() ? aPKO.getStr() : nullptr,
*pPKN = aPKN.getStr(),
*pCOL = aCOL.getStr();
SQLRETURN nRetcode = functions().Columns(m_aStatementHandle,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pPKQ)), (catalog.hasValue() && !aPKQ.isEmpty()) ? SQL_NTS : 0,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pPKO)), pPKO ? SQL_NTS : 0,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pPKN)), SQL_NTS,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pCOL)), SQL_NTS);
auto pPKQ = !aPKQ.empty() ? aPKQ.get() : nullptr,
pPKO = !aPKO.empty() ? aPKO.get() : nullptr;
nRetcode = functions().Columns(m_aStatementHandle,
pPKQ, pPKQ ? SQL_NTS : 0,
pPKO, pPKO ? SQL_NTS : 0,
aPKN.get(), SQL_NTS,
aCOL.get(), SQL_NTS);
}
OTools::ThrowException(m_pConnection.get(),nRetcode,m_aStatementHandle,SQL_HANDLE_STMT,*this);
::std::map<sal_Int32,sal_Int32> aMap;
aMap[SQL_BIT] = DataType::BIT;
@ -1030,74 +1100,103 @@ void ODatabaseMetaDataResultSet::openColumns( const Any& catalog,
}
void ODatabaseMetaDataResultSet::openProcedureColumns( const Any& catalog, const OUString& schemaPattern,
std::u16string_view procedureNamePattern,std::u16string_view columnNamePattern )
const OUString& procedureNamePattern,const OUString& columnNamePattern )
{
const OUString *pSchemaPat = nullptr;
OUString uPKQ;
catalog >>= uPKQ;
SQLRETURN nRetcode;
if (bUseWChar && functions().has(ODBC3SQLFunctionId::ProcedureColumnsW))
{
SQLWChars aPKQ, aPKO;
if (!uPKQ.isEmpty())
aPKQ = SQLWChars(uPKQ);
if (!schemaPattern.isEmpty() && schemaPattern != "%")
aPKO = SQLWChars(schemaPattern);
SQLWChars aPKN(procedureNamePattern);
SQLWChars aCOL(columnNamePattern);
if(schemaPattern != "%")
pSchemaPat = &schemaPattern;
auto pPKQ = !aPKQ.empty() ? aPKQ.get() : nullptr,
pPKO = !aPKO.empty() ? aPKO.get() : nullptr;
nRetcode = functions().ProcedureColumnsW(m_aStatementHandle,
pPKQ, pPKQ ? SQL_NTSL : 0,
pPKO, pPKO ? SQL_NTSL : 0,
aPKN.get(), SQL_NTSL,
aCOL.get(), SQL_NTSL);
}
else
pSchemaPat = nullptr;
{
SQLChars aPKQ, aPKO;
if (!uPKQ.isEmpty())
aPKQ = SQLChars(uPKQ, m_nTextEncoding);
if (!schemaPattern.isEmpty() && schemaPattern != "%")
aPKO = SQLChars(schemaPattern, m_nTextEncoding);
SQLChars aPKN(procedureNamePattern, m_nTextEncoding);
SQLChars aCOL(columnNamePattern, m_nTextEncoding);
OString aPKQ,aPKO,aPKN,aCOL;
if ( catalog.hasValue() )
aPKQ = OUStringToOString(comphelper::getString(catalog),m_nTextEncoding);
aPKO = OUStringToOString(schemaPattern,m_nTextEncoding);
aPKN = OUStringToOString(procedureNamePattern,m_nTextEncoding);
aCOL = OUStringToOString(columnNamePattern,m_nTextEncoding);
const char *pPKQ = catalog.hasValue() && !aPKQ.isEmpty() ? aPKQ.getStr() : nullptr,
*pPKO = pSchemaPat && !pSchemaPat->isEmpty() && !aPKO.isEmpty() ? aPKO.getStr() : nullptr,
*pPKN = aPKN.getStr(),
*pCOL = aCOL.getStr();
SQLRETURN nRetcode = functions().ProcedureColumns(m_aStatementHandle,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pPKQ)), (catalog.hasValue() && !aPKQ.isEmpty()) ? SQL_NTS : 0,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pPKO)), pPKO ? SQL_NTS : 0 ,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pPKN)), SQL_NTS,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pCOL)), SQL_NTS);
auto pPKQ = !aPKQ.empty() ? aPKQ.get() : nullptr,
pPKO = !aPKO.empty() ? aPKO.get() : nullptr;
nRetcode = functions().ProcedureColumns(m_aStatementHandle,
pPKQ, pPKQ ? SQL_NTS : 0,
pPKO, pPKO ? SQL_NTS : 0,
aPKN.get(), SQL_NTS,
aCOL.get(), SQL_NTS);
}
OTools::ThrowException(m_pConnection.get(),nRetcode,m_aStatementHandle,SQL_HANDLE_STMT,*this);
checkColumnCount();
}
void ODatabaseMetaDataResultSet::openProcedures(const Any& catalog, const OUString& schemaPattern,
std::u16string_view procedureNamePattern)
const OUString& procedureNamePattern)
{
const OUString *pSchemaPat = nullptr;
OUString uPKQ;
catalog >>= uPKQ;
SQLRETURN nRetcode;
if (bUseWChar && functions().has(ODBC3SQLFunctionId::ProceduresW))
{
SQLWChars aPKQ, aPKO;
if (!uPKQ.isEmpty())
aPKQ = SQLWChars(uPKQ);
if (!schemaPattern.isEmpty() && schemaPattern != "%")
aPKO = SQLWChars(schemaPattern);
SQLWChars aPKN(procedureNamePattern);
if(schemaPattern != "%")
pSchemaPat = &schemaPattern;
auto pPKQ = !aPKQ.empty() ? aPKQ.get() : nullptr,
pPKO = !aPKO.empty() ? aPKO.get() : nullptr;
nRetcode = functions().ProceduresW(m_aStatementHandle,
pPKQ, pPKQ ? SQL_NTSL : 0,
pPKO, pPKO ? SQL_NTSL : 0,
aPKN.get(), SQL_NTSL);
}
else
pSchemaPat = nullptr;
{
SQLChars aPKQ, aPKO;
if (!uPKQ.isEmpty())
aPKQ = SQLChars(uPKQ, m_nTextEncoding);
if (!schemaPattern.isEmpty() && schemaPattern != "%")
aPKO = SQLChars(schemaPattern, m_nTextEncoding);
SQLChars aPKN(procedureNamePattern, m_nTextEncoding);
OString aPKQ,aPKO,aPKN;
auto pPKQ = !aPKQ.empty() ? aPKQ.get() : nullptr,
pPKO = !aPKO.empty() ? aPKO.get() : nullptr;
if ( catalog.hasValue() )
aPKQ = OUStringToOString(comphelper::getString(catalog),m_nTextEncoding);
aPKO = OUStringToOString(schemaPattern,m_nTextEncoding);
aPKN = OUStringToOString(procedureNamePattern,m_nTextEncoding);
const char *pPKQ = catalog.hasValue() && !aPKQ.isEmpty() ? aPKQ.getStr() : nullptr,
*pPKO = pSchemaPat && !pSchemaPat->isEmpty() && !aPKO.isEmpty() ? aPKO.getStr() : nullptr,
*pPKN = aPKN.getStr();
SQLRETURN nRetcode = functions().Procedures(m_aStatementHandle,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pPKQ)), (catalog.hasValue() && !aPKQ.isEmpty()) ? SQL_NTS : 0,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pPKO)), pPKO ? SQL_NTS : 0 ,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pPKN)), SQL_NTS);
nRetcode = functions().Procedures(m_aStatementHandle,
pPKQ, pPKQ ? SQL_NTS : 0,
pPKO, pPKO ? SQL_NTS : 0,
aPKN.get(), SQL_NTS);
}
OTools::ThrowException(m_pConnection.get(),nRetcode,m_aStatementHandle,SQL_HANDLE_STMT,*this);
checkColumnCount();
}
void ODatabaseMetaDataResultSet::openSpecialColumns(bool _bRowVer,const Any& catalog, const OUString& schema,
std::u16string_view table,sal_Int32 scope, bool nullable )
const OUString& table,sal_Int32 scope, bool nullable )
{
// Some ODBC drivers really don't like getting an empty string as tableName
// E.g. psqlodbc up to at least version 09.01.0100 segfaults
if (table.empty())
if (table.isEmpty())
{
static constexpr OUStringLiteral errMsg
= u"ODBC: Trying to get special columns of empty table name";
@ -1105,42 +1204,59 @@ void ODatabaseMetaDataResultSet::openSpecialColumns(bool _bRowVer,const Any& cat
throw SQLException( errMsg, *this, SQLState, -1, Any() );
}
const OUString *pSchemaPat = nullptr;
OUString uPKQ;
catalog >>= uPKQ;
SQLRETURN nRetcode;
if (bUseWChar && functions().has(ODBC3SQLFunctionId::SpecialColumnsW))
{
SQLWChars aPKQ, aPKO;
if (!uPKQ.isEmpty())
aPKQ = SQLWChars(uPKQ);
if (!schema.isEmpty() && schema != "%")
aPKO = SQLWChars(schema);
SQLWChars aPKN(table);
if(schema != "%")
pSchemaPat = &schema;
auto pPKQ = !aPKQ.empty() ? aPKQ.get() : nullptr,
pPKO = !aPKO.empty() ? aPKO.get() : nullptr;
nRetcode = functions().SpecialColumnsW(m_aStatementHandle, _bRowVer ? SQL_ROWVER : SQL_BEST_ROWID,
pPKQ, pPKQ ? SQL_NTSL : 0,
pPKO, pPKO ? SQL_NTSL : 0,
aPKN.get(), SQL_NTSL,
scope,
nullable ? SQL_NULLABLE : SQL_NO_NULLS);
}
else
pSchemaPat = nullptr;
{
SQLChars aPKQ, aPKO;
if (!uPKQ.isEmpty())
aPKQ = SQLChars(uPKQ, m_nTextEncoding);
if (!schema.isEmpty() && schema != "%")
aPKO = SQLChars(schema, m_nTextEncoding);
SQLChars aPKN(table, m_nTextEncoding);
OString aPKQ,aPKO,aPKN;
if ( catalog.hasValue() )
aPKQ = OUStringToOString(comphelper::getString(catalog),m_nTextEncoding);
aPKO = OUStringToOString(schema,m_nTextEncoding);
aPKN = OUStringToOString(table,m_nTextEncoding);
auto pPKQ = !aPKQ.empty() ? aPKQ.get() : nullptr,
pPKO = !aPKO.empty() ? aPKO.get() : nullptr;
const char *pPKQ = catalog.hasValue() && !aPKQ.isEmpty() ? aPKQ.getStr() : nullptr,
*pPKO = pSchemaPat && !pSchemaPat->isEmpty() && !aPKO.isEmpty() ? aPKO.getStr() : nullptr,
*pPKN = aPKN.getStr();
SQLRETURN nRetcode = functions().SpecialColumns(m_aStatementHandle,_bRowVer ? SQL_ROWVER : SQL_BEST_ROWID,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pPKQ)), (catalog.hasValue() && !aPKQ.isEmpty()) ? SQL_NTS : 0,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pPKO)), pPKO ? SQL_NTS : 0 ,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pPKN)), SQL_NTS,
static_cast<SQLSMALLINT>(scope),
nullable ? SQL_NULLABLE : SQL_NO_NULLS);
nRetcode = functions().SpecialColumns(m_aStatementHandle, _bRowVer ? SQL_ROWVER : SQL_BEST_ROWID,
pPKQ, pPKQ ? SQL_NTS : 0,
pPKO, pPKO ? SQL_NTS : 0,
aPKN.get(), SQL_NTS,
static_cast<SQLSMALLINT>(scope),
nullable ? SQL_NULLABLE : SQL_NO_NULLS);
}
OTools::ThrowException(m_pConnection.get(),nRetcode,m_aStatementHandle,SQL_HANDLE_STMT,*this);
checkColumnCount();
}
void ODatabaseMetaDataResultSet::openVersionColumns(const Any& catalog, const OUString& schema,
std::u16string_view table)
const OUString& table)
{
openSpecialColumns(true,catalog,schema,table,SQL_SCOPE_TRANSACTION,false);
}
void ODatabaseMetaDataResultSet::openBestRowIdentifier( const Any& catalog, const OUString& schema,
std::u16string_view table,sal_Int32 scope,bool nullable )
const OUString& table,sal_Int32 scope,bool nullable )
{
openSpecialColumns(false,catalog,schema,table,scope,nullable);
}
@ -1150,47 +1266,72 @@ void ODatabaseMetaDataResultSet::openForeignKeys( const Any& catalog, const OUSt
const Any& catalog2, const OUString* schema2,
const OUString* table2)
{
OString aPKQ, aPKO, aPKN, aFKQ, aFKO, aFKN;
if ( catalog.hasValue() )
aPKQ = OUStringToOString(comphelper::getString(catalog),m_nTextEncoding);
if ( catalog2.hasValue() )
aFKQ = OUStringToOString(comphelper::getString(catalog2),m_nTextEncoding);
OUString uPKQ, uFKQ;
catalog >>= uPKQ;
catalog2 >>= uFKQ;
SQLRETURN nRetcode;
if (bUseWChar && functions().has(ODBC3SQLFunctionId::ForeignKeysW))
{
SQLWChars aPKQ, aPKO, aPKN, aFKQ, aFKO, aFKN;
if (!uPKQ.isEmpty())
aPKQ = SQLWChars(uPKQ);
if (!uFKQ.isEmpty())
aFKQ = SQLWChars(uFKQ);
if (schema && !schema->isEmpty())
aPKO = SQLWChars(*schema);
if (table)
aPKN = SQLWChars(*table);
if (schema2 && !schema2->isEmpty())
aFKO = SQLWChars(*schema2);
if (table2)
aFKN = SQLWChars(*table2);
const char *pPKQ = catalog.hasValue() && !aPKQ.isEmpty() ? aPKQ.getStr() : nullptr;
const char *pPKO = nullptr;
if (schema && !schema->isEmpty())
{
aPKO = OUStringToOString(*schema,m_nTextEncoding);
pPKO = aPKO.getStr();
}
const char *pPKN = nullptr;
if (table)
{
aPKN = OUStringToOString(*table,m_nTextEncoding);
pPKN = aPKN.getStr();
}
const char *pFKQ = catalog2.hasValue() && !aFKQ.isEmpty() ? aFKQ.getStr() : nullptr;
const char *pFKO = nullptr;
if (schema2 && !schema2->isEmpty())
{
aFKO = OUStringToOString(*schema2,m_nTextEncoding);
pFKO = aFKO.getStr();
}
const char *pFKN = nullptr;
if (table2)
{
aFKN = OUStringToOString(*table2,m_nTextEncoding);
pFKN = aFKN.getStr();
}
auto pPKQ = !aPKQ.empty() ? aPKQ.get() : nullptr;
auto pPKO = !aPKO.empty() ? aPKO.get() : nullptr;
auto pPKN = !aPKN.empty() ? aPKN.get() : nullptr;
auto pFKQ = !aFKQ.empty() ? aFKQ.get() : nullptr;
auto pFKO = !aFKO.empty() ? aFKO.get() : nullptr;
auto pFKN = !aFKN.empty() ? aFKN.get() : nullptr;
SQLRETURN nRetcode = functions().ForeignKeys(m_aStatementHandle,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pPKQ)), (catalog.hasValue() && !aPKQ.isEmpty()) ? SQL_NTS : 0,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pPKO)), pPKO ? SQL_NTS : 0,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pPKN)), pPKN ? SQL_NTS : 0,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pFKQ)), (catalog2.hasValue() && !aFKQ.isEmpty()) ? SQL_NTS : 0,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pFKO)), pFKO ? SQL_NTS : 0,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pFKN)), SQL_NTS
);
nRetcode = functions().ForeignKeysW(m_aStatementHandle,
pPKQ, pPKQ ? SQL_NTSL : 0,
pPKO, pPKO ? SQL_NTSL : 0,
pPKN, pPKN ? SQL_NTSL : 0,
pFKQ, pFKQ ? SQL_NTSL : 0,
pFKO, pFKO ? SQL_NTSL : 0,
pFKN, pFKN ? SQL_NTSL : 0);
}
else
{
SQLChars aPKQ, aPKO, aPKN, aFKQ, aFKO, aFKN;
if (!uPKQ.isEmpty())
aPKQ = SQLChars(uPKQ, m_nTextEncoding);
if (!uFKQ.isEmpty())
aFKQ = SQLChars(uFKQ, m_nTextEncoding);
if (schema && !schema->isEmpty())
aPKO = SQLChars(*schema, m_nTextEncoding);
if (table)
aPKN = SQLChars(*table, m_nTextEncoding);
if (schema2 && !schema2->isEmpty())
aFKO = SQLChars(*schema2, m_nTextEncoding);
if (table2)
aFKN = SQLChars(*table2, m_nTextEncoding);
auto pPKQ = !aPKQ.empty() ? aPKQ.get() : nullptr;
auto pPKO = !aPKO.empty() ? aPKO.get() : nullptr;
auto pPKN = !aPKN.empty() ? aPKN.get() : nullptr;
auto pFKQ = !aFKQ.empty() ? aFKQ.get() : nullptr;
auto pFKO = !aFKO.empty() ? aFKO.get() : nullptr;
auto pFKN = !aFKN.empty() ? aFKN.get() : nullptr;
nRetcode = functions().ForeignKeys(m_aStatementHandle,
pPKQ, pPKQ ? SQL_NTS : 0,
pPKO, pPKO ? SQL_NTS : 0,
pPKN, pPKN ? SQL_NTS : 0,
pFKQ, pFKQ ? SQL_NTS : 0,
pFKO, pFKO ? SQL_NTS : 0,
pFKN, pFKN ? SQL_NTS : 0);
}
OTools::ThrowException(m_pConnection.get(),nRetcode,m_aStatementHandle,SQL_HANDLE_STMT,*this);
checkColumnCount();
}
@ -1209,91 +1350,137 @@ void ODatabaseMetaDataResultSet::openExportedKeys(const Any& catalog, const OUSt
}
void ODatabaseMetaDataResultSet::openPrimaryKeys(const Any& catalog, const OUString& schema,
std::u16string_view table)
const OUString& table)
{
const OUString *pSchemaPat = nullptr;
OUString uPKQ;
catalog >>= uPKQ;
SQLRETURN nRetcode;
if (bUseWChar && functions().has(ODBC3SQLFunctionId::PrimaryKeysW))
{
SQLWChars aPKQ, aPKO;
if (!uPKQ.isEmpty())
aPKQ = SQLWChars(uPKQ);
if (!schema.isEmpty() && schema != "%")
aPKO = SQLWChars(schema);
SQLWChars aPKN(table);
if(schema != "%")
pSchemaPat = &schema;
auto pPKQ = !aPKQ.empty() ? aPKQ.get() : nullptr,
pPKO = !aPKO.empty() ? aPKO.get() : nullptr;
nRetcode = functions().PrimaryKeysW(m_aStatementHandle,
pPKQ, pPKQ ? SQL_NTSL : 0,
pPKO, pPKO ? SQL_NTSL : 0,
aPKN.get(), SQL_NTSL);
}
else
pSchemaPat = nullptr;
{
SQLChars aPKQ, aPKO;
if (!uPKQ.isEmpty())
aPKQ = SQLChars(uPKQ, m_nTextEncoding);
if (!schema.isEmpty() && schema != "%")
aPKO = SQLChars(schema, m_nTextEncoding);
SQLChars aPKN(table, m_nTextEncoding);
OString aPKQ,aPKO,aPKN;
auto pPKQ = !aPKQ.empty() ? aPKQ.get() : nullptr,
pPKO = !aPKO.empty() ? aPKO.get() : nullptr;
if ( catalog.hasValue() )
aPKQ = OUStringToOString(comphelper::getString(catalog),m_nTextEncoding);
aPKO = OUStringToOString(schema,m_nTextEncoding);
aPKN = OUStringToOString(table,m_nTextEncoding);
const char *pPKQ = catalog.hasValue() && !aPKQ.isEmpty() ? aPKQ.getStr() : nullptr,
*pPKO = pSchemaPat && !pSchemaPat->isEmpty() && !aPKO.isEmpty() ? aPKO.getStr() : nullptr,
*pPKN = aPKN.getStr();
SQLRETURN nRetcode = functions().PrimaryKeys(m_aStatementHandle,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pPKQ)), (catalog.hasValue() && !aPKQ.isEmpty()) ? SQL_NTS : 0,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pPKO)), pPKO ? SQL_NTS : 0 ,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pPKN)), SQL_NTS);
nRetcode = functions().PrimaryKeys(m_aStatementHandle,
pPKQ, pPKQ ? SQL_NTS : 0,
pPKO, pPKO ? SQL_NTS : 0,
aPKN.get(), SQL_NTS);
}
OTools::ThrowException(m_pConnection.get(),nRetcode,m_aStatementHandle,SQL_HANDLE_STMT,*this);
checkColumnCount();
}
void ODatabaseMetaDataResultSet::openTablePrivileges(const Any& catalog, const OUString& schemaPattern,
std::u16string_view tableNamePattern)
const OUString& tableNamePattern)
{
const OUString *pSchemaPat = nullptr;
OUString uPKQ;
catalog >>= uPKQ;
SQLRETURN nRetcode;
if (bUseWChar && functions().has(ODBC3SQLFunctionId::TablePrivilegesW))
{
SQLWChars aPKQ, aPKO;
if (!uPKQ.isEmpty())
aPKQ = SQLWChars(uPKQ);
if (!schemaPattern.isEmpty() && schemaPattern != "%")
aPKO = SQLWChars(schemaPattern);
SQLWChars aPKN(tableNamePattern);
if(schemaPattern != "%")
pSchemaPat = &schemaPattern;
auto pPKQ = !aPKQ.empty() ? aPKQ.get() : nullptr,
pPKO = !aPKO.empty() ? aPKO.get() : nullptr;
nRetcode = functions().TablePrivilegesW(m_aStatementHandle,
pPKQ, pPKQ ? SQL_NTSL : 0,
pPKO, pPKO ? SQL_NTSL : 0,
aPKN.get(), SQL_NTSL);
}
else
pSchemaPat = nullptr;
{
SQLChars aPKQ, aPKO;
if (!uPKQ.isEmpty())
aPKQ = SQLChars(uPKQ, m_nTextEncoding);
if (!schemaPattern.isEmpty() && schemaPattern != "%")
aPKO = SQLChars(schemaPattern, m_nTextEncoding);
SQLChars aPKN(tableNamePattern, m_nTextEncoding);
OString aPKQ,aPKO,aPKN;
auto pPKQ = !aPKQ.empty() ? aPKQ.get() : nullptr,
pPKO = !aPKO.empty() ? aPKO.get() : nullptr;
if ( catalog.hasValue() )
aPKQ = OUStringToOString(comphelper::getString(catalog),m_nTextEncoding);
aPKO = OUStringToOString(schemaPattern,m_nTextEncoding);
aPKN = OUStringToOString(tableNamePattern,m_nTextEncoding);
const char *pPKQ = catalog.hasValue() && !aPKQ.isEmpty() ? aPKQ.getStr() : nullptr,
*pPKO = pSchemaPat && !pSchemaPat->isEmpty() && !aPKO.isEmpty() ? aPKO.getStr() : nullptr,
*pPKN = aPKN.getStr();
SQLRETURN nRetcode = functions().TablePrivileges(m_aStatementHandle,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pPKQ)), (catalog.hasValue() && !aPKQ.isEmpty()) ? SQL_NTS : 0,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pPKO)), pPKO ? SQL_NTS : 0 ,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pPKN)), SQL_NTS);
nRetcode = functions().TablePrivileges(m_aStatementHandle,
pPKQ, pPKQ ? SQL_NTS : 0,
pPKO, pPKO ? SQL_NTS : 0,
aPKN.get(), SQL_NTS);
}
OTools::ThrowException(m_pConnection.get(),nRetcode,m_aStatementHandle,SQL_HANDLE_STMT,*this);
checkColumnCount();
}
void ODatabaseMetaDataResultSet::openIndexInfo( const Any& catalog, const OUString& schema,
std::u16string_view table, bool unique, bool approximate )
const OUString& table, bool unique, bool approximate )
{
const OUString *pSchemaPat = nullptr;
OUString uPKQ;
catalog >>= uPKQ;
SQLRETURN nRetcode;
if (bUseWChar && functions().has(ODBC3SQLFunctionId::StatisticsW))
{
SQLWChars aPKQ, aPKO;
if (!uPKQ.isEmpty())
aPKQ = SQLWChars(uPKQ);
if (!schema.isEmpty() && schema != "%")
aPKO = SQLWChars(schema);
SQLWChars aPKN(table);
if(schema != "%")
pSchemaPat = &schema;
auto pPKQ = !aPKQ.empty() ? aPKQ.get() : nullptr,
pPKO = !aPKO.empty() ? aPKO.get() : nullptr;
nRetcode = functions().StatisticsW(m_aStatementHandle,
pPKQ, pPKQ ? SQL_NTSL : 0,
pPKO, pPKO ? SQL_NTSL : 0,
aPKN.get(), SQL_NTSL,
unique ? SQL_INDEX_UNIQUE : SQL_INDEX_ALL,
approximate ? 1 : 0);
}
else
pSchemaPat = nullptr;
{
SQLChars aPKQ, aPKO;
if (!uPKQ.isEmpty())
aPKQ = SQLChars(uPKQ, m_nTextEncoding);
if (!schema.isEmpty() && schema != "%")
aPKO = SQLChars(schema, m_nTextEncoding);
SQLChars aPKN(table, m_nTextEncoding);
OString aPKQ,aPKO,aPKN;
auto pPKQ = !aPKQ.empty() ? aPKQ.get() : nullptr,
pPKO = !aPKO.empty() ? aPKO.get() : nullptr;
if ( catalog.hasValue() )
aPKQ = OUStringToOString(comphelper::getString(catalog),m_nTextEncoding);
aPKO = OUStringToOString(schema,m_nTextEncoding);
aPKN = OUStringToOString(table,m_nTextEncoding);
const char *pPKQ = catalog.hasValue() && !aPKQ.isEmpty() ? aPKQ.getStr() : nullptr,
*pPKO = pSchemaPat && !pSchemaPat->isEmpty() && !aPKO.isEmpty() ? aPKO.getStr() : nullptr,
*pPKN = aPKN.getStr();
SQLRETURN nRetcode = functions().Statistics(m_aStatementHandle,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pPKQ)), (catalog.hasValue() && !aPKQ.isEmpty()) ? SQL_NTS : 0,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pPKO)), pPKO ? SQL_NTS : 0 ,
reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(pPKN)), SQL_NTS,
unique ? SQL_INDEX_UNIQUE : SQL_INDEX_ALL,
approximate ? 1 : 0);
nRetcode = functions().Statistics(m_aStatementHandle,
pPKQ, pPKQ ? SQL_NTS : 0,
pPKO, pPKO ? SQL_NTS : 0,
aPKN.get(), SQL_NTS,
unique ? SQL_INDEX_UNIQUE : SQL_INDEX_ALL,
approximate ? 1 : 0);
}
OTools::ThrowException(m_pConnection.get(),nRetcode,m_aStatementHandle,SQL_HANDLE_STMT,*this);
checkColumnCount();
}

View file

@ -202,6 +202,32 @@ bool LoadFunctions(oslModule pODBCso)
return rpFunc != nullptr;
};
// Optional functions for Unicode support
if (bUseWChar)
{
load(ODBC3SQLFunctionId::DriverConnectW, u"SQLDriverConnectW"_ustr);
load(ODBC3SQLFunctionId::GetInfoW, u"SQLGetInfoW"_ustr);
load(ODBC3SQLFunctionId::SetConnectAttrW, u"SQLSetConnectAttrW"_ustr);
load(ODBC3SQLFunctionId::GetConnectAttrW, u"SQLGetConnectAttrW"_ustr);
load(ODBC3SQLFunctionId::PrepareW, u"SQLPrepareW"_ustr);
load(ODBC3SQLFunctionId::SetCursorNameW, u"SQLSetCursorNameW"_ustr);
load(ODBC3SQLFunctionId::ExecDirectW, u"SQLExecDirectW"_ustr);
load(ODBC3SQLFunctionId::ColAttributeW, u"SQLColAttributeW"_ustr);
load(ODBC3SQLFunctionId::GetDiagRecW, u"SQLGetDiagRecW"_ustr);
load(ODBC3SQLFunctionId::ColumnPrivilegesW, u"SQLColumnPrivilegesW"_ustr);
load(ODBC3SQLFunctionId::ColumnsW, u"SQLColumnsW"_ustr);
load(ODBC3SQLFunctionId::ForeignKeysW, u"SQLForeignKeysW"_ustr);
load(ODBC3SQLFunctionId::PrimaryKeysW, u"SQLPrimaryKeysW"_ustr);
load(ODBC3SQLFunctionId::ProcedureColumnsW, u"SQLProcedureColumnsW"_ustr);
load(ODBC3SQLFunctionId::ProceduresW, u"SQLProceduresW"_ustr);
load(ODBC3SQLFunctionId::SpecialColumnsW, u"SQLSpecialColumnsW"_ustr);
load(ODBC3SQLFunctionId::StatisticsW, u"SQLStatisticsW"_ustr);
load(ODBC3SQLFunctionId::TablePrivilegesW, u"SQLTablePrivilegesW"_ustr);
load(ODBC3SQLFunctionId::TablesW, u"SQLTablesW"_ustr);
load(ODBC3SQLFunctionId::GetCursorNameW, u"SQLGetCursorNameW"_ustr);
load(ODBC3SQLFunctionId::NativeSqlW, u"SQLNativeSqlW"_ustr);
}
return load(ODBC3SQLFunctionId::AllocHandle, u"SQLAllocHandle"_ustr)
&& load(ODBC3SQLFunctionId::DriverConnect, u"SQLDriverConnect"_ustr)
&& load(ODBC3SQLFunctionId::GetInfo, u"SQLGetInfo"_ustr)
@ -329,6 +355,17 @@ public:
StringLength2Ptr, DriverCompletion);
}
SQLRETURN DriverConnectW(SQLHDBC ConnectionHandle, HWND WindowHandle,
SQLWCHAR* InConnectionString, SQLSMALLINT StringLength1,
SQLWCHAR* OutConnectionString, SQLSMALLINT BufferLength,
SQLSMALLINT* StringLength2Ptr,
SQLUSMALLINT DriverCompletion) const override
{
return ODBCFunc(ODBC3SQLFunctionId::DriverConnectW, ConnectionHandle, WindowHandle,
InConnectionString, StringLength1, OutConnectionString, BufferLength,
StringLength2Ptr, DriverCompletion);
}
SQLRETURN GetInfo(SQLHDBC ConnectionHandle, SQLUSMALLINT InfoType, SQLPOINTER InfoValuePtr,
SQLSMALLINT BufferLength, SQLSMALLINT* StringLengthPtr) const override
{
@ -336,6 +373,13 @@ public:
BufferLength, StringLengthPtr);
}
SQLRETURN GetInfoW(SQLHDBC ConnectionHandle, SQLUSMALLINT InfoType, SQLPOINTER InfoValuePtr,
SQLSMALLINT BufferLength, SQLSMALLINT* StringLengthPtr) const override
{
return ODBCFunc(ODBC3SQLFunctionId::GetInfoW, ConnectionHandle, InfoType, InfoValuePtr,
BufferLength, StringLengthPtr);
}
SQLRETURN GetFunctions(SQLHDBC ConnectionHandle, SQLUSMALLINT FunctionId,
SQLUSMALLINT* SupportedPtr) const override
{
@ -355,6 +399,13 @@ public:
StringLength);
}
SQLRETURN SetConnectAttrW(SQLHDBC ConnectionHandle, SQLINTEGER Attribute, SQLPOINTER ValuePtr,
SQLINTEGER StringLength) const override
{
return ODBCFunc(ODBC3SQLFunctionId::SetConnectAttrW, ConnectionHandle, Attribute, ValuePtr,
StringLength);
}
SQLRETURN GetConnectAttr(SQLHDBC ConnectionHandle, SQLINTEGER Attribute, SQLPOINTER ValuePtr,
SQLINTEGER BufferLength, SQLINTEGER* StringLength) const override
{
@ -362,6 +413,13 @@ public:
BufferLength, StringLength);
}
SQLRETURN GetConnectAttrW(SQLHDBC ConnectionHandle, SQLINTEGER Attribute, SQLPOINTER ValuePtr,
SQLINTEGER BufferLength, SQLINTEGER* StringLength) const override
{
return ODBCFunc(ODBC3SQLFunctionId::GetConnectAttrW, ConnectionHandle, Attribute, ValuePtr,
BufferLength, StringLength);
}
SQLRETURN SetEnvAttr(SQLHENV EnvironmentHandle, SQLINTEGER Attribute, SQLPOINTER ValuePtr,
SQLINTEGER StringLength) const override
{
@ -396,6 +454,12 @@ public:
return ODBCFunc(ODBC3SQLFunctionId::Prepare, StatementHandle, StatementText, TextLength);
}
SQLRETURN PrepareW(SQLHSTMT StatementHandle, SQLWCHAR* StatementText,
SQLINTEGER TextLength) const override
{
return ODBCFunc(ODBC3SQLFunctionId::PrepareW, StatementHandle, StatementText, TextLength);
}
SQLRETURN BindParameter(SQLHSTMT StatementHandle, SQLUSMALLINT ParameterNumber,
SQLSMALLINT InputOutputType, SQLSMALLINT ValueType,
SQLSMALLINT ParameterType, SQLULEN ColumnSize,
@ -413,6 +477,12 @@ public:
return ODBCFunc(ODBC3SQLFunctionId::SetCursorName, StatementHandle, CursorName, NameLength);
}
SQLRETURN SetCursorNameW(SQLHSTMT StatementHandle, SQLWCHAR* CursorName,
SQLSMALLINT NameLength) const override
{
return ODBCFunc(ODBC3SQLFunctionId::SetCursorNameW, StatementHandle, CursorName, NameLength);
}
SQLRETURN Execute(SQLHSTMT StatementHandle) const override
{
return ODBCFunc(ODBC3SQLFunctionId::Execute, StatementHandle);
@ -424,6 +494,12 @@ public:
return ODBCFunc(ODBC3SQLFunctionId::ExecDirect, StatementHandle, StatementText, TextLength);
}
SQLRETURN ExecDirectW(SQLHSTMT StatementHandle, SQLWCHAR* StatementText,
SQLINTEGER TextLength) const override
{
return ODBCFunc(ODBC3SQLFunctionId::ExecDirectW, StatementHandle, StatementText, TextLength);
}
SQLRETURN DescribeParam(SQLHSTMT StatementHandle, SQLUSMALLINT ParameterNumber,
SQLSMALLINT* DataTypePtr, SQLULEN* ParameterSizePtr,
SQLSMALLINT* DecimalDigitsPtr, SQLSMALLINT* NullablePtr) const override
@ -468,6 +544,16 @@ public:
NumericAttributePtr);
}
SQLRETURN ColAttributeW(SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber,
SQLUSMALLINT FieldIdentifier, SQLPOINTER CharacterAttributePtr,
SQLSMALLINT BufferLength, SQLSMALLINT* StringLengthPtr,
SQLLEN* NumericAttributePtr) const override
{
return ODBCFunc(ODBC3SQLFunctionId::ColAttributeW, StatementHandle, ColumnNumber,
FieldIdentifier, CharacterAttributePtr, BufferLength, StringLengthPtr,
NumericAttributePtr);
}
SQLRETURN BindCol(SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType,
SQLPOINTER TargetValuePtr, SQLLEN BufferLength,
SQLLEN* StrLen_or_IndPtr) const override
@ -521,6 +607,14 @@ public:
NativeErrorPtr, MessageText, BufferLength, TextLengthPtr);
}
SQLRETURN GetDiagRecW(SQLSMALLINT HandleType, SQLHANDLE Handle, SQLSMALLINT RecNumber,
SQLWCHAR* Sqlstate, SQLINTEGER* NativeErrorPtr, SQLWCHAR* MessageText,
SQLSMALLINT BufferLength, SQLSMALLINT* TextLengthPtr) const override
{
return ODBCFunc(ODBC3SQLFunctionId::GetDiagRecW, HandleType, Handle, RecNumber, Sqlstate,
NativeErrorPtr, MessageText, BufferLength, TextLengthPtr);
}
SQLRETURN ColumnPrivileges(SQLHSTMT StatementHandle, SQLCHAR* CatalogName,
SQLSMALLINT NameLength1, SQLCHAR* SchemaName,
SQLSMALLINT NameLength2, SQLCHAR* TableName, SQLSMALLINT NameLength3,
@ -531,6 +625,16 @@ public:
NameLength4);
}
SQLRETURN ColumnPrivilegesW(SQLHSTMT StatementHandle, SQLWCHAR* CatalogName,
SQLSMALLINT NameLength1, SQLWCHAR* SchemaName,
SQLSMALLINT NameLength2, SQLWCHAR* TableName, SQLSMALLINT NameLength3,
SQLWCHAR* ColumnName, SQLSMALLINT NameLength4) const override
{
return ODBCFunc(ODBC3SQLFunctionId::ColumnPrivilegesW, StatementHandle, CatalogName,
NameLength1, SchemaName, NameLength2, TableName, NameLength3, ColumnName,
NameLength4);
}
SQLRETURN Columns(SQLHSTMT StatementHandle, SQLCHAR* CatalogName, SQLSMALLINT NameLength1,
SQLCHAR* SchemaName, SQLSMALLINT NameLength2, SQLCHAR* TableName,
SQLSMALLINT NameLength3, SQLCHAR* ColumnName,
@ -540,6 +644,15 @@ public:
SchemaName, NameLength2, TableName, NameLength3, ColumnName, NameLength4);
}
SQLRETURN ColumnsW(SQLHSTMT StatementHandle, SQLWCHAR* CatalogName, SQLSMALLINT NameLength1,
SQLWCHAR* SchemaName, SQLSMALLINT NameLength2, SQLWCHAR* TableName,
SQLSMALLINT NameLength3, SQLWCHAR* ColumnName,
SQLSMALLINT NameLength4) const override
{
return ODBCFunc(ODBC3SQLFunctionId::ColumnsW, StatementHandle, CatalogName, NameLength1,
SchemaName, NameLength2, TableName, NameLength3, ColumnName, NameLength4);
}
SQLRETURN ForeignKeys(SQLHSTMT StatementHandle, SQLCHAR* PKCatalogName, SQLSMALLINT NameLength1,
SQLCHAR* PKSchemaName, SQLSMALLINT NameLength2, SQLCHAR* PKTableName,
SQLSMALLINT NameLength3, SQLCHAR* FKCatalogName, SQLSMALLINT NameLength4,
@ -552,6 +665,18 @@ public:
NameLength6);
}
SQLRETURN ForeignKeysW(SQLHSTMT StatementHandle, SQLWCHAR* PKCatalogName, SQLSMALLINT NameLength1,
SQLWCHAR* PKSchemaName, SQLSMALLINT NameLength2, SQLWCHAR* PKTableName,
SQLSMALLINT NameLength3, SQLWCHAR* FKCatalogName, SQLSMALLINT NameLength4,
SQLWCHAR* FKSchemaName, SQLSMALLINT NameLength5, SQLWCHAR* FKTableName,
SQLSMALLINT NameLength6) const override
{
return ODBCFunc(ODBC3SQLFunctionId::ForeignKeysW, StatementHandle, PKCatalogName,
NameLength1, PKSchemaName, NameLength2, PKTableName, NameLength3,
FKCatalogName, NameLength4, FKSchemaName, NameLength5, FKTableName,
NameLength6);
}
SQLRETURN PrimaryKeys(SQLHSTMT StatementHandle, SQLCHAR* CatalogName, SQLSMALLINT NameLength1,
SQLCHAR* SchemaName, SQLSMALLINT NameLength2, SQLCHAR* TableName,
SQLSMALLINT NameLength3) const override
@ -560,6 +685,14 @@ public:
SchemaName, NameLength2, TableName, NameLength3);
}
SQLRETURN PrimaryKeysW(SQLHSTMT StatementHandle, SQLWCHAR* CatalogName, SQLSMALLINT NameLength1,
SQLWCHAR* SchemaName, SQLSMALLINT NameLength2, SQLWCHAR* TableName,
SQLSMALLINT NameLength3) const override
{
return ODBCFunc(ODBC3SQLFunctionId::PrimaryKeysW, StatementHandle, CatalogName, NameLength1,
SchemaName, NameLength2, TableName, NameLength3);
}
SQLRETURN ProcedureColumns(SQLHSTMT StatementHandle, SQLCHAR* CatalogName,
SQLSMALLINT NameLength1, SQLCHAR* SchemaName,
SQLSMALLINT NameLength2, SQLCHAR* ProcName, SQLSMALLINT NameLength3,
@ -570,6 +703,16 @@ public:
NameLength4);
}
SQLRETURN ProcedureColumnsW(SQLHSTMT StatementHandle, SQLWCHAR* CatalogName,
SQLSMALLINT NameLength1, SQLWCHAR* SchemaName,
SQLSMALLINT NameLength2, SQLWCHAR* ProcName, SQLSMALLINT NameLength3,
SQLWCHAR* ColumnName, SQLSMALLINT NameLength4) const override
{
return ODBCFunc(ODBC3SQLFunctionId::ProcedureColumnsW, StatementHandle, CatalogName,
NameLength1, SchemaName, NameLength2, ProcName, NameLength3, ColumnName,
NameLength4);
}
SQLRETURN Procedures(SQLHSTMT StatementHandle, SQLCHAR* CatalogName, SQLSMALLINT NameLength1,
SQLCHAR* SchemaName, SQLSMALLINT NameLength2, SQLCHAR* ProcName,
SQLSMALLINT NameLength3) const override
@ -578,6 +721,14 @@ public:
SchemaName, NameLength2, ProcName, NameLength3);
}
SQLRETURN ProceduresW(SQLHSTMT StatementHandle, SQLWCHAR* CatalogName, SQLSMALLINT NameLength1,
SQLWCHAR* SchemaName, SQLSMALLINT NameLength2, SQLWCHAR* ProcName,
SQLSMALLINT NameLength3) const override
{
return ODBCFunc(ODBC3SQLFunctionId::ProceduresW, StatementHandle, CatalogName, NameLength1,
SchemaName, NameLength2, ProcName, NameLength3);
}
SQLRETURN SpecialColumns(SQLHSTMT StatementHandle, SQLUSMALLINT IdentifierType,
SQLCHAR* CatalogName, SQLSMALLINT NameLength1, SQLCHAR* SchemaName,
SQLSMALLINT NameLength2, SQLCHAR* TableName, SQLSMALLINT NameLength3,
@ -588,6 +739,16 @@ public:
Scope, Nullable);
}
SQLRETURN SpecialColumnsW(SQLHSTMT StatementHandle, SQLUSMALLINT IdentifierType,
SQLWCHAR* CatalogName, SQLSMALLINT NameLength1, SQLWCHAR* SchemaName,
SQLSMALLINT NameLength2, SQLWCHAR* TableName, SQLSMALLINT NameLength3,
SQLUSMALLINT Scope, SQLUSMALLINT Nullable) const override
{
return ODBCFunc(ODBC3SQLFunctionId::SpecialColumnsW, StatementHandle, IdentifierType,
CatalogName, NameLength1, SchemaName, NameLength2, TableName, NameLength3,
Scope, Nullable);
}
SQLRETURN Statistics(SQLHSTMT StatementHandle, SQLCHAR* CatalogName, SQLSMALLINT NameLength1,
SQLCHAR* SchemaName, SQLSMALLINT NameLength2, SQLCHAR* TableName,
SQLSMALLINT NameLength3, SQLUSMALLINT Unique,
@ -597,6 +758,15 @@ public:
SchemaName, NameLength2, TableName, NameLength3, Unique, Reserved);
}
SQLRETURN StatisticsW(SQLHSTMT StatementHandle, SQLWCHAR* CatalogName, SQLSMALLINT NameLength1,
SQLWCHAR* SchemaName, SQLSMALLINT NameLength2, SQLWCHAR* TableName,
SQLSMALLINT NameLength3, SQLUSMALLINT Unique,
SQLUSMALLINT Reserved) const override
{
return ODBCFunc(ODBC3SQLFunctionId::StatisticsW, StatementHandle, CatalogName, NameLength1,
SchemaName, NameLength2, TableName, NameLength3, Unique, Reserved);
}
SQLRETURN TablePrivileges(SQLHSTMT StatementHandle, SQLCHAR* CatalogName,
SQLSMALLINT NameLength1, SQLCHAR* SchemaName, SQLSMALLINT NameLength2,
SQLCHAR* TableName, SQLSMALLINT NameLength3) const override
@ -605,6 +775,14 @@ public:
NameLength1, SchemaName, NameLength2, TableName, NameLength3);
}
SQLRETURN TablePrivilegesW(SQLHSTMT StatementHandle, SQLWCHAR* CatalogName,
SQLSMALLINT NameLength1, SQLWCHAR* SchemaName, SQLSMALLINT NameLength2,
SQLWCHAR* TableName, SQLSMALLINT NameLength3) const override
{
return ODBCFunc(ODBC3SQLFunctionId::TablePrivilegesW, StatementHandle, CatalogName,
NameLength1, SchemaName, NameLength2, TableName, NameLength3);
}
SQLRETURN Tables(SQLHSTMT StatementHandle, SQLCHAR* CatalogName, SQLSMALLINT NameLength1,
SQLCHAR* SchemaName, SQLSMALLINT NameLength2, SQLCHAR* TableName,
SQLSMALLINT NameLength3, SQLCHAR* TableType,
@ -614,6 +792,15 @@ public:
SchemaName, NameLength2, TableName, NameLength3, TableType, NameLength4);
}
SQLRETURN TablesW(SQLHSTMT StatementHandle, SQLWCHAR* CatalogName, SQLSMALLINT NameLength1,
SQLWCHAR* SchemaName, SQLSMALLINT NameLength2, SQLWCHAR* TableName,
SQLSMALLINT NameLength3, SQLWCHAR* TableType,
SQLSMALLINT NameLength4) const override
{
return ODBCFunc(ODBC3SQLFunctionId::TablesW, StatementHandle, CatalogName, NameLength1,
SchemaName, NameLength2, TableName, NameLength3, TableType, NameLength4);
}
SQLRETURN FreeStmt(SQLHSTMT StatementHandle, SQLUSMALLINT Option) const override
{
return ODBCFunc(ODBC3SQLFunctionId::FreeStmt, StatementHandle, Option);
@ -652,6 +839,13 @@ public:
BufferLength, NameLength2);
}
SQLRETURN GetCursorNameW(SQLHSTMT StatementHandle, SQLWCHAR* CursorName, SQLSMALLINT BufferLength,
SQLSMALLINT* NameLength2) const override
{
return ODBCFunc(ODBC3SQLFunctionId::GetCursorNameW, StatementHandle, CursorName,
BufferLength, NameLength2);
}
SQLRETURN NativeSql(SQLHDBC ConnectionHandle, SQLCHAR* InStatementText, SQLINTEGER TextLength1,
SQLCHAR* OutStatementText, SQLINTEGER BufferLength,
SQLINTEGER* TextLength2Ptr) const override
@ -660,6 +854,14 @@ public:
TextLength1, OutStatementText, BufferLength, TextLength2Ptr);
}
SQLRETURN NativeSqlW(SQLHDBC ConnectionHandle, SQLWCHAR* InStatementText, SQLINTEGER TextLength1,
SQLWCHAR* OutStatementText, SQLINTEGER BufferLength,
SQLINTEGER* TextLength2Ptr) const override
{
return ODBCFunc(ODBC3SQLFunctionId::NativeSqlW, ConnectionHandle, InStatementText,
TextLength1, OutStatementText, BufferLength, TextLength2Ptr);
}
protected:
virtual SQLHANDLE EnvironmentHandle() override;

View file

@ -47,14 +47,6 @@ using namespace com::sun::star::util;
IMPLEMENT_SERVICE_INFO(OPreparedStatement,u"com.sun.star.sdbcx.OPreparedStatement"_ustr,u"com.sun.star.sdbc.PreparedStatement"_ustr);
namespace
{
// for now, never use wchar,
// but most of code is prepared to handle it
// in case we make this configurable
const bool bUseWChar = false;
}
OPreparedStatement::OPreparedStatement( OConnection* _pConnection,const OUString& sql)
:OStatement_BASE2(_pConnection)
,numParams(0)
@ -314,36 +306,21 @@ void OPreparedStatement::setParameter(const sal_Int32 parameterIndex, const sal_
*
* Our internal OUString storage is always UTF-16, so no conversion to do here.
*/
static_assert(sizeof (SQLWCHAR) == 2 || sizeof (SQLWCHAR) == 4, "must be 2 or 4");
if (sizeof (SQLWCHAR) == 2)
{
nCharLen = _sData.getLength();
nByteLen = 2 * nCharLen;
pData = allocBindBuf(parameterIndex, nByteLen);
memcpy(pData, _sData.getStr(), nByteLen);
}
else
{
pData = allocBindBuf(parameterIndex, _sData.getLength() * 4);
sal_uInt32* pCursor = static_cast<sal_uInt32*>(pData);
nCharLen = 0;
for (sal_Int32 i = 0; i != _sData.getLength();)
{
*pCursor++ = _sData.iterateCodePoints(&i);
nCharLen += 1;
}
nByteLen = 4 * nCharLen;
}
SQLWChars data(_sData);
nCharLen = data.cch();
nByteLen = data.cb();
pData = allocBindBuf(parameterIndex, nByteLen);
memcpy(pData, data.get(), nByteLen);
}
else
{
assert(getOwnConnection()->getTextEncoding() != RTL_TEXTENCODING_UCS2 &&
getOwnConnection()->getTextEncoding() != RTL_TEXTENCODING_UCS4);
OString sOData(
OUStringToOString(_sData, getOwnConnection()->getTextEncoding()));
nCharLen = nByteLen = sOData.getLength();
SQLChars data(_sData, getOwnConnection()->getTextEncoding());
nCharLen = data.cch();
nByteLen = data.cb();
pData = allocBindBuf(parameterIndex, nByteLen);
memcpy(pData, sOData.getStr(), nByteLen);
memcpy(pData, data.get(), nByteLen);
}
setParameter( parameterIndex, _nType, nCharLen, _nScale, pData, nByteLen, nByteLen );
@ -367,7 +344,7 @@ void OPreparedStatement::setParameter(const sal_Int32 parameterIndex, const sal_
void 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)
{
SQLSMALLINT fCType, fSqlType;
OTools::getBindTypes(bUseWChar, m_pConnection->useOldDateFormat(), OTools::jdbcTypeToOdbc(_nType), fCType, fSqlType);
OTools::getBindTypes(m_pConnection->useOldDateFormat(), OTools::jdbcTypeToOdbc(_nType), fCType, fSqlType);
SQLLEN& rDataLen = boundParams[parameterIndex-1].getBindLengthBuffer();
rDataLen = _nDataLen;
@ -507,8 +484,7 @@ void SAL_CALL OPreparedStatement::setNull( sal_Int32 parameterIndex, const sal_I
SQLSMALLINT fCType;
SQLSMALLINT fSqlType;
OTools::getBindTypes( bUseWChar,
m_pConnection->useOldDateFormat(),
OTools::getBindTypes( m_pConnection->useOldDateFormat(),
OTools::jdbcTypeToOdbc(_nType),
fCType,
fSqlType);
@ -819,7 +795,7 @@ void OPreparedStatement::setStream(
*lenBuf = SQL_LEN_DATA_AT_EXEC (length);
SQLSMALLINT fCType, fSqlType;
OTools::getBindTypes(bUseWChar, m_pConnection->useOldDateFormat(), OTools::jdbcTypeToOdbc(_nType), fCType, fSqlType);
OTools::getBindTypes(m_pConnection->useOldDateFormat(), OTools::jdbcTypeToOdbc(_nType), fCType, fSqlType);
OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
@ -882,8 +858,17 @@ void OPreparedStatement::prepareStatement()
if(!isPrepared())
{
OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
OString aSql(OUStringToOString(m_sSqlStatement,getOwnConnection()->getTextEncoding()));
SQLRETURN nReturn = functions().Prepare(m_aStatementHandle, reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(aSql.getStr())), aSql.getLength());
SQLRETURN nReturn;
if (bUseWChar && functions().has(ODBC3SQLFunctionId::PrepareW))
{
SQLWChars aSql(m_sSqlStatement);
nReturn = functions().PrepareW(m_aStatementHandle, aSql.get(), aSql.cch());
}
else
{
SQLChars aSql(m_sSqlStatement, getOwnConnection()->getTextEncoding());
nReturn = functions().Prepare(m_aStatementHandle, aSql.get(), aSql.cch());
}
OTools::ThrowException(m_pConnection.get(),nReturn,m_aStatementHandle,SQL_HANDLE_STMT,*this);
m_bPrepared = true;
initBoundParam();

View file

@ -31,6 +31,7 @@
#include <cppuhelper/typeprovider.hxx>
#include <cppuhelper/supportsservice.hxx>
#include <comphelper/types.hxx>
#include <comphelper/scopeguard.hxx>
#include <connectivity/dbtools.hxx>
#include <connectivity/dbexception.hxx>
#include <o3tl/safeint.hxx>
@ -55,11 +56,77 @@ static_assert(ODBC_SQL_NOT_DEFINED != SQL_UB_ON, "ODBC_SQL_NOT_DEFINED must be u
static_assert(ODBC_SQL_NOT_DEFINED != SQL_UB_FIXED, "ODBC_SQL_NOT_DEFINED must be unique");
static_assert(ODBC_SQL_NOT_DEFINED != SQL_UB_VARIABLE, "ODBC_SQL_NOT_DEFINED must be unique");
class connectivity::odbc::BindData
{
public:
virtual void* data() = 0;
virtual SQLLEN len() const = 0;
virtual ~BindData() {}
};
namespace
{
const SQLLEN nMaxBookmarkLen = 20;
}
const SQLLEN nMaxBookmarkLen = 20;
template <typename T> class SimpleBindData : public connectivity::odbc::BindData
{
public:
SimpleBindData(const void* p)
: value(*static_cast<const T*>(p))
{
}
void* data() override { return &value; }
SQLLEN len() const override { return sizeof(T); }
private:
T value;
};
template <class CHARS_t> class CharsBindData : public connectivity::odbc::BindData
{
public:
template <typename... Args>
CharsBindData(const void* p, Args... args)
: value(*static_cast<const OUString*>(p), args...)
{
}
template <class S> requires std::is_class_v<S>
CharsBindData(const S& val)
: value(val)
{
}
void* data() override { return value.get(); }
SQLLEN len() const override { return value.cch(); }
private:
CHARS_t value;
};
class NullBindData : public connectivity::odbc::BindData
{
public:
void* data() override { return &value; }
SQLLEN len() const override { return SQL_NULL_DATA; }
private:
char value[2] = {};
};
class BinaryBindData : public connectivity::odbc::BindData
{
public:
BinaryBindData(const void* p)
: value(*static_cast<const css::uno::Sequence<sal_Int8>*>(p))
{
}
void* data() override { return const_cast<sal_Int8*>(value.getConstArray()); }
SQLLEN len() const override { return value.getLength(); }
private:
css::uno::Sequence<sal_Int8> value; // ref-counted CoW
};
}
// IMPLEMENT_SERVICE_INFO(OResultSet,"com.sun.star.sdbcx.OResultSet","com.sun.star.sdbc.ResultSet");
OUString SAL_CALL OResultSet::getImplementationName( )
@ -180,135 +247,17 @@ void OResultSet::disposing()
m_xMetaData.clear();
}
// See OResultSet::updateValue
SQLRETURN OResultSet::unbind(bool _bUnbindHandle)
{
SQLRETURN nRet = 0;
if ( _bUnbindHandle )
nRet = functions().FreeStmt(m_aStatementHandle,SQL_UNBIND);
if ( !m_aBindVector.empty() )
{
for(auto& [rPtrAddr, rType] : m_aBindVector)
{
switch (rType)
{
case DataType::CHAR:
case DataType::VARCHAR:
delete static_cast< OString* >(reinterpret_cast< void * >(rPtrAddr));
break;
case DataType::BIGINT:
delete static_cast< sal_Int64* >(reinterpret_cast< void * >(rPtrAddr));
break;
case DataType::DECIMAL:
case DataType::NUMERIC:
delete static_cast< OString* >(reinterpret_cast< void * >(rPtrAddr));
break;
case DataType::REAL:
case DataType::DOUBLE:
delete static_cast< double* >(reinterpret_cast< void * >(rPtrAddr));
break;
case DataType::LONGVARCHAR:
case DataType::CLOB:
delete [] static_cast< char* >(reinterpret_cast< void * >(rPtrAddr));
break;
case DataType::LONGVARBINARY:
case DataType::BLOB:
delete [] static_cast< char* >(reinterpret_cast< void * >(rPtrAddr));
break;
case DataType::DATE:
delete static_cast< DATE_STRUCT* >(reinterpret_cast< void * >(rPtrAddr));
break;
case DataType::TIME:
delete static_cast< TIME_STRUCT* >(reinterpret_cast< void * >(rPtrAddr));
break;
case DataType::TIMESTAMP:
delete static_cast< TIMESTAMP_STRUCT* >(reinterpret_cast< void * >(rPtrAddr));
break;
case DataType::BIT:
case DataType::TINYINT:
delete static_cast< sal_Int8* >(reinterpret_cast< void * >(rPtrAddr));
break;
case DataType::SMALLINT:
delete static_cast< sal_Int16* >(reinterpret_cast< void * >(rPtrAddr));
break;
case DataType::INTEGER:
delete static_cast< sal_Int32* >(reinterpret_cast< void * >(rPtrAddr));
break;
case DataType::FLOAT:
delete static_cast< float* >(reinterpret_cast< void * >(rPtrAddr));
break;
case DataType::BINARY:
case DataType::VARBINARY:
delete static_cast< sal_Int8* >(reinterpret_cast< void * >(rPtrAddr));
break;
}
}
m_aBindVector.clear();
}
m_aBindVector.clear();
return nRet;
}
TVoidPtr OResultSet::allocBindColumn(sal_Int32 _nType,sal_Int32 _nColumnIndex)
{
TVoidPtr aPair;
switch (_nType)
{
case DataType::CHAR:
case DataType::VARCHAR:
aPair = TVoidPtr(reinterpret_cast< sal_Int64 >(new OString()),_nType);
break;
case DataType::BIGINT:
aPair = TVoidPtr(reinterpret_cast< sal_Int64 >(new sal_Int64(0)),_nType);
break;
case DataType::DECIMAL:
case DataType::NUMERIC:
aPair = TVoidPtr(reinterpret_cast< sal_Int64 >(new OString()),_nType);
break;
case DataType::REAL:
case DataType::DOUBLE:
aPair = TVoidPtr(reinterpret_cast< sal_Int64 >(new double(0.0)),_nType);
break;
case DataType::LONGVARCHAR:
case DataType::CLOB:
aPair = TVoidPtr(reinterpret_cast< sal_Int64 >(new char[2]),_nType); // only for finding
break;
case DataType::LONGVARBINARY:
case DataType::BLOB:
aPair = TVoidPtr(reinterpret_cast< sal_Int64 >(new char[2]),_nType); // only for finding
break;
case DataType::DATE:
aPair = TVoidPtr(reinterpret_cast< sal_Int64 >(new DATE_STRUCT),_nType);
break;
case DataType::TIME:
aPair = TVoidPtr(reinterpret_cast< sal_Int64 >(new TIME_STRUCT),_nType);
break;
case DataType::TIMESTAMP:
aPair = TVoidPtr(reinterpret_cast< sal_Int64 >(new TIMESTAMP_STRUCT),_nType);
break;
case DataType::BIT:
case DataType::TINYINT:
aPair = TVoidPtr(reinterpret_cast< sal_Int64 >(new sal_Int8(0)),_nType);
break;
case DataType::SMALLINT:
aPair = TVoidPtr(reinterpret_cast< sal_Int64 >(new sal_Int16(0)),_nType);
break;
case DataType::INTEGER:
aPair = TVoidPtr(reinterpret_cast< sal_Int64 >(new sal_Int32(0)),_nType);
break;
case DataType::FLOAT:
aPair = TVoidPtr(reinterpret_cast< sal_Int64 >(new float(0)),_nType);
break;
case DataType::BINARY:
case DataType::VARBINARY:
aPair = TVoidPtr(reinterpret_cast< sal_Int64 >(new sal_Int8[m_aRow[_nColumnIndex].getSequence().getLength()]),_nType);
break;
default:
SAL_WARN( "connectivity.odbc", "Unknown type");
aPair = TVoidPtr(0,_nType);
}
return aPair;
}
void OResultSet::allocBuffer()
{
Reference< XResultSetMetaData > xMeta = getMetaData();
@ -852,18 +801,9 @@ void SAL_CALL OResultSet::insertRow( )
fillNeededData( nRet );
}
aBookmark.realloc(nRealLen);
try
{
OTools::ThrowException(m_pStatement->getOwnConnection(),nRet,m_aStatementHandle,SQL_HANDLE_STMT,*this);
}
catch(const SQLException&)
{
nRet = unbind();
throw;
}
nRet = unbind();
SQLRETURN nRet2 = unbind();
OTools::ThrowException(m_pStatement->getOwnConnection(),nRet,m_aStatementHandle,SQL_HANDLE_STMT,*this);
OTools::ThrowException(m_pStatement->getOwnConnection(),nRet2,m_aStatementHandle,SQL_HANDLE_STMT,*this);
if ( bPositionByBookmark )
{
@ -996,30 +936,115 @@ void OResultSet::updateValue(sal_Int32 columnIndex, SQLSMALLINT _nType, void con
::osl::MutexGuard aGuard( m_aMutex );
checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
m_aBindVector.push_back(allocBindColumn(OTools::MapOdbcType2Jdbc(_nType),columnIndex));
void* pData = reinterpret_cast<void*>(m_aBindVector.rbegin()->first);
OSL_ENSURE(pData != nullptr,"Data for update is NULL!");
OTools::bindValue( m_pStatement->getOwnConnection(),
m_aStatementHandle,
columnIndex,
_nType,
0,
_pValue,
pData,
&m_aLengthVector[columnIndex],
**this,
m_nTextEncoding,
m_pStatement->getOwnConnection()->useOldDateFormat());
SQLSMALLINT fCType, dummy;
OTools::getBindTypes(m_pStatement->getOwnConnection()->useOldDateFormat(), _nType, fCType,
dummy);
SQLLEN* const pLen = &m_aLengthVector[columnIndex];
*pLen = 0;
std::unique_ptr<BindData> bindData;
void* pData = nullptr;
if (columnIndex != 0 && !_pValue)
{
bindData = std::make_unique<NullBindData>();
}
else
{
assert(_pValue);
switch (_nType)
{
case SQL_CHAR:
case SQL_VARCHAR:
case SQL_WCHAR:
case SQL_WVARCHAR:
if (fCType == SQL_C_CHAR)
bindData = std::make_unique<CharsBindData<SQLChars>>(_pValue, m_nTextEncoding);
else
bindData = std::make_unique<CharsBindData<SQLWChars>>(_pValue);
break;
case SQL_DECIMAL:
case SQL_NUMERIC:
if (fCType == SQL_C_CHAR)
bindData = std::make_unique<CharsBindData<SQLChars>>(
OString::number(*static_cast<const double*>(_pValue)));
else
bindData = std::make_unique<CharsBindData<SQLWChars>>(
OUString::number(*static_cast<const double*>(_pValue)));
break;
case SQL_BIT:
case SQL_TINYINT:
bindData = std::make_unique<SimpleBindData<sal_Int8>>(_pValue);
break;
case SQL_SMALLINT:
bindData = std::make_unique<SimpleBindData<sal_Int16>>(_pValue);
break;
case SQL_INTEGER:
bindData = std::make_unique<SimpleBindData<sal_Int32>>(_pValue);
break;
case SQL_BIGINT:
bindData = std::make_unique<SimpleBindData<sal_Int64>>(_pValue);
break;
case SQL_FLOAT:
bindData = std::make_unique<SimpleBindData<float>>(_pValue);
break;
case SQL_REAL:
case SQL_DOUBLE:
bindData = std::make_unique<SimpleBindData<double>>(_pValue);
break;
case SQL_BINARY:
case SQL_VARBINARY:
bindData = std::make_unique<BinaryBindData>(_pValue);
break;
case SQL_LONGVARBINARY:
{
/* see https://msdn.microsoft.com/en-us/library/ms716238%28v=vs.85%29.aspx
* for an explanation of that apparently weird cast */
pData = reinterpret_cast<void*>(static_cast<sal_uIntPtr>(columnIndex));
sal_Int32 nLen
= static_cast<const css::uno::Sequence<sal_Int8>*>(_pValue)->getLength();
*pLen = SQL_LEN_DATA_AT_EXEC(nLen);
}
break;
case SQL_LONGVARCHAR:
case SQL_WLONGVARCHAR:
{
/* see https://msdn.microsoft.com/en-us/library/ms716238%28v=vs.85%29.aspx
* for an explanation of that apparently weird cast */
pData = reinterpret_cast<void*>(static_cast<sal_uIntPtr>(columnIndex));
sal_Int32 nLen = static_cast<const OUString*>(_pValue)->getLength();
*pLen = SQL_LEN_DATA_AT_EXEC(nLen);
}
break;
case SQL_DATE:
bindData = std::make_unique<SimpleBindData<DATE_STRUCT>>(_pValue);
break;
case SQL_TIME:
bindData = std::make_unique<SimpleBindData<TIME_STRUCT>>(_pValue);
break;
case SQL_TIMESTAMP:
bindData = std::make_unique<SimpleBindData<TIMESTAMP_STRUCT>>(_pValue);
break;
}
}
if (bindData)
{
pData = bindData->data();
*pLen = bindData->len();
m_aBindVector.push_back(std::move(bindData));
}
SQLRETURN nRetcode
= functions().BindCol(m_aStatementHandle, columnIndex, fCType, pData, 0, pLen);
OTools::ThrowException(m_pStatement->getOwnConnection(), nRetcode, m_aStatementHandle,
SQL_HANDLE_STMT, **this);
}
void SAL_CALL OResultSet::updateNull( sal_Int32 columnIndex )
{
::osl::MutexGuard aGuard( m_aMutex );
checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
m_aBindVector.push_back(allocBindColumn(DataType::CHAR,columnIndex));
void* pData = reinterpret_cast<void*>(m_aBindVector.rbegin()->first);
OTools::bindValue(m_pStatement->getOwnConnection(),m_aStatementHandle,columnIndex,SQL_CHAR,0,nullptr,pData,&m_aLengthVector[columnIndex],**this,m_nTextEncoding,m_pStatement->getOwnConnection()->useOldDateFormat());
updateValue(columnIndex, SQL_CHAR, nullptr);
}
@ -1320,10 +1345,19 @@ sal_Int32 OResultSet::getFetchSize() const
OUString OResultSet::getCursorName() const
{
SQLCHAR pName[258];
SQLSMALLINT nRealLen = 0;
functions().GetCursorName(m_aStatementHandle,pName,256,&nRealLen);
return OUString::createFromAscii(reinterpret_cast<char*>(pName));
if (bUseWChar && functions().has(ODBC3SQLFunctionId::GetCursorNameW))
{
SQLWCHAR pName[258]{};
functions().GetCursorNameW(m_aStatementHandle, pName, 256, &nRealLen);
return toUString(pName, nRealLen);
}
else
{
SQLCHAR pName[258]{};
functions().GetCursorName(m_aStatementHandle, pName, 256, &nRealLen);
return toUString(pName);
}
}
bool OResultSet::isBookmarkable() const
@ -1793,16 +1827,15 @@ void OResultSet::fillNeededData(SQLRETURN _nRet)
break;
case SQL_WLONGVARCHAR:
{
OUString const & sRet = m_aRow[nColumnIndex].getString();
functions().PutData (m_aStatementHandle, static_cast<SQLPOINTER>(const_cast<sal_Unicode *>(sRet.getStr())), sizeof(sal_Unicode)*sRet.getLength());
SQLWChars data(m_aRow[nColumnIndex].getString());
functions().PutData(m_aStatementHandle, data.get(), data.cb());
break;
}
case DataType::LONGVARCHAR:
case DataType::CLOB:
{
OUString sRet = m_aRow[nColumnIndex].getString();
OString aString(OUStringToOString(sRet,m_nTextEncoding));
functions().PutData (m_aStatementHandle, static_cast<SQLPOINTER>(const_cast<char *>(aString.getStr())), aString.getLength());
SQLChars data(m_aRow[nColumnIndex].getString(), m_nTextEncoding);
functions().PutData(m_aStatementHandle, data.get(), data.cb());
break;
}
default:

View file

@ -35,40 +35,77 @@ OUString OResultSetMetaData::getCharColAttrib(sal_Int32 _column,sal_Int32 ident)
if(_column <static_cast<sal_Int32>(m_vMapping.size())) // use mapping
column = m_vMapping[_column];
SQLSMALLINT BUFFER_LEN = 128;
std::unique_ptr<char[]> pName(new char[BUFFER_LEN+1]);
SQLSMALLINT nRealLen=0;
SQLRETURN nRet = functions().ColAttribute(m_aStatementHandle,
static_cast<SQLUSMALLINT>(column),
static_cast<SQLUSMALLINT>(ident),
static_cast<SQLPOINTER>(pName.get()),
BUFFER_LEN,
&nRealLen,
nullptr
);
OUString sValue;
if ( nRet == SQL_SUCCESS )
SQLSMALLINT cbRealLen = 0;
if (bUseWChar && functions().has(ODBC3SQLFunctionId::ColAttributeW))
{
if ( nRealLen < 0 )
nRealLen = BUFFER_LEN;
sValue = OUString(pName.get(),nRealLen,m_pConnection->getTextEncoding());
// SQLColAttributeW gets/returns count of bytes, not characters
SQLSMALLINT cbBufferLen = 128 * sizeof(SQLWCHAR);
auto pName = std::make_unique<SQLWCHAR[]>(cbBufferLen / sizeof(SQLWCHAR) + 1);
SQLRETURN nRet = functions().ColAttributeW(m_aStatementHandle,
column,
ident,
pName.get(),
cbBufferLen,
&cbRealLen,
nullptr);
OTools::ThrowException(m_pConnection, nRet, m_aStatementHandle, SQL_HANDLE_STMT, *this);
if (nRet == SQL_SUCCESS)
{
if (cbRealLen < 0)
cbRealLen = cbBufferLen;
sValue = toUString(pName.get(), cbRealLen / sizeof(SQLWCHAR));
}
if (cbRealLen > cbBufferLen)
{
cbBufferLen = (cbRealLen + 1) & ~1; // Make sure it's even
pName = std::make_unique<SQLWCHAR[]>(cbBufferLen / sizeof(SQLWCHAR) + 1);
nRet = functions().ColAttributeW(m_aStatementHandle,
column,
ident,
pName.get(),
cbBufferLen,
&cbRealLen,
nullptr);
OTools::ThrowException(m_pConnection, nRet, m_aStatementHandle, SQL_HANDLE_STMT, *this);
if (nRet == SQL_SUCCESS && cbRealLen > 0)
sValue = toUString(pName.get(), cbRealLen / sizeof(SQLWCHAR));
}
}
pName.reset();
OTools::ThrowException(m_pConnection,nRet,m_aStatementHandle,SQL_HANDLE_STMT,*this);
if(nRealLen > BUFFER_LEN)
else
{
pName.reset(new char[nRealLen+1]);
nRet = functions().ColAttribute(m_aStatementHandle,
static_cast<SQLUSMALLINT>(column),
static_cast<SQLUSMALLINT>(ident),
static_cast<SQLPOINTER>(pName.get()),
nRealLen,
&nRealLen,
nullptr
);
if ( nRet == SQL_SUCCESS && nRealLen > 0)
sValue = OUString(pName.get(),nRealLen,m_pConnection->getTextEncoding());
SQLSMALLINT BUFFER_LEN = 128;
auto pName = std::make_unique<SQLCHAR[]>(BUFFER_LEN + 1);
SQLRETURN nRet = functions().ColAttribute(m_aStatementHandle,
static_cast<SQLUSMALLINT>(column),
static_cast<SQLUSMALLINT>(ident),
static_cast<SQLPOINTER>(pName.get()),
BUFFER_LEN,
&cbRealLen,
nullptr
);
if ( nRet == SQL_SUCCESS )
{
if ( cbRealLen < 0 )
cbRealLen = BUFFER_LEN;
sValue = toUString(pName.get(), cbRealLen, m_pConnection->getTextEncoding());
}
OTools::ThrowException(m_pConnection,nRet,m_aStatementHandle,SQL_HANDLE_STMT,*this);
if(cbRealLen > BUFFER_LEN)
{
pName = std::make_unique<SQLCHAR[]>(cbRealLen + 1);
nRet = functions().ColAttribute(m_aStatementHandle,
static_cast<SQLUSMALLINT>(column),
static_cast<SQLUSMALLINT>(ident),
static_cast<SQLPOINTER>(pName.get()),
cbRealLen,
&cbRealLen,
nullptr
);
if ( nRet == SQL_SUCCESS && cbRealLen > 0)
sValue = toUString(pName.get(), cbRealLen, m_pConnection->getTextEncoding());
OTools::ThrowException(m_pConnection,nRet,m_aStatementHandle,SQL_HANDLE_STMT,*this);
}
}
return sValue;
@ -143,11 +180,10 @@ sal_Int32 SAL_CALL OResultSetMetaData::getColumnType( sal_Int32 column )
catch(SQLException& ) // in this case we have an odbc 2.0 driver
{
m_bUseODBC2Types = true;
nType = OTools::MapOdbcType2Jdbc(getNumColAttrib(column,SQL_DESC_CONCISE_TYPE ));
}
}
else
nType = OTools::MapOdbcType2Jdbc(getNumColAttrib(column,SQL_DESC_CONCISE_TYPE ));
if (m_bUseODBC2Types)
nType = OTools::MapOdbcType2Jdbc(getNumColAttrib(column, SQL_DESC_CONCISE_TYPE));
aFind = m_aColumnTypes.emplace(column,nType).first;
}
@ -230,30 +266,38 @@ sal_Bool SAL_CALL OResultSetMetaData::isSigned( sal_Int32 column )
sal_Int32 SAL_CALL OResultSetMetaData::getPrecision( sal_Int32 column )
{
sal_Int32 nType = 0;
try
if (!m_bUseODBC2Types)
{
nType = getNumColAttrib(column,SQL_DESC_PRECISION);
}
catch(const SQLException& ) // in this case we have an odbc 2.0 driver
{
m_bUseODBC2Types = true;
nType = getNumColAttrib(column,SQL_COLUMN_PRECISION );
try
{
nType = getNumColAttrib(column, SQL_DESC_PRECISION);
}
catch (const SQLException&) // in this case we have an odbc 2.0 driver
{
m_bUseODBC2Types = true;
}
}
if (m_bUseODBC2Types)
nType = getNumColAttrib(column, SQL_COLUMN_PRECISION);
return nType;
}
sal_Int32 SAL_CALL OResultSetMetaData::getScale( sal_Int32 column )
{
sal_Int32 nType = 0;
try
if (!m_bUseODBC2Types)
{
nType = getNumColAttrib(column,SQL_DESC_SCALE);
}
catch(const SQLException& ) // in this case we have an odbc 2.0 driver
{
m_bUseODBC2Types = true;
nType = getNumColAttrib(column,SQL_COLUMN_SCALE );
try
{
nType = getNumColAttrib(column, SQL_DESC_SCALE);
}
catch (const SQLException&) // in this case we have an odbc 2.0 driver
{
m_bUseODBC2Types = true;
}
}
if (m_bUseODBC2Types)
nType = getNumColAttrib(column, SQL_COLUMN_SCALE);
return nType;
}

View file

@ -314,9 +314,6 @@ sal_Bool SAL_CALL OStatement_Base::execute( const OUString& sql )
checkDisposed(OStatement_BASE::rBHelper.bDisposed);
m_sSqlStatement = sql;
OString aSql(OUStringToOString(sql,getOwnConnection()->getTextEncoding()));
bool hasResultSet = false;
// Reset the statement handle and warning
@ -332,15 +329,24 @@ sal_Bool SAL_CALL OStatement_Base::execute( const OUString& sql )
OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
try {
THROW_SQL(functions().ExecDirect(m_aStatementHandle, reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(aSql.getStr())), aSql.getLength()));
if (bUseWChar && functions().has(ODBC3SQLFunctionId::ExecDirectW))
{
SQLWChars directSQL(sql);
THROW_SQL(functions().ExecDirectW(m_aStatementHandle, directSQL.get(), directSQL.cch()));
}
else
{
SQLChars directSQL(sql, getOwnConnection()->getTextEncoding());
THROW_SQL(functions().ExecDirect(m_aStatementHandle, directSQL.get(), directSQL.cch()));
}
}
catch (const SQLWarning&) {
catch (const SQLWarning&)
{
//TODO: Save pointer to warning and save with ResultSet
// object once it is created.
}
// Now determine if there is a result set associated with
// Now determine if there is a result set associated with
// the SQL statement that was executed. Get the column
// count, and if it is not zero, there is a result set.
@ -470,19 +476,22 @@ Sequence< sal_Int32 > SAL_CALL OStatement::executeBatch( )
::osl::MutexGuard aGuard( m_aMutex );
checkDisposed(OStatement_BASE::rBHelper.bDisposed);
OStringBuffer aBatchSql;
sal_Int32 nLen = m_aBatchVector.size();
for (auto const& elem : m_aBatchVector)
{
aBatchSql.append(OUStringToOString(elem,getOwnConnection()->getTextEncoding())
+ ";");
}
OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
auto s = aBatchSql.makeStringAndClear();
THROW_SQL(functions().ExecDirect(m_aStatementHandle, reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(s.getStr())), s.getLength()));
OUStringBuffer uSql;
comphelper::intersperse(m_aBatchVector.begin(), m_aBatchVector.end(), comphelper::OUStringBufferAppender(uSql), u";");
if (bUseWChar && functions().has(ODBC3SQLFunctionId::ExecDirectW))
{
SQLWChars statement(uSql.makeStringAndClear());
THROW_SQL(functions().ExecDirectW(m_aStatementHandle, statement.get(), statement.cch()));
}
else
{
SQLChars statement(uSql, getOwnConnection()->getTextEncoding());
THROW_SQL(functions().ExecDirect(m_aStatementHandle, statement.get(), statement.cch()));
}
Sequence< sal_Int32 > aRet(nLen);
sal_Int32* pArray = aRet.getArray();
for(sal_Int32 j=0;j<nLen;++j)
@ -702,10 +711,19 @@ sal_Int64 OStatement_Base::getMaxFieldSize() const
OUString OStatement_Base::getCursorName() const
{
OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
SQLCHAR pName[258];
SQLSMALLINT nRealLen = 0;
functions().GetCursorName(m_aStatementHandle,pName,256,&nRealLen);
return OUString::createFromAscii(reinterpret_cast<char*>(pName));
if (bUseWChar && functions().has(ODBC3SQLFunctionId::GetCursorNameW))
{
SQLWCHAR pName[258]{};
functions().GetCursorNameW(m_aStatementHandle, pName, 256, &nRealLen);
return toUString(pName, nRealLen);
}
else
{
SQLCHAR pName[258]{};
functions().GetCursorName(m_aStatementHandle, pName, 256, &nRealLen);
return toUString(pName);
}
}
void OStatement_Base::setQueryTimeOut(sal_Int64 seconds)
@ -829,11 +847,19 @@ void OStatement_Base::setMaxFieldSize(sal_Int64 _par0)
setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_MAX_LENGTH, _par0);
}
void OStatement_Base::setCursorName(std::u16string_view _par0)
void OStatement_Base::setCursorName(const OUString& _par0)
{
OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
OString aName(OUStringToOString(_par0,getOwnConnection()->getTextEncoding()));
functions().SetCursorName(m_aStatementHandle, reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(aName.getStr())), static_cast<SQLSMALLINT>(aName.getLength()));
if (bUseWChar && functions().has(ODBC3SQLFunctionId::SetCursorNameW))
{
SQLWChars name(_par0);
functions().SetCursorNameW(m_aStatementHandle, name.get(), name.cch());
}
else
{
SQLChars name(_par0, getOwnConnection()->getTextEncoding());
functions().SetCursorName(m_aStatementHandle, name.get(), name.cch());
}
}
bool OStatement_Base::isUsingBookmarks() const

View file

@ -115,7 +115,7 @@ void appendSQLWCHARs(OUStringBuffer & s, SQLWCHAR const * d, sal_Int32 n)
if (sizeof (SQLWCHAR) == sizeof (sal_Unicode)) {
s.append(reinterpret_cast<sal_Unicode const *>(d), n);
} else {
for (sal_Int32 i = 0; i != n; ++i) {
for (sal_Int32 i = 0; i < n; ++i) {
s.appendUtf32(d[i]);
}
}
@ -161,144 +161,6 @@ void OTools::getValue( OConnection const * _pConnection,
_bWasNull = pcbValue == SQL_NULL_DATA;
}
void OTools::bindValue( OConnection const * _pConnection,
SQLHANDLE _aStatementHandle,
sal_Int32 columnIndex,
SQLSMALLINT _nType,
SQLSMALLINT _nMaxLen,
const void* _pValue,
void* _pData,
SQLLEN * const pLen,
const css::uno::Reference< css::uno::XInterface >& _xInterface,
rtl_TextEncoding _nTextEncoding,
bool _bUseOldTimeDate)
{
SQLRETURN nRetcode;
SQLSMALLINT fSqlType;
SQLSMALLINT fCType;
OTools::getBindTypes( false,
_bUseOldTimeDate,
_nType,
fCType,
fSqlType);
if (columnIndex != 0 && !_pValue)
{
*pLen = SQL_NULL_DATA;
nRetcode = _pConnection->functions().BindCol(_aStatementHandle,
static_cast<SQLUSMALLINT>(columnIndex),
fCType,
_pData,
_nMaxLen,
pLen
);
}
else
{
try
{
switch (_nType)
{
case SQL_CHAR:
case SQL_VARCHAR:
{
OString aString(OUStringToOString(*static_cast<OUString const *>(_pValue),_nTextEncoding));
*pLen = SQL_NTS;
*static_cast<OString*>(_pData) = aString;
// Pointer on Char*
_pData = const_cast<char *>(aString.getStr());
} break;
case SQL_BIGINT:
*static_cast<sal_Int64*>(_pData) = *static_cast<sal_Int64 const *>(_pValue);
*pLen = sizeof(sal_Int64);
break;
case SQL_DECIMAL:
case SQL_NUMERIC:
{
OString aString = OString::number(*static_cast<double const *>(_pValue));
*pLen = static_cast<SQLSMALLINT>(aString.getLength());
*static_cast<OString*>(_pData) = aString;
// Pointer on Char*
_pData = const_cast<char *>(static_cast<OString*>(_pData)->getStr());
} break;
case SQL_BIT:
case SQL_TINYINT:
*static_cast<sal_Int8*>(_pData) = *static_cast<sal_Int8 const *>(_pValue);
*pLen = sizeof(sal_Int8);
break;
case SQL_SMALLINT:
*static_cast<sal_Int16*>(_pData) = *static_cast<sal_Int16 const *>(_pValue);
*pLen = sizeof(sal_Int16);
break;
case SQL_INTEGER:
*static_cast<sal_Int32*>(_pData) = *static_cast<sal_Int32 const *>(_pValue);
*pLen = sizeof(sal_Int32);
break;
case SQL_FLOAT:
*static_cast<float*>(_pData) = *static_cast<float const *>(_pValue);
*pLen = sizeof(float);
break;
case SQL_REAL:
case SQL_DOUBLE:
*static_cast<double*>(_pData) = *static_cast<double const *>(_pValue);
*pLen = sizeof(double);
break;
case SQL_BINARY:
case SQL_VARBINARY:
{
_pData = const_cast<sal_Int8 *>(static_cast<const css::uno::Sequence< sal_Int8 > *>(_pValue)->getConstArray());
*pLen = static_cast<const css::uno::Sequence< sal_Int8 > *>(_pValue)->getLength();
} break;
case SQL_LONGVARBINARY:
{
/* see https://msdn.microsoft.com/en-us/library/ms716238%28v=vs.85%29.aspx
* for an explanation of that apparently weird cast */
_pData = reinterpret_cast<void*>(static_cast<uintptr_t>(columnIndex));
sal_Int32 nLen = static_cast<const css::uno::Sequence< sal_Int8 > *>(_pValue)->getLength();
*pLen = static_cast<SQLLEN>(SQL_LEN_DATA_AT_EXEC(nLen));
}
break;
case SQL_LONGVARCHAR:
{
/* see https://msdn.microsoft.com/en-us/library/ms716238%28v=vs.85%29.aspx
* for an explanation of that apparently weird cast */
_pData = reinterpret_cast<void*>(static_cast<uintptr_t>(columnIndex));
sal_Int32 nLen = static_cast<OUString const *>(_pValue)->getLength();
*pLen = static_cast<SQLLEN>(SQL_LEN_DATA_AT_EXEC(nLen));
} break;
case SQL_DATE:
*pLen = sizeof(DATE_STRUCT);
*static_cast<DATE_STRUCT*>(_pData) = *static_cast<DATE_STRUCT const *>(_pValue);
break;
case SQL_TIME:
*pLen = sizeof(TIME_STRUCT);
*static_cast<TIME_STRUCT*>(_pData) = *static_cast<TIME_STRUCT const *>(_pValue);
break;
case SQL_TIMESTAMP:
*pLen = sizeof(TIMESTAMP_STRUCT);
*static_cast<TIMESTAMP_STRUCT*>(_pData) = *static_cast<TIMESTAMP_STRUCT const *>(_pValue);
break;
}
}
catch ( ... )
{
}
nRetcode = _pConnection->functions().BindCol(_aStatementHandle,
static_cast<SQLUSMALLINT>(columnIndex),
fCType,
_pData,
_nMaxLen,
pLen
);
}
OTools::ThrowException(_pConnection,nRetcode,_aStatementHandle,SQL_HANDLE_STMT,_xInterface);
}
void OTools::ThrowException(const OConnection* _pConnection,
const SQLRETURN _rRetCode,
const SQLHANDLE _pContext,
@ -328,11 +190,10 @@ void OTools::ThrowException(const OConnection* _pConnection,
// Additional Information on the latest ODBC-functioncall available
// SQLError provides this Information.
SDB_ODBC_CHAR szSqlState[5];
OUString errorMessage;
OUString sqlState;
SQLINTEGER pfNativeError;
SDB_ODBC_CHAR szErrorMessage[SQL_MAX_MESSAGE_LENGTH];
szErrorMessage[0] = '\0';
SQLSMALLINT pcbErrorMsg = 0;
SQLRETURN n;
// Information for latest operation:
// when hstmt != SQL_NULL_HSTMT is (Used from SetStatus in SdbCursor, SdbTable, ...),
@ -340,22 +201,40 @@ void OTools::ThrowException(const OConnection* _pConnection,
// statements of this connection [what in this case will probably be the same, but the Reference
// Manual isn't totally clear in this...].
// corresponding for hdbc.
SQLRETURN n = _pConnection->functions().GetDiagRec(_nHandleType,_pContext,1,
if (bUseWChar && _pConnection->functions().has(ODBC3SQLFunctionId::GetDiagRecW))
{
SQLWCHAR szSqlState[5];
SQLWCHAR szErrorMessage[SQL_MAX_MESSAGE_LENGTH];
szErrorMessage[0] = '\0';
SQLSMALLINT cchErrorMsg = 0;
n = _pConnection->functions().GetDiagRecW(_nHandleType,_pContext,1,
szSqlState,
&pfNativeError,
szErrorMessage, std::size(szErrorMessage) - 1, &cchErrorMsg);
errorMessage = toUString(szErrorMessage, cchErrorMsg);
sqlState = toUString(szSqlState, std::size(szSqlState));
}
else
{
SQLCHAR szSqlState[5];
SQLCHAR szErrorMessage[SQL_MAX_MESSAGE_LENGTH];
szErrorMessage[0] = '\0';
SQLSMALLINT pcbErrorMsg = 0;
n = _pConnection->functions().GetDiagRec(_nHandleType,_pContext,1,
szSqlState,
&pfNativeError,
szErrorMessage,sizeof szErrorMessage - 1,&pcbErrorMsg);
rtl_TextEncoding _nTextEncoding = osl_getThreadTextEncoding();
errorMessage = toUString(szErrorMessage, pcbErrorMsg, _nTextEncoding);
sqlState = toUString(szSqlState, std::size(szSqlState), _nTextEncoding);
}
OSL_ENSURE(n != SQL_INVALID_HANDLE,"SdbODBC3_SetStatus: SQLError returned SQL_INVALID_HANDLE");
OSL_ENSURE(n == SQL_SUCCESS || n == SQL_SUCCESS_WITH_INFO || n == SQL_NO_DATA_FOUND || n == SQL_ERROR,"SdbODBC3_SetStatus: SQLError failed");
rtl_TextEncoding _nTextEncoding = osl_getThreadTextEncoding();
// For the Return Code of SQLError see ODBC 2.0 Programmer's Reference Page 287ff
throw SQLException( OUString(reinterpret_cast<char *>(szErrorMessage), pcbErrorMsg, _nTextEncoding),
_xInterface,
OUString(reinterpret_cast<char *>(szSqlState), 5, _nTextEncoding),
pfNativeError,
Any()
);
throw SQLException(errorMessage, _xInterface, sqlState, pfNativeError, Any());
}
Sequence<sal_Int8> OTools::getBytesValue(const OConnection* _pConnection,
@ -527,13 +406,27 @@ void OTools::GetInfo(OConnection const * _pConnection,
const Reference< XInterface >& _xInterface,
rtl_TextEncoding _nTextEncoding)
{
char aValue[512];
SQLSMALLINT nValueLen=0;
OTools::ThrowException(_pConnection,
_pConnection->functions().GetInfo(_aConnectionHandle,_nInfo,aValue,(sizeof aValue)-1,&nValueLen),
_aConnectionHandle,SQL_HANDLE_DBC,_xInterface);
if (bUseWChar && _pConnection->functions().has(ODBC3SQLFunctionId::GetInfoW))
{
SQLWCHAR aValue[512];
SQLSMALLINT nValueLen=0;
// SQLGetInfoW takes / outputs count of bytes, not characters
OTools::ThrowException(_pConnection,
_pConnection->functions().GetInfoW(_aConnectionHandle,_nInfo,aValue,sizeof(aValue)-sizeof(SQLWCHAR),&nValueLen),
_aConnectionHandle,SQL_HANDLE_DBC,_xInterface);
_rValue = OUString(aValue,nValueLen,_nTextEncoding);
_rValue = toUString(aValue, nValueLen / sizeof(SQLWCHAR));
}
else
{
SQLCHAR aValue[512];
SQLSMALLINT nValueLen=0;
OTools::ThrowException(_pConnection,
_pConnection->functions().GetInfo(_aConnectionHandle,_nInfo,aValue,sizeof(aValue)-1,&nValueLen),
_aConnectionHandle,SQL_HANDLE_DBC,_xInterface);
_rValue = toUString(aValue, nValueLen, _nTextEncoding);
}
}
void OTools::GetInfo(OConnection const * _pConnection,
@ -683,8 +576,7 @@ SQLSMALLINT OTools::jdbcTypeToOdbc(sal_Int32 jdbcType)
return odbcType;
}
void OTools::getBindTypes(bool _bUseWChar,
bool _bUseOldTimeDate,
void OTools::getBindTypes(bool _bUseOldTimeDate,
SQLSMALLINT _nOdbcType,
SQLSMALLINT& fCType,
SQLSMALLINT& fSqlType
@ -692,42 +584,36 @@ void OTools::getBindTypes(bool _bUseWChar,
{
switch(_nOdbcType)
{
case SQL_CHAR: if(_bUseWChar)
{
fCType = SQL_C_WCHAR;
fSqlType = SQL_WCHAR;
}
else
case SQL_CHAR: if (!bUseWChar)
{
fCType = SQL_C_CHAR;
fSqlType = SQL_CHAR;
break;
}
break;
case SQL_VARCHAR: if(_bUseWChar)
{
fCType = SQL_C_WCHAR;
fSqlType = SQL_WVARCHAR;
}
else
[[fallthrough]];
case SQL_WCHAR: fCType = SQL_C_WCHAR;
fSqlType = SQL_WCHAR; break;
case SQL_VARCHAR: if (!bUseWChar)
{
fCType = SQL_C_CHAR;
fSqlType = SQL_VARCHAR;
break;
}
break;
case SQL_LONGVARCHAR: if(_bUseWChar)
{
fCType = SQL_C_WCHAR;
fSqlType = SQL_WLONGVARCHAR;
}
else
[[fallthrough]];
case SQL_WVARCHAR: fCType = SQL_C_WCHAR;
fSqlType = SQL_WVARCHAR; break;
case SQL_LONGVARCHAR: if (!bUseWChar)
{
fCType = SQL_C_CHAR;
fSqlType = SQL_LONGVARCHAR;
break;
}
break;
case SQL_DECIMAL: fCType = _bUseWChar ? SQL_C_WCHAR : SQL_C_CHAR;
[[fallthrough]];
case SQL_WLONGVARCHAR: fCType = SQL_C_WCHAR;
fSqlType = SQL_WLONGVARCHAR; break;
case SQL_DECIMAL: fCType = bUseWChar ? SQL_C_WCHAR : SQL_C_CHAR;
fSqlType = SQL_DECIMAL; break;
case SQL_NUMERIC: fCType = _bUseWChar ? SQL_C_WCHAR : SQL_C_CHAR;
case SQL_NUMERIC: fCType = bUseWChar ? SQL_C_WCHAR : SQL_C_CHAR;
fSqlType = SQL_NUMERIC; break;
case SQL_BIT: fCType = SQL_C_TINYINT;
fSqlType = SQL_INTEGER; break;

View file

@ -196,31 +196,31 @@ namespace connectivity::odbc
/// @throws css::sdbc::SQLException
/// @throws css::uno::RuntimeException
void openTables(const css::uno::Any& catalog, const OUString& schemaPattern,
std::u16string_view tableNamePattern, const css::uno::Sequence< OUString >& types );
const OUString& tableNamePattern, const css::uno::Sequence< OUString >& types );
/// @throws css::sdbc::SQLException
/// @throws css::uno::RuntimeException
void openColumnPrivileges( const css::uno::Any& catalog, const OUString& schema,
std::u16string_view table, std::u16string_view columnNamePattern );
const OUString& table, const OUString& columnNamePattern );
/// @throws css::sdbc::SQLException
/// @throws css::uno::RuntimeException
void openColumns( const css::uno::Any& catalog, const OUString& schemaPattern,
std::u16string_view tableNamePattern, std::u16string_view columnNamePattern );
const OUString& tableNamePattern, const OUString& columnNamePattern );
/// @throws css::sdbc::SQLException
/// @throws css::uno::RuntimeException
void openProcedureColumns( const css::uno::Any& catalog, const OUString& schemaPattern,
std::u16string_view procedureNamePattern,std::u16string_view columnNamePattern );
const OUString& procedureNamePattern,const OUString& columnNamePattern );
/// @throws css::sdbc::SQLException
/// @throws css::uno::RuntimeException
void openProcedures( const css::uno::Any& catalog, const OUString& schemaPattern,
std::u16string_view procedureNamePattern);
const OUString& procedureNamePattern);
/// @throws css::sdbc::SQLException
/// @throws css::uno::RuntimeException
void openVersionColumns(const css::uno::Any& catalog, const OUString& schema,
std::u16string_view table);
const OUString& table);
/// @throws css::sdbc::SQLException
/// @throws css::uno::RuntimeException
void openBestRowIdentifier( const css::uno::Any& catalog, const OUString& schema,
std::u16string_view table,sal_Int32 scope, bool nullable );
const OUString& table,sal_Int32 scope, bool nullable );
/// @throws css::sdbc::SQLException
/// @throws css::uno::RuntimeException
void openForeignKeys( const css::uno::Any& catalog, const OUString* schema,const OUString* table,
@ -233,19 +233,19 @@ namespace connectivity::odbc
void openImportedKeys(const css::uno::Any& catalog, const OUString& schema,const OUString& table);
/// @throws css::sdbc::SQLException
/// @throws css::uno::RuntimeException
void openPrimaryKeys(const css::uno::Any& catalog, const OUString& schema,std::u16string_view table);
void openPrimaryKeys(const css::uno::Any& catalog, const OUString& schema,const OUString& table);
/// @throws css::sdbc::SQLException
/// @throws css::uno::RuntimeException
void openTablePrivileges(const css::uno::Any& catalog, const OUString& schemaPattern,
std::u16string_view tableNamePattern);
const OUString& tableNamePattern);
/// @throws css::sdbc::SQLException
/// @throws css::uno::RuntimeException
void openSpecialColumns(bool _bRowVer,const css::uno::Any& catalog, const OUString& schema,
std::u16string_view table,sal_Int32 scope, bool nullable );
const OUString& table,sal_Int32 scope, bool nullable );
/// @throws css::sdbc::SQLException
/// @throws css::uno::RuntimeException
void openIndexInfo( const css::uno::Any& catalog, const OUString& schema,
std::u16string_view table,bool unique,bool approximate );
const OUString& table,bool unique,bool approximate );
protected:
using OPropertySetHelper::getFastPropertyValue;

View file

@ -43,12 +43,25 @@ public:
SQLSMALLINT BufferLength,
SQLSMALLINT* StringLength2Ptr,
SQLUSMALLINT DriverCompletion) const = 0;
virtual SQLRETURN DriverConnectW(SQLHDBC ConnectionHandle,
HWND WindowHandle,
SQLWCHAR* InConnectionString,
SQLSMALLINT StringLength1,
SQLWCHAR* OutConnectionString,
SQLSMALLINT BufferLength,
SQLSMALLINT* StringLength2Ptr,
SQLUSMALLINT DriverCompletion) const = 0;
// Obtaining information about a driver and data source
virtual SQLRETURN GetInfo(SQLHDBC ConnectionHandle,
SQLUSMALLINT InfoType,
SQLPOINTER InfoValuePtr,
SQLSMALLINT BufferLength,
SQLSMALLINT* StringLengthPtr) const = 0;
virtual SQLRETURN GetInfoW(SQLHDBC ConnectionHandle,
SQLUSMALLINT InfoType,
SQLPOINTER InfoValuePtr,
SQLSMALLINT BufferLength,
SQLSMALLINT* StringLengthPtr) const = 0;
virtual SQLRETURN GetFunctions(SQLHDBC ConnectionHandle,
SQLUSMALLINT FunctionId,
SQLUSMALLINT* SupportedPtr) const = 0;
@ -58,11 +71,20 @@ public:
SQLINTEGER Attribute,
SQLPOINTER ValuePtr,
SQLINTEGER StringLength) const = 0;
virtual SQLRETURN SetConnectAttrW(SQLHDBC ConnectionHandle,
SQLINTEGER Attribute,
SQLPOINTER ValuePtr,
SQLINTEGER StringLength) const = 0;
virtual SQLRETURN GetConnectAttr(SQLHDBC ConnectionHandle,
SQLINTEGER Attribute,
SQLPOINTER ValuePtr,
SQLINTEGER BufferLength,
SQLINTEGER* StringLength) const = 0;
virtual SQLRETURN GetConnectAttrW(SQLHDBC ConnectionHandle,
SQLINTEGER Attribute,
SQLPOINTER ValuePtr,
SQLINTEGER BufferLength,
SQLINTEGER* StringLength) const = 0;
virtual SQLRETURN SetEnvAttr(SQLHENV EnvironmentHandle,
SQLINTEGER Attribute,
SQLPOINTER ValuePtr,
@ -120,6 +142,9 @@ public:
virtual SQLRETURN Prepare(SQLHSTMT StatementHandle,
SQLCHAR* StatementText,
SQLINTEGER TextLength) const = 0;
virtual SQLRETURN PrepareW(SQLHSTMT StatementHandle,
SQLWCHAR* StatementText,
SQLINTEGER TextLength) const = 0;
virtual SQLRETURN BindParameter(SQLHSTMT StatementHandle,
SQLUSMALLINT ParameterNumber,
SQLSMALLINT InputOutputType,
@ -139,11 +164,17 @@ public:
virtual SQLRETURN SetCursorName(SQLHSTMT StatementHandle,
SQLCHAR* CursorName,
SQLSMALLINT NameLength) const = 0;
virtual SQLRETURN SetCursorNameW(SQLHSTMT StatementHandle,
SQLWCHAR* CursorName,
SQLSMALLINT NameLength) const = 0;
// Submitting requests
virtual SQLRETURN Execute(SQLHSTMT StatementHandle) const = 0;
virtual SQLRETURN ExecDirect(SQLHSTMT StatementHandle,
SQLCHAR* StatementText,
SQLINTEGER TextLength) const = 0;
virtual SQLRETURN ExecDirectW(SQLHSTMT StatementHandle,
SQLWCHAR* StatementText,
SQLINTEGER TextLength) const = 0;
virtual SQLRETURN DescribeParam(SQLHSTMT StatementHandle,
SQLUSMALLINT ParameterNumber,
SQLSMALLINT* DataTypePtr,
@ -165,6 +196,13 @@ public:
SQLSMALLINT BufferLength,
SQLSMALLINT* StringLengthPtr,
SQLLEN* NumericAttributePtr) const = 0;
virtual SQLRETURN ColAttributeW(SQLHSTMT StatementHandle,
SQLUSMALLINT ColumnNumber,
SQLUSMALLINT FieldIdentifier,
SQLPOINTER CharacterAttributePtr,
SQLSMALLINT BufferLength,
SQLSMALLINT* StringLengthPtr,
SQLLEN* NumericAttributePtr) const = 0;
virtual SQLRETURN BindCol(SQLHSTMT StatementHandle,
SQLUSMALLINT ColumnNumber,
SQLSMALLINT TargetType,
@ -204,6 +242,14 @@ public:
SQLCHAR* MessageText,
SQLSMALLINT BufferLength,
SQLSMALLINT* TextLengthPtr) const = 0;
virtual SQLRETURN GetDiagRecW(SQLSMALLINT HandleType,
SQLHANDLE Handle,
SQLSMALLINT RecNumber,
SQLWCHAR* Sqlstate,
SQLINTEGER* NativeErrorPtr,
SQLWCHAR* MessageText,
SQLSMALLINT BufferLength,
SQLSMALLINT* TextLengthPtr) const = 0;
// Obtaining information about the data source's system tables (catalog functions)
virtual SQLRETURN ColumnPrivileges(SQLHSTMT StatementHandle,
SQLCHAR* CatalogName,
@ -214,6 +260,15 @@ public:
SQLSMALLINT NameLength3,
SQLCHAR* ColumnName,
SQLSMALLINT NameLength4) const = 0;
virtual SQLRETURN ColumnPrivilegesW(SQLHSTMT StatementHandle,
SQLWCHAR* CatalogName,
SQLSMALLINT NameLength1,
SQLWCHAR* SchemaName,
SQLSMALLINT NameLength2,
SQLWCHAR* TableName,
SQLSMALLINT NameLength3,
SQLWCHAR* ColumnName,
SQLSMALLINT NameLength4) const = 0;
virtual SQLRETURN Columns(SQLHSTMT StatementHandle,
SQLCHAR* CatalogName,
SQLSMALLINT NameLength1,
@ -223,6 +278,15 @@ public:
SQLSMALLINT NameLength3,
SQLCHAR* ColumnName,
SQLSMALLINT NameLength4) const = 0;
virtual SQLRETURN ColumnsW(SQLHSTMT StatementHandle,
SQLWCHAR* CatalogName,
SQLSMALLINT NameLength1,
SQLWCHAR* SchemaName,
SQLSMALLINT NameLength2,
SQLWCHAR* TableName,
SQLSMALLINT NameLength3,
SQLWCHAR* ColumnName,
SQLSMALLINT NameLength4) const = 0;
virtual SQLRETURN ForeignKeys(SQLHSTMT StatementHandle,
SQLCHAR* PKCatalogName,
SQLSMALLINT NameLength1,
@ -236,6 +300,19 @@ public:
SQLSMALLINT NameLength5,
SQLCHAR* FKTableName,
SQLSMALLINT NameLength6) const = 0;
virtual SQLRETURN ForeignKeysW(SQLHSTMT StatementHandle,
SQLWCHAR* PKCatalogName,
SQLSMALLINT NameLength1,
SQLWCHAR* PKSchemaName,
SQLSMALLINT NameLength2,
SQLWCHAR* PKTableName,
SQLSMALLINT NameLength3,
SQLWCHAR* FKCatalogName,
SQLSMALLINT NameLength4,
SQLWCHAR* FKSchemaName,
SQLSMALLINT NameLength5,
SQLWCHAR* FKTableName,
SQLSMALLINT NameLength6) const = 0;
virtual SQLRETURN PrimaryKeys(SQLHSTMT StatementHandle,
SQLCHAR* CatalogName,
SQLSMALLINT NameLength1,
@ -243,6 +320,13 @@ public:
SQLSMALLINT NameLength2,
SQLCHAR* TableName,
SQLSMALLINT NameLength3) const = 0;
virtual SQLRETURN PrimaryKeysW(SQLHSTMT StatementHandle,
SQLWCHAR* CatalogName,
SQLSMALLINT NameLength1,
SQLWCHAR* SchemaName,
SQLSMALLINT NameLength2,
SQLWCHAR* TableName,
SQLSMALLINT NameLength3) const = 0;
virtual SQLRETURN ProcedureColumns(SQLHSTMT StatementHandle,
SQLCHAR* CatalogName,
SQLSMALLINT NameLength1,
@ -252,6 +336,15 @@ public:
SQLSMALLINT NameLength3,
SQLCHAR* ColumnName,
SQLSMALLINT NameLength4) const = 0;
virtual SQLRETURN ProcedureColumnsW(SQLHSTMT StatementHandle,
SQLWCHAR* CatalogName,
SQLSMALLINT NameLength1,
SQLWCHAR* SchemaName,
SQLSMALLINT NameLength2,
SQLWCHAR* ProcName,
SQLSMALLINT NameLength3,
SQLWCHAR* ColumnName,
SQLSMALLINT NameLength4) const = 0;
virtual SQLRETURN Procedures(SQLHSTMT StatementHandle,
SQLCHAR* CatalogName,
SQLSMALLINT NameLength1,
@ -259,6 +352,13 @@ public:
SQLSMALLINT NameLength2,
SQLCHAR* ProcName,
SQLSMALLINT NameLength3) const = 0;
virtual SQLRETURN ProceduresW(SQLHSTMT StatementHandle,
SQLWCHAR* CatalogName,
SQLSMALLINT NameLength1,
SQLWCHAR* SchemaName,
SQLSMALLINT NameLength2,
SQLWCHAR* ProcName,
SQLSMALLINT NameLength3) const = 0;
virtual SQLRETURN SpecialColumns(SQLHSTMT StatementHandle,
SQLUSMALLINT IdentifierType,
SQLCHAR* CatalogName,
@ -269,6 +369,16 @@ public:
SQLSMALLINT NameLength3,
SQLUSMALLINT Scope,
SQLUSMALLINT Nullable) const = 0;
virtual SQLRETURN SpecialColumnsW(SQLHSTMT StatementHandle,
SQLUSMALLINT IdentifierType,
SQLWCHAR* CatalogName,
SQLSMALLINT NameLength1,
SQLWCHAR* SchemaName,
SQLSMALLINT NameLength2,
SQLWCHAR* TableName,
SQLSMALLINT NameLength3,
SQLUSMALLINT Scope,
SQLUSMALLINT Nullable) const = 0;
virtual SQLRETURN Statistics(SQLHSTMT StatementHandle,
SQLCHAR* CatalogName,
SQLSMALLINT NameLength1,
@ -278,6 +388,15 @@ public:
SQLSMALLINT NameLength3,
SQLUSMALLINT Unique,
SQLUSMALLINT Reserved) const = 0;
virtual SQLRETURN StatisticsW(SQLHSTMT StatementHandle,
SQLWCHAR* CatalogName,
SQLSMALLINT NameLength1,
SQLWCHAR* SchemaName,
SQLSMALLINT NameLength2,
SQLWCHAR* TableName,
SQLSMALLINT NameLength3,
SQLUSMALLINT Unique,
SQLUSMALLINT Reserved) const = 0;
virtual SQLRETURN TablePrivileges(SQLHSTMT StatementHandle,
SQLCHAR* CatalogName,
SQLSMALLINT NameLength1,
@ -285,6 +404,13 @@ public:
SQLSMALLINT NameLength2,
SQLCHAR* TableName,
SQLSMALLINT NameLength3) const = 0;
virtual SQLRETURN TablePrivilegesW(SQLHSTMT StatementHandle,
SQLWCHAR* CatalogName,
SQLSMALLINT NameLength1,
SQLWCHAR* SchemaName,
SQLSMALLINT NameLength2,
SQLWCHAR* TableName,
SQLSMALLINT NameLength3) const = 0;
virtual SQLRETURN Tables(SQLHSTMT StatementHandle,
SQLCHAR* CatalogName,
SQLSMALLINT NameLength1,
@ -294,6 +420,15 @@ public:
SQLSMALLINT NameLength3,
SQLCHAR* TableType,
SQLSMALLINT NameLength4) const = 0;
virtual SQLRETURN TablesW(SQLHSTMT StatementHandle,
SQLWCHAR* CatalogName,
SQLSMALLINT NameLength1,
SQLWCHAR* SchemaName,
SQLSMALLINT NameLength2,
SQLWCHAR* TableName,
SQLSMALLINT NameLength3,
SQLWCHAR* TableType,
SQLSMALLINT NameLength4) const = 0;
// Terminating a statement
virtual SQLRETURN FreeStmt(SQLHSTMT StatementHandle, SQLUSMALLINT Option) const = 0;
virtual SQLRETURN CloseCursor(SQLHSTMT StatementHandle) const = 0;
@ -308,12 +443,22 @@ public:
SQLCHAR* CursorName,
SQLSMALLINT BufferLength,
SQLSMALLINT* NameLength2) const = 0;
virtual SQLRETURN GetCursorNameW(SQLHSTMT StatementHandle,
SQLWCHAR* CursorName,
SQLSMALLINT BufferLength,
SQLSMALLINT* NameLength2) const = 0;
virtual SQLRETURN NativeSql(SQLHDBC ConnectionHandle,
SQLCHAR* InStatementText,
SQLINTEGER TextLength1,
SQLCHAR* OutStatementText,
SQLINTEGER BufferLength,
SQLINTEGER* TextLength2Ptr) const = 0;
virtual SQLRETURN NativeSqlW(SQLHDBC ConnectionHandle,
SQLWCHAR* InStatementText,
SQLINTEGER TextLength1,
SQLWCHAR* OutStatementText,
SQLINTEGER BufferLength,
SQLINTEGER* TextLength2Ptr) const = 0;
};
}

View file

@ -60,10 +60,8 @@ namespace connectivity::odbc
css::sdbc::XColumnLocate,
css::lang::XServiceInfo> OResultSet_BASE;
class BindData;
typedef std::pair<sal_Int64,sal_Int32> TVoidPtr;
typedef std::allocator< TVoidPtr > TVoidAlloc;
typedef std::vector<TVoidPtr> TVoidVector;
/// Functor object for class ZZ returntype is void
struct OOO_DLLPUBLIC_ODBCBASE TBookmarkPosMapCompare
{
@ -114,7 +112,7 @@ namespace connectivity::odbc
// used top hold the information about the value and the datatype to save calls to metadata
typedef std::vector<ORowSetValue> TDataRow;
TVoidVector m_aBindVector;
std::vector<std::unique_ptr<BindData>> m_aBindVector;
std::vector<SQLLEN> m_aLengthVector;
std::map<sal_Int32,SWORD> m_aODBCColumnTypes;
@ -169,7 +167,6 @@ namespace connectivity::odbc
void updateValue(sal_Int32 columnIndex, SQLSMALLINT _nType, void const * _pValue);
void fillNeededData(SQLRETURN _nRet);
bool moveImpl(IResultSetHelper::Movement _eCursorPosition, sal_Int32 _nOffset);
TVoidPtr allocBindColumn(sal_Int32 _nType,sal_Int32 _nColumnIndex);
SQLRETURN unbind(bool _bUnbindHandle = true);
SWORD impl_getColumnType_nothrow(sal_Int32 columnIndex);

View file

@ -91,7 +91,7 @@ namespace connectivity::odbc
void setMaxRows(sal_Int64 _par0) ;
void setFetchDirection(sal_Int32 _par0) ;
void setFetchSize(sal_Int32 _par0) ;
void setCursorName(std::u16string_view _par0);
void setCursorName(const OUString& _par0);
void setEscapeProcessing( const bool _bEscapeProc );
template < typename T, SQLINTEGER BufferLength > SQLRETURN setStmtOption (SQLINTEGER fOption, T value) const;

View file

@ -24,6 +24,8 @@
#include <com/sun/star/util/Date.hpp>
#include <com/sun/star/util/Time.hpp>
#include <com/sun/star/util/DateTime.hpp>
#include <o3tl/safeint.hxx>
#include <o3tl/string_view.hxx>
#include <osl/thread.h>
#include <rtl/ustring.hxx>
#include <com/sun/star/uno/Sequence.hxx>
@ -34,20 +36,27 @@ enum class ODBC3SQLFunctionId
FIRST,
AllocHandle,
DriverConnect,
DriverConnectW,
GetInfo,
GetInfoW,
GetFunctions,
GetTypeInfo,
SetConnectAttr,
SetConnectAttrW,
GetConnectAttr,
GetConnectAttrW,
SetEnvAttr,
GetEnvAttr,
SetStmtAttr,
GetStmtAttr,
Prepare,
PrepareW,
BindParameter,
SetCursorName,
SetCursorNameW,
Execute,
ExecDirect,
ExecDirectW,
DescribeParam,
NumParams,
ParamData,
@ -55,6 +64,7 @@ enum class ODBC3SQLFunctionId
RowCount,
NumResultCols,
ColAttribute,
ColAttributeW,
BindCol,
Fetch,
FetchScroll,
@ -63,16 +73,27 @@ enum class ODBC3SQLFunctionId
BulkOperations,
MoreResults,
GetDiagRec,
GetDiagRecW,
ColumnPrivileges,
ColumnPrivilegesW,
Columns,
ColumnsW,
ForeignKeys,
ForeignKeysW,
PrimaryKeys,
PrimaryKeysW,
ProcedureColumns,
ProcedureColumnsW,
Procedures,
ProceduresW,
SpecialColumns,
SpecialColumnsW,
Statistics,
StatisticsW,
TablePrivileges,
TablePrivilegesW,
Tables,
TablesW,
FreeStmt,
CloseCursor,
Cancel,
@ -80,7 +101,9 @@ enum class ODBC3SQLFunctionId
Disconnect,
FreeHandle,
GetCursorName,
GetCursorNameW,
NativeSql,
NativeSqlW,
LAST
};
@ -168,14 +191,12 @@ namespace connectivity::odbc
}
/**
getBindTypes set the ODBC type for C
@param _bUseWChar true when Unicode should be used
@param _bUseOldTimeDate true when the old datetime format should be used
@param _nOdbcType the ODBC sql type
@param fCType the C type for the ODBC type
@param fSqlType the SQL type for the ODBC type
*/
static void getBindTypes(bool _bUseWChar,
bool _bUseOldTimeDate,
static void getBindTypes(bool _bUseOldTimeDate,
SQLSMALLINT _nOdbcType,
SQLSMALLINT& fCType,
SQLSMALLINT& fSqlType);
@ -208,20 +229,6 @@ namespace connectivity::odbc
const css::uno::Reference< css::uno::XInterface >& _xInterface,
void* _pValue,
SQLLEN _nSize);
/// @throws css::sdbc::SQLException
/// @throws css::uno::RuntimeException
static void bindValue( OConnection const * _pConnection,
SQLHANDLE _aStatementHandle,
sal_Int32 columnIndex,
SQLSMALLINT _nType,
SQLSMALLINT _nMaxLen,
const void* _pValue,
void* _pData,
SQLLEN *pLen,
const css::uno::Reference< css::uno::XInterface >& _xInterface,
rtl_TextEncoding _nTextEncoding,
bool _bUseOldTimeDate);
};
/// @throws css::sdbc::SQLException
@ -237,7 +244,110 @@ namespace connectivity::odbc
OTools::getValue(_pConnection,_aStatementHandle,columnIndex,_nType,_bWasNull,_xInterface,&_rValue,sizeof _rValue);
}
// Keep const_ and reinterpret_cast required to convert strings in one place
inline OUString toUString(const SQLCHAR* str, sal_Int32 len, rtl_TextEncoding enc)
{
return OUString(reinterpret_cast<const char*>(str), len, enc);
}
inline OUString toUString(const SQLCHAR* str)
{
return OUString::createFromAscii(reinterpret_cast<const char*>(str));
}
inline OUString toUString(const SQLWCHAR* str, sal_Int32 len)
{
static_assert(sizeof(SQLWCHAR) == sizeof(sal_Unicode) || sizeof(SQLWCHAR) == sizeof(sal_uInt32));
if constexpr (sizeof(SQLWCHAR) == sizeof(sal_Unicode))
return OUString(reinterpret_cast<const sal_Unicode*>(str), len);
else
{
auto* codepoints = reinterpret_cast<const sal_uInt32*>(str);
return OUString(codepoints, len);
}
}
// A templated class to encapsulate conversion from our string types into arrays of
// SQLCHAR / SQLWCHAR (non-const, even if used as input balues, and not modified),
// that ODBC functions take. It owns its buffer (important for delayed reads/writes)
template <typename C, size_t CHAR_SIZE = sizeof(C)> class CHARS {};
template <size_t CHAR_SIZE> class SIZED
{
public:
SQLSMALLINT cch() const { return m_len; } // count of characters
bool empty() const { return m_len == 0; }
SQLSMALLINT cb() const { return m_len * CHAR_SIZE; } // count of bytes
protected:
SQLSMALLINT m_len = 0;
};
template <typename C> class CHARS<C, sizeof(char)> : public SIZED<sizeof(char)>
{
public:
CHARS() = default;
CHARS(std::u16string_view str, rtl_TextEncoding encoding)
: CHARS(OUStringToOString(str, encoding))
{
}
CHARS(const OString& str)
: m_string(str)
{
m_len = std::min(m_string.getLength(), sal_Int32(std::numeric_limits<SQLSMALLINT>::max()));
}
C* get() { return reinterpret_cast<C*>(const_cast<char*>(m_string.getStr())); }
private:
OString m_string; // ref-counted CoW, but in practice always created ad-hoc
};
template <typename C> class CHARS<C, sizeof(sal_Unicode)> : public SIZED<sizeof(sal_Unicode)>
{
public:
CHARS() = default;
CHARS(const OUString& str)
: m_string(str)
{
m_len = std::min(m_string.getLength(), sal_Int32(std::numeric_limits<SQLSMALLINT>::max()));
}
C* get() { return reinterpret_cast<C*>(const_cast<sal_Unicode*>(m_string.getStr())); }
private:
OUString m_string; // ref-counted CoW
};
template <typename C> class CHARS<C, sizeof(sal_uInt32)> : public SIZED<sizeof(sal_uInt32)>
{
public:
CHARS() = default;
CHARS(std::u16string_view str)
{
auto size = std::min(str.size(), size_t(std::numeric_limits<SQLSMALLINT>::max()));
m_buf = std::make_unique<sal_uInt32[]>(size + 1);
auto p = m_buf.get();
for (size_t i = 0; i < str.size() && o3tl::make_unsigned(p - m_buf.get()) < size; ++p)
*p = o3tl::iterateCodePoints(str, &i);
m_len = p - m_buf.get();
*p = 0;
}
C* get() { return reinterpret_cast<C*>(m_buf.get()); }
private:
std::unique_ptr<sal_uInt32[]> m_buf;
};
using SQLChars = CHARS<SQLCHAR>;
using SQLWChars = CHARS<SQLWCHAR>;
// for now, use wchar only on Windows (see comment in OPreparedStatement::setParameter)
#ifdef _WIN32
const bool bUseWChar = true;
#else
const volatile inline bool bUseWChar = false; // volatile to avoid "unreachabe code" warnings
#endif
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */