diff options
Diffstat (limited to 'connectivity')
5 files changed, 124 insertions, 68 deletions
diff --git a/connectivity/qa/connectivity/mysql/mysql.cxx b/connectivity/qa/connectivity/mysql/mysql.cxx index f93885fb34d9..0d1d9ef85145 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> @@ -46,12 +49,14 @@ public: 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(); }; @@ -289,6 +294,43 @@ void MysqlTestDriver::testMultipleResultsets() 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_general.cxx b/connectivity/source/drivers/mysqlc/mysqlc_general.cxx index aa0b0a9e4e5a..5827b4bd35b9 100644 --- a/connectivity/source/drivers/mysqlc/mysqlc_general.cxx +++ b/connectivity/source/drivers/mysqlc/mysqlc_general.cxx @@ -225,11 +225,13 @@ sal_Int32 mysqlStrToOOOType(const OUString& sType) return css::sdbc::DataType::VARCHAR; } -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" }; @@ -294,21 +296,21 @@ 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" }; } diff --git a/connectivity/source/drivers/mysqlc/mysqlc_general.hxx b/connectivity/source/drivers/mysqlc/mysqlc_general.hxx index a7886c3015d2..f8d866964318 100644 --- a/connectivity/source/drivers/mysqlc/mysqlc_general.hxx +++ b/connectivity/source/drivers/mysqlc/mysqlc_general.hxx @@ -92,12 +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); -/// @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); @@ -109,6 +107,8 @@ sal_Int32 mysqlToOOOType(int eType, int charsetnr) noexcept; OUString mysqlTypeToStr(MYSQL_FIELD* pField); +OUString mysqlTypeToStr(unsigned mysql_type, unsigned mysql_flags); + sal_Int32 mysqlStrToOOOType(const OUString& sType); OUString convert(const ::std::string& _string, const rtl_TextEncoding encoding); diff --git a/connectivity/source/drivers/mysqlc/mysqlc_resultsetmetadata.cxx b/connectivity/source/drivers/mysqlc/mysqlc_resultsetmetadata.cxx index f5962a2a54ff..ba8c36da83ce 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); OUStringBuffer sql{ "SHOW COLLATION WHERE Id =" }; - sql.append(OUString::number(pField->charsetnr)); + 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) OUString SAL_CALL OResultSetMetaData::getSchemaName(sal_Int32 column) { checkColumnIndex(column); - MYSQL_FIELD* pField = getField(column); - - return OStringToOUString(pField->db, m_rConnection.getConnectionEncoding()); + return m_fields.at(column - 1).schemaName; } OUString SAL_CALL OResultSetMetaData::getColumnName(sal_Int32 column) { checkColumnIndex(column); - - MYSQL_FIELD* pField = getField(column); - return OStringToOUString(pField->name, m_rConnection.getConnectionEncoding()); + return m_fields.at(column - 1).columnName; } OUString SAL_CALL OResultSetMetaData::getTableName(sal_Int32 column) { checkColumnIndex(column); - MYSQL_FIELD* pField = getField(column); - return OStringToOUString(pField->table, m_rConnection.getConnectionEncoding()); + return m_fields.at(column - 1).tableName; } OUString SAL_CALL OResultSetMetaData::getCatalogName(sal_Int32 column) { checkColumnIndex(column); - MYSQL_FIELD* pField = getField(column); - return OStringToOUString(pField->catalog, m_rConnection.getConnectionEncoding()); + return m_fields.at(column - 1).catalogName; } 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); } OUString SAL_CALL OResultSetMetaData::getColumnLabel(sal_Int32 column) { checkColumnIndex(column); - MYSQL_FIELD* pField = getField(column); - return OStringToOUString(pField->name, m_rConnection.getConnectionEncoding()); + return getColumnName(column); } -OUString SAL_CALL OResultSetMetaData::getColumnServiceName(sal_Int32 column) +OUString SAL_CALL OResultSetMetaData::getColumnServiceName(sal_Int32 /*column*/) { - checkColumnIndex(column); - - OUString aRet = 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) != 0; + 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) ? 0 : 1; + 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)) { OUStringBuffer buf; diff --git a/connectivity/source/drivers/mysqlc/mysqlc_resultsetmetadata.hxx b/connectivity/source/drivers/mysqlc/mysqlc_resultsetmetadata.hxx index 346695def388..a7de887bd78d 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,17 +60,13 @@ class OResultSetMetaData final : public OResultSetMetaData_BASE { private: OConnection& m_rConnection; - MYSQL_RES* m_pRes; + 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) - : m_rConnection(rConn) - , m_pRes(pResult) - { - } + OResultSetMetaData(OConnection& rConn, MYSQL_RES* pResult); sal_Int32 SAL_CALL getColumnCount() override; @@ -89,10 +100,6 @@ public: sal_Bool SAL_CALL isDefinitelyWritable(sal_Int32 column) override; OUString SAL_CALL getColumnServiceName(sal_Int32 column) override; - - /// @throws SQLException - /// @throws RuntimeException - void checkColumnIndex(sal_Int32 columnIndex); }; } } |