connectivity/Library_mysqlc.mk | 1 connectivity/qa/connectivity/mysql/mysql.cxx | 48 ++ connectivity/source/drivers/mysqlc/mysqlc_resultset.cxx | 283 +++++++--------- connectivity/source/drivers/mysqlc/mysqlc_resultset.hxx | 25 + 4 files changed, 200 insertions(+), 157 deletions(-)
New commits: commit 0c6da44c9249e7b9355c0efd9a60004701867275 Author: Tamas Bunth <tamas.bu...@collabora.co.uk> AuthorDate: Tue Oct 30 18:49:46 2018 +0100 Commit: Tamás Bunth <btom...@gmail.com> CommitDate: Mon Nov 5 10:06:03 2018 +0100 mysqlc: allow multiple open statements Change-Id: I07e57ea7d9e6af1c7543483b1ab54a0b8c5be2d5 Reviewed-on: https://gerrit.libreoffice.org/62640 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> Reviewed-by: Tamás Bunth <btom...@gmail.com> 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; _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits