/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * 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/. * * This file incorporates work covered by the following license notice: * * 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 .
*/
namespace
{ /// helper class for column property change events which holds the OComponentDefinition weak class OTableContainerListener: public ::cppu::WeakImplHelper< XContainerListener >
{
OTableHelper* m_pComponent;
std::map< OUString,bool> m_aRefNames;
protected: virtual ~OTableContainerListener() override {} public: explicit OTableContainerListener(OTableHelper* _pComponent) : m_pComponent(_pComponent){} // noncopyable
OTableContainerListener(const OTableContainerListener&) = delete; const OTableContainerListener& operator=(const OTableContainerListener&) = delete; virtualvoid SAL_CALL elementInserted( const css::container::ContainerEvent& /*Event*/ ) override
{
} virtualvoid SAL_CALL elementRemoved( const css::container::ContainerEvent& Event ) override
{ // tdf#137745, perhaps connectivity::OTableHelper::disposing() has been called // which called OTableContainerListener::clear(), so m_pComponent may be null if (m_pComponent == nullptr) return;
namespace
{ /** collects ColumnDesc's from a resultset produced by XDatabaseMetaData::getColumns
*/ void lcl_collectColumnDescs_throw( const Reference< XResultSet >& _rxResult, std::vector< ColumnDesc >& _out_rColumns )
{
Reference< XRow > xRow( _rxResult, UNO_QUERY_THROW ); while ( _rxResult->next() )
{ // tdf#162227: ODBC SQLGetData requires that data must be retrieved in increasing // column number order, unless the driver supports SQL_GD_ANY_ORDER extension (see // https://learn.microsoft.com/en-us/sql/odbc/reference/syntax/sqlgetdata-function). // We can't emplace_back(getString(4), getInt(5), ..., getString(12), getInt(17)), // because MSVC would reorder calls into getInt(17) -> getString(12) -> ..., and then // MS SQL Server ODBC driver will give error on access of column 12 after column 17.
OUString sName = xRow->getString(4); // COLUMN_NAME
sal_Int32 nField5 = xRow->getInt(5);
OUString aField6 = xRow->getString(6);
sal_Int32 nField7 = xRow->getInt(7);
sal_Int32 nField9 = xRow->getInt(9);
sal_Int32 nField11 = xRow->getInt(11);
OUString sField12 = xRow->getString(12);
OUString sField13 = xRow->getString(13);
OrdinalPosition nOrdinalPosition = xRow->getInt(17); // ORDINAL_POSITION
_out_rColumns.emplace_back(sName, nField5, aField6, nField7, nField9, nField11,
sField12, sField13, nOrdinalPosition);
}
}
/** checks a given array of ColumnDesc's whether it has reasonable ordinal positions. If not, they will be normalized to be the array index.
*/ void lcl_sanitizeColumnDescs( std::vector< ColumnDesc >& _rColumns )
{ if ( _rColumns.empty() ) return;
// collect all used ordinals
std::set< OrdinalPosition > aUsedOrdinals; for ( constauto& collect : _rColumns )
aUsedOrdinals.insert( collect.nOrdinalPosition );
// we need to have as much different ordinals as we have different columns bool bDuplicates = aUsedOrdinals.size() != _rColumns.size(); // and it needs to be a continuous range
size_t nOrdinalsRange = *aUsedOrdinals.rbegin() - *aUsedOrdinals.begin() + 1; bool bGaps = nOrdinalsRange != _rColumns.size();
// if that's not the case, normalize it if ( bGaps || bDuplicates )
{
OSL_FAIL( "lcl_sanitizeColumnDescs: database did provide invalid ORDINAL_POSITION values!" );
// what's left is that the range might not be from 1 to <column count>, but for instance // 0 to <column count>-1.
size_t nOffset = *aUsedOrdinals.begin() - 1; for ( auto& offset : _rColumns )
offset.nOrdinalPosition -= nOffset;
}
}
void OTableHelper::refreshColumns()
{
::std::vector< OUString> aVector; if(!isNew())
{
Any aCatalog; if ( !m_CatalogName.isEmpty() )
aCatalog <<= m_CatalogName;
// collect the column names, together with their ordinal position
m_pImpl->m_aColumnDesc.clear();
lcl_collectColumnDescs_throw( xResult, m_pImpl->m_aColumnDesc );
// ensure that the ordinal positions as obtained from the meta data do make sense
lcl_sanitizeColumnDescs( m_pImpl->m_aColumnDesc );
// sort by ordinal position
std::map< OrdinalPosition, OUString > aSortedColumns; for (constauto& copy : m_pImpl->m_aColumnDesc)
aSortedColumns[ copy.nOrdinalPosition ] = copy.sName;
// copy them to aVector, now that we have the proper ordering
std::transform(
aSortedColumns.begin(),
aSortedColumns.end(),
std::insert_iterator< ::std::vector< OUString> >( aVector, aVector.begin() ),
::o3tl::select2nd< std::map< OrdinalPosition, OUString >::value_type >()
);
}
std::shared_ptr<sdbcx::KeyProperties> pKeyProps;
OUString aName,sCatalog,aSchema,sOldFKName; while( xResult->next() )
{ // this must be outside the "if" because we have to call in a right order
sCatalog = xRow->getString(1); if ( xRow->wasNull() )
sCatalog.clear();
aSchema = xRow->getString(2);
aName = xRow->getString(3);
void OTableHelper::refreshIndexes()
{
::std::vector< OUString> aVector; if(!isNew())
{ // fill indexes
Any aCatalog; if ( !m_CatalogName.isEmpty() )
aCatalog <<= m_CatalogName;
Reference< XResultSet > xResult = getMetaData()->getIndexInfo(aCatalog,m_SchemaName,m_Name,false,false);
if(xResult.is())
{
Reference< XRow > xRow(xResult,UNO_QUERY);
OUString sCatalogSep = getMetaData()->getCatalogSeparator();
OUString sPreviousRoundName; while( xResult->next() )
{
OUString aName = xRow->getString(5); if(!aName.isEmpty())
aName += sCatalogSep;
aName += xRow->getString(6); if ( !aName.isEmpty() )
{ // don't insert the name if the last one we inserted was the same if (sPreviousRoundName != aName)
aVector.push_back(aName);
}
sPreviousRoundName = aName;
}
::comphelper::disposeComponent(xResult);
}
}
std::shared_ptr<sdbcx::KeyProperties> OTableHelper::getKeyProperties(const OUString& _sName) const
{
std::shared_ptr<sdbcx::KeyProperties> pKeyProps;
TKeyMap::const_iterator aFind = m_pImpl->m_aKeys.find(_sName); if ( aFind != m_pImpl->m_aKeys.end() )
{
pKeyProps = aFind->second;
} else// only a fall back
{
OSL_FAIL("No key with the given name found");
pKeyProps = std::make_shared<sdbcx::KeyProperties>();
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.