/* -*- 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 . */ #include <connectivity/CommonTools.hxx> #include <TConnection.hxx> #include <ParameterCont.hxx> #include <com/sun/star/awt/XWindow.hpp> #include <com/sun/star/beans/NamedValue.hpp> #include <com/sun/star/beans/PropertyAttribute.hpp> #include <com/sun/star/container/XChild.hpp> #include <com/sun/star/form/FormComponentType.hpp> #include <com/sun/star/io/XInputStream.hpp> #include <com/sun/star/lang/DisposedException.hpp> #include <com/sun/star/lang/IndexOutOfBoundsException.hpp> #include <com/sun/star/lang/XInitialization.hpp> #include <com/sun/star/lang/XMultiServiceFactory.hpp> #include <com/sun/star/sdb/DatabaseContext.hpp> #include <com/sun/star/sdb/BooleanComparisonMode.hpp> #include <com/sun/star/sdb/CommandType.hpp> #include <com/sun/star/sdb/ErrorMessageDialog.hpp> #include <com/sun/star/sdb/ParametersRequest.hpp> #include <com/sun/star/sdb/RowSetVetoException.hpp> #include <com/sun/star/sdb/SQLContext.hpp> #include <com/sun/star/sdb/XCompletedConnection.hpp> #include <com/sun/star/sdb/XInteractionSupplyParameters.hpp> #include <com/sun/star/sdb/XOfficeDatabaseDocument.hpp> #include <com/sun/star/sdb/XParametersSupplier.hpp> #include <com/sun/star/sdb/XQueriesSupplier.hpp> #include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp> #include <com/sun/star/sdbc/ConnectionPool.hpp> #include <com/sun/star/sdbc/DataType.hpp> #include <com/sun/star/sdbc/XConnection.hpp> #include <com/sun/star/sdbc/XDataSource.hpp> #include <com/sun/star/sdbc/XParameters.hpp> #include <com/sun/star/sdbc/XRow.hpp> #include <com/sun/star/sdbc/XRowSet.hpp> #include <com/sun/star/sdbc/XRowUpdate.hpp> #include <com/sun/star/sdbcx/KeyType.hpp> #include <com/sun/star/sdbcx/Privilege.hpp> #include <com/sun/star/sdbcx/XColumnsSupplier.hpp> #include <com/sun/star/sdbcx/XKeysSupplier.hpp> #include <com/sun/star/sdbcx/XTablesSupplier.hpp> #include <com/sun/star/task/InteractionHandler.hpp> #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> #include <com/sun/star/util/NumberFormat.hpp> #include <com/sun/star/util/NumberFormatsSupplier.hpp> #include <com/sun/star/util/XNumberFormatTypes.hpp> #include <comphelper/extract.hxx> #include <comphelper/interaction.hxx> #include <comphelper/property.hxx> #include <comphelper/propertysequence.hxx> #include <comphelper/types.hxx> #include <connectivity/conncleanup.hxx> #include <connectivity/dbconversion.hxx> #include <connectivity/dbexception.hxx> #include <connectivity/dbtools.hxx> #include <connectivity/statementcomposer.hxx> #include <o3tl/any.hxx> #include <o3tl/safeint.hxx> #include <osl/diagnose.h> #include <rtl/ustrbuf.hxx> #include <sal/log.hxx> #include <comphelper/diagnose_ex.hxx> #include <tools/stream.hxx> #include <cppuhelper/implbase.hxx> #include <strings.hrc> #include <resource/sharedresources.hxx> #include <algorithm> #include <iterator> #include <set> using namespace ::comphelper; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::io; using namespace ::com::sun::star::awt; using namespace ::com::sun::star::ui::dialogs; using namespace ::com::sun::star::util; using namespace ::com::sun::star::lang; using namespace ::com::sun::star::beans; using namespace ::com::sun::star::container; using namespace ::com::sun::star::sdb; using namespace ::com::sun::star::sdbc; using namespace ::com::sun::star::sdbcx; using namespace ::com::sun::star::task; using namespace ::com::sun::star::form; using namespace connectivity; namespace dbtools { namespace { typedef sal_Bool (SAL_CALL XDatabaseMetaData::*FMetaDataSupport)(); } sal_Int32 getDefaultNumberFormat(const Reference< XPropertySet >& _xColumn, const Reference< XNumberFormatTypes >& _xTypes, const Locale& _rLocale) { OSL_ENSURE(_xTypes.is() && _xColumn.is(), "dbtools::getDefaultNumberFormat: invalid arg !"); if (!_xTypes.is() || !_xColumn.is()) return NumberFormat::UNDEFINED; sal_Int32 nDataType = 0; sal_Int32 nScale = 0; try { // determine the datatype of the column _xColumn->getPropertyValue("Type") >>= nDataType; if (DataType::NUMERIC == nDataType || DataType::DECIMAL == nDataType) _xColumn->getPropertyValue("Scale") >>= nScale; } catch (Exception&) { return NumberFormat::UNDEFINED; } return getDefaultNumberFormat(nDataType, nScale, ::cppu::any2bool(_xColumn->getPropertyValue("IsCurrency")), _xTypes, _rLocale); } sal_Int32 getDefaultNumberFormat(sal_Int32 _nDataType, sal_Int32 _nScale, bool _bIsCurrency, const Reference< XNumberFormatTypes >& _xTypes, const Locale& _rLocale) { OSL_ENSURE(_xTypes.is() , "dbtools::getDefaultNumberFormat: invalid arg !"); if (!_xTypes.is()) return NumberFormat::UNDEFINED; sal_Int32 nFormat = 0; sal_Int32 nNumberType = _bIsCurrency ? NumberFormat::CURRENCY : NumberFormat::NUMBER; switch (_nDataType) { case DataType::BIT: case DataType::BOOLEAN: nFormat = _xTypes->getStandardFormat(NumberFormat::LOGICAL, _rLocale); break; case DataType::TINYINT: case DataType::SMALLINT: case DataType::INTEGER: case DataType::BIGINT: case DataType::FLOAT: case DataType::REAL: case DataType::DOUBLE: case DataType::NUMERIC: case DataType::DECIMAL: { try { nFormat = _xTypes->getStandardFormat(static_cast<sal_Int16>(nNumberType), _rLocale); if(_nScale > 0) { // generate a new format if necessary Reference< XNumberFormats > xFormats(_xTypes, UNO_QUERY); OUString sNewFormat = xFormats->generateFormat( 0, _rLocale, false, false, static_cast<sal_Int16>(_nScale), 1); // and add it to the formatter if necessary nFormat = xFormats->queryKey(sNewFormat, _rLocale, false); if (nFormat == sal_Int32(-1)) nFormat = xFormats->addNew(sNewFormat, _rLocale); } } catch (Exception&) { nFormat = _xTypes->getStandardFormat(static_cast<sal_Int16>(nNumberType), _rLocale); } } break; case DataType::CHAR: case DataType::VARCHAR: case DataType::LONGVARCHAR: case DataType::CLOB: nFormat = _xTypes->getStandardFormat(NumberFormat::TEXT, _rLocale); break; case DataType::DATE: nFormat = _xTypes->getStandardFormat(NumberFormat::DATE, _rLocale); break; case DataType::TIME: nFormat = _xTypes->getStandardFormat(NumberFormat::TIME, _rLocale); break; case DataType::TIMESTAMP: nFormat = _xTypes->getStandardFormat(NumberFormat::DATETIME, _rLocale); break; case DataType::BINARY: case DataType::VARBINARY: case DataType::LONGVARBINARY: case DataType::SQLNULL: case DataType::OTHER: case DataType::OBJECT: case DataType::DISTINCT: case DataType::STRUCT: case DataType::ARRAY: case DataType::BLOB: case DataType::REF: default: nFormat = _xTypes->getStandardFormat(NumberFormat::UNDEFINED, _rLocale); } return nFormat; } static Reference< XConnection> findConnection(const Reference< XInterface >& xParent) { Reference< XConnection> xConnection(xParent, UNO_QUERY); if (!xConnection.is()) { Reference< XChild> xChild(xParent, UNO_QUERY); if (xChild.is()) xConnection = findConnection(xChild->getParent()); } return xConnection; } static Reference< XDataSource> getDataSource_allowException( const OUString& _rsTitleOrPath, const Reference< XComponentContext >& _rxContext ) { ENSURE_OR_RETURN( !_rsTitleOrPath.isEmpty(), "getDataSource_allowException: invalid arg !", nullptr ); Reference< XDatabaseContext> xDatabaseContext = DatabaseContext::create(_rxContext); return Reference< XDataSource >( xDatabaseContext->getByName( _rsTitleOrPath ), UNO_QUERY ); } Reference< XDataSource > getDataSource( const OUString& _rsTitleOrPath, const Reference< XComponentContext >& _rxContext ) { Reference< XDataSource > xDS; try { xDS = getDataSource_allowException( _rsTitleOrPath, _rxContext ); } catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION("connectivity.commontools"); } return xDS; } static Reference< XConnection > getConnection_allowException( const OUString& _rsTitleOrPath, const OUString& _rsUser, const OUString& _rsPwd, const Reference< XComponentContext>& _rxContext, const Reference< XWindow >& _rxParent) { Reference< XDataSource> xDataSource( getDataSource_allowException(_rsTitleOrPath, _rxContext) ); Reference<XConnection> xConnection; if (xDataSource.is()) { //set ParentWindow for dialog, but just for the duration of this //call, undo at end of scope Reference<XInitialization> xIni(xDataSource, UNO_QUERY); if (xIni.is()) { Sequence< Any > aArgs{ Any(NamedValue( "ParentWindow", Any(_rxParent) )) }; xIni->initialize(aArgs); } // do it with interaction handler if(_rsUser.isEmpty() || _rsPwd.isEmpty()) { Reference<XPropertySet> xProp(xDataSource,UNO_QUERY); OUString sPwd, sUser; bool bPwdReq = false; try { xProp->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PASSWORD)) >>= sPwd; bPwdReq = ::cppu::any2bool(xProp->getPropertyValue("IsPasswordRequired")); xProp->getPropertyValue("User") >>= sUser; } catch(Exception&) { OSL_FAIL("dbtools::getConnection: error while retrieving data source properties!"); } if(bPwdReq && sPwd.isEmpty()) { // password required, but empty -> connect using an interaction handler Reference<XCompletedConnection> xConnectionCompletion(xProp, UNO_QUERY); if (xConnectionCompletion.is()) { // instantiate the default SDB interaction handler Reference< XInteractionHandler > xHandler = InteractionHandler::createWithParent(_rxContext, _rxParent); xConnection = xConnectionCompletion->connectWithCompletion(xHandler); } } else xConnection = xDataSource->getConnection(sUser, sPwd); } if(!xConnection.is()) // try to get one if not already have one, just to make sure xConnection = xDataSource->getConnection(_rsUser, _rsPwd); if (xIni.is()) { Sequence< Any > aArgs{ Any(NamedValue( "ParentWindow", Any(Reference<XWindow>()) )) }; xIni->initialize(aArgs); } } return xConnection; } Reference< XConnection> getConnection_withFeedback(const OUString& _rDataSourceName, const OUString& _rUser, const OUString& _rPwd, const Reference< XComponentContext>& _rxContext, const Reference< XWindow >& _rxParent) { Reference< XConnection > xReturn; try { xReturn = getConnection_allowException(_rDataSourceName, _rUser, _rPwd, _rxContext, _rxParent); } catch(SQLException&) { // allowed to pass throw; } catch(Exception&) { TOOLS_WARN_EXCEPTION( "connectivity.commontools", "::dbtools::getConnection_withFeedback: unexpected (non-SQL) exception caught!"); } return xReturn; } Reference< XConnection> getConnection(const Reference< XRowSet>& _rxRowSet) { Reference< XConnection> xReturn; Reference< XPropertySet> xRowSetProps(_rxRowSet, UNO_QUERY); if (xRowSetProps.is()) xRowSetProps->getPropertyValue("ActiveConnection") >>= xReturn; return xReturn; } // helper function which allows to implement both the connectRowset and the ensureRowSetConnection semantics // if connectRowset (which is deprecated) is removed, this function and one of its parameters are // not needed anymore, the whole implementation can be moved into ensureRowSetConnection then) static SharedConnection lcl_connectRowSet(const Reference< XRowSet>& _rxRowSet, const Reference< XComponentContext >& _rxContext, bool _bAttachAutoDisposer, const Reference< XWindow >& _rxParent) { SharedConnection xConnection; do { Reference< XPropertySet> xRowSetProps(_rxRowSet, UNO_QUERY); if ( !xRowSetProps.is() ) break; // 1. already connected? Reference< XConnection > xExistingConn( xRowSetProps->getPropertyValue("ActiveConnection"), UNO_QUERY ); if ( xExistingConn.is() // 2. embedded in a database? || isEmbeddedInDatabase( _rxRowSet, xExistingConn ) // 3. is there a connection in the parent hierarchy? || ( xExistingConn = findConnection( _rxRowSet ) ).is() ) { xRowSetProps->setPropertyValue("ActiveConnection", Any( xExistingConn ) ); // no auto disposer needed, since we did not create the connection xConnection.reset( xExistingConn, SharedConnection::NoTakeOwnership ); break; } // build a connection with its current settings (4. data source name, or 5. URL) static const OUStringLiteral sUserProp( u"User" ); OUString sDataSourceName; xRowSetProps->getPropertyValue("DataSourceName") >>= sDataSourceName; OUString sURL; xRowSetProps->getPropertyValue("URL") >>= sURL; Reference< XConnection > xPureConnection; if (!sDataSourceName.isEmpty()) { // the row set's data source property is set // -> try to connect, get user and pwd setting for that OUString sUser, sPwd; if (hasProperty(sUserProp, xRowSetProps)) xRowSetProps->getPropertyValue(sUserProp) >>= sUser; if (hasProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PASSWORD), xRowSetProps)) xRowSetProps->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PASSWORD)) >>= sPwd; xPureConnection = getConnection_allowException( sDataSourceName, sUser, sPwd, _rxContext, _rxParent ); } else if (!sURL.isEmpty()) { // the row set has no data source, but a connection url set // -> try to connection with that url Reference< XConnectionPool > xDriverManager; try { xDriverManager = ConnectionPool::create( _rxContext ); } catch( const Exception& ) { } if (xDriverManager.is()) { OUString sUser, sPwd; if (hasProperty(sUserProp, xRowSetProps)) xRowSetProps->getPropertyValue(sUserProp) >>= sUser; if (hasProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PASSWORD), xRowSetProps)) xRowSetProps->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PASSWORD)) >>= sPwd; if (!sUser.isEmpty()) { // use user and pwd together with the url auto aInfo(::comphelper::InitPropertySequence({ { "user", Any(sUser) }, { "password", Any(sPwd) } })); xPureConnection = xDriverManager->getConnectionWithInfo( sURL, aInfo ); } else // just use the url xPureConnection = xDriverManager->getConnection( sURL ); } } xConnection.reset( xPureConnection, _bAttachAutoDisposer ? SharedConnection::NoTakeOwnership : SharedConnection::TakeOwnership /* take ownership if and only if we're *not* going to auto-dispose the connection */ ); // now if we created a connection, forward it to the row set if ( xConnection.is() ) { try { if ( _bAttachAutoDisposer ) { new OAutoConnectionDisposer( _rxRowSet, xConnection ); } else xRowSetProps->setPropertyValue( "ActiveConnection", Any( xConnection.getTyped() ) ); } catch(Exception&) { TOOLS_WARN_EXCEPTION( "connectivity.commontools", "EXception when we set the new active connection!"); } } } while ( false ); return xConnection; } Reference< XConnection> connectRowset(const Reference< XRowSet>& _rxRowSet, const Reference< XComponentContext >& _rxContext, const Reference< XWindow >& _rxParent) { SharedConnection xConnection = lcl_connectRowSet( _rxRowSet, _rxContext, true, _rxParent ); return xConnection.getTyped(); } SharedConnection ensureRowSetConnection(const Reference< XRowSet>& _rxRowSet, const Reference< XComponentContext>& _rxContext, const Reference< XWindow >& _rxParent) { return lcl_connectRowSet( _rxRowSet, _rxContext, false/*bUseAutoConnectionDisposer*/, _rxParent ); } Reference< XNameAccess> getTableFields(const Reference< XConnection>& _rxConn,const OUString& _rName) { Reference< XComponent > xDummy; return getFieldsByCommandDescriptor( _rxConn, CommandType::TABLE, _rName, xDummy ); } Reference< XNameAccess> getPrimaryKeyColumns_throw(const Any& i_aTable) { const Reference< XPropertySet > xTable(i_aTable,UNO_QUERY_THROW); return getPrimaryKeyColumns_throw(xTable); } Reference< XNameAccess> getPrimaryKeyColumns_throw(const Reference< XPropertySet >& i_xTable) { Reference<XNameAccess> xKeyColumns; const Reference<XKeysSupplier> xKeySup(i_xTable,UNO_QUERY); if ( xKeySup.is() ) { const Reference<XIndexAccess> xKeys = xKeySup->getKeys(); if ( xKeys.is() ) { ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap(); const OUString& sPropName = rPropMap.getNameByIndex(PROPERTY_ID_TYPE); Reference<XPropertySet> xProp; const sal_Int32 nCount = xKeys->getCount(); for(sal_Int32 i = 0;i< nCount;++i) { xProp.set(xKeys->getByIndex(i),UNO_QUERY_THROW); sal_Int32 nKeyType = 0; xProp->getPropertyValue(sPropName) >>= nKeyType; if(KeyType::PRIMARY == nKeyType) { const Reference<XColumnsSupplier> xKeyColsSup(xProp,UNO_QUERY_THROW); xKeyColumns = xKeyColsSup->getColumns(); break; } } } } return xKeyColumns; } namespace { enum FieldLookupState { HANDLE_TABLE, HANDLE_QUERY, HANDLE_SQL, RETRIEVE_OBJECT, RETRIEVE_COLUMNS, DONE, FAILED }; } Reference< XNameAccess > getFieldsByCommandDescriptor( const Reference< XConnection >& _rxConnection, const sal_Int32 _nCommandType, const OUString& _rCommand, Reference< XComponent >& _rxKeepFieldsAlive, SQLExceptionInfo* _pErrorInfo ) { OSL_PRECOND( _rxConnection.is(), "::dbtools::getFieldsByCommandDescriptor: invalid connection!" ); OSL_PRECOND( ( CommandType::TABLE == _nCommandType ) || ( CommandType::QUERY == _nCommandType ) || ( CommandType::COMMAND == _nCommandType ), "::dbtools::getFieldsByCommandDescriptor: invalid command type!" ); OSL_PRECOND( !_rCommand.isEmpty(), "::dbtools::getFieldsByCommandDescriptor: invalid command (empty)!" ); Reference< XNameAccess > xFields; // reset the error if ( _pErrorInfo ) *_pErrorInfo = SQLExceptionInfo(); // reset the ownership holder _rxKeepFieldsAlive.clear(); // go for the fields try { // some kind of state machine to ease the sharing of code FieldLookupState eState = FAILED; switch ( _nCommandType ) { case CommandType::TABLE: eState = HANDLE_TABLE; break; case CommandType::QUERY: eState = HANDLE_QUERY; break; case CommandType::COMMAND: eState = HANDLE_SQL; break; } // needed in various states: Reference< XNameAccess > xObjectCollection; Reference< XColumnsSupplier > xSupplyColumns; // go! while ( ( DONE != eState ) && ( FAILED != eState ) ) { switch ( eState ) { case HANDLE_TABLE: { // initial state for handling the tables // get the table objects Reference< XTablesSupplier > xSupplyTables( _rxConnection, UNO_QUERY ); if ( xSupplyTables.is() ) xObjectCollection = xSupplyTables->getTables(); // if something went wrong 'til here, then this will be handled in the next state // next state: get the object eState = RETRIEVE_OBJECT; } break; case HANDLE_QUERY: { // initial state for handling the tables // get the table objects Reference< XQueriesSupplier > xSupplyQueries( _rxConnection, UNO_QUERY ); if ( xSupplyQueries.is() ) xObjectCollection = xSupplyQueries->getQueries(); // if something went wrong 'til here, then this will be handled in the next state // next state: get the object eState = RETRIEVE_OBJECT; } break; case RETRIEVE_OBJECT: // here we should have an object (aka query or table) collection, and are going // to retrieve the desired object // next state: default to FAILED eState = FAILED; OSL_ENSURE( xObjectCollection.is(), "::dbtools::getFieldsByCommandDescriptor: invalid connection (no sdb.Connection, or no Tables-/QueriesSupplier)!"); if ( xObjectCollection.is() && xObjectCollection->hasByName( _rCommand ) ) { xObjectCollection->getByName( _rCommand ) >>= xSupplyColumns; // (xSupplyColumns being NULL will be handled in the next state) // next: go for the columns eState = RETRIEVE_COLUMNS; } break; case RETRIEVE_COLUMNS: OSL_ENSURE( xSupplyColumns.is(), "::dbtools::getFieldsByCommandDescriptor: could not retrieve the columns supplier!" ); // next state: default to FAILED eState = FAILED; if ( xSupplyColumns.is() ) { xFields = xSupplyColumns->getColumns(); // that's it eState = DONE; } break; case HANDLE_SQL: { OUString sStatementToExecute( _rCommand ); // well, the main problem here is to handle statements which contain a parameter // If we would simply execute a parametrized statement, then this will fail because // we cannot supply any parameter values. // Thus, we try to analyze the statement, and to append a WHERE 0=1 filter criterion // This should cause every driver to not really execute the statement, but to return // an empty result set with the proper structure. We then can use this result set // to retrieve the columns. try { Reference< XMultiServiceFactory > xComposerFac( _rxConnection, UNO_QUERY ); if ( xComposerFac.is() ) { Reference< XSingleSelectQueryComposer > xComposer(xComposerFac->createInstance("com.sun.star.sdb.SingleSelectQueryComposer"),UNO_QUERY); if ( xComposer.is() ) { xComposer->setQuery( sStatementToExecute ); // Now set the filter to a dummy restriction which will result in an empty // result set. xComposer->setFilter( "0=1" ); sStatementToExecute = xComposer->getQuery( ); } } } catch( const Exception& ) { // silent this error, this was just a try. If we're here, we did not change sStatementToExecute, // so it will still be _rCommand, which then will be executed without being touched } // now execute Reference< XPreparedStatement > xStatement = _rxConnection->prepareStatement( sStatementToExecute ); // transfer ownership of this temporary object to the caller _rxKeepFieldsAlive.set(xStatement, css::uno::UNO_QUERY); // set the "MaxRows" to 0. This is just in case our attempt to append a 0=1 filter // failed - in this case, the MaxRows restriction should at least ensure that there // is no data returned (which would be potentially expensive) Reference< XPropertySet > xStatementProps( xStatement,UNO_QUERY ); try { if ( xStatementProps.is() ) xStatementProps->setPropertyValue( "MaxRows", Any( sal_Int32( 0 ) ) ); } catch( const Exception& ) { OSL_FAIL( "::dbtools::getFieldsByCommandDescriptor: could not set the MaxRows!" ); // oh damn. Not much of a chance to recover, we will no retrieve the complete // full blown result set } xSupplyColumns.set(xStatement->executeQuery(), css::uno::UNO_QUERY); // this should have given us a result set which does not contain any data, but // the structural information we need // so the next state is to get the columns eState = RETRIEVE_COLUMNS; } break; default: OSL_FAIL( "::dbtools::getFieldsByCommandDescriptor: oops! unhandled state here!" ); eState = FAILED; } } } catch( const SQLContext& e ) { if ( _pErrorInfo ) *_pErrorInfo = SQLExceptionInfo( e ); } catch( const SQLWarning& e ) { if ( _pErrorInfo ) *_pErrorInfo = SQLExceptionInfo( e ); } catch( const SQLException& e ) { if ( _pErrorInfo ) *_pErrorInfo = SQLExceptionInfo( e ); } catch( const Exception& ) { TOOLS_WARN_EXCEPTION( "connectivity.commontools", "::dbtools::getFieldsByCommandDescriptor: caught an exception while retrieving the fields!" ); } return xFields; } Sequence< OUString > getFieldNamesByCommandDescriptor( const Reference< XConnection >& _rxConnection, const sal_Int32 _nCommandType, const OUString& _rCommand, SQLExceptionInfo* _pErrorInfo ) { // get the container for the fields Reference< XComponent > xKeepFieldsAlive; Reference< XNameAccess > xFieldContainer = getFieldsByCommandDescriptor( _rxConnection, _nCommandType, _rCommand, xKeepFieldsAlive, _pErrorInfo ); // get the names of the fields Sequence< OUString > aNames; if ( xFieldContainer.is() ) aNames = xFieldContainer->getElementNames(); // clean up any temporary objects which have been created disposeComponent( xKeepFieldsAlive ); // outta here return aNames; } SQLException prependErrorInfo( const SQLException& _rChainedException, const Reference< XInterface >& _rxContext, const OUString& _rAdditionalError, const StandardSQLState _eSQLState ) { return SQLException( _rAdditionalError, _rxContext, _eSQLState == StandardSQLState::ERROR_UNSPECIFIED ? OUString() : getStandardSQLState( _eSQLState ), 0, Any( _rChainedException ) ); } namespace { struct NameComponentSupport { const bool bCatalogs; const bool bSchemas; NameComponentSupport( const bool _bCatalogs, const bool _bSchemas ) :bCatalogs( _bCatalogs ) ,bSchemas( _bSchemas ) { } }; NameComponentSupport lcl_getNameComponentSupport( const Reference< XDatabaseMetaData >& _rxMetaData, EComposeRule _eComposeRule ) { OSL_PRECOND( _rxMetaData.is(), "lcl_getNameComponentSupport: invalid meta data!" ); FMetaDataSupport pCatalogCall = &XDatabaseMetaData::supportsCatalogsInDataManipulation; FMetaDataSupport pSchemaCall = &XDatabaseMetaData::supportsSchemasInDataManipulation; bool bIgnoreMetaData = false; switch ( _eComposeRule ) { case EComposeRule::InTableDefinitions: pCatalogCall = &XDatabaseMetaData::supportsCatalogsInTableDefinitions; pSchemaCall = &XDatabaseMetaData::supportsSchemasInTableDefinitions; break; case EComposeRule::InIndexDefinitions: pCatalogCall = &XDatabaseMetaData::supportsCatalogsInIndexDefinitions; pSchemaCall = &XDatabaseMetaData::supportsSchemasInIndexDefinitions; break; case EComposeRule::InProcedureCalls: pCatalogCall = &XDatabaseMetaData::supportsCatalogsInProcedureCalls; pSchemaCall = &XDatabaseMetaData::supportsSchemasInProcedureCalls; break; case EComposeRule::InPrivilegeDefinitions: pCatalogCall = &XDatabaseMetaData::supportsCatalogsInPrivilegeDefinitions; pSchemaCall = &XDatabaseMetaData::supportsSchemasInPrivilegeDefinitions; break; case EComposeRule::Complete: bIgnoreMetaData = true; break; case EComposeRule::InDataManipulation: // already properly set above break; } return NameComponentSupport( bIgnoreMetaData || (_rxMetaData.get()->*pCatalogCall)(), bIgnoreMetaData || (_rxMetaData.get()->*pSchemaCall)() ); } } static OUString impl_doComposeTableName( const Reference< XDatabaseMetaData >& _rxMetaData, const OUString& _rCatalog, const OUString& _rSchema, const OUString& _rName, bool _bQuote, EComposeRule _eComposeRule ) { OSL_ENSURE(_rxMetaData.is(), "impl_doComposeTableName : invalid meta data !"); if ( !_rxMetaData.is() ) return OUString(); OSL_ENSURE(!_rName.isEmpty(), "impl_doComposeTableName : at least the name should be non-empty !"); const OUString sQuoteString = _rxMetaData->getIdentifierQuoteString(); const NameComponentSupport aNameComps( lcl_getNameComponentSupport( _rxMetaData, _eComposeRule ) ); OUStringBuffer aComposedName; OUString sCatalogSep; bool bCatalogAtStart = true; if ( !_rCatalog.isEmpty() && aNameComps.bCatalogs ) { sCatalogSep = _rxMetaData->getCatalogSeparator(); bCatalogAtStart = _rxMetaData->isCatalogAtStart(); if ( bCatalogAtStart && !sCatalogSep.isEmpty()) { aComposedName.append( _bQuote ? quoteName( sQuoteString, _rCatalog ) : _rCatalog ); aComposedName.append( sCatalogSep ); } } if ( !_rSchema.isEmpty() && aNameComps.bSchemas ) { aComposedName.append( (_bQuote ? quoteName( sQuoteString, _rSchema ) : _rSchema ) + "." ); } aComposedName.append( _bQuote ? quoteName( sQuoteString, _rName ) : _rName ); if ( !_rCatalog.isEmpty() && !bCatalogAtStart && !sCatalogSep.isEmpty() && aNameComps.bCatalogs ) { aComposedName.append( sCatalogSep ); aComposedName.append( _bQuote ? quoteName( sQuoteString, _rCatalog ) : _rCatalog ); } return aComposedName.makeStringAndClear(); } OUString quoteTableName(const Reference< XDatabaseMetaData>& _rxMeta , const OUString& _rName , EComposeRule _eComposeRule) { OUString sCatalog, sSchema, sTable; qualifiedNameComponents(_rxMeta,_rName,sCatalog,sSchema,sTable,_eComposeRule); return impl_doComposeTableName( _rxMeta, sCatalog, sSchema, sTable, true, _eComposeRule ); } void qualifiedNameComponents(const Reference< XDatabaseMetaData >& _rxConnMetaData, const OUString& _rQualifiedName, OUString& _rCatalog, OUString& _rSchema, OUString& _rName,EComposeRule _eComposeRule) { OSL_ENSURE(_rxConnMetaData.is(), "QualifiedNameComponents : invalid meta data!"); NameComponentSupport aNameComps( lcl_getNameComponentSupport( _rxConnMetaData, _eComposeRule ) ); OUString sSeparator = _rxConnMetaData->getCatalogSeparator(); OUString sName(_rQualifiedName); // do we have catalogs? if ( aNameComps.bCatalogs ) { if (_rxConnMetaData->isCatalogAtStart()) { // search for the catalog name at the beginning sal_Int32 nIndex = sName.indexOf(sSeparator); if (-1 != nIndex) { _rCatalog = sName.copy(0, nIndex); sName = sName.copy(nIndex + 1); } } else { // Catalog name at the end sal_Int32 nIndex = sName.lastIndexOf(sSeparator); if (-1 != nIndex) { _rCatalog = sName.copy(nIndex + 1); sName = sName.copy(0, nIndex); } } } if ( aNameComps.bSchemas ) { sal_Int32 nIndex = sName.indexOf('.'); // OSL_ENSURE(-1 != nIndex, "QualifiedNameComponents: no schema separator!"); if ( nIndex != -1 ) _rSchema = sName.copy(0, nIndex); sName = sName.copy(nIndex + 1); } _rName = sName; } Reference< XNumberFormatsSupplier> getNumberFormats( const Reference< XConnection>& _rxConn, bool _bAlloweDefault, const Reference< XComponentContext>& _rxContext) { // ask the parent of the connection (should be a DatabaseAccess) Reference< XNumberFormatsSupplier> xReturn; Reference< XChild> xConnAsChild(_rxConn, UNO_QUERY); static constexpr OUStringLiteral sPropFormatsSupplier( u"NumberFormatsSupplier" ); if (xConnAsChild.is()) { Reference< XPropertySet> xConnParentProps(xConnAsChild->getParent(), UNO_QUERY); if (xConnParentProps.is() && hasProperty(sPropFormatsSupplier, xConnParentProps)) xConnParentProps->getPropertyValue(sPropFormatsSupplier) >>= xReturn; } else if(_bAlloweDefault && _rxContext.is()) { xReturn = NumberFormatsSupplier::createWithDefaultLocale( _rxContext ); } return xReturn; } void TransferFormComponentProperties( const Reference< XPropertySet>& xOldProps, const Reference< XPropertySet>& xNewProps, const Locale& _rLocale) { try { OSL_ENSURE( xOldProps.is() && xNewProps.is(), "TransferFormComponentProperties: invalid source/dest!" ); if ( !xOldProps.is() || !xNewProps.is() ) return; // First we copy all the Props, that are available in source and target and have the same description Reference< XPropertySetInfo> xOldInfo( xOldProps->getPropertySetInfo()); Reference< XPropertySetInfo> xNewInfo( xNewProps->getPropertySetInfo()); const Sequence< Property> aOldProperties = xOldInfo->getProperties(); const Sequence< Property> aNewProperties = xNewInfo->getProperties(); static constexpr OUStringLiteral sPropFormatsSupplier(u"FormatsSupplier"); static constexpr OUStringLiteral sPropCurrencySymbol(u"CurrencySymbol"); static constexpr OUStringLiteral sPropDecimals(u"Decimals"); static constexpr OUStringLiteral sPropEffectiveMin(u"EffectiveMin"); static constexpr OUStringLiteral sPropEffectiveMax(u"EffectiveMax"); static constexpr OUStringLiteral sPropEffectiveDefault(u"EffectiveDefault"); static constexpr OUStringLiteral sPropDefaultText(u"DefaultText"); static constexpr OUStringLiteral sPropDefaultDate(u"DefaultDate"); static constexpr OUStringLiteral sPropDefaultTime(u"DefaultTime"); static constexpr OUStringLiteral sPropValueMin(u"ValueMin"); static constexpr OUStringLiteral sPropValueMax(u"ValueMax"); static constexpr OUStringLiteral sPropDecimalAccuracy(u"DecimalAccuracy"); static constexpr OUStringLiteral sPropClassId(u"ClassId"); static constexpr OUStringLiteral sFormattedServiceName( u"com.sun.star.form.component.FormattedField" ); for (const Property& rOldProp : aOldProperties) { if ( rOldProp.Name != "DefaultControl" && rOldProp.Name != "LabelControl" ) { // binary search const Property* pResult = std::lower_bound( aNewProperties.begin(), aNewProperties.end(), rOldProp, ::comphelper::PropertyCompareByName()); if ( ( pResult != aNewProperties.end() ) && ( pResult->Name == rOldProp.Name ) && ( (pResult->Attributes & PropertyAttribute::READONLY) == 0 ) && ( pResult->Type.equals(rOldProp.Type)) ) { // Attributes match and the property is not read-only try { xNewProps->setPropertyValue(pResult->Name, xOldProps->getPropertyValue(pResult->Name)); } catch(IllegalArgumentException const &) { TOOLS_WARN_EXCEPTION( "connectivity.commontools", "TransferFormComponentProperties : could not transfer the value for property \"" << pResult->Name << "\""); } } } } // for formatted fields (either old or new) we have some special treatments Reference< XServiceInfo > xSI( xOldProps, UNO_QUERY ); bool bOldIsFormatted = xSI.is() && xSI->supportsService( sFormattedServiceName ); xSI.set( xNewProps, UNO_QUERY ); bool bNewIsFormatted = xSI.is() && xSI->supportsService( sFormattedServiceName ); if (!bOldIsFormatted && !bNewIsFormatted) return; // nothing to do if (bOldIsFormatted && bNewIsFormatted) // if both fields are formatted we do no conversions return; if (bOldIsFormatted) { // get some properties from the selected format and put them in the new Set Any aFormatKey( xOldProps->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FORMATKEY)) ); if (aFormatKey.hasValue()) { Reference< XNumberFormatsSupplier> xSupplier; xOldProps->getPropertyValue(sPropFormatsSupplier) >>= xSupplier; if (xSupplier.is()) { Reference< XNumberFormats> xFormats(xSupplier->getNumberFormats()); Reference< XPropertySet> xFormat(xFormats->getByKey(getINT32(aFormatKey))); if (hasProperty(sPropCurrencySymbol, xFormat)) { Any aVal( xFormat->getPropertyValue(sPropCurrencySymbol) ); if (aVal.hasValue() && hasProperty(sPropCurrencySymbol, xNewProps)) // If the source value hasn't been set then don't copy it // so we don't overwrite the default value xNewProps->setPropertyValue(sPropCurrencySymbol, aVal); } if (hasProperty(sPropDecimals, xFormat) && hasProperty(sPropDecimals, xNewProps)) xNewProps->setPropertyValue(sPropDecimals, xFormat->getPropertyValue(sPropDecimals)); } } // a potential Min-Max-Conversion Any aEffectiveMin( xOldProps->getPropertyValue(sPropEffectiveMin) ); if (aEffectiveMin.hasValue()) { // Unlike the ValueMin the EffectiveMin can be void if (hasProperty(sPropValueMin, xNewProps)) { OSL_ENSURE(aEffectiveMin.getValueType().getTypeClass() == TypeClass_DOUBLE, "TransferFormComponentProperties : invalid property type !"); xNewProps->setPropertyValue(sPropValueMin, aEffectiveMin); } } Any aEffectiveMax( xOldProps->getPropertyValue(sPropEffectiveMax) ); if (aEffectiveMax.hasValue()) { // analog if (hasProperty(sPropValueMax, xNewProps)) { OSL_ENSURE(aEffectiveMax.getValueType().getTypeClass() == TypeClass_DOUBLE, "TransferFormComponentProperties : invalid property type !"); xNewProps->setPropertyValue(sPropValueMax, aEffectiveMax); } } // then we can still convert and copy the default values Any aEffectiveDefault( xOldProps->getPropertyValue(sPropEffectiveDefault) ); if (aEffectiveDefault.hasValue()) { bool bIsString = aEffectiveDefault.getValueType().getTypeClass() == TypeClass_STRING; OSL_ENSURE(bIsString || aEffectiveDefault.getValueType().getTypeClass() == TypeClass_DOUBLE, "TransferFormComponentProperties : invalid property type !"); // The Effective-Properties should always be void or string or double... if (hasProperty(sPropDefaultDate, xNewProps) && !bIsString) { // (to convert an OUString into a date will not always succeed, because it might be bound to a text-column, // but we can work with a double) Date aDate = DBTypeConversion::toDate(getDouble(aEffectiveDefault)); xNewProps->setPropertyValue(sPropDefaultDate, Any(aDate)); } if (hasProperty(sPropDefaultTime, xNewProps) && !bIsString) { // Completely analogous to time css::util::Time aTime = DBTypeConversion::toTime(getDouble(aEffectiveDefault)); xNewProps->setPropertyValue(sPropDefaultTime, Any(aTime)); } if (hasProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE), xNewProps) && !bIsString) { // Here we can simply pass the double xNewProps->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE), aEffectiveDefault); } if (hasProperty(sPropDefaultText, xNewProps) && bIsString) { // and here the OUString xNewProps->setPropertyValue(sPropDefaultText, aEffectiveDefault); } // nyi: The translation between doubles and OUString would offer more alternatives } } // The other direction: the new Control shall be formatted if (bNewIsFormatted) { // first the formatting // we can't set a Supplier, so the new Set must bring one in Reference< XNumberFormatsSupplier> xSupplier; xNewProps->getPropertyValue(sPropFormatsSupplier) >>= xSupplier; if (xSupplier.is()) { Reference< XNumberFormats> xFormats(xSupplier->getNumberFormats()); // Set number of decimals sal_Int16 nDecimals = 2; if (hasProperty(sPropDecimalAccuracy, xOldProps)) xOldProps->getPropertyValue(sPropDecimalAccuracy) >>= nDecimals; // base format (depending on the ClassId of the old Set) sal_Int32 nBaseKey = 0; if (hasProperty(sPropClassId, xOldProps)) { Reference< XNumberFormatTypes> xTypeList(xFormats, UNO_QUERY); if (xTypeList.is()) { sal_Int16 nClassId = 0; xOldProps->getPropertyValue(sPropClassId) >>= nClassId; switch (nClassId) { case FormComponentType::DATEFIELD : nBaseKey = xTypeList->getStandardFormat(NumberFormat::DATE, _rLocale); break; case FormComponentType::TIMEFIELD : nBaseKey = xTypeList->getStandardFormat(NumberFormat::TIME, _rLocale); break; case FormComponentType::CURRENCYFIELD : nBaseKey = xTypeList->getStandardFormat(NumberFormat::CURRENCY, _rLocale); break; } } } // With this we can generate a new format ... OUString sNewFormat = xFormats->generateFormat(nBaseKey, _rLocale, false, false, nDecimals, 0); // No thousands separator, negative numbers are not in red, no leading zeros // ... and add at FormatsSupplier (if needed) sal_Int32 nKey = xFormats->queryKey(sNewFormat, _rLocale, false); if (nKey == sal_Int32(-1)) { // not added yet in my formatter ... nKey = xFormats->addNew(sNewFormat, _rLocale); } xNewProps->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FORMATKEY), Any(nKey)); } // min-/max-Value Any aNewMin, aNewMax; if (hasProperty(sPropValueMin, xOldProps)) aNewMin = xOldProps->getPropertyValue(sPropValueMin); if (hasProperty(sPropValueMax, xOldProps)) aNewMax = xOldProps->getPropertyValue(sPropValueMax); xNewProps->setPropertyValue(sPropEffectiveMin, aNewMin); xNewProps->setPropertyValue(sPropEffectiveMax, aNewMax); // Default-Value Any aNewDefault; if (hasProperty(sPropDefaultDate, xOldProps)) { Any aDate( xOldProps->getPropertyValue(sPropDefaultDate) ); if (aDate.hasValue()) aNewDefault <<= DBTypeConversion::toDouble(*o3tl::doAccess<Date>(aDate)); } if (hasProperty(sPropDefaultTime, xOldProps)) { Any aTime( xOldProps->getPropertyValue(sPropDefaultTime) ); if (aTime.hasValue()) aNewDefault <<= DBTypeConversion::toDouble(*o3tl::doAccess<Time>(aTime)); } // double or OUString will be copied directly if (hasProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE), xOldProps)) aNewDefault = xOldProps->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE)); if (hasProperty(sPropDefaultText, xOldProps)) aNewDefault = xOldProps->getPropertyValue(sPropDefaultText); if (aNewDefault.hasValue()) xNewProps->setPropertyValue(sPropEffectiveDefault, aNewDefault); } } catch(const Exception&) { TOOLS_WARN_EXCEPTION( "connectivity.commontools", "TransferFormComponentProperties" ); } } bool canInsert(const Reference< XPropertySet>& _rxCursorSet) { return (_rxCursorSet.is() && (getINT32(_rxCursorSet->getPropertyValue("Privileges")) & Privilege::INSERT) != 0); } bool canUpdate(const Reference< XPropertySet>& _rxCursorSet) { return (_rxCursorSet.is() && (getINT32(_rxCursorSet->getPropertyValue("Privileges")) & Privilege::UPDATE) != 0); } bool canDelete(const Reference< XPropertySet>& _rxCursorSet) { return (_rxCursorSet.is() && (getINT32(_rxCursorSet->getPropertyValue("Privileges")) & Privilege::DELETE) != 0); } Reference< XDataSource> findDataSource(const Reference< XInterface >& _xParent) { Reference< XOfficeDatabaseDocument> xDatabaseDocument(_xParent, UNO_QUERY); Reference< XDataSource> xDataSource; if ( xDatabaseDocument.is() ) xDataSource = xDatabaseDocument->getDataSource(); if ( !xDataSource.is() ) xDataSource.set(_xParent, UNO_QUERY); if (!xDataSource.is()) { Reference< XChild> xChild(_xParent, UNO_QUERY); if ( xChild.is() ) xDataSource = findDataSource(xChild->getParent()); } return xDataSource; } static Reference< XSingleSelectQueryComposer > getComposedRowSetStatement( const Reference< XPropertySet >& _rxRowSet, const Reference< XComponentContext >& _rxContext, const Reference< XWindow >& _rxParent ) { Reference< XSingleSelectQueryComposer > xComposer; try { Reference< XConnection> xConn = connectRowset( Reference< XRowSet >( _rxRowSet, UNO_QUERY ), _rxContext, _rxParent ); if ( xConn.is() ) // implies _rxRowSet.is() { // build the statement the row set is based on (can't use the ActiveCommand property of the set // as this reflects the status after the last execute, not the currently set properties) sal_Int32 nCommandType = CommandType::COMMAND; OUString sCommand; bool bEscapeProcessing = false; OSL_VERIFY( _rxRowSet->getPropertyValue("CommandType") >>= nCommandType ); OSL_VERIFY( _rxRowSet->getPropertyValue("Command") >>= sCommand ); OSL_VERIFY( _rxRowSet->getPropertyValue("EscapeProcessing") >>= bEscapeProcessing ); StatementComposer aComposer( xConn, sCommand, nCommandType, bEscapeProcessing ); // append sort aComposer.setOrder( getString( _rxRowSet->getPropertyValue("Order") ) ); // append filter bool bApplyFilter = true; _rxRowSet->getPropertyValue("ApplyFilter") >>= bApplyFilter; if ( bApplyFilter ) { aComposer.setFilter( getString( _rxRowSet->getPropertyValue("Filter") ) ); aComposer.setHavingClause( getString( _rxRowSet->getPropertyValue("HavingClause") ) ); } aComposer.getQuery(); xComposer = aComposer.getComposer(); aComposer.setDisposeComposer( false ); } } catch( const SQLException& ) { throw; } catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION("connectivity.commontools"); } return xComposer; } Reference< XSingleSelectQueryComposer > getCurrentSettingsComposer( const Reference< XPropertySet>& _rxRowSetProps, const Reference< XComponentContext>& _rxContext, const Reference< XWindow >& _rxParent) { Reference< XSingleSelectQueryComposer > xReturn; try { xReturn = getComposedRowSetStatement( _rxRowSetProps, _rxContext, _rxParent ); } catch( const SQLException& ) { throw; } catch( const Exception& ) { TOOLS_WARN_EXCEPTION( "connectivity.commontools", "::getCurrentSettingsComposer : caught an exception !" ); } return xReturn; } OUString composeTableName( const Reference< XDatabaseMetaData >& _rxMetaData, const OUString& _rCatalog, const OUString& _rSchema, const OUString& _rName, bool _bQuote, EComposeRule _eComposeRule) { return impl_doComposeTableName( _rxMetaData, _rCatalog, _rSchema, _rName, _bQuote, _eComposeRule ); } OUString composeTableNameForSelect( const Reference< XConnection >& _rxConnection, const OUString& _rCatalog, const OUString& _rSchema, const OUString& _rName ) { bool bUseCatalogInSelect = isDataSourcePropertyEnabled( _rxConnection, "UseCatalogInSelect", true ); bool bUseSchemaInSelect = isDataSourcePropertyEnabled( _rxConnection, "UseSchemaInSelect", true ); return impl_doComposeTableName( _rxConnection->getMetaData(), bUseCatalogInSelect ? _rCatalog : OUString(), bUseSchemaInSelect ? _rSchema : OUString(), _rName, true, EComposeRule::InDataManipulation ); } namespace { void lcl_getTableNameComponents( const Reference<XPropertySet>& _xTable, OUString& _out_rCatalog, OUString& _out_rSchema, OUString& _out_rName ) { ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap(); Reference< XPropertySetInfo > xInfo; if (_xTable.is()) xInfo = _xTable->getPropertySetInfo(); if ( xInfo.is() && xInfo->hasPropertyByName(rPropMap.getNameByIndex(PROPERTY_ID_NAME)) ) { if ( xInfo->hasPropertyByName(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME)) && xInfo->hasPropertyByName(rPropMap.getNameByIndex(PROPERTY_ID_SCHEMANAME)) ) { _xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME)) >>= _out_rCatalog; _xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_SCHEMANAME)) >>= _out_rSchema; } _xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME)) >>= _out_rName; } else OSL_FAIL( "::dbtools::lcl_getTableNameComponents: this is no table object!" ); } } OUString composeTableNameForSelect( const Reference< XConnection >& _rxConnection, const Reference<XPropertySet>& _xTable ) { OUString sCatalog, sSchema, sName; lcl_getTableNameComponents( _xTable, sCatalog, sSchema, sName ); return composeTableNameForSelect( _rxConnection, sCatalog, sSchema, sName ); } OUString composeTableName(const Reference<XDatabaseMetaData>& _xMetaData, const Reference<XPropertySet>& _xTable, EComposeRule _eComposeRule, bool _bQuote ) { OUString sCatalog, sSchema, sName; lcl_getTableNameComponents( _xTable, sCatalog, sSchema, sName ); return impl_doComposeTableName( _xMetaData, sCatalog, sSchema, sName, _bQuote, _eComposeRule ); } sal_Int32 getSearchColumnFlag( const Reference< XConnection>& _rxConn,sal_Int32 _nDataType) { sal_Int32 nSearchFlag = 0; Reference<XResultSet> xSet = _rxConn->getMetaData()->getTypeInfo(); if(xSet.is()) { Reference<XRow> xRow(xSet,UNO_QUERY); while(xSet->next()) { if(xRow->getInt(2) == _nDataType) { nSearchFlag = xRow->getInt(9); break; } } } return nSearchFlag; } OUString createUniqueName( const Sequence< OUString >& _rNames, const OUString& _rBaseName, bool _bStartWithNumber ) { std::set< OUString > aUsedNames(_rNames.begin(), _rNames.end()); OUString sName( _rBaseName ); sal_Int32 nPos = 1; if ( _bStartWithNumber ) sName += OUString::number( nPos ); while ( aUsedNames.find( sName ) != aUsedNames.end() ) { sName = _rBaseName + OUString::number( ++nPos ); } return sName; } OUString createUniqueName(const Reference<XNameAccess>& _rxContainer,const OUString& _rBaseName, bool _bStartWithNumber) { Sequence< OUString > aElementNames; OSL_ENSURE( _rxContainer.is(), "createUniqueName: invalid container!" ); if ( _rxContainer.is() ) aElementNames = _rxContainer->getElementNames(); return createUniqueName( aElementNames, _rBaseName, _bStartWithNumber ); } void showError(const SQLExceptionInfo& _rInfo, const Reference< XWindow>& _xParent, const Reference< XComponentContext >& _rxContext) { if (_rInfo.isValid()) { try { Reference< XExecutableDialog > xErrorDialog = ErrorMessageDialog::create( _rxContext, "", _xParent, _rInfo.get() ); xErrorDialog->execute(); } catch(const Exception&) { OSL_FAIL("showError: could not display the error message!"); } } } bool implUpdateObject(const Reference< XRowUpdate >& _rxUpdatedObject, const sal_Int32 _nColumnIndex, const Any& _rValue) { bool bSuccessfullyReRouted = true; switch (_rValue.getValueTypeClass()) { case TypeClass_ANY: { bSuccessfullyReRouted = implUpdateObject(_rxUpdatedObject, _nColumnIndex, _rValue); } break; case TypeClass_VOID: _rxUpdatedObject->updateNull(_nColumnIndex); break; case TypeClass_STRING: _rxUpdatedObject->updateString(_nColumnIndex, *o3tl::forceAccess<OUString>(_rValue)); break; case TypeClass_BOOLEAN: _rxUpdatedObject->updateBoolean(_nColumnIndex, *o3tl::forceAccess<bool>(_rValue)); break; case TypeClass_BYTE: _rxUpdatedObject->updateByte(_nColumnIndex, *o3tl::forceAccess<sal_Int8>(_rValue)); break; case TypeClass_UNSIGNED_SHORT: case TypeClass_SHORT: _rxUpdatedObject->updateShort(_nColumnIndex, *o3tl::forceAccess<sal_Int16>(_rValue)); break; case TypeClass_CHAR: _rxUpdatedObject->updateString(_nColumnIndex,OUString(*o3tl::forceAccess<sal_Unicode>(_rValue))); break; case TypeClass_UNSIGNED_LONG: case TypeClass_LONG: _rxUpdatedObject->updateInt(_nColumnIndex, *o3tl::forceAccess<sal_Int32>(_rValue)); break; case TypeClass_HYPER: { sal_Int64 nValue = 0; OSL_VERIFY( _rValue >>= nValue ); _rxUpdatedObject->updateLong( _nColumnIndex, nValue ); } break; case TypeClass_FLOAT: _rxUpdatedObject->updateFloat(_nColumnIndex, *o3tl::forceAccess<float>(_rValue)); break; case TypeClass_DOUBLE: _rxUpdatedObject->updateDouble(_nColumnIndex, *o3tl::forceAccess<double>(_rValue)); break; case TypeClass_SEQUENCE: if (auto s = o3tl::tryAccess<Sequence< sal_Int8 >>(_rValue)) _rxUpdatedObject->updateBytes(_nColumnIndex, *s); else bSuccessfullyReRouted = false; break; case TypeClass_STRUCT: if (auto s1 = o3tl::tryAccess<DateTime>(_rValue)) _rxUpdatedObject->updateTimestamp(_nColumnIndex, *s1); else if (auto s2 = o3tl::tryAccess<Date>(_rValue)) _rxUpdatedObject->updateDate(_nColumnIndex, *s2); else if (auto s3 = o3tl::tryAccess<Time>(_rValue)) _rxUpdatedObject->updateTime(_nColumnIndex, *s3); else bSuccessfullyReRouted = false; break; case TypeClass_INTERFACE: if (auto xStream = o3tl::tryAccess<Reference<XInputStream>>(_rValue)) { _rxUpdatedObject->updateBinaryStream(_nColumnIndex, *xStream, (*xStream)->available()); break; } [[fallthrough]]; default: bSuccessfullyReRouted = false; } return bSuccessfullyReRouted; } bool implSetObject( const Reference< XParameters >& _rxParameters, const sal_Int32 _nColumnIndex, const Any& _rValue) { bool bSuccessfullyReRouted = true; switch (_rValue.getValueTypeClass()) { case TypeClass_UNSIGNED_HYPER: { sal_uInt64 nValue = 0; OSL_VERIFY( _rValue >>= nValue ); _rxParameters->setString(_nColumnIndex, OUString::number(nValue)); } break; case TypeClass_UNSIGNED_LONG: case TypeClass_HYPER: { sal_Int64 nValue = 0; OSL_VERIFY( _rValue >>= nValue ); _rxParameters->setLong( _nColumnIndex, nValue ); } break; case TypeClass_ANY: { bSuccessfullyReRouted = implSetObject(_rxParameters, _nColumnIndex, _rValue); } break; case TypeClass_VOID: _rxParameters->setNull(_nColumnIndex,DataType::VARCHAR); break; case TypeClass_STRING: _rxParameters->setString(_nColumnIndex, *o3tl::forceAccess<OUString>(_rValue)); break; case TypeClass_BOOLEAN: _rxParameters->setBoolean(_nColumnIndex, *o3tl::forceAccess<bool>(_rValue)); break; case TypeClass_BYTE: _rxParameters->setByte(_nColumnIndex, *o3tl::forceAccess<sal_Int8>(_rValue)); break; case TypeClass_SHORT: _rxParameters->setShort(_nColumnIndex, *o3tl::forceAccess<sal_Int16>(_rValue)); break; case TypeClass_CHAR: _rxParameters->setString(_nColumnIndex, OUString(*o3tl::forceAccess<sal_Unicode>(_rValue))); break; case TypeClass_UNSIGNED_SHORT: case TypeClass_LONG: { sal_Int32 nValue = 0; OSL_VERIFY( _rValue >>= nValue ); _rxParameters->setInt(_nColumnIndex, nValue); break; } case TypeClass_FLOAT: _rxParameters->setFloat(_nColumnIndex, *o3tl::forceAccess<float>(_rValue)); break; case TypeClass_DOUBLE: _rxParameters->setDouble(_nColumnIndex, *o3tl::forceAccess<double>(_rValue)); break; case TypeClass_SEQUENCE: if (auto s = o3tl::tryAccess<Sequence< sal_Int8 >>(_rValue)) { _rxParameters->setBytes(_nColumnIndex, *s); } else bSuccessfullyReRouted = false; break; case TypeClass_STRUCT: if (auto s1 = o3tl::tryAccess<DateTime>(_rValue)) _rxParameters->setTimestamp(_nColumnIndex, *s1); else if (auto s2 = o3tl::tryAccess<Date>(_rValue)) _rxParameters->setDate(_nColumnIndex, *s2); else if (auto s3 = o3tl::tryAccess<Time>(_rValue)) _rxParameters->setTime(_nColumnIndex, *s3); else bSuccessfullyReRouted = false; break; case TypeClass_INTERFACE: if (_rValue.getValueType() == cppu::UnoType<XInputStream>::get()) { Reference< XInputStream > xStream; _rValue >>= xStream; _rxParameters->setBinaryStream(_nColumnIndex, xStream, xStream->available()); break; } [[fallthrough]]; default: bSuccessfullyReRouted = false; } return bSuccessfullyReRouted; } namespace { class OParameterWrapper : public ::cppu::WeakImplHelper< XIndexAccess > { std::vector<bool, std::allocator<bool> > m_aSet; Reference<XIndexAccess> m_xSource; public: OParameterWrapper(std::vector<bool, std::allocator<bool> >&& _aSet,const Reference<XIndexAccess>& _xSource) : m_aSet(std::move(_aSet)), m_xSource(_xSource) {} private: // css::container::XElementAccess virtual Type SAL_CALL getElementType() override { return m_xSource->getElementType(); } virtual sal_Bool SAL_CALL hasElements( ) override { if ( m_aSet.empty() ) return m_xSource->hasElements(); return std::count(m_aSet.begin(),m_aSet.end(),false) != 0; } // css::container::XIndexAccess virtual sal_Int32 SAL_CALL getCount( ) override { if ( m_aSet.empty() ) return m_xSource->getCount(); return std::count(m_aSet.begin(),m_aSet.end(),false); } virtual Any SAL_CALL getByIndex( sal_Int32 Index ) override { if ( m_aSet.empty() ) return m_xSource->getByIndex(Index); if ( Index < 0 || m_aSet.size() < o3tl::make_unsigned(Index) ) throw IndexOutOfBoundsException(); std::vector<bool, std::allocator<bool> >::const_iterator aIter = m_aSet.begin(); std::vector<bool, std::allocator<bool> >::const_iterator aEnd = m_aSet.end(); sal_Int32 i = 0; for(; aIter != aEnd && i <= Index; ++aIter) { if ( !*aIter ) { ++i; } } auto nParamPos = static_cast<sal_Int32>(std::distance(m_aSet.cbegin(), aIter)) - 1; return m_xSource->getByIndex(nParamPos); } }; } void askForParameters(const Reference< XSingleSelectQueryComposer >& _xComposer, const Reference<XParameters>& _xParameters, const Reference< XConnection>& _xConnection, const Reference< XInteractionHandler >& _rxHandler, const std::vector<bool, std::allocator<bool> >& _aParametersSet) { OSL_ENSURE(_xComposer.is(),"dbtools::askForParameters XSQLQueryComposer is null!"); OSL_ENSURE(_xParameters.is(),"dbtools::askForParameters XParameters is null!"); OSL_ENSURE(_xConnection.is(),"dbtools::askForParameters XConnection is null!"); OSL_ENSURE(_rxHandler.is(),"dbtools::askForParameters XInteractionHandler is null!"); // we have to set this here again because getCurrentSettingsComposer can force a setpropertyvalue Reference<XParametersSupplier> xParameters(_xComposer, UNO_QUERY); Reference<XIndexAccess> xParamsAsIndicies = xParameters.is() ? xParameters->getParameters() : Reference<XIndexAccess>(); sal_Int32 nParamCount = xParamsAsIndicies.is() ? xParamsAsIndicies->getCount() : 0; std::vector<bool, std::allocator<bool> > aNewParameterSet( _aParametersSet ); if ( !(nParamCount && std::count(aNewParameterSet.begin(),aNewParameterSet.end(),true) != nParamCount) ) return; static const OUString PROPERTY_NAME(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)); aNewParameterSet.resize(nParamCount ,false); typedef std::map< OUString, std::vector<sal_Int32> > TParameterPositions; TParameterPositions aParameterNames; for(sal_Int32 i = 0; i < nParamCount; ++i) { Reference<XPropertySet> xParam(xParamsAsIndicies->getByIndex(i),UNO_QUERY); OUString sName; xParam->getPropertyValue(PROPERTY_NAME) >>= sName; TParameterPositions::const_iterator aFind = aParameterNames.find(sName); if ( aFind != aParameterNames.end() ) aNewParameterSet[i] = true; aParameterNames[sName].push_back(i+1); } // build an interaction request // two continuations (Ok and Cancel) rtl::Reference<OInteractionAbort> pAbort = new OInteractionAbort; rtl::Reference<OParameterContinuation> pParams = new OParameterContinuation; // the request ParametersRequest aRequest; Reference<XIndexAccess> xWrappedParameters = new OParameterWrapper(std::move(aNewParameterSet),xParamsAsIndicies); aRequest.Parameters = xWrappedParameters; aRequest.Connection = _xConnection; rtl::Reference<OInteractionRequest> pRequest = new OInteractionRequest(Any(aRequest)); // some knittings pRequest->addContinuation(pAbort); pRequest->addContinuation(pParams); // execute the request _rxHandler->handle(pRequest); if (!pParams->wasSelected()) { // canceled by the user (i.e. (s)he canceled the dialog) RowSetVetoException e; e.ErrorCode = ParameterInteractionCancelled; throw e; } // now transfer the values from the continuation object to the parameter columns Sequence< PropertyValue > aFinalValues = pParams->getValues(); const PropertyValue* pFinalValues = aFinalValues.getConstArray(); for (sal_Int32 i=0; i<aFinalValues.getLength(); ++i, ++pFinalValues) { Reference< XPropertySet > xParamColumn(xWrappedParameters->getByIndex(i),UNO_QUERY); if (xParamColumn.is()) { OUString sName; xParamColumn->getPropertyValue(PROPERTY_NAME) >>= sName; OSL_ENSURE(sName == pFinalValues->Name, "::dbaui::askForParameters: inconsistent parameter names!"); // determine the field type and ... sal_Int32 nParamType = 0; xParamColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)) >>= nParamType; // ... the scale of the parameter column sal_Int32 nScale = 0; if (hasProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE), xParamColumn)) xParamColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE)) >>= nScale; // (the index of the parameters is one-based) TParameterPositions::const_iterator aFind = aParameterNames.find(pFinalValues->Name); for(const auto& rItem : aFind->second) { if ( _aParametersSet.empty() || !_aParametersSet[rItem-1] ) { _xParameters->setObjectWithInfo(rItem, pFinalValues->Value, nParamType, nScale); } } } } } void setObjectWithInfo(const Reference<XParameters>& _xParams, sal_Int32 parameterIndex, const Any& x, sal_Int32 sqlType, sal_Int32 scale) { ORowSetValue aVal; aVal.fill(x); setObjectWithInfo(_xParams,parameterIndex,aVal,sqlType,scale); } void setObjectWithInfo(const Reference<XParameters>& _xParams, sal_Int32 parameterIndex, const ::connectivity::ORowSetValue& _rValue, sal_Int32 sqlType, sal_Int32 scale) { if ( _rValue.isNull() ) _xParams->setNull(parameterIndex,sqlType); else { switch(sqlType) { case DataType::DECIMAL: case DataType::NUMERIC: _xParams->setObjectWithInfo(parameterIndex,_rValue.makeAny(),sqlType,scale); break; case DataType::CHAR: case DataType::VARCHAR: case DataType::LONGVARCHAR: _xParams->setString(parameterIndex,_rValue.getString()); break; case DataType::CLOB: { Any x(_rValue.makeAny()); OUString sValue; if ( x >>= sValue ) _xParams->setString(parameterIndex,sValue); else { Reference< XClob > xClob; if(x >>= xClob) _xParams->setClob(parameterIndex,xClob); else { Reference< css::io::XInputStream > xStream; if(x >>= xStream) _xParams->setCharacterStream(parameterIndex,xStream,xStream->available()); } } } break; case DataType::BIGINT: if ( _rValue.isSigned() ) _xParams->setLong(parameterIndex,_rValue.getLong()); else _xParams->setString(parameterIndex,_rValue.getString()); break; case DataType::FLOAT: _xParams->setFloat(parameterIndex,_rValue.getFloat()); break; case DataType::REAL: case DataType::DOUBLE: _xParams->setDouble(parameterIndex,_rValue.getDouble()); break; case DataType::DATE: _xParams->setDate(parameterIndex,_rValue.getDate()); break; case DataType::TIME: _xParams->setTime(parameterIndex,_rValue.getTime()); break; case DataType::TIMESTAMP: _xParams->setTimestamp(parameterIndex,_rValue.getDateTime()); break; case DataType::BINARY: case DataType::VARBINARY: case DataType::LONGVARBINARY: case DataType::BLOB: { Any x(_rValue.makeAny()); Sequence< sal_Int8> aBytes; if(x >>= aBytes) _xParams->setBytes(parameterIndex,aBytes); else { Reference< XBlob > xBlob; if(x >>= xBlob) _xParams->setBlob(parameterIndex,xBlob); else { Reference< XClob > xClob; if(x >>= xClob) _xParams->setClob(parameterIndex,xClob); else { Reference< css::io::XInputStream > xBinStream; if(x >>= xBinStream) _xParams->setBinaryStream(parameterIndex,xBinStream,xBinStream->available()); } } } } break; case DataType::BIT: case DataType::BOOLEAN: _xParams->setBoolean(parameterIndex,_rValue.getBool()); break; case DataType::TINYINT: if ( _rValue.isSigned() ) _xParams->setByte(parameterIndex,_rValue.getInt8()); else _xParams->setShort(parameterIndex,_rValue.getInt16()); break; case DataType::SMALLINT: if ( _rValue.isSigned() ) _xParams->setShort(parameterIndex,_rValue.getInt16()); else _xParams->setInt(parameterIndex,_rValue.getInt32()); break; case DataType::INTEGER: if ( _rValue.isSigned() ) _xParams->setInt(parameterIndex,_rValue.getULong()); else _xParams->setLong(parameterIndex,_rValue.getLong()); break; default: { ::connectivity::SharedResources aResources; const OUString sError( aResources.getResourceStringWithSubstitution( STR_UNKNOWN_PARA_TYPE, "$position$", OUString::number(parameterIndex) ) ); ::dbtools::throwGenericSQLException(sError,nullptr); } } } } void getBooleanComparisonPredicate( std::u16string_view _rExpression, const bool _bValue, const sal_Int32 _nBooleanComparisonMode, OUStringBuffer& _out_rSQLPredicate ) { switch ( _nBooleanComparisonMode ) { case BooleanComparisonMode::IS_LITERAL: _out_rSQLPredicate.append( _rExpression ); if ( _bValue ) _out_rSQLPredicate.append( " IS TRUE" ); else _out_rSQLPredicate.append( " IS FALSE" ); break; case BooleanComparisonMode::EQUAL_LITERAL: _out_rSQLPredicate.append( _rExpression ); _out_rSQLPredicate.appendAscii( _bValue ? " = TRUE" : " = FALSE" ); break; case BooleanComparisonMode::ACCESS_COMPAT: if ( _bValue ) { _out_rSQLPredicate.append( " NOT ( ( " ); _out_rSQLPredicate.append( _rExpression ); _out_rSQLPredicate.append( " = 0 ) OR ( " ); _out_rSQLPredicate.append( _rExpression ); _out_rSQLPredicate.append( " IS NULL ) )" ); } else { _out_rSQLPredicate.append( _rExpression ); _out_rSQLPredicate.append( " = 0" ); } break; case BooleanComparisonMode::EQUAL_INTEGER: // fall through default: _out_rSQLPredicate.append( _rExpression ); _out_rSQLPredicate.appendAscii( _bValue ? " = 1" : " = 0" ); break; } } } // namespace dbtools namespace connectivity { void checkDisposed(bool _bThrow) { if (_bThrow) throw DisposedException(); } OSQLColumns::const_iterator find(const OSQLColumns::const_iterator& first, const OSQLColumns::const_iterator& last, std::u16string_view _rVal, const ::comphelper::UStringMixEqual& _rCase) { OUString sName = OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME); return find(first,last,sName,_rVal,_rCase); } OSQLColumns::const_iterator findRealName(const OSQLColumns::const_iterator& first, const OSQLColumns::const_iterator& last, std::u16string_view _rVal, const ::comphelper::UStringMixEqual& _rCase) { OUString sRealName = OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_REALNAME); return find(first,last,sRealName,_rVal,_rCase); } OSQLColumns::const_iterator find(OSQLColumns::const_iterator first, const OSQLColumns::const_iterator& last, const OUString& _rProp, std::u16string_view _rVal, const ::comphelper::UStringMixEqual& _rCase) { while (first != last && !_rCase(getString((*first)->getPropertyValue(_rProp)),_rVal)) ++first; return first; } namespace dbase { bool dbfDecodeCharset(rtl_TextEncoding &_out_encoding, sal_uInt8 nType, sal_uInt8 nCodepage) { switch (nType) { // dBaseIII header doesn't contain language driver ID // See http://dbase.free.fr/tlcharge/structure%20tables.pdf case dBaseIII: case dBaseIIIMemo: break; case dBaseIV: case dBaseV: case VisualFoxPro: case VisualFoxProAuto: case dBaseFS: case dBaseFSMemo: case dBaseIVMemoSQL: case FoxProMemo: { if (nCodepage != 0x00) { auto eEncoding(RTL_TEXTENCODING_DONTKNOW); switch(nCodepage) { case 0x01: eEncoding = RTL_TEXTENCODING_IBM_437; break; // DOS USA code page 437 case 0x02: eEncoding = RTL_TEXTENCODING_IBM_850; break; // DOS Multilingual code page 850 case 0x03: eEncoding = RTL_TEXTENCODING_MS_1252; break; // Windows ANSI code page 1252 case 0x04: eEncoding = RTL_TEXTENCODING_APPLE_ROMAN; break; // Standard Macintosh case 0x64: eEncoding = RTL_TEXTENCODING_IBM_852; break; // EE MS-DOS code page 852 case 0x65: eEncoding = RTL_TEXTENCODING_IBM_866; break; // Russian MS-DOS code page 866 case 0x66: eEncoding = RTL_TEXTENCODING_IBM_865; break; // Nordic MS-DOS code page 865 case 0x67: eEncoding = RTL_TEXTENCODING_IBM_861; break; // Icelandic MS-DOS case 0x68: eEncoding = RTL_TEXTENCODING_KAMENICKY; break; // Kamenicky (Czech) MS-DOS case 0x69: eEncoding = RTL_TEXTENCODING_MAZOVIA; break; // Mazovia (Polish) MS-DOS case 0x6A: eEncoding = RTL_TEXTENCODING_IBM_737; break; // Greek MS-DOS (437G) case 0x6B: eEncoding = RTL_TEXTENCODING_IBM_857; break; // Turkish MS-DOS case 0x6C: eEncoding = RTL_TEXTENCODING_IBM_863; break; // MS-DOS, Canada case 0x78: eEncoding = RTL_TEXTENCODING_MS_950; break; // Windows, Traditional Chinese case 0x79: eEncoding = RTL_TEXTENCODING_MS_949; break; // Windows, Korean (Hangul) case 0x7A: eEncoding = RTL_TEXTENCODING_MS_936; break; // Windows, Simplified Chinese case 0x7B: eEncoding = RTL_TEXTENCODING_MS_932; break; // Windows, Japanese (Shift-jis) case 0x7C: eEncoding = RTL_TEXTENCODING_MS_874; break; // Windows, Thai case 0x7D: eEncoding = RTL_TEXTENCODING_MS_1255; break; // Windows, Hebrew case 0x7E: eEncoding = RTL_TEXTENCODING_MS_1256; break; // Windows, Arabic case 0x96: eEncoding = RTL_TEXTENCODING_APPLE_CYRILLIC; break; // Russian Macintosh case 0x97: eEncoding = RTL_TEXTENCODING_APPLE_CENTEURO; break; // Eastern European Macintosh case 0x98: eEncoding = RTL_TEXTENCODING_APPLE_GREEK; break; // Greek Macintosh case 0xC8: eEncoding = RTL_TEXTENCODING_MS_1250; break; // Windows EE code page 1250 case 0xC9: eEncoding = RTL_TEXTENCODING_MS_1251; break; // Russian Windows case 0xCA: eEncoding = RTL_TEXTENCODING_MS_1254; break; // Turkish Windows case 0xCB: eEncoding = RTL_TEXTENCODING_MS_1253; break; // Greek Windows case 0xCC: eEncoding = RTL_TEXTENCODING_MS_1257; break; // Windows, Baltic } if(eEncoding != RTL_TEXTENCODING_DONTKNOW) { _out_encoding = eEncoding; return true; } } } } return false; } bool dbfReadCharset(rtl_TextEncoding &nCharSet, SvStream* dbf_Stream) { sal_uInt8 nType=0; dbf_Stream->ReadUChar( nType ); dbf_Stream->Seek(STREAM_SEEK_TO_BEGIN + 29); if (dbf_Stream->eof()) { return false; } else { sal_uInt8 nEncoding=0; dbf_Stream->ReadUChar( nEncoding ); return dbfDecodeCharset(nCharSet, nType, nEncoding); } } } } //namespace connectivity /* vim:set shiftwidth=4 softtabstop=4 expandtab: */