summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTamas Bunth <tamas.bunth@collabora.co.uk>2018-12-29 15:22:56 +0100
committerAndras Timar <andras.timar@collabora.com>2019-01-06 09:04:33 +0100
commit371b9f748c104aed2a3420cf1d230ecdb0aa3422 (patch)
tree1da7b1427854365c9fe39e65f3b0438eb2d42539
parent2b21e754cc41bb4aaf9a0c01638e06825eff780e (diff)
mysqlc: Fix result set metadata related issue
In order to allow fetching result of multiple result sets at time same time, all the data is fetched and copied on demand from the mysql result set. The mysql result set (MYSQL_RES) is freed afterwards. That means we need a copy of the meta information as well. Now all the meta data is stored in the driver for each result set, so it does not depend on the MYSQL_RES structure anymore. Also add test case for invoking some meta data queries before and after fetching the result set. Change-Id: Ie8bf993926ebe89cd362ab0b311d1f3d164b84df Reviewed-on: https://gerrit.libreoffice.org/65855 Reviewed-by: Andras Timar <andras.timar@collabora.com> Tested-by: Andras Timar <andras.timar@collabora.com>
-rw-r--r--connectivity/qa/connectivity/mysql/mysql.cxx78
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_databasemetadata.cxx1
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_general.cxx40
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_general.hxx12
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_prepared_resultset.cxx2
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_preparedstatement.cxx3
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_resultset.cxx2
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_resultsetmetadata.cxx101
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_resultsetmetadata.hxx38
9 files changed, 167 insertions, 110 deletions
diff --git a/connectivity/qa/connectivity/mysql/mysql.cxx b/connectivity/qa/connectivity/mysql/mysql.cxx
index 1a6d1e89e0e8..758f7eb123ff 100644
--- a/connectivity/qa/connectivity/mysql/mysql.cxx
+++ b/connectivity/qa/connectivity/mysql/mysql.cxx
@@ -13,7 +13,10 @@
#include <com/sun/star/sdbc/XColumnLocate.hpp>
#include <com/sun/star/sdbc/XConnection.hpp>
#include <com/sun/star/sdbc/XResultSet.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaData.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
#include <com/sun/star/sdbc/XParameters.hpp>
#include <com/sun/star/sdbc/XStatement.hpp>
#include <com/sun/star/sdbc/XDriver.hpp>
@@ -44,11 +47,15 @@ public:
void testCreateAndDropTable();
void testIntegerInsertAndQuery();
void testDBPositionChange();
+ void testMultipleResultsets();
+ void testDBMetaData();
CPPUNIT_TEST_SUITE(MysqlTestDriver);
CPPUNIT_TEST(testDBConnection);
CPPUNIT_TEST(testCreateAndDropTable);
CPPUNIT_TEST(testIntegerInsertAndQuery);
+ CPPUNIT_TEST(testMultipleResultsets);
+ CPPUNIT_TEST(testDBMetaData);
CPPUNIT_TEST_SUITE_END();
};
@@ -238,6 +245,77 @@ void MysqlTestDriver::testDBPositionChange()
CPPUNIT_ASSERT_EQUAL(0, nUpdateCount); // it's a DDL statement
}
+void MysqlTestDriver::testMultipleResultsets()
+{
+ Reference<XConnection> xConnection = m_xDriver->connect(m_sUrl, m_infos);
+ CPPUNIT_ASSERT(xConnection.is());
+ Reference<XStatement> xStatement = xConnection->createStatement();
+ CPPUNIT_ASSERT(xStatement.is());
+ // create two tables
+ xStatement->executeUpdate("DROP TABLE IF EXISTS myTestTable");
+ xStatement->executeUpdate("DROP TABLE IF EXISTS otherTable");
+ xStatement->executeUpdate("CREATE TABLE myTestTable (id INTEGER PRIMARY KEY)");
+ xStatement->executeUpdate("INSERT INTO myTestTable VALUES (1)");
+ xStatement->executeUpdate("CREATE TABLE otherTable (id INTEGER PRIMARY KEY)");
+ xStatement->executeUpdate("INSERT INTO otherTable VALUES (2)");
+
+ // create first result set
+ Reference<XResultSet> xResultSet = xStatement->executeQuery("SELECT id from myTestTable");
+ CPPUNIT_ASSERT_MESSAGE("result set cannot be instantiated after query", xResultSet.is());
+ // use it
+ xResultSet->next();
+ Reference<XRow> xRowFirst(xResultSet, UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(1l, xRowFirst->getLong(1));
+ // create second result set
+ Reference<XResultSet> xResultSet2 = xStatement->executeQuery("SELECT id from otherTable");
+ // use second result set
+ xResultSet2->next();
+ Reference<XRow> xRowSecond(xResultSet2, UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(2l, xRowSecond->getLong(1));
+ // now use the first result set again
+ CPPUNIT_ASSERT_EQUAL(1l, xRowFirst->getLong(1));
+
+ xStatement->executeUpdate("DROP TABLE myTestTable");
+ xStatement->executeUpdate("DROP TABLE otherTable");
+}
+
+void MysqlTestDriver::testDBMetaData()
+{
+ Reference<XConnection> xConnection = m_xDriver->connect(m_sUrl, m_infos);
+ if (!xConnection.is())
+ CPPUNIT_ASSERT_MESSAGE("cannot connect to data source!", xConnection.is());
+ uno::Reference<XStatement> xStatement = xConnection->createStatement();
+ CPPUNIT_ASSERT(xStatement.is());
+ xStatement->executeUpdate("DROP TABLE IF EXISTS myTestTable");
+
+ auto nUpdateCount = xStatement->executeUpdate(
+ "CREATE TABLE myTestTable (id INTEGER PRIMARY KEY, name VARCHAR(20))");
+ Reference<XPreparedStatement> xPrepared
+ = xConnection->prepareStatement(OUString{ "INSERT INTO myTestTable VALUES (?, ?)" });
+ Reference<XParameters> xParams(xPrepared, UNO_QUERY);
+ constexpr int ROW_COUNT = 3;
+ for (int i = 0; i < ROW_COUNT; ++i)
+ {
+ xParams->setLong(1, i);
+ xParams->setString(2, "lorem");
+ xPrepared->executeUpdate();
+ }
+
+ Reference<XResultSet> xResultSet = xStatement->executeQuery("SELECT * from myTestTable");
+ Reference<XResultSetMetaDataSupplier> xMetaDataSupplier(xResultSet, UNO_QUERY);
+ Reference<XResultSetMetaData> xMetaData = xMetaDataSupplier->getMetaData();
+ CPPUNIT_ASSERT_EQUAL(OUString{ "id" }, xMetaData->getColumnName(1));
+ CPPUNIT_ASSERT_EQUAL(OUString{ "name" }, xMetaData->getColumnName(2));
+ CPPUNIT_ASSERT(!xMetaData->isAutoIncrement(1));
+ CPPUNIT_ASSERT(!xMetaData->isCaseSensitive(2)); // default collation should be case insensitive
+ xResultSet->next(); // use it
+ // test that meta data is usable even after fetching result set
+ CPPUNIT_ASSERT_EQUAL(OUString{ "name" }, xMetaData->getColumnName(2));
+ CPPUNIT_ASSERT_THROW_MESSAGE("exception expected when indexing out of range",
+ xMetaData->getColumnName(3), sdbc::SQLException);
+ nUpdateCount = xStatement->executeUpdate("DROP TABLE myTestTable");
+}
+
CPPUNIT_TEST_SUITE_REGISTRATION(MysqlTestDriver);
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_databasemetadata.cxx b/connectivity/source/drivers/mysqlc/mysqlc_databasemetadata.cxx
index 78e6337bb76d..02419d6aa12f 100644
--- a/connectivity/source/drivers/mysqlc/mysqlc_databasemetadata.cxx
+++ b/connectivity/source/drivers/mysqlc/mysqlc_databasemetadata.cxx
@@ -43,7 +43,6 @@ using namespace com::sun::star::uno;
using namespace com::sun::star::lang;
using namespace com::sun::star::beans;
using namespace com::sun::star::sdbc;
-using mysqlc_sdbc_driver::getStringFromAny;
#include <sal/macros.h>
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_general.cxx b/connectivity/source/drivers/mysqlc/mysqlc_general.cxx
index 18315ed69fc4..c77eab4674f3 100644
--- a/connectivity/source/drivers/mysqlc/mysqlc_general.cxx
+++ b/connectivity/source/drivers/mysqlc/mysqlc_general.cxx
@@ -87,16 +87,6 @@ void allocateSqlVar(void** mem, enum_field_types eType, unsigned nSize)
}
}
-/// Use this intead of mysql_real_escape_string, because that one also escapes
-/// single quote ('), which should not be escaped
-rtl::OString escapeSql(const rtl::OString& from)
-{
- rtl::OString sRet = from.replaceAll("\\", "\\\\");
- sRet = sRet.replaceAll("\"", "\\\"");
- sRet = sRet.replaceAll("`", "\\`");
- return sRet;
-}
-
void throwFeatureNotImplementedException(const sal_Char* _pAsciiFeatureName,
const css::uno::Reference<XInterface>& _rxContext)
{
@@ -123,13 +113,6 @@ void throwSQLExceptionWithMsg(const char* msg, unsigned int errorNum,
errorNum, Any());
}
-rtl::OUString getStringFromAny(const Any& _rAny)
-{
- rtl::OUString nReturn;
- OSL_VERIFY(_rAny >>= nReturn);
- return nReturn;
-}
-
sal_Int32 mysqlToOOOType(int eType, int charsetnr) noexcept
{
// charset number 63 indicates binary
@@ -242,11 +225,13 @@ sal_Int32 mysqlStrToOOOType(const rtl::OUString& sType)
return css::sdbc::DataType::VARCHAR;
}
-rtl::OUString mysqlTypeToStr(MYSQL_FIELD* field)
+OUString mysqlTypeToStr(MYSQL_FIELD* field) { return mysqlTypeToStr(field->type, field->flags); }
+
+OUString mysqlTypeToStr(unsigned type, unsigned flags)
{
- bool isUnsigned = (field->flags & UNSIGNED_FLAG) != 0;
- bool isZerofill = (field->flags & ZEROFILL_FLAG) != 0;
- switch (field->type)
+ bool isUnsigned = (flags & UNSIGNED_FLAG) != 0;
+ bool isZerofill = (flags & ZEROFILL_FLAG) != 0;
+ switch (type)
{
case MYSQL_TYPE_BIT:
return OUString{ "BIT" };
@@ -311,21 +296,21 @@ rtl::OUString mysqlTypeToStr(MYSQL_FIELD* field)
}
case MYSQL_TYPE_VARCHAR:
case MYSQL_TYPE_VAR_STRING:
- if (field->flags & ENUM_FLAG)
+ if (flags & ENUM_FLAG)
{
return OUString{ "ENUM" };
}
- if (field->flags & SET_FLAG)
+ if (flags & SET_FLAG)
{
return OUString{ "SET" };
}
return OUString{ "VARCHAR" };
case MYSQL_TYPE_STRING:
- if (field->flags & ENUM_FLAG)
+ if (flags & ENUM_FLAG)
{
return OUString{ "ENUM" };
}
- if (field->flags & SET_FLAG)
+ if (flags & SET_FLAG)
{
return OUString{ "SET" };
}
@@ -344,11 +329,6 @@ rtl::OUString convert(const ::std::string& _string, const rtl_TextEncoding encod
return rtl::OUString(_string.c_str(), _string.size(), encoding);
}
-::std::string convert(const rtl::OUString& _string, const rtl_TextEncoding encoding)
-{
- return ::std::string(rtl::OUStringToOString(_string, encoding).getStr());
-}
-
} /* namespace */
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_general.hxx b/connectivity/source/drivers/mysqlc/mysqlc_general.hxx
index 2c0879a14d9c..5fe60f68284a 100644
--- a/connectivity/source/drivers/mysqlc/mysqlc_general.hxx
+++ b/connectivity/source/drivers/mysqlc/mysqlc_general.hxx
@@ -92,16 +92,10 @@ void resetSqlVar(void** target, T* pValue, enum_field_types type, sal_Int32 nSiz
void allocateSqlVar(void** mem, enum_field_types eType, unsigned nSize = 0);
-rtl::OString escapeSql(const rtl::OString& from);
-
-rtl::OUString getStringFromAny(const css::uno::Any& _rAny);
-
-/// @throws css::sdbc::SQLException
void throwFeatureNotImplementedException(
const sal_Char* _pAsciiFeatureName,
const css::uno::Reference<css::uno::XInterface>& _rxContext);
-/// @throws css::sdbc::SQLException
void throwInvalidArgumentException(const sal_Char* _pAsciiFeatureName,
const css::uno::Reference<css::uno::XInterface>& _rxContext);
@@ -115,9 +109,11 @@ rtl::OUString mysqlTypeToStr(MYSQL_FIELD* pField);
sal_Int32 mysqlStrToOOOType(const rtl::OUString& sType);
-rtl::OUString convert(const ::std::string& _string, const rtl_TextEncoding encoding);
+OUString mysqlTypeToStr(unsigned mysql_type, unsigned mysql_flags);
+
+sal_Int32 mysqlStrToOOOType(const OUString& sType);
-::std::string convert(const rtl::OUString& _string, const rtl_TextEncoding encoding);
+OUString convert(const ::std::string& _string, const rtl_TextEncoding encoding);
}
#endif
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_prepared_resultset.cxx b/connectivity/source/drivers/mysqlc/mysqlc_prepared_resultset.cxx
index b59afae53687..e9f07f8947c0 100644
--- a/connectivity/source/drivers/mysqlc/mysqlc_prepared_resultset.cxx
+++ b/connectivity/source/drivers/mysqlc/mysqlc_prepared_resultset.cxx
@@ -297,7 +297,7 @@ uno::Reference<XResultSetMetaData> SAL_CALL OPreparedResultSet::getMetaData()
checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
if (!m_xMetaData.is())
{
- m_xMetaData = new OResultSetMetaData(m_rConnection, m_pResult, m_encoding);
+ m_xMetaData = new OResultSetMetaData(m_rConnection, m_pResult);
}
return m_xMetaData;
}
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_preparedstatement.cxx b/connectivity/source/drivers/mysqlc/mysqlc_preparedstatement.cxx
index e9bcc1f76c37..1e1ec8468d0b 100644
--- a/connectivity/source/drivers/mysqlc/mysqlc_preparedstatement.cxx
+++ b/connectivity/source/drivers/mysqlc/mysqlc_preparedstatement.cxx
@@ -110,8 +110,7 @@ Reference<XResultSetMetaData> SAL_CALL OPreparedStatement::getMetaData()
{
MYSQL_RES* pRes = mysql_stmt_result_metadata(m_pStmt);
// TODO warning or error if no meta data.
- m_xMetaData = new OResultSetMetaData(*m_xConnection.get(), pRes,
- getOwnConnection()->getConnectionEncoding());
+ m_xMetaData = new OResultSetMetaData(*m_xConnection.get(), pRes);
}
return m_xMetaData;
}
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_resultset.cxx b/connectivity/source/drivers/mysqlc/mysqlc_resultset.cxx
index 12c0f5375ca4..4f1945d9a769 100644
--- a/connectivity/source/drivers/mysqlc/mysqlc_resultset.cxx
+++ b/connectivity/source/drivers/mysqlc/mysqlc_resultset.cxx
@@ -125,7 +125,7 @@ OResultSet::OResultSet(OConnection& rConn, OCommonStatement* pStmt, MYSQL_RES* p
, m_pResult(pResult)
, m_encoding(_encoding)
{
- m_xMetaData = new OResultSetMetaData(m_rConnection, m_pResult, m_encoding);
+ m_xMetaData = new OResultSetMetaData(m_rConnection, m_pResult);
}
void OResultSet::ensureResultFetched()
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_resultsetmetadata.cxx b/connectivity/source/drivers/mysqlc/mysqlc_resultsetmetadata.cxx
index 11e1d6996c70..79961b53d16b 100644
--- a/connectivity/source/drivers/mysqlc/mysqlc_resultsetmetadata.cxx
+++ b/connectivity/source/drivers/mysqlc/mysqlc_resultsetmetadata.cxx
@@ -23,41 +23,61 @@
#include <com/sun/star/sdbc/XRow.hpp>
#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
using namespace connectivity::mysqlc;
using namespace com::sun::star::uno;
using namespace com::sun::star::lang;
using namespace com::sun::star::sdbc;
-MYSQL_FIELD* OResultSetMetaData::getField(sal_Int32 column) const
+OResultSetMetaData::OResultSetMetaData(OConnection& rConn, MYSQL_RES* pResult)
+ : m_rConnection(rConn)
{
- return mysql_fetch_field_direct(m_pRes, column - 1);
+ MYSQL_FIELD* fields = mysql_fetch_field(pResult);
+ unsigned nFieldCount = mysql_num_fields(pResult);
+ for (unsigned i = 0; i < nFieldCount; ++i)
+ {
+ MySqlFieldInfo fieldInfo{
+ OUString{ fields[i].name, static_cast<sal_Int32>(fields[i].name_length),
+ m_rConnection.getConnectionEncoding() }, // column name
+ static_cast<sal_Int32>(fields[i].length), // length
+ mysqlc_sdbc_driver::mysqlToOOOType(fields[i].type, fields[i].charsetnr), // type
+ fields[i].type, // mysql_type
+ fields[i].charsetnr, // charset number
+ fields[i].flags,
+ OUString{ fields[i].db, static_cast<sal_Int32>(fields[i].db_length),
+ m_rConnection.getConnectionEncoding() }, // schema name
+ OUString{ fields[i].table, static_cast<sal_Int32>(fields[i].table_length),
+ m_rConnection.getConnectionEncoding() }, // table name
+ OUString{ fields[i].catalog, static_cast<sal_Int32>(fields[i].catalog_length),
+ m_rConnection.getConnectionEncoding() }, // catalog
+ static_cast<sal_Int32>(fields[i].decimals),
+ static_cast<sal_Int32>(fields[i].max_length)
+ };
+ m_fields.push_back(std::move(fieldInfo));
+ }
}
sal_Int32 SAL_CALL OResultSetMetaData::getColumnDisplaySize(sal_Int32 column)
{
- MYSQL_FIELD* pField = getField(column);
- return pField->length;
+ checkColumnIndex(column);
+ return m_fields.at(column - 1).length;
}
sal_Int32 SAL_CALL OResultSetMetaData::getColumnType(sal_Int32 column)
{
checkColumnIndex(column);
- MYSQL_FIELD* pField = getField(column);
-
- return mysqlc_sdbc_driver::mysqlToOOOType(pField->type, pField->charsetnr);
+ return m_fields.at(column - 1).type;
}
-sal_Int32 SAL_CALL OResultSetMetaData::getColumnCount() { return mysql_num_fields(m_pRes); }
+sal_Int32 SAL_CALL OResultSetMetaData::getColumnCount() { return m_fields.size(); }
sal_Bool SAL_CALL OResultSetMetaData::isCaseSensitive(sal_Int32 column)
{
- checkColumnIndex(column);
// MYSQL_FIELD::charsetnr is the collation identifier
// _ci postfix means it's insensitive
- MYSQL_FIELD* pField = getField(column);
- rtl::OUStringBuffer sql{ "SHOW COLLATION WHERE Id =" };
- sql.append(rtl::OUString::number(pField->charsetnr));
+ OUStringBuffer sql{ "SHOW COLLATION WHERE Id =" };
+ sql.append(OUString::number(m_fields.at(column - 1).charsetNumber));
Reference<XStatement> stmt = m_rConnection.createStatement();
Reference<XResultSet> rs = stmt->executeQuery(sql.makeStringAndClear());
@@ -74,54 +94,43 @@ sal_Bool SAL_CALL OResultSetMetaData::isCaseSensitive(sal_Int32 column)
rtl::OUString SAL_CALL OResultSetMetaData::getSchemaName(sal_Int32 column)
{
checkColumnIndex(column);
- MYSQL_FIELD* pField = getField(column);
-
- return rtl::OStringToOUString(pField->db, m_rConnection.getConnectionEncoding());
+ return m_fields.at(column - 1).schemaName;
}
rtl::OUString SAL_CALL OResultSetMetaData::getColumnName(sal_Int32 column)
{
checkColumnIndex(column);
-
- MYSQL_FIELD* pField = getField(column);
- return rtl::OStringToOUString(pField->name, m_rConnection.getConnectionEncoding());
+ return m_fields.at(column - 1).columnName;
}
rtl::OUString SAL_CALL OResultSetMetaData::getTableName(sal_Int32 column)
{
checkColumnIndex(column);
- MYSQL_FIELD* pField = getField(column);
- return rtl::OStringToOUString(pField->table, m_rConnection.getConnectionEncoding());
+ return m_fields.at(column - 1).tableName;
}
rtl::OUString SAL_CALL OResultSetMetaData::getCatalogName(sal_Int32 column)
{
checkColumnIndex(column);
- MYSQL_FIELD* pField = getField(column);
- return rtl::OStringToOUString(pField->catalog, m_rConnection.getConnectionEncoding());
+ return m_fields.at(column - 1).catalogName;
}
rtl::OUString SAL_CALL OResultSetMetaData::getColumnTypeName(sal_Int32 column)
{
checkColumnIndex(column);
- MYSQL_FIELD* pField = getField(column);
-
- return mysqlc_sdbc_driver::mysqlTypeToStr(pField);
+ return mysqlc_sdbc_driver::mysqlTypeToStr(m_fields.at(column - 1).mysql_type,
+ m_fields.at(column - 1).flags);
}
rtl::OUString SAL_CALL OResultSetMetaData::getColumnLabel(sal_Int32 column)
{
checkColumnIndex(column);
- MYSQL_FIELD* pField = getField(column);
- return rtl::OStringToOUString(pField->name, m_rConnection.getConnectionEncoding());
+ return getColumnName(column);
}
-rtl::OUString SAL_CALL OResultSetMetaData::getColumnServiceName(sal_Int32 column)
+OUString SAL_CALL OResultSetMetaData::getColumnServiceName(sal_Int32 /*column*/)
{
- checkColumnIndex(column);
-
- rtl::OUString aRet = rtl::OUString();
- return aRet;
+ return OUString{};
}
sal_Bool SAL_CALL OResultSetMetaData::isCurrency(sal_Int32 /*column*/)
@@ -132,47 +141,43 @@ sal_Bool SAL_CALL OResultSetMetaData::isCurrency(sal_Int32 /*column*/)
sal_Bool SAL_CALL OResultSetMetaData::isAutoIncrement(sal_Int32 column)
{
checkColumnIndex(column);
-
- MYSQL_FIELD* pField = getField(column);
- return pField->flags & AUTO_INCREMENT_FLAG;
+ return (m_fields.at(column - 1).flags & AUTO_INCREMENT_FLAG) != 0;
}
sal_Bool SAL_CALL OResultSetMetaData::isSigned(sal_Int32 column)
{
checkColumnIndex(column);
-
- MYSQL_FIELD* pField = getField(column);
- return !(pField->flags & UNSIGNED_FLAG);
+ return !(m_fields.at(column - 1).flags & UNSIGNED_FLAG);
}
sal_Int32 SAL_CALL OResultSetMetaData::getPrecision(sal_Int32 column)
{
checkColumnIndex(column);
- MYSQL_FIELD* pField = getField(column);
- return pField->max_length - pField->decimals;
+ return m_fields.at(column - 1).max_length - m_fields.at(column - 1).decimals;
}
sal_Int32 SAL_CALL OResultSetMetaData::getScale(sal_Int32 column)
{
checkColumnIndex(column);
- MYSQL_FIELD* pField = getField(column);
- return pField->decimals;
+ return m_fields.at(column - 1).decimals;
}
sal_Int32 SAL_CALL OResultSetMetaData::isNullable(sal_Int32 column)
{
checkColumnIndex(column);
- MYSQL_FIELD* pField = getField(column);
- return !(pField->flags & NOT_NULL_FLAG);
+ return (m_fields.at(column - 1).flags & NOT_NULL_FLAG) ? 0 : 1;
}
-sal_Bool SAL_CALL OResultSetMetaData::isSearchable(sal_Int32 /*column*/) { return true; }
+sal_Bool SAL_CALL OResultSetMetaData::isSearchable(sal_Int32 column)
+{
+ checkColumnIndex(column);
+ return true;
+}
sal_Bool SAL_CALL OResultSetMetaData::isReadOnly(sal_Int32 column)
{
checkColumnIndex(column);
- MYSQL_FIELD* pField = getField(column);
- return !(pField->db && strlen(pField->db));
+ return m_fields.at(column - 1).schemaName.isEmpty();
}
sal_Bool SAL_CALL OResultSetMetaData::isDefinitelyWritable(sal_Int32 column)
@@ -189,7 +194,7 @@ sal_Bool SAL_CALL OResultSetMetaData::isWritable(sal_Int32 column)
void OResultSetMetaData::checkColumnIndex(sal_Int32 columnIndex)
{
- unsigned nColCount = mysql_num_fields(m_pRes);
+ auto nColCount = m_fields.size();
if (columnIndex < 1 || columnIndex > static_cast<sal_Int32>(nColCount))
{
rtl::OUStringBuffer buf;
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_resultsetmetadata.hxx b/connectivity/source/drivers/mysqlc/mysqlc_resultsetmetadata.hxx
index a78b8c9eb694..075733855314 100644
--- a/connectivity/source/drivers/mysqlc/mysqlc_resultsetmetadata.hxx
+++ b/connectivity/source/drivers/mysqlc/mysqlc_resultsetmetadata.hxx
@@ -37,6 +37,21 @@ using ::com::sun::star::sdbc::SQLException;
using ::com::sun::star::uno::RuntimeException;
using ::com::sun::star::uno::RuntimeException;
+struct MySqlFieldInfo
+{
+ OUString columnName;
+ sal_Int32 length = 0;
+ sal_Int32 type = 0;
+ unsigned mysql_type = 0;
+ unsigned charsetNumber = 0;
+ unsigned flags = 0;
+ OUString schemaName;
+ OUString tableName;
+ OUString catalogName;
+ sal_Int32 decimals;
+ sal_Int32 max_length;
+};
+
//************ Class: ResultSetMetaData
typedef ::cppu::WeakImplHelper1<css::sdbc::XResultSetMetaData> OResultSetMetaData_BASE;
@@ -45,24 +60,13 @@ class OResultSetMetaData final : public OResultSetMetaData_BASE
{
private:
OConnection& m_rConnection;
- MYSQL_RES* m_pRes;
- rtl_TextEncoding m_encoding;
+ std::vector<MySqlFieldInfo> m_fields;
+ void checkColumnIndex(sal_Int32 columnIndex);
virtual ~OResultSetMetaData() override = default;
- MYSQL_FIELD* getField(sal_Int32 column) const;
public:
- OResultSetMetaData(OConnection& rConn, MYSQL_RES* pResult, rtl_TextEncoding _encoding)
- : m_rConnection(rConn)
- , m_pRes(pResult)
- , m_encoding(_encoding)
- {
- }
-
- rtl::OUString convert(const ::std::string& _string) const
- {
- return rtl::OUString(_string.c_str(), _string.size(), m_encoding);
- }
+ OResultSetMetaData(OConnection& rConn, MYSQL_RES* pResult);
sal_Int32 SAL_CALL getColumnCount() SAL_OVERRIDE;
@@ -95,11 +99,7 @@ public:
sal_Bool SAL_CALL isWritable(sal_Int32 column) SAL_OVERRIDE;
sal_Bool SAL_CALL isDefinitelyWritable(sal_Int32 column) SAL_OVERRIDE;
- rtl::OUString SAL_CALL getColumnServiceName(sal_Int32 column) SAL_OVERRIDE;
-
- /// @throws SQLException
- /// @throws RuntimeException
- void checkColumnIndex(sal_Int32 columnIndex);
+ OUString SAL_CALL getColumnServiceName(sal_Int32 column) override;
};
}
}