| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_connectivity.hxx" |
| #include "mysql/YTable.hxx" |
| #include "mysql/YTables.hxx" |
| #include <com/sun/star/sdbc/XRow.hpp> |
| #include <com/sun/star/sdbc/XResultSet.hpp> |
| #include <com/sun/star/sdbcx/KeyType.hpp> |
| #include <com/sun/star/sdbc/KeyRule.hpp> |
| #include <cppuhelper/typeprovider.hxx> |
| #include <com/sun/star/lang/DisposedException.hpp> |
| #include <com/sun/star/sdbc/ColumnValue.hpp> |
| #include <com/sun/star/sdbcx/Privilege.hpp> |
| #include <comphelper/property.hxx> |
| #include <comphelper/extract.hxx> |
| #include <comphelper/types.hxx> |
| #include "connectivity/dbtools.hxx" |
| #include "connectivity/sdbcx/VColumn.hxx" |
| #include "connectivity/TKeys.hxx" |
| #include "connectivity/TIndexes.hxx" |
| #include "connectivity/TColumnsHelper.hxx" |
| #include "mysql/YCatalog.hxx" |
| #include "mysql/YColumns.hxx" |
| #include "TConnection.hxx" |
| |
| |
| using namespace ::comphelper; |
| using namespace connectivity::mysql; |
| using namespace connectivity::sdbcx; |
| using namespace connectivity; |
| using namespace ::com::sun::star::uno; |
| using namespace ::com::sun::star::beans; |
| using namespace ::com::sun::star::sdbcx; |
| using namespace ::com::sun::star::sdbc; |
| using namespace ::com::sun::star::container; |
| using namespace ::com::sun::star::lang; |
| namespace connectivity |
| { |
| namespace mysql |
| { |
| class OMySQLKeysHelper : public OKeysHelper |
| { |
| protected: |
| // ----------------------------------------------------------------------------- |
| virtual ::rtl::OUString getDropForeignKey() const |
| { |
| return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" DROP FOREIGN KEY ")); |
| } |
| public: |
| OMySQLKeysHelper( OTableHelper* _pTable, |
| ::osl::Mutex& _rMutex, |
| const TStringVector& _rVector |
| ) : OKeysHelper(_pTable,_rMutex,_rVector){} |
| |
| }; |
| } |
| } |
| |
| OMySQLTable::OMySQLTable( sdbcx::OCollection* _pTables, |
| const Reference< XConnection >& _xConnection) |
| :OTableHelper(_pTables,_xConnection,sal_True) |
| { |
| // we create a new table here, so we should have all the rights or ;-) |
| m_nPrivileges = Privilege::DROP | |
| Privilege::REFERENCE | |
| Privilege::ALTER | |
| Privilege::CREATE | |
| Privilege::READ | |
| Privilege::DELETE | |
| Privilege::UPDATE | |
| Privilege::INSERT | |
| Privilege::SELECT; |
| construct(); |
| } |
| // ------------------------------------------------------------------------- |
| OMySQLTable::OMySQLTable( sdbcx::OCollection* _pTables, |
| const Reference< XConnection >& _xConnection, |
| const ::rtl::OUString& _Name, |
| const ::rtl::OUString& _Type, |
| const ::rtl::OUString& _Description , |
| const ::rtl::OUString& _SchemaName, |
| const ::rtl::OUString& _CatalogName, |
| sal_Int32 _nPrivileges |
| ) : OTableHelper( _pTables, |
| _xConnection, |
| sal_True, |
| _Name, |
| _Type, |
| _Description, |
| _SchemaName, |
| _CatalogName) |
| , m_nPrivileges(_nPrivileges) |
| { |
| construct(); |
| } |
| // ------------------------------------------------------------------------- |
| void OMySQLTable::construct() |
| { |
| OTableHelper::construct(); |
| if ( !isNew() ) |
| registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRIVILEGES), PROPERTY_ID_PRIVILEGES,PropertyAttribute::READONLY,&m_nPrivileges, ::getCppuType(&m_nPrivileges)); |
| } |
| // ----------------------------------------------------------------------------- |
| ::cppu::IPropertyArrayHelper* OMySQLTable::createArrayHelper( sal_Int32 /*_nId*/ ) const |
| { |
| return doCreateArrayHelper(); |
| } |
| // ------------------------------------------------------------------------- |
| ::cppu::IPropertyArrayHelper & OMySQLTable::getInfoHelper() |
| { |
| return *static_cast<OMySQLTable_PROP*>(const_cast<OMySQLTable*>(this))->getArrayHelper(isNew() ? 1 : 0); |
| } |
| // ----------------------------------------------------------------------------- |
| sdbcx::OCollection* OMySQLTable::createColumns(const TStringVector& _rNames) |
| { |
| OMySQLColumns* pColumns = new OMySQLColumns(*this,sal_True,m_aMutex,_rNames); |
| pColumns->setParent(this); |
| return pColumns; |
| } |
| // ----------------------------------------------------------------------------- |
| sdbcx::OCollection* OMySQLTable::createKeys(const TStringVector& _rNames) |
| { |
| return new OMySQLKeysHelper(this,m_aMutex,_rNames); |
| } |
| // ----------------------------------------------------------------------------- |
| sdbcx::OCollection* OMySQLTable::createIndexes(const TStringVector& _rNames) |
| { |
| return new OIndexesHelper(this,m_aMutex,_rNames); |
| } |
| //-------------------------------------------------------------------------- |
| Sequence< sal_Int8 > OMySQLTable::getUnoTunnelImplementationId() |
| { |
| static ::cppu::OImplementationId * pId = 0; |
| if (! pId) |
| { |
| ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); |
| if (! pId) |
| { |
| static ::cppu::OImplementationId aId; |
| pId = &aId; |
| } |
| } |
| return pId->getImplementationId(); |
| } |
| |
| // com::sun::star::lang::XUnoTunnel |
| //------------------------------------------------------------------ |
| sal_Int64 OMySQLTable::getSomething( const Sequence< sal_Int8 > & rId ) throw (RuntimeException) |
| { |
| return (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(), rId.getConstArray(), 16 ) ) |
| ? reinterpret_cast< sal_Int64 >( this ) |
| : OTable_TYPEDEF::getSomething(rId); |
| } |
| // ------------------------------------------------------------------------- |
| // XAlterTable |
| void SAL_CALL OMySQLTable::alterColumnByName( const ::rtl::OUString& colName, const Reference< XPropertySet >& descriptor ) throw(SQLException, NoSuchElementException, RuntimeException) |
| { |
| ::osl::MutexGuard aGuard(m_aMutex); |
| checkDisposed( |
| #ifdef GCC |
| ::connectivity::sdbcx::OTableDescriptor_BASE::rBHelper.bDisposed |
| #else |
| rBHelper.bDisposed |
| #endif |
| ); |
| |
| if ( m_pColumns && !m_pColumns->hasByName(colName) ) |
| throw NoSuchElementException(colName,*this); |
| |
| |
| if ( !isNew() ) |
| { |
| // first we have to check what should be altered |
| Reference<XPropertySet> xProp; |
| m_pColumns->getByName(colName) >>= xProp; |
| // first check the types |
| sal_Int32 nOldType = 0,nNewType = 0,nOldPrec = 0,nNewPrec = 0,nOldScale = 0,nNewScale = 0; |
| |
| ::dbtools::OPropertyMap& rProp = OMetaConnection::getPropMap(); |
| xProp->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_TYPE)) >>= nOldType; |
| descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_TYPE)) >>= nNewType; |
| // and precsions and scale |
| xProp->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_PRECISION)) >>= nOldPrec; |
| descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_PRECISION))>>= nNewPrec; |
| xProp->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_SCALE)) >>= nOldScale; |
| descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_SCALE)) >>= nNewScale; |
| // second: check the "is nullable" value |
| sal_Int32 nOldNullable = 0,nNewNullable = 0; |
| xProp->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_ISNULLABLE)) >>= nOldNullable; |
| descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_ISNULLABLE)) >>= nNewNullable; |
| |
| // check also the auto_increment |
| sal_Bool bOldAutoIncrement = sal_False,bAutoIncrement = sal_False; |
| xProp->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_ISAUTOINCREMENT)) >>= bOldAutoIncrement; |
| descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_ISAUTOINCREMENT)) >>= bAutoIncrement; |
| bool bColumnNameChanged = false; |
| ::rtl::OUString sOldDesc,sNewDesc; |
| xProp->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_DESCRIPTION)) >>= sOldDesc; |
| descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_DESCRIPTION)) >>= sNewDesc; |
| |
| if ( nOldType != nNewType |
| || nOldPrec != nNewPrec |
| || nOldScale != nNewScale |
| || nNewNullable != nOldNullable |
| || bOldAutoIncrement != bAutoIncrement |
| || sOldDesc != sNewDesc ) |
| { |
| // special handling because they change dthe type names to distinguish |
| // if a column should be an auto_incmrement one |
| if ( bOldAutoIncrement != bAutoIncrement ) |
| { |
| ::rtl::OUString sTypeName; |
| descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_TYPENAME)) >>= sTypeName; |
| |
| static ::rtl::OUString s_sAutoIncrement(RTL_CONSTASCII_USTRINGPARAM("auto_increment")); |
| if ( bAutoIncrement ) |
| { |
| if ( sTypeName.indexOf(s_sAutoIncrement) == -1 ) |
| { |
| sTypeName += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" ")); |
| sTypeName += s_sAutoIncrement; |
| } |
| } |
| else |
| { |
| sal_Int32 nIndex = 0; |
| if ( sTypeName.getLength() && (nIndex = sTypeName.indexOf(s_sAutoIncrement)) != -1 ) |
| { |
| sTypeName = sTypeName.copy(0,nIndex); |
| descriptor->setPropertyValue(rProp.getNameByIndex(PROPERTY_ID_TYPENAME),makeAny(sTypeName)); |
| } |
| } |
| } |
| alterColumnType(nNewType,colName,descriptor); |
| bColumnNameChanged = true; |
| } |
| |
| // third: check the default values |
| ::rtl::OUString sNewDefault,sOldDefault; |
| xProp->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_DEFAULTVALUE)) >>= sOldDefault; |
| descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_DEFAULTVALUE)) >>= sNewDefault; |
| |
| if(sOldDefault.getLength()) |
| { |
| dropDefaultValue(colName); |
| if(sNewDefault.getLength() && sOldDefault != sNewDefault) |
| alterDefaultValue(sNewDefault,colName); |
| } |
| else if(!sOldDefault.getLength() && sNewDefault.getLength()) |
| alterDefaultValue(sNewDefault,colName); |
| |
| // now we should look if the name of the column changed |
| ::rtl::OUString sNewColumnName; |
| descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_NAME)) >>= sNewColumnName; |
| if ( !sNewColumnName.equalsIgnoreAsciiCase(colName) && !bColumnNameChanged ) |
| { |
| ::rtl::OUString sSql = getAlterTableColumnPart(); |
| sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" CHANGE ")); |
| const ::rtl::OUString sQuote = getMetaData()->getIdentifierQuoteString( ); |
| sSql += ::dbtools::quoteName(sQuote,colName); |
| sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" ")); |
| sSql += OTables::adjustSQL(::dbtools::createStandardColumnPart(descriptor,getConnection(),static_cast<OTables*>(m_pTables),getTypeCreatePattern())); |
| executeStatement(sSql); |
| } |
| m_pColumns->refresh(); |
| } |
| else |
| { |
| if(m_pColumns) |
| { |
| m_pColumns->dropByName(colName); |
| m_pColumns->appendByDescriptor(descriptor); |
| } |
| } |
| |
| } |
| // ----------------------------------------------------------------------------- |
| void OMySQLTable::alterColumnType(sal_Int32 nNewType,const ::rtl::OUString& _rColName, const Reference<XPropertySet>& _xDescriptor) |
| { |
| ::rtl::OUString sSql = getAlterTableColumnPart(); |
| sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" CHANGE ")); |
| const ::rtl::OUString sQuote = getMetaData()->getIdentifierQuoteString( ); |
| sSql += ::dbtools::quoteName(sQuote,_rColName); |
| sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" ")); |
| |
| OColumn* pColumn = new OColumn(sal_True); |
| Reference<XPropertySet> xProp = pColumn; |
| ::comphelper::copyProperties(_xDescriptor,xProp); |
| xProp->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE),makeAny(nNewType)); |
| |
| sSql += OTables::adjustSQL(::dbtools::createStandardColumnPart(xProp,getConnection(),static_cast<OTables*>(m_pTables),getTypeCreatePattern())); |
| executeStatement(sSql); |
| } |
| // ----------------------------------------------------------------------------- |
| ::rtl::OUString OMySQLTable::getTypeCreatePattern() const |
| { |
| static const ::rtl::OUString s_sCreatePattern(RTL_CONSTASCII_USTRINGPARAM("(M,D)")); |
| return s_sCreatePattern; |
| } |
| // ----------------------------------------------------------------------------- |
| void OMySQLTable::alterDefaultValue(const ::rtl::OUString& _sNewDefault,const ::rtl::OUString& _rColName) |
| { |
| ::rtl::OUString sSql = getAlterTableColumnPart(); |
| sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" ALTER ")); |
| |
| const ::rtl::OUString sQuote = getMetaData()->getIdentifierQuoteString( ); |
| sSql += ::dbtools::quoteName(sQuote,_rColName); |
| sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" SET DEFAULT '")) + _sNewDefault; |
| sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("'")); |
| |
| executeStatement(sSql); |
| } |
| // ----------------------------------------------------------------------------- |
| void OMySQLTable::dropDefaultValue(const ::rtl::OUString& _rColName) |
| { |
| ::rtl::OUString sSql = getAlterTableColumnPart(); |
| sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" ALTER ")); |
| |
| const ::rtl::OUString sQuote = getMetaData()->getIdentifierQuoteString( ); |
| sSql += ::dbtools::quoteName(sQuote,_rColName); |
| sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" DROP DEFAULT")); |
| |
| executeStatement(sSql); |
| } |
| // ----------------------------------------------------------------------------- |
| ::rtl::OUString OMySQLTable::getAlterTableColumnPart() |
| { |
| ::rtl::OUString sSql = ::rtl::OUString::createFromAscii("ALTER TABLE "); |
| const ::rtl::OUString sQuote = getMetaData()->getIdentifierQuoteString( ); |
| |
| ::rtl::OUString sComposedName( |
| ::dbtools::composeTableName( getMetaData(), m_CatalogName, m_SchemaName, m_Name, sal_True, ::dbtools::eInTableDefinitions ) ); |
| sSql += sComposedName; |
| |
| return sSql; |
| } |
| // ----------------------------------------------------------------------------- |
| void OMySQLTable::executeStatement(const ::rtl::OUString& _rStatement ) |
| { |
| ::rtl::OUString sSQL = _rStatement; |
| if(sSQL.lastIndexOf(',') == (sSQL.getLength()-1)) |
| sSQL = sSQL.replaceAt(sSQL.getLength()-1,1,::rtl::OUString::createFromAscii(")")); |
| |
| Reference< XStatement > xStmt = getConnection()->createStatement( ); |
| if ( xStmt.is() ) |
| { |
| xStmt->execute(sSQL); |
| ::comphelper::disposeComponent(xStmt); |
| } |
| } |
| // ----------------------------------------------------------------------------- |
| ::rtl::OUString OMySQLTable::getRenameStart() const |
| { |
| return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("RENAME TABLE ")); |
| } |
| |
| |
| |
| |