/* -*- 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 .
*/
if (aIter == aPair.second)
{ for(aIter = aPair.first; aIter != aPair.second; ++aIter)
{
sal_Int32 nPrec = aIter->second->nPrecision;
sal_Int32 nScale = aIter->second->nMaximumScale; // search the best matching type (now comparing the local names) if ( (aIter->second->aLocalTypeName.equalsIgnoreAsciiCase(_sTypeName))
&& (nPrec >= _nPrecision)
&& (nScale >= _nScale)
&& ( (_bAutoIncrement && aIter->second->bAutoIncrement) || !_bAutoIncrement )
)
{
SAL_WARN("dbaccess.ui", "getTypeInfoFromType: assuming column type " <<
aIter->second->aTypeName << "\" (expected type name " <<
_sTypeName << " matches the type's local name)."); break;
}
}
}
if (aIter == aPair.second)
{ // no match for the names, no match for the local names // -> drop the precision and the scale restriction, accept any type with the property // type id (nType)
for(aIter = aPair.first; aIter != aPair.second; ++aIter)
{ // search the best matching type (now comparing the local names)
sal_Int32 nPrec = aIter->second->nPrecision;
sal_Int32 nScale = aIter->second->nMaximumScale; if ( (nPrec >= _nPrecision)
&& (nScale >= _nScale)
&& ( (_bAutoIncrement && aIter->second->bAutoIncrement) || !_bAutoIncrement )
) break;
}
} if (aIter == aPair.second)
{ if ( _bAutoIncrement )
{ for(aIter = aPair.first; aIter != aPair.second; ++aIter)
{ // search the best matching type (now comparing the local names)
sal_Int32 nScale = aIter->second->nMaximumScale; if ( (nScale >= _nScale)
&& (aIter->second->bAutoIncrement == _bAutoIncrement)
) break;
} if ( aIter == aPair.second )
{ // try it without the auto increment flag
pTypeInfo = getTypeInfoFromType(_rTypeInfo,
_nType,
_sTypeName,
_sCreateParams,
_nPrecision,
_nScale, false,
_brForceToType);
} else
pTypeInfo = aIter->second;
} else
{
pTypeInfo = aPair.first->second;
_brForceToType = true;
}
} else
pTypeInfo = aIter->second;
} else
{
::comphelper::UStringMixEqual aCase(false); // search for typeinfo where the typename is equal _sTypeName for (autoconst& elem : _rTypeInfo)
{ if ( aCase( elem.second->getDBName() , _sTypeName ) )
{
pTypeInfo = elem.second; break;
}
}
}
OSL_ENSURE(pTypeInfo, "getTypeInfoFromType: no type info found for this type!"); return pTypeInfo;
}
void fillTypeInfo( const Reference< css::sdbc::XConnection>& _rxConnection,
std::u16string_view _rsTypeNames,
OTypeInfoMap& _rTypeInfoMap,
std::vector<OTypeInfoMap::iterator>& _rTypeInfoIters)
{ if(!_rxConnection.is()) return;
Reference< XResultSet> xRs = _rxConnection->getMetaData ()->getTypeInfo ();
Reference< XRow> xRow(xRs,UNO_QUERY); // Information for a single SQL type if(!xRs.is()) return;
Reference<XResultSetMetaData> xResultSetMetaData = Reference<XResultSetMetaDataSupplier>(xRs,UNO_QUERY_THROW)->getMetaData();
::connectivity::ORowSetValue aValue;
std::vector<sal_Int32> aTypes;
std::vector<bool> aNullable; // Loop on the result set until we reach end of file while (xRs->next())
{
TOTypeInfoSP pInfo = std::make_shared<OTypeInfo>();
sal_Int32 nPos = 1; if ( aTypes.empty() )
{
sal_Int32 nCount = xResultSetMetaData->getColumnCount(); if ( nCount < 1 )
nCount = 18;
aTypes.reserve(nCount+1);
aTypes.push_back(-1);
aNullable.push_back(false); for (sal_Int32 j = 1; j <= nCount ; ++j)
{
aTypes.push_back(xResultSetMetaData->getColumnType(j));
aNullable.push_back(xResultSetMetaData->isNullable(j) != ColumnValue::NO_NULLS);
}
}
// check if values are less than zero like it happens in a oracle jdbc driver if( pInfo->nPrecision < 0)
pInfo->nPrecision = 0; if( pInfo->nMinimumScale < 0)
pInfo->nMinimumScale = 0; if( pInfo->nMaximumScale < 0)
pInfo->nMaximumScale = 0; if( pInfo->nNumPrecRadix <= 1)
pInfo->nNumPrecRadix = 10;
std::u16string_view aName; switch(pInfo->nType)
{ case DataType::CHAR:
aName = o3tl::getToken(_rsTypeNames, TYPE_CHAR, ';'); break; case DataType::VARCHAR:
aName = o3tl::getToken(_rsTypeNames, TYPE_TEXT, ';'); break; case DataType::DECIMAL:
aName = o3tl::getToken(_rsTypeNames, TYPE_DECIMAL, ';'); break; case DataType::NUMERIC:
aName = o3tl::getToken(_rsTypeNames, TYPE_NUMERIC, ';'); break; case DataType::BIGINT:
aName = o3tl::getToken(_rsTypeNames, TYPE_BIGINT, ';'); break; case DataType::FLOAT:
aName = o3tl::getToken(_rsTypeNames, TYPE_FLOAT, ';'); break; case DataType::DOUBLE:
aName = o3tl::getToken(_rsTypeNames, TYPE_DOUBLE, ';'); break; case DataType::LONGVARCHAR:
aName = o3tl::getToken(_rsTypeNames, TYPE_MEMO, ';'); break; case DataType::LONGVARBINARY:
aName = o3tl::getToken(_rsTypeNames, TYPE_IMAGE, ';'); break; case DataType::DATE:
aName = o3tl::getToken(_rsTypeNames, TYPE_DATE, ';'); break; case DataType::TIME:
aName = o3tl::getToken(_rsTypeNames, TYPE_TIME, ';'); break; case DataType::TIMESTAMP:
aName = o3tl::getToken(_rsTypeNames, TYPE_DATETIME, ';'); break; case DataType::BIT: if ( !pInfo->aCreateParams.isEmpty() )
{
aName = o3tl::getToken(_rsTypeNames, TYPE_BIT, ';'); break;
}
[[fallthrough]]; case DataType::BOOLEAN:
aName = o3tl::getToken(_rsTypeNames, TYPE_BOOL, ';'); break; case DataType::TINYINT:
aName = o3tl::getToken(_rsTypeNames, TYPE_TINYINT, ';'); break; case DataType::SMALLINT:
aName = o3tl::getToken(_rsTypeNames, TYPE_SMALLINT, ';'); break; case DataType::INTEGER:
aName = o3tl::getToken(_rsTypeNames, TYPE_INTEGER, ';'); break; case DataType::REAL:
aName = o3tl::getToken(_rsTypeNames, TYPE_REAL, ';'); break; case DataType::BINARY:
aName = o3tl::getToken(_rsTypeNames, TYPE_BINARY, ';'); break; case DataType::VARBINARY:
aName = o3tl::getToken(_rsTypeNames, TYPE_VARBINARY, ';'); break; case DataType::SQLNULL:
aName = o3tl::getToken(_rsTypeNames, TYPE_SQLNULL, ';'); break; case DataType::OBJECT:
aName = o3tl::getToken(_rsTypeNames, TYPE_OBJECT, ';'); break; case DataType::DISTINCT:
aName = o3tl::getToken(_rsTypeNames, TYPE_DISTINCT, ';'); break; case DataType::STRUCT:
aName = o3tl::getToken(_rsTypeNames, TYPE_STRUCT, ';'); break; case DataType::ARRAY:
aName = o3tl::getToken(_rsTypeNames, TYPE_ARRAY, ';'); break; case DataType::BLOB:
aName = o3tl::getToken(_rsTypeNames, TYPE_BLOB, ';'); break; case DataType::CLOB:
aName = o3tl::getToken(_rsTypeNames, TYPE_CLOB, ';'); break; case DataType::REF:
aName = o3tl::getToken(_rsTypeNames, TYPE_REF, ';'); break; case DataType::OTHER:
aName = o3tl::getToken(_rsTypeNames, TYPE_OTHER, ';'); break;
} if ( !aName.empty() )
{
pInfo->aUIName = aName;
pInfo->aUIName += " [ ";
}
pInfo->aUIName += pInfo->aTypeName; if ( !aName.empty() )
pInfo->aUIName += " ]"; // Now that we have the type info, save it in the multimap
_rTypeInfoMap.emplace(pInfo->nType,pInfo);
} // for a faster index access
_rTypeInfoIters.reserve(_rTypeInfoMap.size());
void setColumnProperties(const Reference<XPropertySet>& _rxColumn,const OFieldDescription* _pFieldDesc)
{
_rxColumn->setPropertyValue(PROPERTY_NAME,Any(_pFieldDesc->GetName()));
_rxColumn->setPropertyValue(PROPERTY_TYPENAME,Any(_pFieldDesc->getTypeInfo()->aTypeName));
_rxColumn->setPropertyValue(PROPERTY_TYPE,Any(_pFieldDesc->GetType()));
_rxColumn->setPropertyValue(PROPERTY_PRECISION,Any(_pFieldDesc->GetPrecision()));
_rxColumn->setPropertyValue(PROPERTY_SCALE,Any(_pFieldDesc->GetScale()));
_rxColumn->setPropertyValue(PROPERTY_ISNULLABLE, Any(_pFieldDesc->GetIsNullable()));
_rxColumn->setPropertyValue(PROPERTY_ISAUTOINCREMENT, css::uno::Any(_pFieldDesc->IsAutoIncrement()));
_rxColumn->setPropertyValue(PROPERTY_DESCRIPTION,Any(_pFieldDesc->GetDescription())); if ( _rxColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_ISCURRENCY) && _pFieldDesc->IsCurrency() )
_rxColumn->setPropertyValue(PROPERTY_ISCURRENCY, css::uno::Any(_pFieldDesc->IsCurrency())); // set autoincrement value when available // and only set when the entry is not empty, that lets the value in the column untouched if ( _pFieldDesc->IsAutoIncrement() && !_pFieldDesc->GetAutoIncrementValue().isEmpty() && _rxColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_AUTOINCREMENTCREATION) )
_rxColumn->setPropertyValue(PROPERTY_AUTOINCREMENTCREATION,Any(_pFieldDesc->GetAutoIncrementValue()));
}
std::optional<SfxItemSet> pFormatDescriptor(SfxItemSet(*pPool, aAttrMap)); // fill it
pFormatDescriptor->Put(SvxHorJustifyItem(_eJustify, SBA_ATTR_ALIGN_HOR_JUSTIFY)); bool bText = false; if (_bHasFormat)
{ // if the col is bound to a text field we have to disallow all non-text formats if ((DataType::CHAR == _nDataType) || (DataType::VARCHAR == _nDataType) || (DataType::LONGVARCHAR == _nDataType) || (DataType::CLOB == _nDataType))
{
bText = true;
pFormatDescriptor->Put(SfxBoolItem(SID_ATTR_NUMBERFORMAT_ONE_AREA, true)); if (!_pFormatter->IsTextFormat(_nFormatKey)) // text fields can only have text formats
_nFormatKey = _pFormatter->GetStandardFormat(SvNumFormatType::TEXT, Application::GetSettings().GetLanguageTag().getLanguageType());
}
if (!bText)
{
SvxNumberInfoItem aFormatter(_pFormatter, 1234.56789, SID_ATTR_NUMBERFORMAT_INFO);
pFormatDescriptor->Put(aFormatter);
}
{ // want the dialog to be destroyed before our set
SbaSbAttrDlg aDlg(_pParent, &*pFormatDescriptor, _pFormatter, _bHasFormat); if (RET_OK == aDlg.run())
{ // ItemSet->UNO // UNO-properties const SfxItemSet* pSet = aDlg.GetExampleSet(); // (of course we could put the modified items directly into the column, but then the UNO-model // won't reflect these changes, and why do we have a model, then ?)
std::shared_ptr<const SfxFilter> getStandardDatabaseFilter()
{
std::shared_ptr<const SfxFilter> pFilter = SfxFilter::GetFilterByName(u"StarOffice XML (Base)"_ustr);
OSL_ENSURE(pFilter,"Filter: StarOffice XML (Base) could not be found!"); return pFilter;
}
TOTypeInfoSP queryPrimaryKeyType(const OTypeInfoMap& _rTypeInfo)
{
TOTypeInfoSP pTypeInfo, pFallback; // first we search for a largest type which supports autoIncrement for (autoconst& elem : _rTypeInfo)
{ if (elem.second->bAutoIncrement && TypeIsGreater(elem.second, pTypeInfo))
pTypeInfo = elem.second; if (pTypeInfo) continue; if (elem.second->nType == DataType::INTEGER)
pFallback = elem.second; // default alternative elseif (!pFallback && elem.second->nType == DataType::DOUBLE)
pFallback = elem.second; // alternative elseif (!pFallback && elem.second->nType == DataType::REAL)
pFallback = elem.second; // alternative
} if ( !pTypeInfo ) // just a fallback
pTypeInfo = pFallback ? std::move(pFallback) : queryTypeInfoByType(DataType::VARCHAR, _rTypeInfo);
OSL_ENSURE(pTypeInfo,"checkColumns: can't find a type which is usable as a key!"); return pTypeInfo;
}
TOTypeInfoSP queryTypeInfoByType(sal_Int32 _nDataType,const OTypeInfoMap& _rTypeInfo)
{
OTypeInfoMap::const_iterator aIter = _rTypeInfo.find(_nDataType); if(aIter != _rTypeInfo.end()) return aIter->second; // fall back if the type is unknown
TOTypeInfoSP pTypeInfo; switch(_nDataType)
{ case DataType::TINYINT: if( (pTypeInfo = queryTypeInfoByType(DataType::SMALLINT,_rTypeInfo) ) ) break;
[[fallthrough]]; case DataType::SMALLINT: if( (pTypeInfo = queryTypeInfoByType(DataType::INTEGER,_rTypeInfo) ) ) break;
[[fallthrough]]; case DataType::INTEGER: if( (pTypeInfo = queryTypeInfoByType(DataType::FLOAT,_rTypeInfo) ) ) break;
[[fallthrough]]; case DataType::FLOAT: if( (pTypeInfo = queryTypeInfoByType(DataType::REAL,_rTypeInfo) ) ) break;
[[fallthrough]]; case DataType::DATE: case DataType::TIME: if( DataType::DATE == _nDataType || DataType::TIME == _nDataType )
{ if( (pTypeInfo = queryTypeInfoByType(DataType::TIMESTAMP,_rTypeInfo) ) ) break;
}
[[fallthrough]]; case DataType::TIMESTAMP: case DataType::REAL: case DataType::BIGINT: if ( (pTypeInfo = queryTypeInfoByType(DataType::DOUBLE,_rTypeInfo) ) ) break;
[[fallthrough]]; case DataType::DOUBLE: if ( (pTypeInfo = queryTypeInfoByType(DataType::NUMERIC,_rTypeInfo) ) ) break;
[[fallthrough]]; case DataType::NUMERIC:
pTypeInfo = queryTypeInfoByType(DataType::DECIMAL,_rTypeInfo); break; case DataType::DECIMAL: if ( (pTypeInfo = queryTypeInfoByType(DataType::NUMERIC,_rTypeInfo) ) ) break; if ( (pTypeInfo = queryTypeInfoByType(DataType::DOUBLE,_rTypeInfo) ) ) break; break; case DataType::VARCHAR: if ( (pTypeInfo = queryTypeInfoByType(DataType::LONGVARCHAR,_rTypeInfo) ) ) break; break; case DataType::LONGVARCHAR: if ( (pTypeInfo = queryTypeInfoByType(DataType::CLOB,_rTypeInfo) ) ) break; break; default:
;
} if ( !pTypeInfo )
{ bool bForce = true;
pTypeInfo = ::dbaui::getTypeInfoFromType(_rTypeInfo,DataType::VARCHAR,OUString(),u"x"_ustr,50,0,false,bForce);
}
OSL_ENSURE(pTypeInfo,"Wrong DataType supplied!"); return pTypeInfo;
}
xView = nullptr; // we need to reget the view because after appending it, it is no longer valid // but this time it isn't a view object it is a table object with type "VIEW"
Reference<XTablesSupplier> xTabSup(_rxConnection,UNO_QUERY);
Reference< XNameAccess > xTables; if ( xTabSup.is() )
{
xTables = xTabSup->getTables(); if ( xTables.is() && xTables->hasByName( _rName ) )
xTables->getByName( _rName ) >>= xView;
}
// here we have everything needed to create a new query object ...
HierarchicalNameCheck aNameChecker( _xNames, _sParentFolder ); // ... ehm, except a new name
OSaveAsDlg aAskForName(pParent,
_rxContext,
sTargetName,
sLabel,
aNameChecker,
SADFlags::AdditionalDescription | SADFlags::TitlePasteAs); if ( RET_OK != aAskForName.run() ) // cancelled by the user returnfalse;
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.