Bump for 3.6-28
[LibreOffice.git] / connectivity / source / commontools / dbtools.cxx
blobb4bb0521f1824d1f1cd68e7ec389b15d54fbf18d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include "connectivity/CommonTools.hxx"
31 #include "diagnose_ex.h"
32 #include "TConnection.hxx"
33 #include "connectivity/ParameterCont.hxx"
35 /** === begin UNO includes === **/
36 #include <com/sun/star/awt/XWindow.hpp>
37 #include <com/sun/star/beans/PropertyAttribute.hpp>
38 #include <com/sun/star/container/XChild.hpp>
39 #include <com/sun/star/form/FormComponentType.hpp>
40 #include <com/sun/star/io/XInputStream.hpp>
41 #include <com/sun/star/lang/DisposedException.hpp>
42 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
43 #include <com/sun/star/sdb/BooleanComparisonMode.hpp>
44 #include <com/sun/star/sdb/CommandType.hpp>
45 #include <com/sun/star/sdb/ParametersRequest.hpp>
46 #include <com/sun/star/sdb/RowSetVetoException.hpp>
47 #include <com/sun/star/sdb/SQLContext.hpp>
48 #include <com/sun/star/sdb/XCompletedConnection.hpp>
49 #include <com/sun/star/sdb/XInteractionSupplyParameters.hpp>
50 #include <com/sun/star/sdb/XOfficeDatabaseDocument.hpp>
51 #include <com/sun/star/sdb/XParametersSupplier.hpp>
52 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
53 #include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
54 #include <com/sun/star/sdbc/DataType.hpp>
55 #include <com/sun/star/sdbc/XConnection.hpp>
56 #include <com/sun/star/sdbc/XDataSource.hpp>
57 #include <com/sun/star/sdbc/XDriverManager.hpp>
58 #include <com/sun/star/sdbc/XParameters.hpp>
59 #include <com/sun/star/sdbc/XRow.hpp>
60 #include <com/sun/star/sdbc/XRowSet.hpp>
61 #include <com/sun/star/sdbc/XRowUpdate.hpp>
62 #include <com/sun/star/sdbcx/KeyType.hpp>
63 #include <com/sun/star/sdbcx/Privilege.hpp>
64 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
65 #include <com/sun/star/sdbcx/XKeysSupplier.hpp>
66 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
67 #include <com/sun/star/task/XInteractionHandler.hpp>
68 #include <com/sun/star/task/XInteractionRequest.hpp>
69 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
70 #include <com/sun/star/uno/XNamingService.hpp>
71 #include <com/sun/star/util/NumberFormat.hpp>
72 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
73 #include <com/sun/star/util/XNumberFormatTypes.hpp>
74 /** === end UNO includes === **/
76 #include <comphelper/extract.hxx>
77 #include <comphelper/interaction.hxx>
78 #include <comphelper/property.hxx>
79 #include <connectivity/conncleanup.hxx>
80 #include <connectivity/dbconversion.hxx>
81 #include <connectivity/dbexception.hxx>
82 #include <connectivity/dbtools.hxx>
83 #include <connectivity/statementcomposer.hxx>
84 #include <osl/diagnose.h>
85 #include <rtl/ustrbuf.hxx>
86 #include <tools/diagnose_ex.h>
88 #include "resource/common_res.hrc"
89 #include "resource/sharedresources.hxx"
90 #include "connectivity/OSubComponent.hxx"
92 #include <algorithm>
94 using namespace ::comphelper;
95 using namespace ::com::sun::star::uno;
96 using namespace ::com::sun::star::io;
97 using namespace ::com::sun::star::awt;
98 using namespace ::com::sun::star::ui::dialogs;
99 using namespace ::com::sun::star::util;
100 using namespace ::com::sun::star::lang;
101 using namespace ::com::sun::star::beans;
102 using namespace ::com::sun::star::container;
103 using namespace ::com::sun::star::sdb;
104 using namespace ::com::sun::star::sdbc;
105 using namespace ::com::sun::star::sdbcx;
106 using namespace ::com::sun::star::form;
107 using namespace connectivity;
109 //.........................................................................
110 namespace dbtools
112 //.........................................................................
114 using namespace ::com::sun::star::uno;
115 using namespace ::com::sun::star::beans;
116 using namespace ::com::sun::star::util;
117 using namespace ::com::sun::star::task;
118 using namespace ::com::sun::star::uno;
119 using namespace ::com::sun::star::lang;
120 using namespace ::com::sun::star::sdbc;
121 using namespace ::com::sun::star::task;
123 //==============================================================================
124 //==============================================================================
125 namespace
127 typedef sal_Bool (SAL_CALL XDatabaseMetaData::*FMetaDataSupport)();
129 //==============================================================================
130 //==============================================================================
131 sal_Int32 getDefaultNumberFormat(const Reference< XPropertySet >& _xColumn,
132 const Reference< XNumberFormatTypes >& _xTypes,
133 const Locale& _rLocale)
135 OSL_ENSURE(_xTypes.is() && _xColumn.is(), "dbtools::getDefaultNumberFormat: invalid arg !");
136 if (!_xTypes.is() || !_xColumn.is())
137 return NumberFormat::UNDEFINED;
139 sal_Int32 nDataType = 0;
140 sal_Int32 nScale = 0;
143 // determine the datatype of the column
144 _xColumn->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Type"))) >>= nDataType;
146 if (DataType::NUMERIC == nDataType || DataType::DECIMAL == nDataType)
147 _xColumn->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Scale"))) >>= nScale;
149 catch (Exception&)
151 return NumberFormat::UNDEFINED;
153 return getDefaultNumberFormat(nDataType,
154 nScale,
155 ::cppu::any2bool(_xColumn->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("IsCurrency")))),
156 _xTypes,
157 _rLocale);
160 //------------------------------------------------------------------
161 sal_Int32 getDefaultNumberFormat(sal_Int32 _nDataType,
162 sal_Int32 _nScale,
163 sal_Bool _bIsCurrency,
164 const Reference< XNumberFormatTypes >& _xTypes,
165 const Locale& _rLocale)
167 OSL_ENSURE(_xTypes.is() , "dbtools::getDefaultNumberFormat: invalid arg !");
168 if (!_xTypes.is())
169 return NumberFormat::UNDEFINED;
171 sal_Int32 nFormat = 0;
172 sal_Int32 nNumberType = _bIsCurrency ? NumberFormat::CURRENCY : NumberFormat::NUMBER;
173 switch (_nDataType)
175 case DataType::BIT:
176 case DataType::BOOLEAN:
177 nFormat = _xTypes->getStandardFormat(NumberFormat::LOGICAL, _rLocale);
178 break;
179 case DataType::TINYINT:
180 case DataType::SMALLINT:
181 case DataType::INTEGER:
182 case DataType::BIGINT:
183 case DataType::FLOAT:
184 case DataType::REAL:
185 case DataType::DOUBLE:
186 case DataType::NUMERIC:
187 case DataType::DECIMAL:
191 nFormat = _xTypes->getStandardFormat((sal_Int16)nNumberType, _rLocale);
192 if(_nScale > 0)
194 // generate a new format if necessary
195 Reference< XNumberFormats > xFormats(_xTypes, UNO_QUERY);
196 ::rtl::OUString sNewFormat = xFormats->generateFormat( 0L, _rLocale, sal_False, sal_False, (sal_Int16)_nScale, sal_True);
198 // and add it to the formatter if necessary
199 nFormat = xFormats->queryKey(sNewFormat, _rLocale, sal_False);
200 if (nFormat == (sal_Int32)-1)
201 nFormat = xFormats->addNew(sNewFormat, _rLocale);
204 catch (Exception&)
206 nFormat = _xTypes->getStandardFormat((sal_Int16)nNumberType, _rLocale);
208 } break;
209 case DataType::CHAR:
210 case DataType::VARCHAR:
211 case DataType::LONGVARCHAR:
212 case DataType::CLOB:
213 nFormat = _xTypes->getStandardFormat(NumberFormat::TEXT, _rLocale);
214 break;
215 case DataType::DATE:
216 nFormat = _xTypes->getStandardFormat(NumberFormat::DATE, _rLocale);
217 break;
218 case DataType::TIME:
219 nFormat = _xTypes->getStandardFormat(NumberFormat::TIME, _rLocale);
220 break;
221 case DataType::TIMESTAMP:
222 nFormat = _xTypes->getStandardFormat(NumberFormat::DATETIME, _rLocale);
223 break;
224 case DataType::BINARY:
225 case DataType::VARBINARY:
226 case DataType::LONGVARBINARY:
227 case DataType::SQLNULL:
228 case DataType::OTHER:
229 case DataType::OBJECT:
230 case DataType::DISTINCT:
231 case DataType::STRUCT:
232 case DataType::ARRAY:
233 case DataType::BLOB:
234 case DataType::REF:
235 default:
236 nFormat = _xTypes->getStandardFormat(NumberFormat::UNDEFINED, _rLocale);
237 //nFormat = NumberFormat::UNDEFINED;
239 return nFormat;
242 //==============================================================================
243 //------------------------------------------------------------------------------
244 Reference< XConnection> findConnection(const Reference< XInterface >& xParent)
246 Reference< XConnection> xConnection(xParent, UNO_QUERY);
247 if (!xConnection.is())
249 Reference< XChild> xChild(xParent, UNO_QUERY);
250 if (xChild.is())
251 xConnection = findConnection(xChild->getParent());
253 return xConnection;
256 //------------------------------------------------------------------------------
257 Reference< XDataSource> getDataSource_allowException(
258 const ::rtl::OUString& _rsTitleOrPath,
259 const Reference< XMultiServiceFactory >& _rxFactory )
261 ENSURE_OR_RETURN( !_rsTitleOrPath.isEmpty(), "getDataSource_allowException: invalid arg !", NULL );
263 Reference< XNameAccess> xDatabaseContext(
264 _rxFactory->createInstance(
265 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.DatabaseContext" )) ),UNO_QUERY );
266 OSL_ENSURE( xDatabaseContext.is(), "getDataSource_allowException: could not obtain the database context!" );
268 return Reference< XDataSource >( xDatabaseContext->getByName( _rsTitleOrPath ), UNO_QUERY );
271 //------------------------------------------------------------------------------
272 Reference< XDataSource > getDataSource(
273 const ::rtl::OUString& _rsTitleOrPath,
274 const Reference< XMultiServiceFactory >& _rxFactory )
276 Reference< XDataSource > xDS;
279 xDS = getDataSource_allowException( _rsTitleOrPath, _rxFactory );
281 catch( const Exception& )
283 DBG_UNHANDLED_EXCEPTION();
286 return xDS;
289 //------------------------------------------------------------------------------
290 Reference< XConnection > getConnection_allowException(
291 const ::rtl::OUString& _rsTitleOrPath,
292 const ::rtl::OUString& _rsUser,
293 const ::rtl::OUString& _rsPwd,
294 const Reference< XMultiServiceFactory>& _rxFactory)
296 Reference< XDataSource> xDataSource( getDataSource_allowException(_rsTitleOrPath, _rxFactory) );
297 Reference<XConnection> xConnection;
298 if (xDataSource.is())
300 // do it with interaction handler
301 if(_rsUser.isEmpty() || _rsPwd.isEmpty())
303 Reference<XPropertySet> xProp(xDataSource,UNO_QUERY);
304 ::rtl::OUString sPwd, sUser;
305 sal_Bool bPwdReq = sal_False;
308 xProp->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PASSWORD)) >>= sPwd;
309 bPwdReq = ::cppu::any2bool(xProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("IsPasswordRequired"))));
310 xProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("User"))) >>= sUser;
312 catch(Exception&)
314 OSL_FAIL("dbtools::getConnection: error while retrieving data source properties!");
316 if(bPwdReq && sPwd.isEmpty())
317 { // password required, but empty -> connect using an interaction handler
318 Reference<XCompletedConnection> xConnectionCompletion(xProp, UNO_QUERY);
319 if (xConnectionCompletion.is())
320 { // instantiate the default SDB interaction handler
321 Reference< XInteractionHandler > xHandler(_rxFactory->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.task.InteractionHandler"))), UNO_QUERY);
322 OSL_ENSURE(xHandler.is(), "dbtools::getConnection service com.sun.star.task.InteractionHandler not available!");
323 if (xHandler.is())
325 xConnection = xConnectionCompletion->connectWithCompletion(xHandler);
329 else
330 xConnection = xDataSource->getConnection(sUser, sPwd);
332 if(!xConnection.is()) // try to get one if not already have one, just to make sure
333 xConnection = xDataSource->getConnection(_rsUser, _rsPwd);
335 return xConnection;
338 //------------------------------------------------------------------------------
339 Reference< XConnection> getConnection_withFeedback(const ::rtl::OUString& _rDataSourceName,
340 const ::rtl::OUString& _rUser, const ::rtl::OUString& _rPwd, const Reference< XMultiServiceFactory>& _rxFactory)
341 SAL_THROW ( (SQLException) )
343 Reference< XConnection > xReturn;
346 xReturn = getConnection_allowException(_rDataSourceName, _rUser, _rPwd, _rxFactory);
348 catch(SQLException&)
350 // allowed to pass
351 throw;
353 catch(Exception&)
355 OSL_FAIL("::dbtools::getConnection_withFeedback: unexpected (non-SQL) exception caught!");
357 return xReturn;
360 //------------------------------------------------------------------------------
361 Reference< XConnection> getConnection(
362 const ::rtl::OUString& _rsTitleOrPath,
363 const ::rtl::OUString& _rsUser,
364 const ::rtl::OUString& _rsPwd,
365 const Reference< XMultiServiceFactory>& _rxFactory)
367 Reference< XConnection > xReturn;
370 xReturn = getConnection_allowException(_rsTitleOrPath, _rsUser, _rsPwd, _rxFactory);
372 catch(Exception&)
376 // TODO: if there were not dozens of places which rely on getConnection not throwing an exception ....
377 // I would change this ...
379 return xReturn;
382 //------------------------------------------------------------------------------
383 Reference< XConnection> getConnection(const Reference< XRowSet>& _rxRowSet) throw (RuntimeException)
385 Reference< XConnection> xReturn;
386 Reference< XPropertySet> xRowSetProps(_rxRowSet, UNO_QUERY);
387 if (xRowSetProps.is())
388 xRowSetProps->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ActiveConnection"))) >>= xReturn;
389 return xReturn;
392 //------------------------------------------------------------------------------
393 // helper function which allows to implement both the connectRowset and the ensureRowSetConnection semantics
394 // if connectRowset (which is deprecated) is removed, this function and one of its parameters are
395 // not needed anymore, the whole implementation can be moved into ensureRowSetConnection then)
396 SharedConnection lcl_connectRowSet(const Reference< XRowSet>& _rxRowSet, const Reference< XMultiServiceFactory>& _rxFactory,
397 bool _bSetAsActiveConnection, bool _bAttachAutoDisposer )
398 SAL_THROW ( ( SQLException, WrappedTargetException, RuntimeException ) )
400 SharedConnection xConnection;
404 Reference< XPropertySet> xRowSetProps(_rxRowSet, UNO_QUERY);
405 if ( !xRowSetProps.is() )
406 break;
408 // 1. already connected?
409 Reference< XConnection > xExistingConn(
410 xRowSetProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ActiveConnection" ) ) ),
411 UNO_QUERY );
413 if ( xExistingConn.is()
414 // 2. embedded in a database?
415 || isEmbeddedInDatabase( _rxRowSet, xExistingConn )
416 // 3. is there a connection in the parent hierarchy?
417 || ( xExistingConn = findConnection( _rxRowSet ) ).is()
420 if ( _bSetAsActiveConnection )
422 xRowSetProps->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ActiveConnection" ) ), makeAny( xExistingConn ) );
423 // no auto disposer needed, since we did not create the connection
426 xConnection.reset( xExistingConn, SharedConnection::NoTakeOwnership );
427 break;
430 // build a connection with it's current settings (4. data source name, or 5. URL)
432 const ::rtl::OUString sUserProp( RTL_CONSTASCII_USTRINGPARAM( "User" ));
433 ::rtl::OUString sDataSourceName;
434 xRowSetProps->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DataSourceName"))) >>= sDataSourceName;
435 ::rtl::OUString sURL;
436 xRowSetProps->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("URL"))) >>= sURL;
438 Reference< XConnection > xPureConnection;
439 if (!sDataSourceName.isEmpty())
440 { // the row set's data source property is set
441 // -> try to connect, get user and pwd setting for that
442 ::rtl::OUString sUser, sPwd;
444 if (hasProperty(sUserProp, xRowSetProps))
445 xRowSetProps->getPropertyValue(sUserProp) >>= sUser;
446 if (hasProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PASSWORD), xRowSetProps))
447 xRowSetProps->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PASSWORD)) >>= sPwd;
449 xPureConnection = getConnection_allowException( sDataSourceName, sUser, sPwd, _rxFactory );
451 else if (!sURL.isEmpty())
452 { // the row set has no data source, but a connection url set
453 // -> try to connection with that url
454 Reference< XDriverManager > xDriverManager(
455 _rxFactory->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sdbc.ConnectionPool"))), UNO_QUERY);
456 if (xDriverManager.is())
458 ::rtl::OUString sUser, sPwd;
459 if (hasProperty(sUserProp, xRowSetProps))
460 xRowSetProps->getPropertyValue(sUserProp) >>= sUser;
461 if (hasProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PASSWORD), xRowSetProps))
462 xRowSetProps->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PASSWORD)) >>= sPwd;
463 if (!sUser.isEmpty())
464 { // use user and pwd together with the url
465 Sequence< PropertyValue> aInfo(2);
466 aInfo.getArray()[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("user"));
467 aInfo.getArray()[0].Value <<= sUser;
468 aInfo.getArray()[1].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("password"));
469 aInfo.getArray()[1].Value <<= sPwd;
470 xPureConnection = xDriverManager->getConnectionWithInfo( sURL, aInfo );
472 else
473 // just use the url
474 xPureConnection = xDriverManager->getConnection( sURL );
477 xConnection.reset(
478 xPureConnection,
479 _bAttachAutoDisposer ? SharedConnection::NoTakeOwnership : SharedConnection::TakeOwnership
480 /* take ownership if and only if we're *not* going to auto-dispose the connection */
483 // now if we created a connection, forward it to the row set
484 if ( xConnection.is() && _bSetAsActiveConnection )
488 if ( _bAttachAutoDisposer )
490 OAutoConnectionDisposer* pAutoDispose = new OAutoConnectionDisposer( _rxRowSet, xConnection );
491 Reference< XPropertyChangeListener > xEnsureDelete(pAutoDispose);
493 else
494 xRowSetProps->setPropertyValue(
495 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ActiveConnection" ) ),
496 makeAny( xConnection.getTyped() )
499 catch(Exception&)
501 OSL_FAIL("EXception when we set the new active connection!");
505 while ( false );
507 return xConnection;
510 //------------------------------------------------------------------------------
511 Reference< XConnection> connectRowset(const Reference< XRowSet>& _rxRowSet, const Reference< XMultiServiceFactory>& _rxFactory,
512 sal_Bool _bSetAsActiveConnection ) SAL_THROW ( ( SQLException, WrappedTargetException, RuntimeException ) )
514 SharedConnection xConnection = lcl_connectRowSet( _rxRowSet, _rxFactory, _bSetAsActiveConnection, true );
515 return xConnection.getTyped();
518 //------------------------------------------------------------------------------
519 SharedConnection ensureRowSetConnection(const Reference< XRowSet>& _rxRowSet, const Reference< XMultiServiceFactory>& _rxFactory,
520 bool _bUseAutoConnectionDisposer ) SAL_THROW ( ( SQLException, WrappedTargetException, RuntimeException ) )
522 return lcl_connectRowSet( _rxRowSet, _rxFactory, true, _bUseAutoConnectionDisposer );
525 //------------------------------------------------------------------------------
526 Reference< XNameAccess> getTableFields(const Reference< XConnection>& _rxConn,const ::rtl::OUString& _rName)
528 Reference< XComponent > xDummy;
529 return getFieldsByCommandDescriptor( _rxConn, CommandType::TABLE, _rName, xDummy );
531 //------------------------------------------------------------------------------
532 Reference< XNameAccess> getPrimaryKeyColumns_throw(const Any& i_aTable)
534 const Reference< XPropertySet > xTable(i_aTable,UNO_QUERY_THROW);
535 return getPrimaryKeyColumns_throw(xTable);
537 //------------------------------------------------------------------------------
538 Reference< XNameAccess> getPrimaryKeyColumns_throw(const Reference< XPropertySet >& i_xTable)
540 Reference<XNameAccess> xKeyColumns;
541 const Reference<XKeysSupplier> xKeySup(i_xTable,UNO_QUERY);
542 if ( xKeySup.is() )
544 const Reference<XIndexAccess> xKeys = xKeySup->getKeys();
545 if ( xKeys.is() )
547 ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap();
548 const ::rtl::OUString sPropName = rPropMap.getNameByIndex(PROPERTY_ID_TYPE);
549 Reference<XPropertySet> xProp;
550 const sal_Int32 nCount = xKeys->getCount();
551 for(sal_Int32 i = 0;i< nCount;++i)
553 xProp.set(xKeys->getByIndex(i),UNO_QUERY_THROW);
554 if ( xProp.is() )
556 sal_Int32 nKeyType = 0;
557 xProp->getPropertyValue(sPropName) >>= nKeyType;
558 if(KeyType::PRIMARY == nKeyType)
560 const Reference<XColumnsSupplier> xKeyColsSup(xProp,UNO_QUERY_THROW);
561 xKeyColumns = xKeyColsSup->getColumns();
562 break;
569 return xKeyColumns;
572 //------------------------------------------------------------------------------
573 namespace
575 enum FieldLookupState
577 HANDLE_TABLE, HANDLE_QUERY, HANDLE_SQL, RETRIEVE_OBJECT, RETRIEVE_COLUMNS, DONE, FAILED
581 //------------------------------------------------------------------------------
582 Reference< XNameAccess > getFieldsByCommandDescriptor( const Reference< XConnection >& _rxConnection,
583 const sal_Int32 _nCommandType, const ::rtl::OUString& _rCommand,
584 Reference< XComponent >& _rxKeepFieldsAlive, SQLExceptionInfo* _pErrorInfo ) SAL_THROW( ( ) )
586 OSL_PRECOND( _rxConnection.is(), "::dbtools::getFieldsByCommandDescriptor: invalid connection!" );
587 OSL_PRECOND( ( CommandType::TABLE == _nCommandType ) || ( CommandType::QUERY == _nCommandType ) || ( CommandType::COMMAND == _nCommandType ),
588 "::dbtools::getFieldsByCommandDescriptor: invalid command type!" );
589 OSL_PRECOND( !_rCommand.isEmpty(), "::dbtools::getFieldsByCommandDescriptor: invalid command (empty)!" );
591 Reference< XNameAccess > xFields;
593 // reset the error
594 if ( _pErrorInfo )
595 *_pErrorInfo = SQLExceptionInfo();
596 // reset the ownership holder
597 _rxKeepFieldsAlive.clear();
599 // go for the fields
602 // some kind of state machine to ease the sharing of code
603 FieldLookupState eState = FAILED;
604 switch ( _nCommandType )
606 case CommandType::TABLE:
607 eState = HANDLE_TABLE;
608 break;
609 case CommandType::QUERY:
610 eState = HANDLE_QUERY;
611 break;
612 case CommandType::COMMAND:
613 eState = HANDLE_SQL;
614 break;
617 // needed in various states:
618 Reference< XNameAccess > xObjectCollection;
619 Reference< XColumnsSupplier > xSupplyColumns;
621 // go!
622 while ( ( DONE != eState ) && ( FAILED != eState ) )
624 switch ( eState )
626 case HANDLE_TABLE:
628 // initial state for handling the tables
630 // get the table objects
631 Reference< XTablesSupplier > xSupplyTables( _rxConnection, UNO_QUERY );
632 if ( xSupplyTables.is() )
633 xObjectCollection = xSupplyTables->getTables();
634 // if something went wrong 'til here, then this will be handled in the next state
636 // next state: get the object
637 eState = RETRIEVE_OBJECT;
639 break;
641 case HANDLE_QUERY:
643 // initial state for handling the tables
645 // get the table objects
646 Reference< XQueriesSupplier > xSupplyQueries( _rxConnection, UNO_QUERY );
647 if ( xSupplyQueries.is() )
648 xObjectCollection = xSupplyQueries->getQueries();
649 // if something went wrong 'til here, then this will be handled in the next state
651 // next state: get the object
652 eState = RETRIEVE_OBJECT;
654 break;
656 case RETRIEVE_OBJECT:
657 // here we should have an object (aka query or table) collection, and are going
658 // to retrieve the desired object
660 // next state: default to FAILED
661 eState = FAILED;
663 OSL_ENSURE( xObjectCollection.is(), "::dbtools::getFieldsByCommandDescriptor: invalid connection (no sdb.Connection, or no Tables-/QueriesSupplier)!");
664 if ( xObjectCollection.is() )
666 if ( xObjectCollection.is() && xObjectCollection->hasByName( _rCommand ) )
668 xObjectCollection->getByName( _rCommand ) >>= xSupplyColumns;
669 // (xSupplyColumns being NULL will be handled in the next state)
671 // next: go for the columns
672 eState = RETRIEVE_COLUMNS;
675 break;
677 case RETRIEVE_COLUMNS:
678 OSL_ENSURE( xSupplyColumns.is(), "::dbtools::getFieldsByCommandDescriptor: could not retrieve the columns supplier!" );
680 // next state: default to FAILED
681 eState = FAILED;
683 if ( xSupplyColumns.is() )
685 xFields = xSupplyColumns->getColumns();
686 // that's it
687 eState = DONE;
689 break;
691 case HANDLE_SQL:
693 ::rtl::OUString sStatementToExecute( _rCommand );
695 // well, the main problem here is to handle statements which contain a parameter
696 // If we would simply execute a parametrized statement, then this will fail because
697 // we cannot supply any parameter values.
698 // Thus, we try to analyze the statement, and to append a WHERE 0=1 filter criterion
699 // This should cause every driver to not really execute the statement, but to return
700 // an empty result set with the proper structure. We then can use this result set
701 // to retrieve the columns.
705 Reference< XMultiServiceFactory > xComposerFac( _rxConnection, UNO_QUERY );
707 if ( xComposerFac.is() )
709 Reference< XSingleSelectQueryComposer > xComposer(xComposerFac->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sdb.SingleSelectQueryComposer"))),UNO_QUERY);
710 if ( xComposer.is() )
712 xComposer->setQuery( sStatementToExecute );
714 // Now set the filter to a dummy restriction which will result in an empty
715 // result set.
716 xComposer->setFilter( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "0=1" )) );
717 sStatementToExecute = xComposer->getQuery( );
721 catch( const Exception& )
723 // silent this error, this was just a try. If we're here, we did not change sStatementToExecute,
724 // so it will still be _rCommand, which then will be executed without being touched
727 // now execute
728 Reference< XPreparedStatement > xStatement = _rxConnection->prepareStatement( sStatementToExecute );
729 // transfer ownership of this temporary object to the caller
730 _rxKeepFieldsAlive = _rxKeepFieldsAlive.query( xStatement );
732 // set the "MaxRows" to 0. This is just in case our attempt to append a 0=1 filter
733 // failed - in this case, the MaxRows restriction should at least ensure that there
734 // is no data returned (which would be potentially expensive)
735 Reference< XPropertySet > xStatementProps( xStatement,UNO_QUERY );
738 if ( xStatementProps.is() )
739 xStatementProps->setPropertyValue(
740 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MaxRows" ) ),
741 makeAny( sal_Int32( 0 ) )
744 catch( const Exception& )
746 OSL_FAIL( "::dbtools::getFieldsByCommandDescriptor: could not set the MaxRows!" );
747 // oh damn. Not much of a chance to recover, we will no retrieve the complete
748 // full blown result set
751 xSupplyColumns = xSupplyColumns.query( xStatement->executeQuery() );
752 // this should have given us a result set which does not contain any data, but
753 // the structural information we need
755 // so the next state is to get the columns
756 eState = RETRIEVE_COLUMNS;
758 break;
760 default:
761 OSL_FAIL( "::dbtools::getFieldsByCommandDescriptor: oops! unhandled state here!" );
762 eState = FAILED;
766 catch( const SQLContext& e ) { if ( _pErrorInfo ) *_pErrorInfo = SQLExceptionInfo( e ); }
767 catch( const SQLWarning& e ) { if ( _pErrorInfo ) *_pErrorInfo = SQLExceptionInfo( e ); }
768 catch( const SQLException& e ) { if ( _pErrorInfo ) *_pErrorInfo = SQLExceptionInfo( e ); }
769 catch( const Exception& )
771 OSL_FAIL( "::dbtools::getFieldsByCommandDescriptor: caught an exception while retrieving the fields!" );
774 return xFields;
777 //------------------------------------------------------------------------------
778 Sequence< ::rtl::OUString > getFieldNamesByCommandDescriptor( const Reference< XConnection >& _rxConnection,
779 const sal_Int32 _nCommandType, const ::rtl::OUString& _rCommand,
780 SQLExceptionInfo* _pErrorInfo ) SAL_THROW( ( ) )
782 // get the container for the fields
783 Reference< XComponent > xKeepFieldsAlive;
784 Reference< XNameAccess > xFieldContainer = getFieldsByCommandDescriptor( _rxConnection, _nCommandType, _rCommand, xKeepFieldsAlive, _pErrorInfo );
786 // get the names of the fields
787 Sequence< ::rtl::OUString > aNames;
788 if ( xFieldContainer.is() )
789 aNames = xFieldContainer->getElementNames();
791 // clean up any temporary objects which have been created
792 disposeComponent( xKeepFieldsAlive );
794 // outta here
795 return aNames;
798 //------------------------------------------------------------------------------
799 SQLContext prependContextInfo(const SQLException& _rException, const Reference< XInterface >& _rxContext, const ::rtl::OUString& _rContextDescription, const ::rtl::OUString& _rContextDetails)
801 return SQLContext( _rContextDescription, _rxContext, ::rtl::OUString(), 0, makeAny( _rException ), _rContextDetails );
803 //------------------------------------------------------------------------------
804 SQLException prependErrorInfo( const SQLException& _rChainedException, const Reference< XInterface >& _rxContext,
805 const ::rtl::OUString& _rAdditionalError, const StandardSQLState _eSQLState, const sal_Int32 _nErrorCode )
807 return SQLException( _rAdditionalError, _rxContext,
808 _eSQLState == SQL_ERROR_UNSPECIFIED ? ::rtl::OUString() : getStandardSQLState( _eSQLState ),
809 _nErrorCode, makeAny( _rChainedException ) );
812 //--------------------------------------------------------------------------
813 namespace
815 struct NameComponentSupport
817 const bool bCatalogs;
818 const bool bSchemas;
820 NameComponentSupport( )
821 :bCatalogs( true )
822 ,bSchemas( true )
826 NameComponentSupport( const bool _bCatalogs, const bool _bSchemas )
827 :bCatalogs( _bCatalogs )
828 ,bSchemas( _bSchemas )
833 NameComponentSupport lcl_getNameComponentSupport( const Reference< XDatabaseMetaData >& _rxMetaData, EComposeRule _eComposeRule )
835 OSL_PRECOND( _rxMetaData.is(), "lcl_getNameComponentSupport: invalid meta data!" );
837 FMetaDataSupport pCatalogCall = &XDatabaseMetaData::supportsCatalogsInDataManipulation;
838 FMetaDataSupport pSchemaCall = &XDatabaseMetaData::supportsSchemasInDataManipulation;
839 bool bIgnoreMetaData = false;
841 switch ( _eComposeRule )
843 case eInTableDefinitions:
844 pCatalogCall = &XDatabaseMetaData::supportsCatalogsInTableDefinitions;
845 pSchemaCall = &XDatabaseMetaData::supportsSchemasInTableDefinitions;
846 break;
847 case eInIndexDefinitions:
848 pCatalogCall = &XDatabaseMetaData::supportsCatalogsInIndexDefinitions;
849 pSchemaCall = &XDatabaseMetaData::supportsSchemasInIndexDefinitions;
850 break;
851 case eInProcedureCalls:
852 pCatalogCall = &XDatabaseMetaData::supportsCatalogsInProcedureCalls;
853 pSchemaCall = &XDatabaseMetaData::supportsSchemasInProcedureCalls;
854 break;
855 case eInPrivilegeDefinitions:
856 pCatalogCall = &XDatabaseMetaData::supportsCatalogsInPrivilegeDefinitions;
857 pSchemaCall = &XDatabaseMetaData::supportsSchemasInPrivilegeDefinitions;
858 break;
859 case eComplete:
860 bIgnoreMetaData = true;
861 break;
862 case eInDataManipulation:
863 // already properly set above
864 break;
866 return NameComponentSupport(
867 bIgnoreMetaData ? true : (_rxMetaData.get()->*pCatalogCall)(),
868 bIgnoreMetaData ? true : (_rxMetaData.get()->*pSchemaCall)()
873 //--------------------------------------------------------------------------
874 static ::rtl::OUString impl_doComposeTableName( const Reference< XDatabaseMetaData >& _rxMetaData,
875 const ::rtl::OUString& _rCatalog, const ::rtl::OUString& _rSchema, const ::rtl::OUString& _rName,
876 sal_Bool _bQuote, EComposeRule _eComposeRule )
878 OSL_ENSURE(_rxMetaData.is(), "impl_doComposeTableName : invalid meta data !");
879 if ( !_rxMetaData.is() )
880 return ::rtl::OUString();
881 OSL_ENSURE(!_rName.isEmpty(), "impl_doComposeTableName : at least the name should be non-empty !");
883 const ::rtl::OUString sQuoteString = _rxMetaData->getIdentifierQuoteString();
884 const NameComponentSupport aNameComps( lcl_getNameComponentSupport( _rxMetaData, _eComposeRule ) );
886 ::rtl::OUStringBuffer aComposedName;
888 ::rtl::OUString sCatalogSep;
889 sal_Bool bCatlogAtStart = sal_True;
890 if ( !_rCatalog.isEmpty() && aNameComps.bCatalogs )
892 sCatalogSep = _rxMetaData->getCatalogSeparator();
893 bCatlogAtStart = _rxMetaData->isCatalogAtStart();
895 if ( bCatlogAtStart && !sCatalogSep.isEmpty())
897 aComposedName.append( _bQuote ? quoteName( sQuoteString, _rCatalog ) : _rCatalog );
898 aComposedName.append( sCatalogSep );
902 if ( !_rSchema.isEmpty() && aNameComps.bSchemas )
904 aComposedName.append( _bQuote ? quoteName( sQuoteString, _rSchema ) : _rSchema );
905 aComposedName.appendAscii( "." );
908 aComposedName.append( _bQuote ? quoteName( sQuoteString, _rName ) : _rName );
910 if ( !_rCatalog.isEmpty()
911 && !bCatlogAtStart
912 && !sCatalogSep.isEmpty()
913 && aNameComps.bCatalogs
916 aComposedName.append( sCatalogSep );
917 aComposedName.append( _bQuote ? quoteName( sQuoteString, _rCatalog ) : _rCatalog );
920 return aComposedName.makeStringAndClear();
923 //------------------------------------------------------------------------------
924 ::rtl::OUString quoteTableName(const Reference< XDatabaseMetaData>& _rxMeta
925 , const ::rtl::OUString& _rName
926 , EComposeRule _eComposeRule)
928 ::rtl::OUString sCatalog, sSchema, sTable;
929 qualifiedNameComponents(_rxMeta,_rName,sCatalog,sSchema,sTable,_eComposeRule);
930 return impl_doComposeTableName( _rxMeta, sCatalog, sSchema, sTable, sal_True, _eComposeRule );
933 //------------------------------------------------------------------------------
934 void qualifiedNameComponents(const Reference< XDatabaseMetaData >& _rxConnMetaData, const ::rtl::OUString& _rQualifiedName, ::rtl::OUString& _rCatalog, ::rtl::OUString& _rSchema, ::rtl::OUString& _rName,EComposeRule _eComposeRule)
936 OSL_ENSURE(_rxConnMetaData.is(), "QualifiedNameComponents : invalid meta data!");
938 NameComponentSupport aNameComps( lcl_getNameComponentSupport( _rxConnMetaData, _eComposeRule ) );
940 ::rtl::OUString sSeparator = _rxConnMetaData->getCatalogSeparator();
942 ::rtl::OUString sName(_rQualifiedName);
943 // do we have catalogs ?
944 if ( aNameComps.bCatalogs )
946 if (_rxConnMetaData->isCatalogAtStart())
948 // search for the catalog name at the beginning
949 sal_Int32 nIndex = sName.indexOf(sSeparator);
950 if (-1 != nIndex)
952 _rCatalog = sName.copy(0, nIndex);
953 sName = sName.copy(nIndex + 1);
956 else
958 // Catalogue name at the end
959 sal_Int32 nIndex = sName.lastIndexOf(sSeparator);
960 if (-1 != nIndex)
962 _rCatalog = sName.copy(nIndex + 1);
963 sName = sName.copy(0, nIndex);
968 if ( aNameComps.bSchemas )
970 sal_Int32 nIndex = sName.indexOf((sal_Unicode)'.');
971 // OSL_ENSURE(-1 != nIndex, "QualifiedNameComponents : no schema separator!");
972 if ( nIndex != -1 )
973 _rSchema = sName.copy(0, nIndex);
974 sName = sName.copy(nIndex + 1);
977 _rName = sName;
980 //------------------------------------------------------------------------------
981 Reference< XNumberFormatsSupplier> getNumberFormats(
982 const Reference< XConnection>& _rxConn,
983 sal_Bool _bAlloweDefault,
984 const Reference< XMultiServiceFactory>& _rxFactory)
986 // ask the parent of the connection (should be an DatabaseAccess)
987 Reference< XNumberFormatsSupplier> xReturn;
988 Reference< XChild> xConnAsChild(_rxConn, UNO_QUERY);
989 ::rtl::OUString sPropFormatsSupplier( RTL_CONSTASCII_USTRINGPARAM( "NumberFormatsSupplier" ));
990 if (xConnAsChild.is())
992 Reference< XPropertySet> xConnParentProps(xConnAsChild->getParent(), UNO_QUERY);
993 if (xConnParentProps.is() && hasProperty(sPropFormatsSupplier, xConnParentProps))
994 xConnParentProps->getPropertyValue(sPropFormatsSupplier) >>= xReturn;
996 else if(_bAlloweDefault && _rxFactory.is())
998 xReturn = Reference< XNumberFormatsSupplier>(_rxFactory->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.NumberFormatsSupplier"))),UNO_QUERY);
1000 return xReturn;
1003 //==============================================================================
1004 //------------------------------------------------------------------------------
1005 void TransferFormComponentProperties(
1006 const Reference< XPropertySet>& xOldProps,
1007 const Reference< XPropertySet>& xNewProps,
1008 const Locale& _rLocale)
1012 OSL_ENSURE( xOldProps.is() && xNewProps.is(), "TransferFormComponentProperties: invalid source/dest!" );
1013 if ( !xOldProps.is() || !xNewProps.is() )
1014 return;
1016 // First we copy all the Props, that are available in source and target and have the same description
1017 Reference< XPropertySetInfo> xOldInfo( xOldProps->getPropertySetInfo());
1018 Reference< XPropertySetInfo> xNewInfo( xNewProps->getPropertySetInfo());
1020 Sequence< Property> aOldProperties = xOldInfo->getProperties();
1021 Sequence< Property> aNewProperties = xNewInfo->getProperties();
1022 int nNewLen = aNewProperties.getLength();
1024 Property* pOldProps = aOldProperties.getArray();
1025 Property* pNewProps = aNewProperties.getArray();
1027 ::rtl::OUString sPropDefaultControl(RTL_CONSTASCII_USTRINGPARAM("DefaultControl"));
1028 ::rtl::OUString sPropLabelControl(RTL_CONSTASCII_USTRINGPARAM("LabelControl"));
1029 ::rtl::OUString sPropFormatsSupplier(RTL_CONSTASCII_USTRINGPARAM("FormatsSupplier"));
1030 ::rtl::OUString sPropCurrencySymbol(RTL_CONSTASCII_USTRINGPARAM("CurrencySymbol"));
1031 ::rtl::OUString sPropDecimals(RTL_CONSTASCII_USTRINGPARAM("Decimals"));
1032 ::rtl::OUString sPropEffectiveMin(RTL_CONSTASCII_USTRINGPARAM("EffectiveMin"));
1033 ::rtl::OUString sPropEffectiveMax(RTL_CONSTASCII_USTRINGPARAM("EffectiveMax"));
1034 ::rtl::OUString sPropEffectiveDefault(RTL_CONSTASCII_USTRINGPARAM("EffectiveDefault"));
1035 ::rtl::OUString sPropDefaultText(RTL_CONSTASCII_USTRINGPARAM("DefaultText"));
1036 ::rtl::OUString sPropDefaultDate(RTL_CONSTASCII_USTRINGPARAM("DefaultDate"));
1037 ::rtl::OUString sPropDefaultTime(RTL_CONSTASCII_USTRINGPARAM("DefaultTime"));
1038 ::rtl::OUString sPropValueMin(RTL_CONSTASCII_USTRINGPARAM("ValueMin"));
1039 ::rtl::OUString sPropValueMax(RTL_CONSTASCII_USTRINGPARAM("ValueMax"));
1040 ::rtl::OUString sPropDecimalAccuracy(RTL_CONSTASCII_USTRINGPARAM("DecimalAccuracy"));
1041 ::rtl::OUString sPropClassId(RTL_CONSTASCII_USTRINGPARAM("ClassId"));
1042 ::rtl::OUString sFormattedServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.component.FormattedField" ) );
1044 for (sal_Int16 i=0; i<aOldProperties.getLength(); ++i)
1046 if ( (!pOldProps[i].Name.equals(sPropDefaultControl))
1047 && (!pOldProps[i].Name.equals(sPropLabelControl))
1050 // binary search
1051 Property* pResult = ::std::lower_bound(
1052 pNewProps, pNewProps + nNewLen, pOldProps[i], ::comphelper::PropertyCompareByName());
1054 if ( pResult
1055 && ( pResult != pNewProps + nNewLen && pResult->Name == pOldProps[i].Name )
1056 && ( (pResult->Attributes & PropertyAttribute::READONLY) == 0 )
1057 && ( pResult->Type.equals(pOldProps[i].Type)) )
1058 { // Attributes match and the property is not read-only
1061 xNewProps->setPropertyValue(pResult->Name, xOldProps->getPropertyValue(pResult->Name));
1063 catch(IllegalArgumentException& e)
1065 OSL_UNUSED( e );
1066 #ifdef DBG_UTIL
1067 ::rtl::OUString sMessage(RTL_CONSTASCII_USTRINGPARAM("TransferFormComponentProperties : could not transfer the value for property \""));
1068 sMessage += pResult->Name;
1069 sMessage += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\""));
1070 OSL_FAIL(::rtl::OUStringToOString(sMessage, RTL_TEXTENCODING_ASCII_US).getStr());
1071 #endif
1077 // for formatted fields (either old or new) we have some special treatments
1078 Reference< XServiceInfo > xSI( xOldProps, UNO_QUERY );
1079 sal_Bool bOldIsFormatted = xSI.is() && xSI->supportsService( sFormattedServiceName );
1080 xSI = Reference< XServiceInfo >( xNewProps, UNO_QUERY );
1081 sal_Bool bNewIsFormatted = xSI.is() && xSI->supportsService( sFormattedServiceName );
1083 if (!bOldIsFormatted && !bNewIsFormatted)
1084 return; // nothing to do
1086 if (bOldIsFormatted && bNewIsFormatted)
1087 // if both fields are formatted we do no conversions
1088 return;
1090 if (bOldIsFormatted)
1092 // get some properties from the selected format and put them in the new Set
1093 Any aFormatKey( xOldProps->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FORMATKEY)) );
1094 if (aFormatKey.hasValue())
1096 Reference< XNumberFormatsSupplier> xSupplier;
1097 xOldProps->getPropertyValue(sPropFormatsSupplier) >>= xSupplier;
1098 if (xSupplier.is())
1100 Reference< XNumberFormats> xFormats(xSupplier->getNumberFormats());
1101 Reference< XPropertySet> xFormat(xFormats->getByKey(getINT32(aFormatKey)));
1102 if (hasProperty(sPropCurrencySymbol, xFormat))
1104 Any aVal( xFormat->getPropertyValue(sPropCurrencySymbol) );
1105 if (aVal.hasValue() && hasProperty(sPropCurrencySymbol, xNewProps))
1106 // If the source value hasn't been set then don't copy it, so we don´t overwrite the default value
1107 xNewProps->setPropertyValue(sPropCurrencySymbol, aVal);
1109 if (hasProperty(sPropDecimals, xFormat) && hasProperty(sPropDecimals, xNewProps))
1110 xNewProps->setPropertyValue(sPropDecimals, xFormat->getPropertyValue(sPropDecimals));
1114 // a potential Min-Max-Conversion
1115 Any aEffectiveMin( xOldProps->getPropertyValue(sPropEffectiveMin) );
1116 if (aEffectiveMin.hasValue())
1117 { // Unlike the ValueMin the EffectiveMin can be void
1118 if (hasProperty(sPropValueMin, xNewProps))
1120 OSL_ENSURE(aEffectiveMin.getValueType().getTypeClass() == TypeClass_DOUBLE,
1121 "TransferFormComponentProperties : invalid property type !");
1122 xNewProps->setPropertyValue(sPropValueMin, aEffectiveMin);
1125 Any aEffectiveMax( xOldProps->getPropertyValue(sPropEffectiveMax) );
1126 if (aEffectiveMax.hasValue())
1127 { // analog
1128 if (hasProperty(sPropValueMax, xNewProps))
1130 OSL_ENSURE(aEffectiveMax.getValueType().getTypeClass() == TypeClass_DOUBLE,
1131 "TransferFormComponentProperties : invalid property type !");
1132 xNewProps->setPropertyValue(sPropValueMax, aEffectiveMax);
1136 // then we can still convert and copy the default values
1137 Any aEffectiveDefault( xOldProps->getPropertyValue(sPropEffectiveDefault) );
1138 if (aEffectiveDefault.hasValue())
1140 sal_Bool bIsString = aEffectiveDefault.getValueType().getTypeClass() == TypeClass_STRING;
1141 OSL_ENSURE(bIsString || aEffectiveDefault.getValueType().getTypeClass() == TypeClass_DOUBLE,
1142 "TransferFormComponentProperties : invalid property type !");
1143 // The Effective-Properties should always be void or string or double ....
1145 if (hasProperty(sPropDefaultDate, xNewProps) && !bIsString)
1146 { // (to convert a ::rtl::OUString into a date will not always succeed, because it might be bound to a text-column,
1147 // but we can work with a double)
1148 Date aDate = DBTypeConversion::toDate(getDouble(aEffectiveDefault));
1149 xNewProps->setPropertyValue(sPropDefaultDate, makeAny(aDate));
1152 if (hasProperty(sPropDefaultTime, xNewProps) && !bIsString)
1153 { // Completely analogous to time
1154 Time aTime = DBTypeConversion::toTime(getDouble(aEffectiveDefault));
1155 xNewProps->setPropertyValue(sPropDefaultTime, makeAny(aTime));
1158 if (hasProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE), xNewProps) && !bIsString)
1159 { // Here we can simply pass the double
1160 xNewProps->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE), aEffectiveDefault);
1163 if (hasProperty(sPropDefaultText, xNewProps) && bIsString)
1164 { // and here the ::rtl::OUString
1165 xNewProps->setPropertyValue(sPropDefaultText, aEffectiveDefault);
1168 // nyi: The translation between doubles and ::rtl::OUString would offer more alternatives
1172 // The other direction: the new Control shall be formatted
1173 if (bNewIsFormatted)
1175 // first the formatting
1176 // we can't set a Supplier, so the new Set must bring one in
1177 Reference< XNumberFormatsSupplier> xSupplier;
1178 xNewProps->getPropertyValue(sPropFormatsSupplier) >>= xSupplier;
1179 if (xSupplier.is())
1181 Reference< XNumberFormats> xFormats(xSupplier->getNumberFormats());
1183 // Set number of decimals
1184 sal_Int16 nDecimals = 2;
1185 if (hasProperty(sPropDecimalAccuracy, xOldProps))
1186 xOldProps->getPropertyValue(sPropDecimalAccuracy) >>= nDecimals;
1188 // base format (depending on the ClassId of the old Set)
1189 sal_Int32 nBaseKey = 0;
1190 if (hasProperty(sPropClassId, xOldProps))
1192 Reference< XNumberFormatTypes> xTypeList(xFormats, UNO_QUERY);
1193 if (xTypeList.is())
1195 sal_Int16 nClassId = 0;
1196 xOldProps->getPropertyValue(sPropClassId) >>= nClassId;
1197 switch (nClassId)
1199 case FormComponentType::DATEFIELD :
1200 nBaseKey = xTypeList->getStandardFormat(NumberFormat::DATE, _rLocale);
1201 break;
1203 case FormComponentType::TIMEFIELD :
1204 nBaseKey = xTypeList->getStandardFormat(NumberFormat::TIME, _rLocale);
1205 break;
1207 case FormComponentType::CURRENCYFIELD :
1208 nBaseKey = xTypeList->getStandardFormat(NumberFormat::CURRENCY, _rLocale);
1209 break;
1214 // With this we can generate a new format ...
1215 ::rtl::OUString sNewFormat = xFormats->generateFormat(nBaseKey, _rLocale, sal_False, sal_False, nDecimals, 0);
1216 // No thousands separator, negative numbers are not in red, no leading zeros
1218 // ... and add at FormatsSupplier (if needed)
1219 sal_Int32 nKey = xFormats->queryKey(sNewFormat, _rLocale, sal_False);
1220 if (nKey == (sal_Int32)-1)
1221 { // not added yet in my formatter ...
1222 nKey = xFormats->addNew(sNewFormat, _rLocale);
1225 xNewProps->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FORMATKEY), makeAny((sal_Int32)nKey));
1228 // min-/max-Value
1229 Any aNewMin, aNewMax;
1230 if (hasProperty(sPropValueMin, xOldProps))
1231 aNewMin = xOldProps->getPropertyValue(sPropValueMin);
1232 if (hasProperty(sPropValueMax, xOldProps))
1233 aNewMax = xOldProps->getPropertyValue(sPropValueMax);
1234 xNewProps->setPropertyValue(sPropEffectiveMin, aNewMin);
1235 xNewProps->setPropertyValue(sPropEffectiveMax, aNewMax);
1237 // Default-Value
1238 Any aNewDefault;
1239 if (hasProperty(sPropDefaultDate, xOldProps))
1241 Any aDate( xOldProps->getPropertyValue(sPropDefaultDate) );
1242 if (aDate.hasValue())
1243 aNewDefault <<= DBTypeConversion::toDouble(*(Date*)aDate.getValue());
1246 if (hasProperty(sPropDefaultTime, xOldProps))
1248 Any aTime( xOldProps->getPropertyValue(sPropDefaultTime) );
1249 if (aTime.hasValue())
1250 aNewDefault <<= DBTypeConversion::toDouble(*(Time*)aTime.getValue());
1253 // double or ::rtl::OUString will be copied directly
1254 if (hasProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE), xOldProps))
1255 aNewDefault = xOldProps->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE));
1256 if (hasProperty(sPropDefaultText, xOldProps))
1257 aNewDefault = xOldProps->getPropertyValue(sPropDefaultText);
1259 if (aNewDefault.hasValue())
1260 xNewProps->setPropertyValue(sPropEffectiveDefault, aNewDefault);
1263 catch(const Exception&)
1265 OSL_FAIL( "TransferFormComponentProperties: caught an exception!" );
1269 //------------------------------------------------------------------------------
1270 sal_Bool canInsert(const Reference< XPropertySet>& _rxCursorSet)
1272 return ((_rxCursorSet.is() && (getINT32(_rxCursorSet->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Privileges")))) & Privilege::INSERT) != 0));
1275 //------------------------------------------------------------------------------
1276 sal_Bool canUpdate(const Reference< XPropertySet>& _rxCursorSet)
1278 return ((_rxCursorSet.is() && (getINT32(_rxCursorSet->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Privileges")))) & Privilege::UPDATE) != 0));
1281 //------------------------------------------------------------------------------
1282 sal_Bool canDelete(const Reference< XPropertySet>& _rxCursorSet)
1284 return ((_rxCursorSet.is() && (getINT32(_rxCursorSet->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Privileges")))) & Privilege::DELETE) != 0));
1286 // -----------------------------------------------------------------------------
1287 Reference< XDataSource> findDataSource(const Reference< XInterface >& _xParent)
1289 Reference< XOfficeDatabaseDocument> xDatabaseDocument(_xParent, UNO_QUERY);
1290 Reference< XDataSource> xDataSource;
1291 if ( xDatabaseDocument.is() )
1292 xDataSource = xDatabaseDocument->getDataSource();
1293 if ( !xDataSource.is() )
1294 xDataSource.set(_xParent, UNO_QUERY);
1295 if (!xDataSource.is())
1297 Reference< XChild> xChild(_xParent, UNO_QUERY);
1298 if ( xChild.is() )
1299 xDataSource = findDataSource(xChild->getParent());
1301 return xDataSource;
1304 //------------------------------------------------------------------------------
1305 Reference< XSingleSelectQueryComposer > getComposedRowSetStatement( const Reference< XPropertySet >& _rxRowSet, const Reference< XMultiServiceFactory>& _rxFactory )
1306 SAL_THROW( ( SQLException ) )
1308 Reference< XSingleSelectQueryComposer > xComposer;
1311 Reference< XConnection> xConn = connectRowset( Reference< XRowSet >( _rxRowSet, UNO_QUERY ), _rxFactory, sal_True );
1312 if ( xConn.is() ) // implies _rxRowSet.is()
1314 // build the statement the row set is based on (can't use the ActiveCommand property of the set
1315 // as this reflects the status after the last execute, not the currently set properties)
1317 sal_Int32 nCommandType = CommandType::COMMAND;
1318 ::rtl::OUString sCommand;
1319 sal_Bool bEscapeProcessing = sal_False;
1321 OSL_VERIFY( _rxRowSet->getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "CommandType" )) ) >>= nCommandType );
1322 OSL_VERIFY( _rxRowSet->getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Command" )) ) >>= sCommand );
1323 OSL_VERIFY( _rxRowSet->getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "EscapeProcessing" )) ) >>= bEscapeProcessing );
1325 StatementComposer aComposer( xConn, sCommand, nCommandType, bEscapeProcessing );
1326 // append sort
1327 aComposer.setOrder( getString( _rxRowSet->getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Order" )) ) ) );
1329 // append filter
1330 sal_Bool bApplyFilter = sal_True;
1331 _rxRowSet->getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "ApplyFilter" )) ) >>= bApplyFilter;
1332 if ( bApplyFilter )
1333 aComposer.setFilter( getString( _rxRowSet->getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Filter" )) ) ) );
1335 aComposer.getQuery();
1337 xComposer = aComposer.getComposer();
1338 aComposer.setDisposeComposer( false );
1341 catch( const SQLException& )
1343 throw;
1345 catch( const Exception& )
1347 DBG_UNHANDLED_EXCEPTION();
1350 return xComposer;
1353 //------------------------------------------------------------------------------
1354 Reference< XSingleSelectQueryComposer > getCurrentSettingsComposer(
1355 const Reference< XPropertySet>& _rxRowSetProps,
1356 const Reference< XMultiServiceFactory>& _rxFactory)
1358 Reference< XSingleSelectQueryComposer > xReturn;
1361 xReturn = getComposedRowSetStatement( _rxRowSetProps, _rxFactory );
1363 catch( const SQLException& )
1365 throw;
1367 catch( const Exception& )
1369 OSL_FAIL( "::getCurrentSettingsComposer : caught an exception !" );
1372 return xReturn;
1374 //--------------------------------------------------------------------------
1375 ::rtl::OUString composeTableName( const Reference< XDatabaseMetaData >& _rxMetaData,
1376 const ::rtl::OUString& _rCatalog,
1377 const ::rtl::OUString& _rSchema,
1378 const ::rtl::OUString& _rName,
1379 sal_Bool _bQuote,
1380 EComposeRule _eComposeRule)
1382 return impl_doComposeTableName( _rxMetaData, _rCatalog, _rSchema, _rName, _bQuote, _eComposeRule );
1385 // -----------------------------------------------------------------------------
1386 ::rtl::OUString composeTableNameForSelect( const Reference< XConnection >& _rxConnection,
1387 const ::rtl::OUString& _rCatalog, const ::rtl::OUString& _rSchema, const ::rtl::OUString& _rName )
1389 sal_Bool bUseCatalogInSelect = isDataSourcePropertyEnabled( _rxConnection, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseCatalogInSelect" ) ), sal_True );
1390 sal_Bool bUseSchemaInSelect = isDataSourcePropertyEnabled( _rxConnection, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseSchemaInSelect" ) ), sal_True );
1392 return impl_doComposeTableName(
1393 _rxConnection->getMetaData(),
1394 bUseCatalogInSelect ? _rCatalog : ::rtl::OUString(),
1395 bUseSchemaInSelect ? _rSchema : ::rtl::OUString(),
1396 _rName,
1397 true,
1398 eInDataManipulation
1402 // -----------------------------------------------------------------------------
1403 namespace
1405 static void lcl_getTableNameComponents( const Reference<XPropertySet>& _xTable,
1406 ::rtl::OUString& _out_rCatalog, ::rtl::OUString& _out_rSchema, ::rtl::OUString& _out_rName )
1408 ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap();
1409 Reference< XPropertySetInfo > xInfo;
1410 if (_xTable.is())
1411 xInfo = _xTable->getPropertySetInfo();
1412 if ( xInfo.is()
1413 && xInfo->hasPropertyByName(rPropMap.getNameByIndex(PROPERTY_ID_NAME)) )
1415 if ( xInfo->hasPropertyByName(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME))
1416 && xInfo->hasPropertyByName(rPropMap.getNameByIndex(PROPERTY_ID_SCHEMANAME)) )
1418 _xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME)) >>= _out_rCatalog;
1419 _xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_SCHEMANAME)) >>= _out_rSchema;
1421 _xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME)) >>= _out_rName;
1423 else
1424 OSL_FAIL( "::dbtools::lcl_getTableNameComponents: this is no table object!" );
1428 // -----------------------------------------------------------------------------
1429 ::rtl::OUString composeTableNameForSelect( const Reference< XConnection >& _rxConnection, const Reference<XPropertySet>& _xTable )
1431 ::rtl::OUString sCatalog, sSchema, sName;
1432 lcl_getTableNameComponents( _xTable, sCatalog, sSchema, sName );
1434 return composeTableNameForSelect( _rxConnection, sCatalog, sSchema, sName );
1437 // -----------------------------------------------------------------------------
1438 ::rtl::OUString composeTableName(const Reference<XDatabaseMetaData>& _xMetaData,
1439 const Reference<XPropertySet>& _xTable,
1440 EComposeRule _eComposeRule,
1441 bool _bSuppressCatalog,
1442 bool _bSuppressSchema,
1443 bool _bQuote )
1445 ::rtl::OUString sCatalog, sSchema, sName;
1446 lcl_getTableNameComponents( _xTable, sCatalog, sSchema, sName );
1448 return impl_doComposeTableName(
1449 _xMetaData,
1450 _bSuppressCatalog ? ::rtl::OUString() : sCatalog,
1451 _bSuppressSchema ? ::rtl::OUString() : sSchema,
1452 sName,
1453 _bQuote,
1454 _eComposeRule
1457 // -----------------------------------------------------------------------------
1458 sal_Int32 getSearchColumnFlag( const Reference< XConnection>& _rxConn,sal_Int32 _nDataType)
1460 sal_Int32 nSearchFlag = 0;
1461 Reference<XResultSet> xSet = _rxConn->getMetaData()->getTypeInfo();
1462 if(xSet.is())
1464 Reference<XRow> xRow(xSet,UNO_QUERY);
1465 while(xSet->next())
1467 if(xRow->getInt(2) == _nDataType)
1469 nSearchFlag = xRow->getInt(9);
1470 break;
1474 return nSearchFlag;
1477 // -----------------------------------------------------------------------------
1478 ::rtl::OUString createUniqueName( const Sequence< ::rtl::OUString >& _rNames, const ::rtl::OUString& _rBaseName, sal_Bool _bStartWithNumber )
1480 ::std::set< ::rtl::OUString > aUsedNames;
1481 ::std::copy(
1482 _rNames.getConstArray(),
1483 _rNames.getConstArray() + _rNames.getLength(),
1484 ::std::insert_iterator< ::std::set< ::rtl::OUString > >( aUsedNames, aUsedNames.end() )
1487 ::rtl::OUString sName( _rBaseName );
1488 sal_Int32 nPos = 1;
1489 if ( _bStartWithNumber )
1490 sName += ::rtl::OUString::valueOf( nPos );
1492 while ( aUsedNames.find( sName ) != aUsedNames.end() )
1494 sName = _rBaseName;
1495 sName += ::rtl::OUString::valueOf( ++nPos );
1497 return sName;
1500 // -----------------------------------------------------------------------------
1501 ::rtl::OUString createUniqueName(const Reference<XNameAccess>& _rxContainer,const ::rtl::OUString& _rBaseName,sal_Bool _bStartWithNumber)
1503 Sequence< ::rtl::OUString > aElementNames;
1505 OSL_ENSURE( _rxContainer.is(), "createUniqueName: invalid container!" );
1506 if ( _rxContainer.is() )
1507 aElementNames = _rxContainer->getElementNames();
1509 return createUniqueName( aElementNames, _rBaseName, _bStartWithNumber );
1512 // -----------------------------------------------------------------------------
1513 void showError(const SQLExceptionInfo& _rInfo,
1514 const Reference< XWindow>& _xParent,
1515 const Reference< XMultiServiceFactory >& _xFactory)
1517 if (_rInfo.isValid())
1521 Sequence< Any > aArgs(2);
1522 aArgs[0] <<= PropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SQLException")), 0, _rInfo.get(), PropertyState_DIRECT_VALUE);
1523 aArgs[1] <<= PropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ParentWindow")), 0, makeAny(_xParent), PropertyState_DIRECT_VALUE);
1525 static ::rtl::OUString s_sDialogServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.ErrorMessageDialog" ));
1526 Reference< XExecutableDialog > xErrorDialog(
1527 _xFactory->createInstanceWithArguments(s_sDialogServiceName, aArgs), UNO_QUERY);
1528 if (xErrorDialog.is())
1529 xErrorDialog->execute();
1530 else
1532 OSL_FAIL("dbtools::showError: no XExecutableDialog found!");
1535 catch(Exception&)
1537 OSL_FAIL("showError: could not display the error message!");
1542 // -------------------------------------------------------------------------
1543 sal_Bool implUpdateObject(const Reference< XRowUpdate >& _rxUpdatedObject,
1544 const sal_Int32 _nColumnIndex, const Any& _rValue) SAL_THROW ( ( SQLException, RuntimeException ) )
1546 sal_Bool bSuccessfullyReRouted = sal_True;
1547 switch (_rValue.getValueTypeClass())
1549 case TypeClass_ANY:
1551 Any aInnerValue;
1552 _rValue >>= aInnerValue;
1553 bSuccessfullyReRouted = implUpdateObject(_rxUpdatedObject, _nColumnIndex, aInnerValue);
1555 break;
1557 case TypeClass_VOID:
1558 _rxUpdatedObject->updateNull(_nColumnIndex);
1559 break;
1561 case TypeClass_STRING:
1562 _rxUpdatedObject->updateString(_nColumnIndex, *(rtl::OUString*)_rValue.getValue());
1563 break;
1565 case TypeClass_BOOLEAN:
1566 _rxUpdatedObject->updateBoolean(_nColumnIndex, *(sal_Bool *)_rValue.getValue());
1567 break;
1569 case TypeClass_BYTE:
1570 _rxUpdatedObject->updateByte(_nColumnIndex, *(sal_Int8 *)_rValue.getValue());
1571 break;
1573 case TypeClass_UNSIGNED_SHORT:
1574 case TypeClass_SHORT:
1575 _rxUpdatedObject->updateShort(_nColumnIndex, *(sal_Int16*)_rValue.getValue());
1576 break;
1578 case TypeClass_CHAR:
1579 _rxUpdatedObject->updateString(_nColumnIndex,::rtl::OUString((sal_Unicode *)_rValue.getValue(),1));
1580 break;
1582 case TypeClass_UNSIGNED_LONG:
1583 case TypeClass_LONG:
1584 _rxUpdatedObject->updateInt(_nColumnIndex, *(sal_Int32*)_rValue.getValue());
1585 break;
1587 case TypeClass_HYPER:
1589 sal_Int64 nValue = 0;
1590 OSL_VERIFY( _rValue >>= nValue );
1591 _rxUpdatedObject->updateLong( _nColumnIndex, nValue );
1593 break;
1595 case TypeClass_FLOAT:
1596 _rxUpdatedObject->updateFloat(_nColumnIndex, *(float*)_rValue.getValue());
1597 break;
1599 case TypeClass_DOUBLE:
1600 _rxUpdatedObject->updateDouble(_nColumnIndex, *(double*)_rValue.getValue());
1601 break;
1603 case TypeClass_SEQUENCE:
1604 if (_rValue.getValueType() == ::getCppuType((const Sequence< sal_Int8 > *)0))
1605 _rxUpdatedObject->updateBytes(_nColumnIndex, *(Sequence<sal_Int8>*)_rValue.getValue());
1606 else
1607 bSuccessfullyReRouted = sal_False;
1608 break;
1609 case TypeClass_STRUCT:
1610 if (_rValue.getValueType() == ::getCppuType((const DateTime*)0))
1611 _rxUpdatedObject->updateTimestamp(_nColumnIndex, *(DateTime*)_rValue.getValue());
1612 else if (_rValue.getValueType() == ::getCppuType((const Date*)0))
1613 _rxUpdatedObject->updateDate(_nColumnIndex, *(Date*)_rValue.getValue());
1614 else if (_rValue.getValueType() == ::getCppuType((const Time*)0))
1615 _rxUpdatedObject->updateTime(_nColumnIndex, *(Time*)_rValue.getValue());
1616 else
1617 bSuccessfullyReRouted = sal_False;
1618 break;
1620 case TypeClass_INTERFACE:
1621 if (_rValue.getValueType() == ::getCppuType(static_cast<Reference< XInputStream>*>(NULL)))
1623 Reference< XInputStream > xStream;
1624 _rValue >>= xStream;
1625 _rxUpdatedObject->updateBinaryStream(_nColumnIndex, xStream, xStream->available());
1626 break;
1628 // run through
1629 default:
1630 bSuccessfullyReRouted = sal_False;
1633 return bSuccessfullyReRouted;
1635 // -------------------------------------------------------------------------
1636 sal_Bool implSetObject( const Reference< XParameters >& _rxParameters,
1637 const sal_Int32 _nColumnIndex, const Any& _rValue) SAL_THROW ( ( SQLException, RuntimeException ) )
1639 sal_Bool bSuccessfullyReRouted = sal_True;
1640 switch (_rValue.getValueTypeClass())
1642 case TypeClass_HYPER:
1644 sal_Int64 nValue = 0;
1645 OSL_VERIFY( _rValue >>= nValue );
1646 _rxParameters->setLong( _nColumnIndex, nValue );
1648 break;
1650 case TypeClass_ANY:
1652 Any aInnerValue;
1653 _rValue >>= aInnerValue;
1654 bSuccessfullyReRouted = implSetObject(_rxParameters, _nColumnIndex, aInnerValue);
1656 break;
1658 case TypeClass_VOID:
1659 _rxParameters->setNull(_nColumnIndex,DataType::VARCHAR);
1660 break;
1662 case TypeClass_STRING:
1663 _rxParameters->setString(_nColumnIndex, *(rtl::OUString*)_rValue.getValue());
1664 break;
1666 case TypeClass_BOOLEAN:
1667 _rxParameters->setBoolean(_nColumnIndex, *(sal_Bool *)_rValue.getValue());
1668 break;
1670 case TypeClass_BYTE:
1671 _rxParameters->setByte(_nColumnIndex, *(sal_Int8 *)_rValue.getValue());
1672 break;
1674 case TypeClass_UNSIGNED_SHORT:
1675 case TypeClass_SHORT:
1676 _rxParameters->setShort(_nColumnIndex, *(sal_Int16*)_rValue.getValue());
1677 break;
1679 case TypeClass_CHAR:
1680 _rxParameters->setString(_nColumnIndex, ::rtl::OUString((sal_Unicode *)_rValue.getValue(),1));
1681 break;
1683 case TypeClass_UNSIGNED_LONG:
1684 case TypeClass_LONG:
1685 _rxParameters->setInt(_nColumnIndex, *(sal_Int32*)_rValue.getValue());
1686 break;
1688 case TypeClass_FLOAT:
1689 _rxParameters->setFloat(_nColumnIndex, *(float*)_rValue.getValue());
1690 break;
1692 case TypeClass_DOUBLE:
1693 _rxParameters->setDouble(_nColumnIndex, *(double*)_rValue.getValue());
1694 break;
1696 case TypeClass_SEQUENCE:
1697 if (_rValue.getValueType() == ::getCppuType((const Sequence< sal_Int8 > *)0))
1699 _rxParameters->setBytes(_nColumnIndex, *(Sequence<sal_Int8>*)_rValue.getValue());
1701 else
1702 bSuccessfullyReRouted = sal_False;
1703 break;
1704 case TypeClass_STRUCT:
1705 if (_rValue.getValueType() == ::getCppuType((const DateTime*)0))
1706 _rxParameters->setTimestamp(_nColumnIndex, *(DateTime*)_rValue.getValue());
1707 else if (_rValue.getValueType() == ::getCppuType((const Date*)0))
1708 _rxParameters->setDate(_nColumnIndex, *(Date*)_rValue.getValue());
1709 else if (_rValue.getValueType() == ::getCppuType((const Time*)0))
1710 _rxParameters->setTime(_nColumnIndex, *(Time*)_rValue.getValue());
1711 else
1712 bSuccessfullyReRouted = sal_False;
1713 break;
1715 case TypeClass_INTERFACE:
1716 if (_rValue.getValueType() == ::getCppuType(static_cast<Reference< XInputStream>*>(NULL)))
1718 Reference< XInputStream > xStream;
1719 _rValue >>= xStream;
1720 _rxParameters->setBinaryStream(_nColumnIndex, xStream, xStream->available());
1721 break;
1723 // run through
1724 default:
1725 bSuccessfullyReRouted = sal_False;
1729 return bSuccessfullyReRouted;
1732 //..................................................................
1733 namespace
1735 class OParameterWrapper : public ::cppu::WeakImplHelper1< XIndexAccess >
1737 ::std::vector<bool, std::allocator<bool> > m_aSet;
1738 Reference<XIndexAccess> m_xSource;
1739 public:
1740 OParameterWrapper(const ::std::vector<bool, std::allocator<bool> >& _aSet,const Reference<XIndexAccess>& _xSource) : m_aSet(_aSet),m_xSource(_xSource){}
1741 private:
1742 // ::com::sun::star::container::XElementAccess
1743 virtual Type SAL_CALL getElementType() throw(RuntimeException)
1745 return m_xSource->getElementType();
1747 virtual sal_Bool SAL_CALL hasElements( ) throw(RuntimeException)
1749 if ( m_aSet.empty() )
1750 return m_xSource->hasElements();
1751 return ::std::count(m_aSet.begin(),m_aSet.end(),false) != 0;
1753 // ::com::sun::star::container::XIndexAccess
1754 virtual sal_Int32 SAL_CALL getCount( ) throw(RuntimeException)
1756 if ( m_aSet.empty() )
1757 return m_xSource->getCount();
1758 return ::std::count(m_aSet.begin(),m_aSet.end(),false);
1760 virtual Any SAL_CALL getByIndex( sal_Int32 Index ) throw(IndexOutOfBoundsException, WrappedTargetException, RuntimeException)
1762 if ( m_aSet.empty() )
1763 return m_xSource->getByIndex(Index);
1764 if ( m_aSet.size() < (size_t)Index )
1765 throw IndexOutOfBoundsException();
1767 ::std::vector<bool, std::allocator<bool> >::iterator aIter = m_aSet.begin();
1768 ::std::vector<bool, std::allocator<bool> >::iterator aEnd = m_aSet.end();
1769 sal_Int32 i = 0;
1770 sal_Int32 nParamPos = -1;
1771 for(; aIter != aEnd && i <= Index; ++aIter)
1773 ++nParamPos;
1774 if ( !*aIter )
1776 ++i;
1779 return m_xSource->getByIndex(nParamPos);
1784 // -----------------------------------------------------------------------------
1785 void askForParameters(const Reference< XSingleSelectQueryComposer >& _xComposer,
1786 const Reference<XParameters>& _xParameters,
1787 const Reference< XConnection>& _xConnection,
1788 const Reference< XInteractionHandler >& _rxHandler,
1789 const ::std::vector<bool, std::allocator<bool> >& _aParametersSet)
1791 OSL_ENSURE(_xComposer.is(),"dbtools::askForParameters XSQLQueryComposer is null!");
1792 OSL_ENSURE(_xParameters.is(),"dbtools::askForParameters XParameters is null!");
1793 OSL_ENSURE(_xConnection.is(),"dbtools::askForParameters XConnection is null!");
1794 OSL_ENSURE(_rxHandler.is(),"dbtools::askForParameters XInteractionHandler is null!");
1796 // we have to set this here again because getCurrentSettingsComposer can force a setpropertyvalue
1797 Reference<XParametersSupplier> xParameters = Reference<XParametersSupplier> (_xComposer, UNO_QUERY);
1799 Reference<XIndexAccess> xParamsAsIndicies = xParameters.is() ? xParameters->getParameters() : Reference<XIndexAccess>();
1800 Reference<XNameAccess> xParamsAsNames(xParamsAsIndicies, UNO_QUERY);
1801 sal_Int32 nParamCount = xParamsAsIndicies.is() ? xParamsAsIndicies->getCount() : 0;
1802 ::std::vector<bool, std::allocator<bool> > aNewParameterSet( _aParametersSet );
1803 if ( nParamCount && ::std::count(aNewParameterSet.begin(),aNewParameterSet.end(),true) != nParamCount )
1805 static const ::rtl::OUString PROPERTY_NAME(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME));
1806 aNewParameterSet.resize(nParamCount ,false);
1807 typedef ::std::map< ::rtl::OUString, ::std::vector<sal_Int32> > TParameterPositions;
1808 TParameterPositions aParameterNames;
1809 for(sal_Int32 i = 0; i < nParamCount; ++i)
1811 Reference<XPropertySet> xParam(xParamsAsIndicies->getByIndex(i),UNO_QUERY);
1812 ::rtl::OUString sName;
1813 xParam->getPropertyValue(PROPERTY_NAME) >>= sName;
1815 TParameterPositions::iterator aFind = aParameterNames.find(sName);
1816 if ( aFind != aParameterNames.end() )
1817 aNewParameterSet[i] = true;
1818 aParameterNames[sName].push_back(i+1);
1820 // build an interaction request
1821 // two continuations (Ok and Cancel)
1822 OInteractionAbort* pAbort = new OInteractionAbort;
1823 OParameterContinuation* pParams = new OParameterContinuation;
1824 // the request
1825 ParametersRequest aRequest;
1826 Reference<XIndexAccess> xWrappedParameters = new OParameterWrapper(aNewParameterSet,xParamsAsIndicies);
1827 aRequest.Parameters = xWrappedParameters;
1828 aRequest.Connection = _xConnection;
1829 OInteractionRequest* pRequest = new OInteractionRequest(makeAny(aRequest));
1830 Reference< XInteractionRequest > xRequest(pRequest);
1831 // some knittings
1832 pRequest->addContinuation(pAbort);
1833 pRequest->addContinuation(pParams);
1835 // execute the request
1836 _rxHandler->handle(xRequest);
1838 if (!pParams->wasSelected())
1840 // canceled by the user (i.e. (s)he canceled the dialog)
1841 RowSetVetoException e;
1842 e.ErrorCode = ParameterInteractionCancelled;
1843 throw e;
1846 // now transfer the values from the continuation object to the parameter columns
1847 Sequence< PropertyValue > aFinalValues = pParams->getValues();
1848 const PropertyValue* pFinalValues = aFinalValues.getConstArray();
1849 for (sal_Int32 i=0; i<aFinalValues.getLength(); ++i, ++pFinalValues)
1851 Reference< XPropertySet > xParamColumn(xWrappedParameters->getByIndex(i),UNO_QUERY);
1852 if (xParamColumn.is())
1854 ::rtl::OUString sName;
1855 xParamColumn->getPropertyValue(PROPERTY_NAME) >>= sName;
1856 OSL_ENSURE(sName.equals(pFinalValues->Name), "::dbaui::askForParameters: inconsistent parameter names!");
1858 // determine the field type and ...
1859 sal_Int32 nParamType = 0;
1860 xParamColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)) >>= nParamType;
1861 // ... the scale of the parameter column
1862 sal_Int32 nScale = 0;
1863 if (hasProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE), xParamColumn))
1864 xParamColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE)) >>= nScale;
1865 // (the index of the parameters is one-based)
1866 TParameterPositions::iterator aFind = aParameterNames.find(pFinalValues->Name);
1867 ::std::vector<sal_Int32>::iterator aIterPos = aFind->second.begin();
1868 ::std::vector<sal_Int32>::iterator aEndPos = aFind->second.end();
1869 for(;aIterPos != aEndPos;++aIterPos)
1871 if ( _aParametersSet.empty() || !_aParametersSet[(*aIterPos)-1] )
1873 _xParameters->setObjectWithInfo(*aIterPos, pFinalValues->Value, nParamType, nScale);
1880 // -----------------------------------------------------------------------------
1881 void setObjectWithInfo(const Reference<XParameters>& _xParams,
1882 sal_Int32 parameterIndex,
1883 const Any& x,
1884 sal_Int32 sqlType,
1885 sal_Int32 scale) throw(SQLException, RuntimeException)
1887 ORowSetValue aVal;
1888 aVal.fill(x);
1889 setObjectWithInfo(_xParams,parameterIndex,aVal,sqlType,scale);
1891 // -----------------------------------------------------------------------------
1892 void setObjectWithInfo(const Reference<XParameters>& _xParams,
1893 sal_Int32 parameterIndex,
1894 const ::connectivity::ORowSetValue& _rValue,
1895 sal_Int32 sqlType,
1896 sal_Int32 scale) throw(SQLException, RuntimeException)
1898 if ( _rValue.isNull() )
1899 _xParams->setNull(parameterIndex,sqlType);
1900 else
1902 switch(sqlType)
1904 case DataType::DECIMAL:
1905 case DataType::NUMERIC:
1906 _xParams->setObjectWithInfo(parameterIndex,_rValue.makeAny(),sqlType,scale);
1907 break;
1908 case DataType::CHAR:
1909 case DataType::VARCHAR:
1910 case DataType::LONGVARCHAR:
1911 _xParams->setString(parameterIndex,_rValue);
1912 break;
1913 case DataType::CLOB:
1915 Any x(_rValue.makeAny());
1916 ::rtl::OUString sValue;
1917 if ( x >>= sValue )
1918 _xParams->setString(parameterIndex,sValue);
1919 else
1921 Reference< XClob > xClob;
1922 if(x >>= xClob)
1923 _xParams->setClob(parameterIndex,xClob);
1924 else
1926 Reference< ::com::sun::star::io::XInputStream > xStream;
1927 if(x >>= xStream)
1928 _xParams->setCharacterStream(parameterIndex,xStream,xStream->available());
1932 break;
1933 case DataType::BIGINT:
1934 if ( _rValue.isSigned() )
1935 _xParams->setLong(parameterIndex,_rValue);
1936 else
1937 _xParams->setString(parameterIndex,_rValue);
1938 break;
1940 case DataType::FLOAT:
1941 _xParams->setFloat(parameterIndex,_rValue);
1942 break;
1943 case DataType::REAL:
1944 case DataType::DOUBLE:
1945 _xParams->setDouble(parameterIndex,_rValue);
1946 break;
1947 case DataType::DATE:
1948 _xParams->setDate(parameterIndex,_rValue);
1949 break;
1950 case DataType::TIME:
1951 _xParams->setTime(parameterIndex,_rValue);
1952 break;
1953 case DataType::TIMESTAMP:
1954 _xParams->setTimestamp(parameterIndex,_rValue);
1955 break;
1956 case DataType::BINARY:
1957 case DataType::VARBINARY:
1958 case DataType::LONGVARBINARY:
1959 case DataType::BLOB:
1961 Any x(_rValue.makeAny());
1962 Sequence< sal_Int8> aBytes;
1963 if(x >>= aBytes)
1964 _xParams->setBytes(parameterIndex,aBytes);
1965 else
1967 Reference< XBlob > xBlob;
1968 if(x >>= xBlob)
1969 _xParams->setBlob(parameterIndex,xBlob);
1970 else
1972 Reference< XClob > xClob;
1973 if(x >>= xClob)
1974 _xParams->setClob(parameterIndex,xClob);
1975 else
1977 Reference< ::com::sun::star::io::XInputStream > xBinStream;
1978 if(x >>= xBinStream)
1979 _xParams->setBinaryStream(parameterIndex,xBinStream,xBinStream->available());
1984 break;
1985 case DataType::BIT:
1986 case DataType::BOOLEAN:
1987 _xParams->setBoolean(parameterIndex,_rValue);
1988 break;
1989 case DataType::TINYINT:
1990 if ( _rValue.isSigned() )
1991 _xParams->setByte(parameterIndex,_rValue);
1992 else
1993 _xParams->setShort(parameterIndex,_rValue);
1994 break;
1995 case DataType::SMALLINT:
1996 if ( _rValue.isSigned() )
1997 _xParams->setShort(parameterIndex,_rValue);
1998 else
1999 _xParams->setInt(parameterIndex,_rValue);
2000 break;
2001 case DataType::INTEGER:
2002 if ( _rValue.isSigned() )
2003 _xParams->setInt(parameterIndex,_rValue);
2004 else
2005 _xParams->setLong(parameterIndex,_rValue);
2006 break;
2007 default:
2009 ::connectivity::SharedResources aResources;
2010 const ::rtl::OUString sError( aResources.getResourceStringWithSubstitution(
2011 STR_UNKNOWN_PARA_TYPE,
2012 "$position$", ::rtl::OUString::valueOf(parameterIndex)
2013 ) );
2014 ::dbtools::throwGenericSQLException(sError,NULL);
2020 // --------------------------------------------------------------------
2021 void getBoleanComparisonPredicate( const ::rtl::OUString& _rExpression, const sal_Bool _bValue, const sal_Int32 _nBooleanComparisonMode,
2022 ::rtl::OUStringBuffer& _out_rSQLPredicate )
2024 switch ( _nBooleanComparisonMode )
2026 case BooleanComparisonMode::IS_LITERAL:
2027 _out_rSQLPredicate.append( _rExpression );
2028 if ( _bValue )
2029 _out_rSQLPredicate.appendAscii( " IS TRUE" );
2030 else
2031 _out_rSQLPredicate.appendAscii( " IS FALSE" );
2032 break;
2034 case BooleanComparisonMode::EQUAL_LITERAL:
2035 _out_rSQLPredicate.append( _rExpression );
2036 _out_rSQLPredicate.appendAscii( _bValue ? " = TRUE" : " = FALSE" );
2037 break;
2039 case BooleanComparisonMode::ACCESS_COMPAT:
2040 if ( _bValue )
2042 _out_rSQLPredicate.appendAscii( " NOT ( ( " );
2043 _out_rSQLPredicate.append( _rExpression );
2044 _out_rSQLPredicate.appendAscii( " = 0 ) OR ( " );
2045 _out_rSQLPredicate.append( _rExpression );
2046 _out_rSQLPredicate.appendAscii( " IS NULL ) )" );
2048 else
2050 _out_rSQLPredicate.append( _rExpression );
2051 _out_rSQLPredicate.appendAscii( " = 0" );
2053 break;
2055 case BooleanComparisonMode::EQUAL_INTEGER:
2056 // fall through
2057 default:
2058 _out_rSQLPredicate.append( _rExpression );
2059 _out_rSQLPredicate.appendAscii( _bValue ? " = 1" : " = 0" );
2060 break;
2064 //.........................................................................
2065 } // namespace dbtools
2066 //.........................................................................
2068 //.........................................................................
2069 namespace connectivity
2071 //.........................................................................
2073 void release(oslInterlockedCount& _refCount,
2074 ::cppu::OBroadcastHelper& rBHelper,
2075 Reference< XInterface >& _xInterface,
2076 ::com::sun::star::lang::XComponent* _pObject)
2078 if (osl_decrementInterlockedCount( &_refCount ) == 0)
2080 osl_incrementInterlockedCount( &_refCount );
2082 if (!rBHelper.bDisposed && !rBHelper.bInDispose)
2084 // remember the parent
2085 Reference< XInterface > xParent;
2087 ::osl::MutexGuard aGuard( rBHelper.rMutex );
2088 xParent = _xInterface;
2089 _xInterface = NULL;
2092 // First dispose
2093 _pObject->dispose();
2095 // only the alive ref holds the object
2096 OSL_ASSERT( _refCount == 1 );
2098 // release the parent in the ~
2099 if (xParent.is())
2101 ::osl::MutexGuard aGuard( rBHelper.rMutex );
2102 _xInterface = xParent;
2105 // // destroy the object if xHoldAlive decrement the refcount to 0
2106 // m_pDerivedImplementation->WEAK::release();
2109 else
2110 osl_incrementInterlockedCount( &_refCount );
2113 void checkDisposed(sal_Bool _bThrow) throw ( DisposedException )
2115 if (_bThrow)
2116 throw DisposedException();
2119 // -------------------------------------------------------------------------
2120 OSQLColumns::Vector::const_iterator find( OSQLColumns::Vector::const_iterator __first,
2121 OSQLColumns::Vector::const_iterator __last,
2122 const ::rtl::OUString& _rVal,
2123 const ::comphelper::UStringMixEqual& _rCase)
2125 ::rtl::OUString sName = OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME);
2126 return find(__first,__last,sName,_rVal,_rCase);
2128 // -------------------------------------------------------------------------
2129 OSQLColumns::Vector::const_iterator findRealName( OSQLColumns::Vector::const_iterator __first,
2130 OSQLColumns::Vector::const_iterator __last,
2131 const ::rtl::OUString& _rVal,
2132 const ::comphelper::UStringMixEqual& _rCase)
2134 ::rtl::OUString sRealName = OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_REALNAME);
2135 return find(__first,__last,sRealName,_rVal,_rCase);
2137 // -------------------------------------------------------------------------
2138 OSQLColumns::Vector::const_iterator find( OSQLColumns::Vector::const_iterator __first,
2139 OSQLColumns::Vector::const_iterator __last,
2140 const ::rtl::OUString& _rProp,
2141 const ::rtl::OUString& _rVal,
2142 const ::comphelper::UStringMixEqual& _rCase)
2144 while (__first != __last && !_rCase(getString((*__first)->getPropertyValue(_rProp)),_rVal))
2145 ++__first;
2146 return __first;
2149 // -----------------------------------------------------------------------------
2150 } //namespace connectivity
2151 // -----------------------------------------------------------------------------
2153 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */