summaryrefslogtreecommitdiff
path: root/connectivity
diff options
context:
space:
mode:
authorTamas Bunth <tamas.bunth@collabora.co.uk>2018-10-30 18:49:46 +0100
committerTamás Bunth <btomi96@gmail.com>2018-11-05 10:06:03 +0100
commit0c6da44c9249e7b9355c0efd9a60004701867275 (patch)
treec23bb2a2421c3e1ffecc31e08880bb5588efbdcd /connectivity
parentf2cd1c3c7cce2699d1341f726fc90cf30b52612c (diff)
mysqlc: allow multiple open statements
Change-Id: I07e57ea7d9e6af1c7543483b1ab54a0b8c5be2d5 Reviewed-on: https://gerrit.libreoffice.org/62640 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk> Reviewed-by: Tamás Bunth <btomi96@gmail.com>
Diffstat (limited to 'connectivity')
-rw-r--r--connectivity/Library_mysqlc.mk1
-rw-r--r--connectivity/qa/connectivity/mysql/mysql.cxx48
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_resultset.cxx283
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_resultset.hxx25
4 files changed, 200 insertions, 157 deletions
diff --git a/connectivity/Library_mysqlc.mk b/connectivity/Library_mysqlc.mk
index 42a10e40cdf8..9dba7769a9a2 100644
--- a/connectivity/Library_mysqlc.mk
+++ b/connectivity/Library_mysqlc.mk
@@ -33,6 +33,7 @@ $(eval $(call gb_Library_use_libraries,mysqlc,\
cppu \
sal \
salhelper \
+ comphelper \
cppuhelper \
))
diff --git a/connectivity/qa/connectivity/mysql/mysql.cxx b/connectivity/qa/connectivity/mysql/mysql.cxx
index f5057dce1519..f78ea2ea57e5 100644
--- a/connectivity/qa/connectivity/mysql/mysql.cxx
+++ b/connectivity/qa/connectivity/mysql/mysql.cxx
@@ -43,6 +43,7 @@ public:
void testDBConnection();
void testCreateAndDropTable();
void testIntegerInsertAndQuery();
+ void testDBPositionChange();
CPPUNIT_TEST_SUITE(MysqlTestDriver);
CPPUNIT_TEST(testDBConnection);
@@ -175,6 +176,53 @@ void MysqlTestDriver::testIntegerInsertAndQuery()
CPPUNIT_ASSERT_EQUAL(0, nUpdateCount); // it's a DDL statement
}
+void MysqlTestDriver::testDBPositionChange()
+{
+ Reference<XConnection> xConnection = m_xDriver->connect(m_sUrl, m_infos);
+ if (!xConnection.is())
+ {
+ CPPUNIT_ASSERT_MESSAGE("cannot connect to data source!", xConnection.is());
+ }
+
+ Reference<XStatement> xStatement = xConnection->createStatement();
+ CPPUNIT_ASSERT(xStatement.is());
+
+ auto nUpdateCount
+ = xStatement->executeUpdate("CREATE TABLE myTestTable (id INTEGER PRIMARY KEY)");
+ CPPUNIT_ASSERT_EQUAL(0, nUpdateCount); // it's a DDL statement
+ Reference<XPreparedStatement> xPrepared
+ = xConnection->prepareStatement(OUString{ "INSERT INTO myTestTable VALUES (?)" });
+ Reference<XParameters> xParams(xPrepared, UNO_QUERY);
+ constexpr int ROW_COUNT = 3;
+ for (int i = 1; i <= ROW_COUNT; ++i)
+ {
+ xParams->setLong(1, i); // first and only column
+ nUpdateCount = xPrepared->executeUpdate();
+ CPPUNIT_ASSERT_EQUAL(1, nUpdateCount); // one row is inserted at a time
+ }
+ Reference<XResultSet> xResultSet = xStatement->executeQuery("SELECT id from myTestTable");
+ CPPUNIT_ASSERT_MESSAGE("result set cannot be instantiated after query", xResultSet.is());
+ Reference<XRow> xRow(xResultSet, UNO_QUERY);
+ CPPUNIT_ASSERT_MESSAGE("cannot extract row from result set!", xRow.is());
+
+ xResultSet->afterLast();
+ CPPUNIT_ASSERT_EQUAL(ROW_COUNT + 1, xResultSet->getRow());
+ xResultSet->last();
+ CPPUNIT_ASSERT_EQUAL(ROW_COUNT, nUpdateCount);
+ CPPUNIT_ASSERT_EQUAL(ROW_COUNT, xResultSet->getRow());
+ bool successPrevios = xResultSet->previous();
+ CPPUNIT_ASSERT(successPrevios);
+ CPPUNIT_ASSERT_EQUAL(ROW_COUNT - 1, nUpdateCount);
+ xResultSet->beforeFirst();
+ xResultSet->next();
+ CPPUNIT_ASSERT_EQUAL(1, xResultSet->getRow());
+ xResultSet->first();
+ CPPUNIT_ASSERT_EQUAL(1, xResultSet->getRow());
+
+ nUpdateCount = xStatement->executeUpdate("DROP TABLE myTestTable");
+ CPPUNIT_ASSERT_EQUAL(0, nUpdateCount); // it's a DDL statement
+}
+
CPPUNIT_TEST_SUITE_REGISTRATION(MysqlTestDriver);
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_resultset.cxx b/connectivity/source/drivers/mysqlc/mysqlc_resultset.cxx
index ab018ef9a777..b3a172f0c2de 100644
--- a/connectivity/source/drivers/mysqlc/mysqlc_resultset.cxx
+++ b/connectivity/source/drivers/mysqlc/mysqlc_resultset.cxx
@@ -31,6 +31,7 @@
#include <com/sun/star/sdbcx/CompareBookmark.hpp>
#include <cppuhelper/supportsservice.hxx>
#include <cppuhelper/typeprovider.hxx>
+#include <comphelper/seqstream.hxx>
#include <sal/log.hxx>
@@ -48,6 +49,7 @@ using namespace com::sun::star::sdbc;
using namespace com::sun::star::sdbcx;
using namespace com::sun::star::container;
using namespace com::sun::star::io;
+using namespace com::sun::star::uno;
using namespace com::sun::star::util;
using namespace ::comphelper;
using ::osl::MutexGuard;
@@ -58,13 +60,13 @@ namespace
{
// copied from string misc, it should be replaced when library is not an
// extension anymore
-std::vector<OUString> lcl_split(const OUString& rStr, sal_Unicode cSeparator)
+std::vector<OString> lcl_split(const OString& rStr, char cSeparator)
{
- std::vector<OUString> vec;
+ std::vector<OString> vec;
sal_Int32 idx = 0;
do
{
- OUString kw = rStr.getToken(0, cSeparator, idx);
+ OString kw = rStr.getToken(0, cSeparator, idx);
kw = kw.trim();
if (!kw.isEmpty())
{
@@ -77,12 +79,23 @@ std::vector<OUString> lcl_split(const OUString& rStr, sal_Unicode cSeparator)
void OResultSet::checkRowIndex()
{
- if (m_nRowPosition <= 0 || m_nRowPosition > m_nRowCount)
+ if (m_nRowPosition < 0 || m_nRowPosition >= m_nRowCount)
{
throw SQLException("Cursor position out of range", *this, OUString(), 1, Any());
}
}
+bool OResultSet::checkNull(sal_Int32 column)
+{
+ if (m_aRows[m_nRowPosition][column - 1].isEmpty())
+ {
+ m_bWasNull = true;
+ return true;
+ }
+ m_bWasNull = false;
+ return false;
+}
+
OUString SAL_CALL OResultSet::getImplementationName()
{
return OUString("com.sun.star.sdbcx.mysqlc.ResultSet");
@@ -106,18 +119,55 @@ OResultSet::OResultSet(OConnection& rConn, OCommonStatement* pStmt, MYSQL_RES* p
: OResultSet_BASE(m_aMutex)
, OPropertySetHelper(OResultSet_BASE::rBHelper)
, m_rConnection(rConn)
- , m_aRow(nullptr)
, m_pMysql(rConn.getMysqlConnection())
, m_aStatement(static_cast<OWeakObject*>(pStmt))
, m_pResult(pResult)
- , fieldCount(0)
, m_encoding(_encoding)
{
- fieldCount = mysql_num_fields(pResult);
+ m_xMetaData = new OResultSetMetaData(m_rConnection, m_pResult);
+}
+
+void OResultSet::ensureResultFetched()
+{
+ if (!m_bResultFetched)
+ {
+ fetchResult();
+ }
+}
+
+void OResultSet::fetchResult()
+{
+ // Mysql C API does not allow simultaneously opened result sets, but sdbc does.
+ // Because of that we need to fetch all of the data ASAP
// it works only if result set is produced via mysql_store_result
// TODO ensure that
- m_nRowCount = mysql_num_rows(pResult);
+ m_nRowCount = mysql_num_rows(m_pResult);
+
+ // fetch all the data
+ m_aRows.reserve(m_nRowCount);
+
+ m_nFieldCount = mysql_num_fields(m_pResult);
+ MYSQL_FIELD* pFields = mysql_fetch_fields(m_pResult);
+ m_aFields.assign(pFields, pFields + m_nFieldCount);
+
+ for (sal_Int32 row = 0; row < m_nRowCount; ++row)
+ {
+ MYSQL_ROW data = mysql_fetch_row(m_pResult);
+ unsigned long* lengths = mysql_fetch_lengths(m_pResult);
+ m_aRows.push_back(DataFields{});
+ // MYSQL_ROW is char**, array of strings
+ for (unsigned col = 0; col < m_nFieldCount; ++col)
+ {
+ m_aRows.back().push_back(OString{ data[col], static_cast<sal_Int32>(lengths[col]) });
+ }
+ }
+ unsigned errorNum = mysql_errno(m_pMysql);
+ if (errorNum)
+ mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_error(m_pMysql), errorNum, *this,
+ m_encoding);
+ m_bResultFetched = true;
+ mysql_free_result(m_pResult);
}
void OResultSet::disposing()
@@ -154,10 +204,9 @@ sal_Int32 SAL_CALL OResultSet::findColumn(const OUString& columnName)
MutexGuard aGuard(m_aMutex);
checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
- MYSQL_FIELD* pFields = mysql_fetch_fields(m_pResult);
- for (unsigned int i = 0; i < fieldCount; ++i)
+ for (unsigned int i = 0; i < m_nFieldCount; ++i)
{
- if (columnName.equalsIgnoreAsciiCaseAscii(pFields[i].name))
+ if (columnName.equalsIgnoreAsciiCaseAscii(m_aFields[i].name))
return i + 1; // sdbc indexes from 1
}
@@ -171,9 +220,12 @@ uno::Reference<XInputStream> SAL_CALL OResultSet::getBinaryStream(sal_Int32 colu
checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
checkColumnIndex(column);
checkRowIndex();
+ if (checkNull(column))
+ return nullptr;
- mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::getBinaryStream", *this);
- return nullptr;
+ OString sVal = m_aRows[m_nRowPosition][column - 1];
+ return new SequenceInputStream{ uno::Sequence<sal_Int8>(
+ reinterpret_cast<sal_Int8 const*>(sVal.getStr()), getDataLength(column - 1)) };
}
uno::Reference<XInputStream> SAL_CALL OResultSet::getCharacterStream(sal_Int32 column)
@@ -182,7 +234,6 @@ uno::Reference<XInputStream> SAL_CALL OResultSet::getCharacterStream(sal_Int32 c
checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
checkColumnIndex(column);
checkRowIndex();
-
mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::getCharacterStream",
*this);
return nullptr;
@@ -194,16 +245,11 @@ sal_Bool SAL_CALL OResultSet::getBoolean(sal_Int32 column)
checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
checkColumnIndex(column);
checkRowIndex();
-
- char* pValue = m_aRow[column - 1];
- if (!pValue)
- {
- m_bWasNull = true;
+ if (checkNull(column))
return false;
- }
- m_bWasNull = false;
- return static_cast<bool>(std::atoi(pValue));
+ OString sVal = m_aRows[m_nRowPosition][column - 1];
+ return sVal.toInt32() != 0;
}
sal_Int8 SAL_CALL OResultSet::getByte(sal_Int32 column)
@@ -212,32 +258,24 @@ sal_Int8 SAL_CALL OResultSet::getByte(sal_Int32 column)
checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
checkColumnIndex(column);
checkRowIndex();
-
- char* pValue = m_aRow[column - 1];
- if (!pValue)
- {
- m_bWasNull = true;
+ if (checkNull(column))
return 0;
- }
- m_bWasNull = false;
- return static_cast<sal_Int8>(std::atoi(pValue));
+ OString sVal = m_aRows[m_nRowPosition][column - 1];
+
+ return static_cast<sal_Int8>(sVal.toInt32());
}
uno::Sequence<sal_Int8> SAL_CALL OResultSet::getBytes(sal_Int32 column)
{
checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
MutexGuard aGuard(m_aMutex);
-
- char* pValue = m_aRow[column - 1];
- if (!pValue)
- {
- m_bWasNull = true;
+ OString sVal = m_aRows[m_nRowPosition][column - 1];
+ if (checkNull(column))
return uno::Sequence<sal_Int8>();
- }
- m_bWasNull = false;
- return uno::Sequence<sal_Int8>(reinterpret_cast<sal_Int8 const*>(pValue),
- m_aLengths[column - 1]);
+
+ return uno::Sequence<sal_Int8>(reinterpret_cast<sal_Int8 const*>(sVal.getStr()),
+ getDataLength(column - 1));
}
Date SAL_CALL OResultSet::getDate(sal_Int32 column)
@@ -247,13 +285,12 @@ Date SAL_CALL OResultSet::getDate(sal_Int32 column)
checkColumnIndex(column);
checkRowIndex();
- Date d; // TODO initialize
- char* dateStr = m_aRow[column - 1];
- if (!dateStr)
- {
- m_bWasNull = true;
+ Date d;
+
+ if (checkNull(column))
return d;
- }
+
+ OString dateStr = m_aRows[m_nRowPosition][column - 1];
OString dateString(dateStr);
OString token;
@@ -276,7 +313,6 @@ Date SAL_CALL OResultSet::getDate(sal_Int32 column)
}
i++;
} while (nIndex >= 0);
- m_bWasNull = false;
return d;
}
@@ -287,15 +323,11 @@ double SAL_CALL OResultSet::getDouble(sal_Int32 column)
checkColumnIndex(column);
checkRowIndex();
- char* pValue = m_aRow[column - 1];
- if (!pValue)
- {
- m_bWasNull = true;
+ if (checkNull(column))
return 0.0;
- }
- m_bWasNull = false;
- return std::strtod(pValue, nullptr);
+ OString sVal = m_aRows[m_nRowPosition][column - 1];
+ return sVal.toDouble();
}
float SAL_CALL OResultSet::getFloat(sal_Int32 column)
@@ -304,31 +336,22 @@ float SAL_CALL OResultSet::getFloat(sal_Int32 column)
checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
checkColumnIndex(column);
checkRowIndex();
-
- char* pValue = m_aRow[column - 1];
- if (!pValue)
- {
- m_bWasNull = true;
+ if (checkNull(column))
return 0.0f;
- }
- m_bWasNull = false;
- return std::strtod(pValue, nullptr);
+ OString sVal = m_aRows[m_nRowPosition][column - 1];
+ return sVal.toFloat();
}
sal_Int32 SAL_CALL OResultSet::getInt(sal_Int32 column)
{
MutexGuard aGuard(m_aMutex);
checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
- char* pValue = m_aRow[column - 1];
- if (!pValue)
- {
- m_bWasNull = true;
+ if (checkNull(column))
return 0;
- }
- m_bWasNull = false;
- return std::atoi(pValue);
+ OString sVal = m_aRows[m_nRowPosition][column - 1];
+ return sVal.toInt32();
}
sal_Int32 SAL_CALL OResultSet::getRow()
@@ -336,7 +359,7 @@ sal_Int32 SAL_CALL OResultSet::getRow()
MutexGuard aGuard(m_aMutex);
checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
- return m_nRowPosition;
+ return m_nRowPosition + 1; // indexed from 1
}
sal_Int64 SAL_CALL OResultSet::getLong(sal_Int32 column)
@@ -345,26 +368,17 @@ sal_Int64 SAL_CALL OResultSet::getLong(sal_Int32 column)
checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
checkColumnIndex(column);
checkRowIndex();
-
- char* pValue = m_aRow[column - 1];
- if (!pValue)
- {
- m_bWasNull = true;
+ if (checkNull(column))
return 0LL;
- }
- m_bWasNull = false;
- return std::atol(pValue);
+ OString sVal = m_aRows[m_nRowPosition][column - 1];
+ return sVal.toInt64();
}
uno::Reference<XResultSetMetaData> SAL_CALL OResultSet::getMetaData()
{
MutexGuard aGuard(m_aMutex);
checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
- if (!m_xMetaData.is())
- {
- m_xMetaData = new OResultSetMetaData(m_rConnection, m_pResult);
- }
return m_xMetaData;
}
@@ -432,15 +446,11 @@ sal_Int16 SAL_CALL OResultSet::getShort(sal_Int32 column)
checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
checkColumnIndex(column);
checkRowIndex();
-
- char* pValue = m_aRow[column - 1];
- if (!pValue)
- {
- m_bWasNull = true;
+ if (checkNull(column))
return 0;
- }
- m_bWasNull = false;
- return std::atoi(pValue);
+
+ OString sVal = m_aRows[m_nRowPosition][column - 1];
+ return sVal.toInt32();
}
OUString SAL_CALL OResultSet::getString(sal_Int32 column)
@@ -449,15 +459,11 @@ OUString SAL_CALL OResultSet::getString(sal_Int32 column)
checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
checkColumnIndex(column);
checkRowIndex();
+ if (checkNull(column))
+ return rtl::OUString{};
- char* pValue = m_aRow[column - 1];
- if (!pValue)
- {
- m_bWasNull = true;
- return OUString{};
- }
- m_bWasNull = false;
- return OUString(pValue, static_cast<sal_Int32>(m_aLengths[column - 1]), m_encoding);
+ OString sVal = m_aRows[m_nRowPosition][column - 1];
+ return OStringToOUString(sVal, m_encoding);
}
Time SAL_CALL OResultSet::getTime(sal_Int32 column)
@@ -467,15 +473,13 @@ Time SAL_CALL OResultSet::getTime(sal_Int32 column)
checkColumnIndex(column);
checkRowIndex();
- Time t; // initialize
- char* pValue = m_aRow[column - 1];
- if (!pValue)
- {
- m_bWasNull = true;
+ Time t;
+ if (checkNull(column))
return t;
- }
- OUString timeString{ pValue, static_cast<sal_Int32>(m_aLengths[column - 1]), m_encoding };
- OUString token;
+
+ OString sVal = m_aRows[m_nRowPosition][column - 1];
+ OString timeString{ sVal.getStr(), getDataLength(column - 1) };
+ OString token;
sal_Int32 nIndex, i = 0;
nIndex = timeString.indexOf(' ') + 1;
@@ -497,7 +501,6 @@ Time SAL_CALL OResultSet::getTime(sal_Int32 column)
i++;
} while (nIndex >= 0);
- m_bWasNull = false;
return t;
}
@@ -508,19 +511,17 @@ DateTime SAL_CALL OResultSet::getTimestamp(sal_Int32 column)
checkColumnIndex(column);
checkRowIndex();
- char* pValue = m_aRow[column - 1];
- if (!pValue)
- {
- m_bWasNull = true;
- return DateTime{}; // init
- }
+ if (checkNull(column))
+ return DateTime{};
+
+ OString sVal = m_aRows[m_nRowPosition][column - 1];
// YY-MM-DD HH:MM:SS
- std::vector<OUString> dateAndTime = lcl_split(
- OUString{ pValue, static_cast<sal_Int32>(m_aLengths[column - 1]), m_encoding }, u' ');
+ std::vector<OString> dateAndTime
+ = lcl_split(OString{ sVal.getStr(), getDataLength(column - 1) }, ' ');
- auto dateParts = lcl_split(dateAndTime.at(0), u'-');
- auto timeParts = lcl_split(dateAndTime.at(1), u':');
+ auto dateParts = lcl_split(dateAndTime.at(0), '-');
+ auto timeParts = lcl_split(dateAndTime.at(1), ':');
DateTime dt;
@@ -530,7 +531,6 @@ DateTime SAL_CALL OResultSet::getTimestamp(sal_Int32 column)
dt.Hours = timeParts.at(0).toUInt32();
dt.Minutes = timeParts.at(1).toUInt32();
dt.Seconds = timeParts.at(2).toUInt32();
- m_bWasNull = false;
return dt;
}
@@ -539,7 +539,7 @@ sal_Bool SAL_CALL OResultSet::isBeforeFirst()
MutexGuard aGuard(m_aMutex);
checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
- return m_nRowPosition == 0;
+ return m_nRowPosition < 0;
}
sal_Bool SAL_CALL OResultSet::isAfterLast()
@@ -547,7 +547,7 @@ sal_Bool SAL_CALL OResultSet::isAfterLast()
MutexGuard aGuard(m_aMutex);
checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
- return m_nRowPosition > m_nRowCount;
+ return m_nRowPosition >= m_nRowCount;
}
sal_Bool SAL_CALL OResultSet::isFirst()
@@ -555,7 +555,7 @@ sal_Bool SAL_CALL OResultSet::isFirst()
MutexGuard aGuard(m_aMutex);
checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
- return m_nRowPosition == 1 && !isAfterLast();
+ return m_nRowPosition == 0 && !isAfterLast();
}
sal_Bool SAL_CALL OResultSet::isLast()
@@ -563,23 +563,21 @@ sal_Bool SAL_CALL OResultSet::isLast()
MutexGuard aGuard(m_aMutex);
checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
- return m_nRowPosition == m_nRowCount;
+ return m_nRowPosition == m_nRowCount - 1;
}
void SAL_CALL OResultSet::beforeFirst()
{
MutexGuard aGuard(m_aMutex);
checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
- mysql_data_seek(m_pResult, 0);
- m_nRowPosition = 0;
+ m_nRowPosition = -1;
}
void SAL_CALL OResultSet::afterLast()
{
MutexGuard aGuard(m_aMutex);
checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
- mysql_data_seek(m_pResult, m_nRowCount + 1);
- m_nRowPosition = m_nRowCount + 1;
+ m_nRowPosition = m_nRowCount;
}
void SAL_CALL OResultSet::close()
@@ -587,7 +585,6 @@ void SAL_CALL OResultSet::close()
MutexGuard aGuard(m_aMutex);
checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
- mysql_free_result(m_pResult);
m_pResult = nullptr;
dispose();
}
@@ -596,10 +593,7 @@ sal_Bool SAL_CALL OResultSet::first()
{
MutexGuard aGuard(m_aMutex);
checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
-
- mysql_data_seek(m_pResult, 0);
m_nRowPosition = 0;
- next();
return true;
}
@@ -608,10 +602,7 @@ sal_Bool SAL_CALL OResultSet::last()
{
MutexGuard aGuard(m_aMutex);
checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
-
- mysql_data_seek(m_pResult, m_nRowCount - 1);
m_nRowPosition = m_nRowCount - 1;
- next();
return true;
}
@@ -621,7 +612,7 @@ sal_Bool SAL_CALL OResultSet::absolute(sal_Int32 row)
MutexGuard aGuard(m_aMutex);
checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
- sal_Int32 nToGo = row < 0 ? m_nRowCount - row : row - 1;
+ sal_Int32 nToGo = row < 0 ? (m_nRowCount - 1) - row : row - 1;
if (nToGo >= m_nRowCount)
nToGo = m_nRowCount - 1;
@@ -629,8 +620,6 @@ sal_Bool SAL_CALL OResultSet::absolute(sal_Int32 row)
nToGo = 0;
m_nRowPosition = nToGo;
- mysql_data_seek(m_pResult, nToGo);
- next();
return true;
}
@@ -650,8 +639,6 @@ sal_Bool SAL_CALL OResultSet::relative(sal_Int32 row)
nToGo = 0;
m_nRowPosition = nToGo;
- mysql_data_seek(m_pResult, nToGo);
- next();
return true;
}
@@ -661,12 +648,10 @@ sal_Bool SAL_CALL OResultSet::previous()
MutexGuard aGuard(m_aMutex);
checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
- if (m_nRowPosition <= 1)
+ if (m_nRowPosition <= 0)
return false;
- m_nRowPosition -= 2;
- mysql_data_seek(m_pResult, m_nRowPosition);
- next();
+ m_nRowPosition--;
return true;
}
@@ -706,17 +691,11 @@ sal_Bool SAL_CALL OResultSet::next()
{
MutexGuard aGuard(m_aMutex);
checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
-
- m_aRow = mysql_fetch_row(m_pResult);
- m_aLengths = mysql_fetch_lengths(m_pResult);
-
- unsigned errorNum = mysql_errno(m_pMysql);
- if (errorNum)
- mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_error(m_pMysql), errorNum, *this,
- m_encoding);
+ ensureResultFetched();
+ if (m_nRowPosition >= m_nRowCount)
+ return false;
++m_nRowPosition;
-
- return m_aRow != nullptr;
+ return true;
}
sal_Bool SAL_CALL OResultSet::wasNull()
@@ -1108,7 +1087,7 @@ css::uno::Reference<css::beans::XPropertySetInfo> SAL_CALL OResultSet::getProper
void OResultSet::checkColumnIndex(sal_Int32 index)
{
- if (index < 1 || index > static_cast<int>(fieldCount))
+ if (index < 1 || index > static_cast<int>(m_nFieldCount))
{
/* static object for efficiency or thread safety is a problem ? */
throw SQLException("index out of range", *this, OUString(), 1, Any());
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_resultset.hxx b/connectivity/source/drivers/mysqlc/mysqlc_resultset.hxx
index ce9f7bd61db8..3241420aa3f6 100644
--- a/connectivity/source/drivers/mysqlc/mysqlc_resultset.hxx
+++ b/connectivity/source/drivers/mysqlc/mysqlc_resultset.hxx
@@ -63,16 +63,29 @@ class OResultSet final : public OBase_Mutex,
public OPropertyArrayUsageHelper<OResultSet>
{
OConnection& m_rConnection;
- MYSQL_ROW m_aRow;
- unsigned long* m_aLengths = nullptr;
+
+ using DataFields = std::vector<OString>;
+ std::vector<DataFields> m_aRows;
+ std::vector<MYSQL_FIELD> m_aFields;
MYSQL* m_pMysql = nullptr;
css::uno::WeakReferenceHelper m_aStatement;
css::uno::Reference<css::sdbc::XResultSetMetaData> m_xMetaData;
MYSQL_RES* m_pResult;
- unsigned int fieldCount;
+ unsigned int m_nFieldCount = 0;
rtl_TextEncoding m_encoding;
bool m_bWasNull = false; // did the last getXXX result null?
- sal_Int32 m_nRowPosition = 0;
+ bool m_bResultFetched = false;
+
+ sal_Int32 getDataLength(sal_Int32 column)
+ {
+ return m_aRows[m_nRowCount][column - 1].getLength();
+ }
+ bool checkNull(sal_Int32 column);
+
+ /**
+ * Position of cursor indexed from 0
+ */
+ sal_Int32 m_nRowPosition = -1;
sal_Int32 m_nRowCount = 0;
// OPropertyArrayUsageHelper
@@ -87,9 +100,11 @@ class OResultSet final : public OBase_Mutex,
void SAL_CALL getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const override;
- // you can't delete objects of this type
virtual ~OResultSet() override = default;
+ void ensureResultFetched();
+ void fetchResult();
+
public:
virtual OUString SAL_CALL getImplementationName() override;