connectivity/source/drivers/mysqlc/mysqlc_column.cxx  |   48 ++++
 connectivity/source/drivers/mysqlc/mysqlc_column.hxx  |   32 ++
 connectivity/source/drivers/mysqlc/mysqlc_columns.cxx |   35 +++
 connectivity/source/drivers/mysqlc/mysqlc_columns.hxx |   29 ++
 connectivity/source/drivers/mysqlc/mysqlc_table.cxx   |  175 +++++++++++++++
 connectivity/source/drivers/mysqlc/mysqlc_table.hxx   |   80 ++++++
 connectivity/source/drivers/mysqlc/mysqlc_tables.cxx  |  209 ++++++++++++++++++
 connectivity/source/drivers/mysqlc/mysqlc_tables.hxx  |   58 ++++
 8 files changed, 666 insertions(+)

New commits:
commit bb29b12a9e367d181a5d9d962d466df41e093e0c
Author:     Julien Nabet <serval2...@yahoo.fr>
AuthorDate: Tue Jan 11 22:10:59 2022 +0100
Commit:     Julien Nabet <serval2...@yahoo.fr>
CommitDate: Tue Jan 11 23:42:51 2022 +0100

    Mysql/MariaDB: add column(s) + table(s) (almost) skeleton part
    
    Change-Id: I9447d7220faeb7a8147e649f0cca57ae15d3e9aa
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128301
    Tested-by: Jenkins
    Reviewed-by: Julien Nabet <serval2...@yahoo.fr>

diff --git a/connectivity/source/drivers/mysqlc/mysqlc_column.cxx 
b/connectivity/source/drivers/mysqlc/mysqlc_column.cxx
new file mode 100644
index 000000000000..960f0ff97526
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/mysqlc_column.cxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "mysqlc_column.hxx"
+
+#include <TConnection.hxx>
+
+using namespace connectivity;
+using namespace connectivity::mysqlc;
+using namespace connectivity::sdbcx;
+
+Column::Column()
+    : OColumn(true) // case sensitive
+{
+    construct();
+}
+
+void Column::construct()
+{
+    m_sAutoIncrement = "auto_increment";
+    registerProperty(
+        
OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_AUTOINCREMENTCREATION),
+        PROPERTY_ID_AUTOINCREMENTCREATION, 0, &m_sAutoIncrement,
+        cppu::UnoType<decltype(m_sAutoIncrement)>::get());
+}
+
+::cppu::IPropertyArrayHelper* Column::createArrayHelper(sal_Int32 /*_nId*/) 
const
+{
+    return doCreateArrayHelper();
+}
+
+::cppu::IPropertyArrayHelper& SAL_CALL Column::getInfoHelper()
+{
+    return *Column_PROP::getArrayHelper(isNew() ? 1 : 0);
+}
+
+css::uno::Sequence<OUString> SAL_CALL Column::getSupportedServiceNames()
+{
+    return { "com.sun.star.sdbcx.Column" };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_column.hxx 
b/connectivity/source/drivers/mysqlc/mysqlc_column.hxx
new file mode 100644
index 000000000000..f69ef1afcea7
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/mysqlc_column.hxx
@@ -0,0 +1,32 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+#pragma once
+
+#include <connectivity/sdbcx/VColumn.hxx>
+
+namespace connectivity::mysqlc
+{
+class Column;
+typedef ::comphelper::OIdPropertyArrayUsageHelper<Column> Column_PROP;
+class Column : public sdbcx::OColumn, public Column_PROP
+{
+    OUString m_sAutoIncrement;
+
+protected:
+    virtual ::cppu::IPropertyArrayHelper* createArrayHelper(sal_Int32 _nId) 
const override;
+    virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+
+public:
+    Column();
+    virtual void construct() override;
+    virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() 
override;
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_columns.cxx 
b/connectivity/source/drivers/mysqlc/mysqlc_columns.cxx
new file mode 100644
index 000000000000..6f1837ba2e8c
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/mysqlc_columns.cxx
@@ -0,0 +1,35 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "mysqlc_columns.hxx"
+#include "mysqlc_column.hxx"
+
+using namespace ::connectivity;
+using namespace ::connectivity::mysqlc;
+using namespace ::connectivity::sdbcx;
+
+using namespace ::cppu;
+using namespace ::osl;
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::uno;
+
+Columns::Columns(Table& rTable, Mutex& rMutex, const ::std::vector<OUString>& 
rVector)
+    : OColumnsHelper(rTable,
+                     true, // case sensitivity
+                     rMutex, rVector,
+                     /*bUseHardRef*/ true)
+{
+    OColumnsHelper::setParent(&rTable);
+}
+
+Reference<css::beans::XPropertySet> Columns::createDescriptor() { return new 
Column; }
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_columns.hxx 
b/connectivity/source/drivers/mysqlc/mysqlc_columns.hxx
new file mode 100644
index 000000000000..34230db37bb5
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/mysqlc_columns.hxx
@@ -0,0 +1,29 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include "mysqlc_table.hxx"
+
+#include <connectivity/TColumnsHelper.hxx>
+
+namespace connectivity::mysqlc
+{
+class Columns : public ::connectivity::OColumnsHelper
+{
+protected:
+    virtual css::uno::Reference<css::beans::XPropertySet> createDescriptor() 
override;
+
+public:
+    Columns(Table& rTable, ::osl::Mutex& rMutex, const 
::std::vector<OUString>& _rVector);
+};
+
+} // namespace connectivity::mysqlc
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_table.cxx 
b/connectivity/source/drivers/mysqlc/mysqlc_table.cxx
new file mode 100644
index 000000000000..cd877f26cbac
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/mysqlc_table.cxx
@@ -0,0 +1,175 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "mysqlc_columns.hxx"
+#include "mysqlc_indexes.hxx"
+#include "mysqlc_keys.hxx"
+#include "mysqlc_table.hxx"
+
+#include <TConnection.hxx>
+
+#include <sal/log.hxx>
+#include <comphelper/sequence.hxx>
+#include <connectivity/dbtools.hxx>
+
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#include <com/sun/star/sdbcx/Privilege.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+
+using namespace ::connectivity;
+using namespace ::connectivity::mysqlc;
+using namespace ::connectivity::sdbcx;
+
+using namespace ::osl;
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::uno;
+
+Table::Table(Tables* pTables, Mutex& rMutex, const 
uno::Reference<XConnection>& rConnection)
+    : OTableHelper(pTables, rConnection, true)
+    , m_rMutex(rMutex)
+    , m_nPrivileges(0)
+{
+    construct();
+}
+
+Table::Table(Tables* pTables, Mutex& rMutex, const 
uno::Reference<XConnection>& rConnection,
+             const OUString& rName, const OUString& rType, const OUString& 
rDescription)
+    : OTableHelper(pTables, rConnection, true, rName, rType, rDescription, "", 
"")
+    , m_rMutex(rMutex)
+    , m_nPrivileges(0)
+{
+    construct();
+}
+
+void Table::construct()
+{
+    OTableHelper::construct();
+    if (isNew())
+        return;
+
+    // TODO: get privileges when in non-embedded mode.
+    m_nPrivileges = Privilege::DROP | Privilege::REFERENCE | Privilege::ALTER 
| Privilege::CREATE
+                    | Privilege::READ | Privilege::DELETE | Privilege::UPDATE 
| Privilege::INSERT
+                    | Privilege::SELECT;
+    
registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRIVILEGES),
+                     PROPERTY_ID_PRIVILEGES, PropertyAttribute::READONLY, 
&m_nPrivileges,
+                     cppu::UnoType<decltype(m_nPrivileges)>::get());
+}
+//----- OTableHelper ---------------------------------------------------------
+OCollection* Table::createColumns(const ::std::vector<OUString>& rNames)
+{
+    return new Columns(*this, m_rMutex, rNames);
+}
+
+OCollection* Table::createKeys(const ::std::vector<OUString>& rNames)
+{
+    return new Keys(this, m_rMutex, rNames);
+}
+
+OCollection* Table::createIndexes(const ::std::vector<OUString>& rNames)
+{
+    return new Indexes(this, m_rMutex, rNames);
+}
+
+//----- XAlterTable -----------------------------------------------------------
+void SAL_CALL Table::alterColumnByName(const OUString& /* rColName */,
+                                       const uno::Reference<XPropertySet>& /* 
rDescriptor */)
+{
+    MutexGuard aGuard(m_rMutex);
+    checkDisposed(WeakComponentImplHelperBase::rBHelper.bDisposed);
+
+    uno::Reference<XPropertySet> xColumn(m_xColumns->getByName(rColName), 
UNO_QUERY);
+
+    // sdbcx::Descriptor
+    const bool bNameChanged
+        = xColumn->getPropertyValue("Name") != 
rDescriptor->getPropertyValue("Name");
+    // sdbcx::ColumnDescriptor
+    const bool bTypeChanged
+        = xColumn->getPropertyValue("Type") != 
rDescriptor->getPropertyValue("Type");
+    const bool bTypeNameChanged
+        = xColumn->getPropertyValue("TypeName") != 
rDescriptor->getPropertyValue("TypeName");
+    const bool bPrecisionChanged
+        = xColumn->getPropertyValue("Precision") != 
rDescriptor->getPropertyValue("Precision");
+    const bool bScaleChanged
+        = xColumn->getPropertyValue("Scale") != 
rDescriptor->getPropertyValue("Scale");
+    const bool bIsNullableChanged
+        = xColumn->getPropertyValue("IsNullable") != 
rDescriptor->getPropertyValue("IsNullable");
+    const bool bIsAutoIncrementChanged = 
xColumn->getPropertyValue("IsAutoIncrement")
+                                         != 
rDescriptor->getPropertyValue("IsAutoIncrement");
+
+    // TODO: remainder -- these are all "optional" so have to detect presence 
and change.
+
+    bool bDefaultChanged = xColumn->getPropertyValue("DefaultValue")
+                           != rDescriptor->getPropertyValue("DefaultValue");
+
+    // TODO: tests to do
+    if (bTypeChanged || bTypeNameChanged || bPrecisionChanged || bScaleChanged 
|| bIsNullableChanged
+        || bIsAutoIncrementChanged || bDefaultChanged)
+    {
+        // If bPrecisionChanged this will only succeed if we have increased the
+        // precision, otherwise an exception is thrown -- however the base
+        // gui then offers to delete and recreate the column.
+        OUString sSql(getAlterTableColumn(rColName) + "TYPE "
+                      + ::dbtools::createStandardTypePart(rDescriptor, 
getConnection()));
+        getConnection()->createStatement()->execute(sSql);
+        // TODO: could cause errors e.g. if incompatible types, deal with them 
here as appropriate.
+        // possibly we have to wrap things in Util::evaluateStatusVector.
+    }
+
+    // TODO: tests to do
+    // TODO: quote identifiers as needed.
+    if (bNameChanged)
+    {
+        OUString sNewColName;
+        rDescriptor->getPropertyValue("Name") >>= sNewColName;
+        OUString sSql(getAlterTableColumn(rColName) + " TO \"" + sNewColName + 
"\"");
+
+        getConnection()->createStatement()->execute(sSql);
+    }
+
+    m_xColumns->refresh();
+}
+
+void SAL_CALL Table::alterColumnByIndex(
+    sal_Int32 /* index */, const 
css::uno::Reference<css::beans::XPropertySet>& /* descriptor */)
+{
+    MutexGuard aGuard(m_rMutex);
+    // TODO: implement
+}
+
+// ----- XRename --------------------------------------------------------------
+void SAL_CALL Table::rename(const OUString&)
+{
+    MutexGuard aGuard(m_rMutex);
+    // TODO: implement
+}
+
+// ----- XInterface -----------------------------------------------------------
+Any SAL_CALL Table::queryInterface(const Type& rType)
+{
+    if (rType.getTypeName() == "com.sun.star.sdbcx.XRename")
+        return Any();
+    return OTableHelper::queryInterface(rType);
+}
+
+// ----- XTypeProvider --------------------------------------------------------
+uno::Sequence<Type> SAL_CALL Table::getTypes() { return 
OTableHelper::getTypes(); }
+
+OUString Table::getAlterTableColumn(std::u16string_view rColumn)
+{
+    // TODO: test
+    return ("ALTER TABLE \"" + getName() + "\" ALTER COLUMN \"" + rColumn + 
"\" ");
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_table.hxx 
b/connectivity/source/drivers/mysqlc/mysqlc_table.hxx
new file mode 100644
index 000000000000..18e21c4c9126
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/mysqlc_table.hxx
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include "mysqlc_tables.hxx"
+
+#include <connectivity/TTableHelper.hxx>
+
+namespace connectivity::mysqlc
+{
+/**
+* Implements sdbcx.Table. We don't support table renaming (XRename)
+* hence the appropriate methods are overridden.
+*/
+class Table : public OTableHelper
+{
+private:
+    ::osl::Mutex& m_rMutex;
+    sal_Int32 m_nPrivileges;
+
+    /**
+    * Get the ALTER TABLE [TABLE] ALTER [COLUMN] String.
+    * Includes a trailing space.
+    */
+    OUString getAlterTableColumn(std::u16string_view rColumn);
+
+protected:
+    void construct() override;
+
+public:
+    Table(Tables* pTables, ::osl::Mutex& rMutex,
+          const css::uno::Reference<css::sdbc::XConnection>& _xConnection);
+    Table(Tables* pTables, ::osl::Mutex& rMutex,
+          const css::uno::Reference<css::sdbc::XConnection>& _xConnection, 
const OUString& rName,
+          const OUString& rType, const OUString& rDescription);
+
+    // OTableHelper
+    virtual ::connectivity::sdbcx::OCollection*
+    createColumns(const ::std::vector<OUString>& rNames) override;
+    virtual ::connectivity::sdbcx::OCollection*
+    createKeys(const ::std::vector<OUString>& rNames) override;
+    virtual ::connectivity::sdbcx::OCollection*
+    createIndexes(const ::std::vector<OUString>& rNames) override;
+
+    // XAlterTable
+    /**
+    * See css::sdbcx::ColumnDescriptor for details of
+    * rDescriptor.
+    */
+    virtual void SAL_CALL
+    alterColumnByName(const OUString& rColName,
+                      const css::uno::Reference<css::beans::XPropertySet>& 
rDescriptor) override;
+
+    virtual void SAL_CALL alterColumnByIndex(
+        sal_Int32 index, const css::uno::Reference<css::beans::XPropertySet>& 
descriptor) override;
+
+    // XRename
+    virtual void SAL_CALL rename(const OUString& sName) override;
+
+    //XInterface
+    virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type& rType) 
override;
+
+    //XTypeProvider
+    virtual css::uno::Sequence<css::uno::Type> SAL_CALL getTypes() override;
+};
+
+} // namespace connectivity::mysqlc
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_tables.cxx 
b/connectivity/source/drivers/mysqlc/mysqlc_tables.cxx
new file mode 100644
index 000000000000..f32e5b4c275f
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/mysqlc_tables.cxx
@@ -0,0 +1,209 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "mysqlc_table.hxx"
+#include "mysqlc_tables.hxx"
+
+#include <TConnection.hxx>
+
+#include <connectivity/dbtools.hxx>
+
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <comphelper/types.hxx>
+
+using namespace ::connectivity;
+using namespace ::connectivity::mysqlc;
+using namespace ::connectivity::sdbcx;
+using namespace ::cppu;
+using namespace ::osl;
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::uno;
+
+//----- OCollection -----------------------------------------------------------
+void Tables::impl_refresh()
+{
+    // TODO implement
+}
+
+ObjectType Tables::createObject(const OUString& rName)
+{
+    // Only retrieving a single table, so table type is irrelevant (param 4)
+    uno::Reference<XResultSet> xTables
+        = m_xMetaData->getTables(Any(), u"%", rName, 
uno::Sequence<OUString>());
+
+    if (!xTables.is())
+        throw RuntimeException("Could not acquire table.");
+
+    uno::Reference<XRow> xRow(xTables, UNO_QUERY_THROW);
+
+    if (!xTables->next())
+        throw RuntimeException();
+
+    ObjectType xRet(new Table(this, m_rMutex, m_xMetaData->getConnection(),
+                              xRow->getString(3), // Name
+                              xRow->getString(4), // Type
+                              xRow->getString(5))); // Description / Remarks / 
Comments
+
+    if (xTables->next())
+        throw RuntimeException("Found more tables than expected.");
+
+    return xRet;
+}
+
+OUString Tables::createStandardColumnPart(const Reference<XPropertySet>& 
xColProp,
+                                          const Reference<XConnection>& 
_xConnection)
+{
+    // TODO test
+    Reference<XDatabaseMetaData> xMetaData = _xConnection->getMetaData();
+
+    ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap();
+
+    bool bIsAutoIncrement = false;
+    
xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_ISAUTOINCREMENT))
+        >>= bIsAutoIncrement;
+
+    const OUString sQuoteString = xMetaData->getIdentifierQuoteString();
+    OUStringBuffer aSql(
+        ::dbtools::quoteName(sQuoteString, 
::comphelper::getString(xColProp->getPropertyValue(
+                                               
rPropMap.getNameByIndex(PROPERTY_ID_NAME)))));
+
+    // check if the user enter a specific string to create autoincrement values
+    OUString sAutoIncrementValue;
+    Reference<XPropertySetInfo> xPropInfo = xColProp->getPropertySetInfo();
+
+    if (xPropInfo.is()
+        && 
xPropInfo->hasPropertyByName(rPropMap.getNameByIndex(PROPERTY_ID_AUTOINCREMENTCREATION)))
+        
xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_AUTOINCREMENTCREATION))
+            >>= sAutoIncrementValue;
+
+    aSql.append(" ");
+
+    aSql.append(dbtools::createStandardTypePart(xColProp, _xConnection));
+    // Add character set for (VAR)BINARY (fix) types:
+    // (VAR) BINARY is distinguished from other CHAR types by its character 
set.
+    // Octets is a special character set for binary data.
+    if (xPropInfo.is() && 
xPropInfo->hasPropertyByName(rPropMap.getNameByIndex(PROPERTY_ID_TYPE)))
+    {
+        sal_Int32 aType = 0;
+        xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_TYPE)) 
>>= aType;
+        if (aType == DataType::BINARY || aType == DataType::VARBINARY)
+        {
+            aSql.append(" ");
+            aSql.append("CHARACTER SET OCTETS");
+        }
+    }
+
+    if (bIsAutoIncrement && !sAutoIncrementValue.isEmpty())
+    {
+        aSql.append(" ");
+        aSql.append(sAutoIncrementValue);
+    }
+    // AutoIncrement "IDENTITY" is implicitly "NOT NULL"
+    else if (::comphelper::getINT32(
+                 
xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_ISNULLABLE)))
+             == ColumnValue::NO_NULLS)
+        aSql.append(" NOT NULL");
+
+    return aSql.makeStringAndClear();
+}
+
+uno::Reference<XPropertySet> Tables::createDescriptor()
+{
+    // There is some internal magic so that the same class can be used as 
either
+    // a descriptor or as a normal table. See VTable.cxx for the details. In 
our
+    // case we just need to ensure we use the correct constructor.
+    return new Table(this, m_rMutex, m_xMetaData->getConnection());
+}
+
+//----- XAppend ---------------------------------------------------------------
+ObjectType Tables::appendObject(const OUString& rName,
+                                const uno::Reference<XPropertySet>& 
rDescriptor)
+{
+    /* OUString sSql(::dbtools::createSqlCreateTableStatement(rDescriptor,
+                                                            
m_xMetaData->getConnection())); */
+    OUStringBuffer aSqlBuffer("CREATE TABLE ");
+    OUString sCatalog, sSchema, sComposedName, sTable;
+    const Reference<XConnection>& xConnection = m_xMetaData->getConnection();
+
+    ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap();
+
+    
rDescriptor->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME)) 
>>= sCatalog;
+    
rDescriptor->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_SCHEMANAME)) 
>>= sSchema;
+    rDescriptor->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME)) 
>>= sTable;
+
+    sComposedName = ::dbtools::composeTableName(m_xMetaData, sCatalog, 
sSchema, sTable, true,
+                                                
::dbtools::EComposeRule::InTableDefinitions);
+    if (sComposedName.isEmpty())
+        ::dbtools::throwFunctionSequenceException(xConnection);
+
+    aSqlBuffer.append(sComposedName);
+    aSqlBuffer.append(" (");
+
+    // columns
+    Reference<XColumnsSupplier> xColumnSup(rDescriptor, UNO_QUERY);
+    Reference<XIndexAccess> xColumns(xColumnSup->getColumns(), UNO_QUERY);
+    // check if there are columns
+    if (!xColumns.is() || !xColumns->getCount())
+        ::dbtools::throwFunctionSequenceException(xConnection);
+
+    Reference<XPropertySet> xColProp;
+
+    sal_Int32 nCount = xColumns->getCount();
+    for (sal_Int32 i = 0; i < nCount; ++i)
+    {
+        if ((xColumns->getByIndex(i) >>= xColProp) && xColProp.is())
+        {
+            aSqlBuffer.append(createStandardColumnPart(xColProp, xConnection));
+            aSqlBuffer.append(",");
+        }
+    }
+    OUString sSql = aSqlBuffer.makeStringAndClear();
+
+    const OUString sKeyStmt = 
::dbtools::createStandardKeyStatement(rDescriptor, xConnection);
+    if (!sKeyStmt.isEmpty())
+        sSql += sKeyStmt;
+    else
+    {
+        if (sSql.endsWith(","))
+            sSql = sSql.replaceAt(sSql.getLength() - 1, 1, u")");
+        else
+            sSql += ")";
+    }
+
+    m_xMetaData->getConnection()->createStatement()->execute(sSql);
+
+    return createObject(rName);
+}
+
+//----- XDrop -----------------------------------------------------------------
+void Tables::dropObject(sal_Int32 nPosition, const OUString& sName)
+{
+    uno::Reference<XPropertySet> xTable(getObject(nPosition));
+
+    if (ODescriptor::isNew(xTable))
+        return;
+
+    OUString sType;
+    xTable->getPropertyValue("Type") >>= sType;
+
+    const OUString sQuoteString = m_xMetaData->getIdentifierQuoteString();
+
+    m_xMetaData->getConnection()->createStatement()->execute(
+        "DROP " + sType + ::dbtools::quoteName(sQuoteString, sName));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_tables.hxx 
b/connectivity/source/drivers/mysqlc/mysqlc_tables.hxx
new file mode 100644
index 000000000000..0dae3658f12a
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/mysqlc_tables.hxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
+
+#include <connectivity/sdbcx/VCollection.hxx>
+
+namespace connectivity::mysqlc
+{
+/**
+* This implements com.sun.star.sdbcx.Container, which seems to be
+* also known by the name of Tables and Collection.
+*/
+class Tables : public ::connectivity::sdbcx::OCollection
+{
+protected:
+    css::uno::Reference<css::sdbc::XDatabaseMetaData> m_xMetaData;
+
+    static OUString createStandardColumnPart(
+        const css::uno::Reference<css::beans::XPropertySet>& xColProp,
+        const css::uno::Reference<com::sun::star::sdbc::XConnection>& 
_xConnection);
+
+    // OCollection
+    virtual void impl_refresh() override;
+    virtual ::connectivity::sdbcx::ObjectType createObject(const OUString& 
rName) override;
+    virtual css::uno::Reference<css::beans::XPropertySet> createDescriptor() 
override;
+    virtual ::connectivity::sdbcx::ObjectType
+    appendObject(const OUString& rName,
+                 const css::uno::Reference<css::beans::XPropertySet>& 
rDescriptor) override;
+
+public:
+    Tables(const css::uno::Reference<css::sdbc::XDatabaseMetaData>& rMetaData,
+           ::cppu::OWeakObject& rParent, ::osl::Mutex& rMutex,
+           ::std::vector<OUString> const& rNames)
+        : sdbcx::OCollection(rParent, true, rMutex, rNames)
+        , m_xMetaData(rMetaData)
+    {
+    }
+
+    // TODO: we should also implement XDataDescriptorFactory, XRefreshable,
+    // XAppend,  etc., but all are optional.
+
+    // XDrop
+    virtual void dropObject(sal_Int32 nPosition, const OUString& rName) 
override;
+};
+
+} // namespace connectivity::mysqlc
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */

Reply via email to