xref: /trunk/main/connectivity/source/commontools/dbtools.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_dbtools.hxx"
26 
27 #include "connectivity/CommonTools.hxx"
28 #include "diagnose_ex.h"
29 #include "TConnection.hxx"
30 #include "connectivity/ParameterCont.hxx"
31 
32 /** === begin UNO includes === **/
33 #include <com/sun/star/awt/XWindow.hpp>
34 #include <com/sun/star/beans/PropertyAttribute.hpp>
35 #include <com/sun/star/container/XChild.hpp>
36 #include <com/sun/star/form/FormComponentType.hpp>
37 #include <com/sun/star/io/XInputStream.hpp>
38 #include <com/sun/star/lang/DisposedException.hpp>
39 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
40 #include <com/sun/star/sdb/BooleanComparisonMode.hpp>
41 #include <com/sun/star/sdb/CommandType.hpp>
42 #include <com/sun/star/sdb/ParametersRequest.hpp>
43 #include <com/sun/star/sdb/RowSetVetoException.hpp>
44 #include <com/sun/star/sdb/SQLContext.hpp>
45 #include <com/sun/star/sdb/XCompletedConnection.hpp>
46 #include <com/sun/star/sdb/XInteractionSupplyParameters.hpp>
47 #include <com/sun/star/sdb/XOfficeDatabaseDocument.hpp>
48 #include <com/sun/star/sdb/XParametersSupplier.hpp>
49 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
50 #include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
51 #include <com/sun/star/sdbc/DataType.hpp>
52 #include <com/sun/star/sdbc/XConnection.hpp>
53 #include <com/sun/star/sdbc/XDataSource.hpp>
54 #include <com/sun/star/sdbc/XDriverManager.hpp>
55 #include <com/sun/star/sdbc/XParameters.hpp>
56 #include <com/sun/star/sdbc/XRow.hpp>
57 #include <com/sun/star/sdbc/XRowSet.hpp>
58 #include <com/sun/star/sdbc/XRowUpdate.hpp>
59 #include <com/sun/star/sdbcx/KeyType.hpp>
60 #include <com/sun/star/sdbcx/Privilege.hpp>
61 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
62 #include <com/sun/star/sdbcx/XKeysSupplier.hpp>
63 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
64 #include <com/sun/star/task/XInteractionHandler.hpp>
65 #include <com/sun/star/task/XInteractionRequest.hpp>
66 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
67 #include <com/sun/star/uno/XNamingService.hpp>
68 #include <com/sun/star/util/NumberFormat.hpp>
69 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
70 #include <com/sun/star/util/XNumberFormatTypes.hpp>
71 /** === end UNO includes === **/
72 
73 #include <comphelper/extract.hxx>
74 #include <comphelper/interaction.hxx>
75 #include <comphelper/property.hxx>
76 #include <connectivity/conncleanup.hxx>
77 #include <connectivity/dbconversion.hxx>
78 #include <connectivity/dbexception.hxx>
79 #include <connectivity/dbtools.hxx>
80 #include <connectivity/statementcomposer.hxx>
81 #include <osl/diagnose.h>
82 #include <rtl/ustrbuf.hxx>
83 #include <tools/diagnose_ex.h>
84 
85 #include "resource/common_res.hrc"
86 #include "resource/sharedresources.hxx"
87 #include "OSubComponent.hxx"
88 
89 #include <algorithm>
90 #include <iterator>
91 
92 using namespace ::comphelper;
93 using namespace ::com::sun::star::uno;
94 using namespace ::com::sun::star::io;
95 using namespace ::com::sun::star::awt;
96 using namespace ::com::sun::star::ui::dialogs;
97 using namespace ::com::sun::star::util;
98 using namespace ::com::sun::star::lang;
99 using namespace ::com::sun::star::beans;
100 using namespace ::com::sun::star::container;
101 using namespace ::com::sun::star::sdb;
102 using namespace ::com::sun::star::sdbc;
103 using namespace ::com::sun::star::sdbcx;
104 using namespace ::com::sun::star::form;
105 using namespace connectivity;
106 
107 //.........................................................................
108 namespace dbtools
109 {
110 //.........................................................................
111 
112     using namespace ::com::sun::star::uno;
113     using namespace ::com::sun::star::beans;
114     using namespace ::com::sun::star::util;
115     using namespace ::com::sun::star::task;
116     using namespace ::com::sun::star::uno;
117     using namespace ::com::sun::star::lang;
118     using namespace ::com::sun::star::sdbc;
119     using namespace ::com::sun::star::task;
120 //  using namespace cppu;
121 //  using namespace osl;
122 
123 //==============================================================================
124 //==============================================================================
125 namespace
126 {
127     typedef sal_Bool (SAL_CALL XDatabaseMetaData::*FMetaDataSupport)();
128 }
129 //==============================================================================
130 //==============================================================================
getDefaultNumberFormat(const Reference<XPropertySet> & _xColumn,const Reference<XNumberFormatTypes> & _xTypes,const Locale & _rLocale)131 sal_Int32 getDefaultNumberFormat(const Reference< XPropertySet >& _xColumn,
132                                  const Reference< XNumberFormatTypes >& _xTypes,
133                                  const Locale& _rLocale)
134 {
135     OSL_ENSURE(_xTypes.is() && _xColumn.is(), "dbtools::getDefaultNumberFormat: invalid arg !");
136     if (!_xTypes.is() || !_xColumn.is())
137         return NumberFormat::UNDEFINED;
138 
139     sal_Int32 nDataType = 0;
140     sal_Int32 nScale = 0;
141     try
142     {
143         // determine the datatype of the column
144         _xColumn->getPropertyValue(::rtl::OUString::createFromAscii("Type")) >>= nDataType;
145 
146         if (DataType::NUMERIC == nDataType || DataType::DECIMAL == nDataType)
147             _xColumn->getPropertyValue(::rtl::OUString::createFromAscii("Scale")) >>= nScale;
148     }
149     catch (Exception&)
150     {
151         return NumberFormat::UNDEFINED;
152     }
153     return getDefaultNumberFormat(nDataType,
154                     nScale,
155                     ::cppu::any2bool(_xColumn->getPropertyValue(::rtl::OUString::createFromAscii("IsCurrency"))),
156                     _xTypes,
157                     _rLocale);
158 }
159 
160 //------------------------------------------------------------------
getDefaultNumberFormat(sal_Int32 _nDataType,sal_Int32 _nScale,sal_Bool _bIsCurrency,const Reference<XNumberFormatTypes> & _xTypes,const Locale & _rLocale)161 sal_Int32 getDefaultNumberFormat(sal_Int32 _nDataType,
162                                  sal_Int32 _nScale,
163                                  sal_Bool _bIsCurrency,
164                                  const Reference< XNumberFormatTypes >& _xTypes,
165                                  const Locale& _rLocale)
166 {
167     OSL_ENSURE(_xTypes.is() , "dbtools::getDefaultNumberFormat: invalid arg !");
168     if (!_xTypes.is())
169         return NumberFormat::UNDEFINED;
170 
171     sal_Int32 nFormat = 0;
172     sal_Int32 nNumberType   = _bIsCurrency ? NumberFormat::CURRENCY : NumberFormat::NUMBER;
173     switch (_nDataType)
174     {
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:
188         {
189             try
190             {
191                 nFormat = _xTypes->getStandardFormat((sal_Int16)nNumberType, _rLocale);
192                 if(_nScale > 0)
193                 {
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);
197 
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);
202                 }
203             }
204             catch (Exception&)
205             {
206                 nFormat = _xTypes->getStandardFormat((sal_Int16)nNumberType, _rLocale);
207             }
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;
238     }
239     return nFormat;
240 }
241 
242 //==============================================================================
243 //------------------------------------------------------------------------------
findConnection(const Reference<XInterface> & xParent)244 Reference< XConnection> findConnection(const Reference< XInterface >& xParent)
245 {
246     Reference< XConnection> xConnection(xParent, UNO_QUERY);
247     if (!xConnection.is())
248     {
249         Reference< XChild> xChild(xParent, UNO_QUERY);
250         if (xChild.is())
251             xConnection = findConnection(xChild->getParent());
252     }
253     return xConnection;
254 }
255 
256 //------------------------------------------------------------------------------
getDataSource_allowException(const::rtl::OUString & _rsTitleOrPath,const Reference<XMultiServiceFactory> & _rxFactory)257 Reference< XDataSource> getDataSource_allowException(
258             const ::rtl::OUString& _rsTitleOrPath,
259             const Reference< XMultiServiceFactory >& _rxFactory )
260 {
261     ENSURE_OR_RETURN( _rsTitleOrPath.getLength(), "getDataSource_allowException: invalid arg !", NULL );
262 
263     Reference< XNameAccess> xDatabaseContext(
264         _rxFactory->createInstance(
265             ::rtl::OUString::createFromAscii( "com.sun.star.sdb.DatabaseContext" ) ),UNO_QUERY );
266     OSL_ENSURE( xDatabaseContext.is(), "getDataSource_allowException: could not obtain the database context!" );
267 
268     return Reference< XDataSource >( xDatabaseContext->getByName( _rsTitleOrPath ), UNO_QUERY );
269 }
270 
271 //------------------------------------------------------------------------------
getDataSource(const::rtl::OUString & _rsTitleOrPath,const Reference<XMultiServiceFactory> & _rxFactory)272 Reference< XDataSource > getDataSource(
273             const ::rtl::OUString& _rsTitleOrPath,
274             const Reference< XMultiServiceFactory >& _rxFactory )
275 {
276     Reference< XDataSource > xDS;
277     try
278     {
279         xDS = getDataSource_allowException( _rsTitleOrPath, _rxFactory );
280     }
281     catch( const Exception& )
282     {
283         DBG_UNHANDLED_EXCEPTION();
284     }
285 
286     return xDS;
287 }
288 
289 //------------------------------------------------------------------------------
getConnection_allowException(const::rtl::OUString & _rsTitleOrPath,const::rtl::OUString & _rsUser,const::rtl::OUString & _rsPwd,const Reference<XMultiServiceFactory> & _rxFactory)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)
295 {
296     Reference< XDataSource> xDataSource( getDataSource_allowException(_rsTitleOrPath, _rxFactory) );
297     Reference<XConnection> xConnection;
298     if (xDataSource.is())
299     {
300         // do it with interaction handler
301         if(!_rsUser.getLength() || !_rsPwd.getLength())
302         {
303             Reference<XPropertySet> xProp(xDataSource,UNO_QUERY);
304             ::rtl::OUString sPwd, sUser;
305             sal_Bool bPwdReq = sal_False;
306             try
307             {
308                 xProp->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PASSWORD)) >>= sPwd;
309                 bPwdReq = ::cppu::any2bool(xProp->getPropertyValue(::rtl::OUString::createFromAscii("IsPasswordRequired")));
310                 xProp->getPropertyValue(::rtl::OUString::createFromAscii("User")) >>= sUser;
311             }
312             catch(Exception&)
313             {
314                 OSL_ENSURE(sal_False, "dbtools::getConnection: error while retrieving data source properties!");
315             }
316             if(bPwdReq && !sPwd.getLength())
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::createFromAscii("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())
324                     {
325                         xConnection = xConnectionCompletion->connectWithCompletion(xHandler);
326                     }
327                 }
328             }
329             else
330                 xConnection = xDataSource->getConnection(sUser, sPwd);
331         }
332         if(!xConnection.is()) // try to get one if not already have one, just to make sure
333             xConnection = xDataSource->getConnection(_rsUser, _rsPwd);
334     }
335     return xConnection;
336 }
337 
338 //------------------------------------------------------------------------------
getConnection_withFeedback(const::rtl::OUString & _rDataSourceName,const::rtl::OUString & _rUser,const::rtl::OUString & _rPwd,const Reference<XMultiServiceFactory> & _rxFactory)339 Reference< XConnection> getConnection_withFeedback(const ::rtl::OUString& _rDataSourceName,
340         const ::rtl::OUString& _rUser, const ::rtl::OUString& _rPwd, const Reference< XMultiServiceFactory>& _rxFactory)
341 {
342     Reference< XConnection > xReturn;
343     try
344     {
345         xReturn = getConnection_allowException(_rDataSourceName, _rUser, _rPwd, _rxFactory);
346     }
347     catch(SQLException&)
348     {
349         // allowed to pass
350         throw;
351     }
352     catch(Exception&)
353     {
354         OSL_ENSURE(sal_False, "::dbtools::getConnection_withFeedback: unexpected (non-SQL) exception caught!");
355     }
356     return xReturn;
357 }
358 
359 //------------------------------------------------------------------------------
getConnection(const::rtl::OUString & _rsTitleOrPath,const::rtl::OUString & _rsUser,const::rtl::OUString & _rsPwd,const Reference<XMultiServiceFactory> & _rxFactory)360 Reference< XConnection> getConnection(
361             const ::rtl::OUString& _rsTitleOrPath,
362             const ::rtl::OUString& _rsUser,
363             const ::rtl::OUString& _rsPwd,
364             const Reference< XMultiServiceFactory>& _rxFactory)
365 {
366     Reference< XConnection > xReturn;
367     try
368     {
369         xReturn = getConnection_allowException(_rsTitleOrPath, _rsUser, _rsPwd, _rxFactory);
370     }
371     catch(Exception&)
372     {
373     }
374 
375     // TODO: if there were not dozens of places which rely on getConnection not throwing an exception ....
376     // I would change this ...
377 
378     return xReturn;
379 }
380 
381 //------------------------------------------------------------------------------
getConnection(const Reference<XRowSet> & _rxRowSet)382 Reference< XConnection> getConnection(const Reference< XRowSet>& _rxRowSet)
383 {
384     Reference< XConnection> xReturn;
385     Reference< XPropertySet> xRowSetProps(_rxRowSet, UNO_QUERY);
386     if (xRowSetProps.is())
387         xRowSetProps->getPropertyValue(::rtl::OUString::createFromAscii("ActiveConnection")) >>= xReturn;
388     return xReturn;
389 }
390 
391 //------------------------------------------------------------------------------
392 // helper function which allows to implement both the connectRowset and the ensureRowSetConnection semantics
393 // if connectRowset (which is deprecated) is removed, this function and one of its parameters are
394 // not needed anymore, the whole implementation can be moved into ensureRowSetConnection then)
lcl_connectRowSet(const Reference<XRowSet> & _rxRowSet,const Reference<XMultiServiceFactory> & _rxFactory,bool _bSetAsActiveConnection,bool _bAttachAutoDisposer)395 SharedConnection lcl_connectRowSet(const Reference< XRowSet>& _rxRowSet, const Reference< XMultiServiceFactory>& _rxFactory,
396         bool _bSetAsActiveConnection, bool _bAttachAutoDisposer )
397 {
398     SharedConnection xConnection;
399 
400     do
401     {
402         Reference< XPropertySet> xRowSetProps(_rxRowSet, UNO_QUERY);
403         if ( !xRowSetProps.is() )
404             break;
405 
406         // 1. already connected?
407         Reference< XConnection > xExistingConn(
408             xRowSetProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ActiveConnection" ) ) ),
409             UNO_QUERY );
410 
411         if  (   xExistingConn.is()
412             // 2. embedded in a database?
413             ||  isEmbeddedInDatabase( _rxRowSet, xExistingConn )
414             // 3. is there a connection in the parent hierarchy?
415             ||  ( xExistingConn = findConnection( _rxRowSet ) ).is()
416             )
417         {
418             if ( _bSetAsActiveConnection )
419             {
420                 xRowSetProps->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ActiveConnection" ) ), makeAny( xExistingConn ) );
421                 // no auto disposer needed, since we did not create the connection
422             }
423 
424             xConnection.reset( xExistingConn, SharedConnection::NoTakeOwnership );
425             break;
426         }
427 
428         // build a connection with it's current settings (4. data source name, or 5. URL)
429 
430         const ::rtl::OUString sUserProp = ::rtl::OUString::createFromAscii("User");
431         ::rtl::OUString sDataSourceName;
432         xRowSetProps->getPropertyValue(::rtl::OUString::createFromAscii("DataSourceName")) >>= sDataSourceName;
433         ::rtl::OUString sURL;
434         xRowSetProps->getPropertyValue(::rtl::OUString::createFromAscii("URL")) >>= sURL;
435 
436         Reference< XConnection > xPureConnection;
437         if (sDataSourceName.getLength())
438         {   // the row set's data source property is set
439             // -> try to connect, get user and pwd setting for that
440             ::rtl::OUString sUser, sPwd;
441 
442             if (hasProperty(sUserProp, xRowSetProps))
443                 xRowSetProps->getPropertyValue(sUserProp) >>= sUser;
444             if (hasProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PASSWORD), xRowSetProps))
445                 xRowSetProps->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PASSWORD)) >>= sPwd;
446 
447             xPureConnection = getConnection_allowException( sDataSourceName, sUser, sPwd, _rxFactory );
448         }
449         else if (sURL.getLength())
450         {   // the row set has no data source, but a connection url set
451             // -> try to connection with that url
452             Reference< XDriverManager > xDriverManager(
453                 _rxFactory->createInstance( ::rtl::OUString::createFromAscii("com.sun.star.sdbc.ConnectionPool")), UNO_QUERY);
454             if (xDriverManager.is())
455             {
456                 ::rtl::OUString sUser, sPwd;
457                 if (hasProperty(sUserProp, xRowSetProps))
458                     xRowSetProps->getPropertyValue(sUserProp) >>= sUser;
459                 if (hasProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PASSWORD), xRowSetProps))
460                     xRowSetProps->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PASSWORD)) >>= sPwd;
461                 if (sUser.getLength())
462                 {   // use user and pwd together with the url
463                     Sequence< PropertyValue> aInfo(2);
464                     aInfo.getArray()[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("user"));
465                     aInfo.getArray()[0].Value <<= sUser;
466                     aInfo.getArray()[1].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("password"));
467                     aInfo.getArray()[1].Value <<= sPwd;
468                     xPureConnection = xDriverManager->getConnectionWithInfo( sURL, aInfo );
469                 }
470                 else
471                     // just use the url
472                     xPureConnection = xDriverManager->getConnection( sURL );
473             }
474         }
475         xConnection.reset(
476             xPureConnection,
477             _bAttachAutoDisposer ? SharedConnection::NoTakeOwnership : SharedConnection::TakeOwnership
478             /* take ownership if and only if we're *not* going to auto-dispose the connection */
479         );
480 
481         // now if we created a connection, forward it to the row set
482         if ( xConnection.is() && _bSetAsActiveConnection )
483         {
484             try
485             {
486                 if ( _bAttachAutoDisposer )
487                 {
488                     OAutoConnectionDisposer* pAutoDispose = new OAutoConnectionDisposer( _rxRowSet, xConnection );
489                     Reference< XPropertyChangeListener > xEnsureDelete(pAutoDispose);
490                 }
491                 else
492                     xRowSetProps->setPropertyValue(
493                         ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ActiveConnection" ) ),
494                         makeAny( xConnection.getTyped() )
495                     );
496             }
497             catch(Exception&)
498             {
499                 OSL_ENSURE(0,"EXception when we set the new active connection!");
500             }
501         }
502     }
503     while ( false );
504 
505     return xConnection;
506 }
507 
508 //------------------------------------------------------------------------------
connectRowset(const Reference<XRowSet> & _rxRowSet,const Reference<XMultiServiceFactory> & _rxFactory,sal_Bool _bSetAsActiveConnection)509 Reference< XConnection> connectRowset(const Reference< XRowSet>& _rxRowSet, const Reference< XMultiServiceFactory>& _rxFactory,
510     sal_Bool _bSetAsActiveConnection )
511 {
512     SharedConnection xConnection = lcl_connectRowSet( _rxRowSet, _rxFactory, _bSetAsActiveConnection, true );
513     return xConnection.getTyped();
514 }
515 
516 //------------------------------------------------------------------------------
ensureRowSetConnection(const Reference<XRowSet> & _rxRowSet,const Reference<XMultiServiceFactory> & _rxFactory,bool _bUseAutoConnectionDisposer)517 SharedConnection ensureRowSetConnection(const Reference< XRowSet>& _rxRowSet, const Reference< XMultiServiceFactory>& _rxFactory,
518     bool _bUseAutoConnectionDisposer )
519 {
520     return lcl_connectRowSet( _rxRowSet, _rxFactory, true, _bUseAutoConnectionDisposer );
521 }
522 
523 //------------------------------------------------------------------------------
getTableFields(const Reference<XConnection> & _rxConn,const::rtl::OUString & _rName)524 Reference< XNameAccess> getTableFields(const Reference< XConnection>& _rxConn,const ::rtl::OUString& _rName)
525 {
526     Reference< XComponent > xDummy;
527     return getFieldsByCommandDescriptor( _rxConn, CommandType::TABLE, _rName, xDummy );
528 }
529 //------------------------------------------------------------------------------
getPrimaryKeyColumns_throw(const Any & i_aTable)530 Reference< XNameAccess> getPrimaryKeyColumns_throw(const Any& i_aTable)
531 {
532     const Reference< XPropertySet > xTable(i_aTable,UNO_QUERY_THROW);
533     return getPrimaryKeyColumns_throw(xTable);
534 }
535 //------------------------------------------------------------------------------
getPrimaryKeyColumns_throw(const Reference<XPropertySet> & i_xTable)536 Reference< XNameAccess> getPrimaryKeyColumns_throw(const Reference< XPropertySet >& i_xTable)
537 {
538     Reference<XNameAccess> xKeyColumns;
539     const Reference<XKeysSupplier> xKeySup(i_xTable,UNO_QUERY);
540     if ( xKeySup.is() )
541     {
542         const Reference<XIndexAccess> xKeys = xKeySup->getKeys();
543         if ( xKeys.is() )
544         {
545             ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap();
546             const ::rtl::OUString sPropName = rPropMap.getNameByIndex(PROPERTY_ID_TYPE);
547             Reference<XPropertySet> xProp;
548             const sal_Int32 nCount = xKeys->getCount();
549             for(sal_Int32 i = 0;i< nCount;++i)
550             {
551                 xProp.set(xKeys->getByIndex(i),UNO_QUERY_THROW);
552                 if ( xProp.is() )
553                 {
554                     sal_Int32 nKeyType = 0;
555                     xProp->getPropertyValue(sPropName) >>= nKeyType;
556                     if(KeyType::PRIMARY == nKeyType)
557                     {
558                         const Reference<XColumnsSupplier> xKeyColsSup(xProp,UNO_QUERY_THROW);
559                         xKeyColumns = xKeyColsSup->getColumns();
560                         break;
561                     }
562                 }
563             }
564         }
565     }
566 
567     return xKeyColumns;
568 }
569 
570 //------------------------------------------------------------------------------
571 namespace
572 {
573     enum FieldLookupState
574     {
575         HANDLE_TABLE, HANDLE_QUERY, HANDLE_SQL, RETRIEVE_OBJECT, RETRIEVE_COLUMNS, DONE, FAILED
576     };
577 }
578 
579 //------------------------------------------------------------------------------
getFieldsByCommandDescriptor(const Reference<XConnection> & _rxConnection,const sal_Int32 _nCommandType,const::rtl::OUString & _rCommand,Reference<XComponent> & _rxKeepFieldsAlive,SQLExceptionInfo * _pErrorInfo)580 Reference< XNameAccess > getFieldsByCommandDescriptor( const Reference< XConnection >& _rxConnection,
581     const sal_Int32 _nCommandType, const ::rtl::OUString& _rCommand,
582     Reference< XComponent >& _rxKeepFieldsAlive, SQLExceptionInfo* _pErrorInfo ) SAL_THROW( ( ) )
583 {
584     OSL_PRECOND( _rxConnection.is(), "::dbtools::getFieldsByCommandDescriptor: invalid connection!" );
585     OSL_PRECOND( ( CommandType::TABLE == _nCommandType ) || ( CommandType::QUERY == _nCommandType ) || ( CommandType::COMMAND == _nCommandType ),
586         "::dbtools::getFieldsByCommandDescriptor: invalid command type!" );
587     OSL_PRECOND( _rCommand.getLength(), "::dbtools::getFieldsByCommandDescriptor: invalid command (empty)!" );
588 
589     Reference< XNameAccess > xFields;
590 
591     // reset the error
592     if ( _pErrorInfo )
593         *_pErrorInfo = SQLExceptionInfo();
594     // reset the ownership holder
595     _rxKeepFieldsAlive.clear();
596 
597     // go for the fields
598     try
599     {
600         // some kind of state machine to ease the sharing of code
601         FieldLookupState eState = FAILED;
602         switch ( _nCommandType )
603         {
604             case CommandType::TABLE:
605                 eState = HANDLE_TABLE;
606                 break;
607             case CommandType::QUERY:
608                 eState = HANDLE_QUERY;
609                 break;
610             case CommandType::COMMAND:
611                 eState = HANDLE_SQL;
612                 break;
613         }
614 
615         // needed in various states:
616         Reference< XNameAccess > xObjectCollection;
617         Reference< XColumnsSupplier > xSupplyColumns;
618 
619         // go!
620         while ( ( DONE != eState ) && ( FAILED != eState ) )
621         {
622             switch ( eState )
623             {
624                 case HANDLE_TABLE:
625                 {
626                     // initial state for handling the tables
627 
628                     // get the table objects
629                     Reference< XTablesSupplier > xSupplyTables( _rxConnection, UNO_QUERY );
630                     if ( xSupplyTables.is() )
631                         xObjectCollection = xSupplyTables->getTables();
632                     // if something went wrong 'til here, then this will be handled in the next state
633 
634                     // next state: get the object
635                     eState = RETRIEVE_OBJECT;
636                 }
637                 break;
638 
639                 case HANDLE_QUERY:
640                 {
641                     // initial state for handling the tables
642 
643                     // get the table objects
644                     Reference< XQueriesSupplier > xSupplyQueries( _rxConnection, UNO_QUERY );
645                     if ( xSupplyQueries.is() )
646                         xObjectCollection = xSupplyQueries->getQueries();
647                     // if something went wrong 'til here, then this will be handled in the next state
648 
649                     // next state: get the object
650                     eState = RETRIEVE_OBJECT;
651                 }
652                 break;
653 
654                 case RETRIEVE_OBJECT:
655                     // here we should have an object (aka query or table) collection, and are going
656                     // to retrieve the desired object
657 
658                     // next state: default to FAILED
659                     eState = FAILED;
660 
661                     OSL_ENSURE( xObjectCollection.is(), "::dbtools::getFieldsByCommandDescriptor: invalid connection (no sdb.Connection, or no Tables-/QueriesSupplier)!");
662                     if ( xObjectCollection.is() )
663                     {
664                         if ( xObjectCollection.is() && xObjectCollection->hasByName( _rCommand ) )
665                         {
666                             xObjectCollection->getByName( _rCommand ) >>= xSupplyColumns;
667                                 // (xSupplyColumns being NULL will be handled in the next state)
668 
669                             // next: go for the columns
670                             eState = RETRIEVE_COLUMNS;
671                         }
672                     }
673                     break;
674 
675                 case RETRIEVE_COLUMNS:
676                     OSL_ENSURE( xSupplyColumns.is(), "::dbtools::getFieldsByCommandDescriptor: could not retrieve the columns supplier!" );
677 
678                     // next state: default to FAILED
679                     eState = FAILED;
680 
681                     if ( xSupplyColumns.is() )
682                     {
683                         xFields = xSupplyColumns->getColumns();
684                         // that's it
685                         eState = DONE;
686                     }
687                     break;
688 
689                 case HANDLE_SQL:
690                 {
691                     ::rtl::OUString sStatementToExecute( _rCommand );
692 
693                     // well, the main problem here is to handle statements which contain a parameter
694                     // If we would simply execute a parametrized statement, then this will fail because
695                     // we cannot supply any parameter values.
696                     // Thus, we try to analyze the statement, and to append a WHERE 0=1 filter criterion
697                     // This should cause every driver to not really execute the statement, but to return
698                     // an empty result set with the proper structure. We then can use this result set
699                     // to retrieve the columns.
700 
701                     try
702                     {
703                         Reference< XMultiServiceFactory > xComposerFac( _rxConnection, UNO_QUERY );
704 
705                         if ( xComposerFac.is() )
706                         {
707                             Reference< XSingleSelectQueryComposer > xComposer(xComposerFac->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sdb.SingleSelectQueryComposer"))),UNO_QUERY);
708                             if ( xComposer.is() )
709                             {
710                                 xComposer->setQuery( sStatementToExecute );
711 
712                                 // Now set the filter to a dummy restriction which will result in an empty
713                                 // result set.
714                                 xComposer->setFilter( ::rtl::OUString::createFromAscii( "0=1" ) );
715                                 sStatementToExecute = xComposer->getQuery( );
716                             }
717                         }
718                     }
719                     catch( const Exception& )
720                     {
721                         // silent this error, this was just a try. If we're here, we did not change sStatementToExecute,
722                         // so it will still be _rCommand, which then will be executed without being touched
723                     }
724 
725                     // now execute
726                     Reference< XPreparedStatement > xStatement = _rxConnection->prepareStatement( sStatementToExecute );
727                     // transfer ownership of this temporary object to the caller
728                     _rxKeepFieldsAlive = _rxKeepFieldsAlive.query( xStatement );
729 
730                     // set the "MaxRows" to 0. This is just in case our attempt to append a 0=1 filter
731                     // failed - in this case, the MaxRows restriction should at least ensure that there
732                     // is no data returned (which would be potentially expensive)
733                     Reference< XPropertySet > xStatementProps( xStatement,UNO_QUERY );
734                     try
735                     {
736                         if ( xStatementProps.is() )
737                             xStatementProps->setPropertyValue(
738                                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MaxRows" ) ),
739                                 makeAny( sal_Int32( 0 ) )
740                             );
741                     }
742                     catch( const Exception& )
743                     {
744                         OSL_ENSURE( sal_False, "::dbtools::getFieldsByCommandDescriptor: could not set the MaxRows!" );
745                         // oh damn. Not much of a chance to recover, we will no retrieve the complete
746                         // full blown result set
747                     }
748 
749                     xSupplyColumns = xSupplyColumns.query( xStatement->executeQuery() );
750                     // this should have given us a result set which does not contain any data, but
751                     // the structural information we need
752 
753                     // so the next state is to get the columns
754                     eState = RETRIEVE_COLUMNS;
755                 }
756                 break;
757 
758                 default:
759                     OSL_ENSURE( sal_False, "::dbtools::getFieldsByCommandDescriptor: oops! unhandled state here!" );
760                     eState = FAILED;
761             }
762         }
763     }
764     catch( const SQLContext& e ) { if ( _pErrorInfo ) *_pErrorInfo = SQLExceptionInfo( e ); }
765     catch( const SQLWarning& e ) { if ( _pErrorInfo ) *_pErrorInfo = SQLExceptionInfo( e ); }
766     catch( const SQLException& e ) { if ( _pErrorInfo ) *_pErrorInfo = SQLExceptionInfo( e ); }
767     catch( const Exception& )
768     {
769         OSL_ENSURE( sal_False, "::dbtools::getFieldsByCommandDescriptor: caught an exception while retrieving the fields!" );
770     }
771 
772     return xFields;
773 }
774 
775 //------------------------------------------------------------------------------
getFieldNamesByCommandDescriptor(const Reference<XConnection> & _rxConnection,const sal_Int32 _nCommandType,const::rtl::OUString & _rCommand,SQLExceptionInfo * _pErrorInfo)776 Sequence< ::rtl::OUString > getFieldNamesByCommandDescriptor( const Reference< XConnection >& _rxConnection,
777     const sal_Int32 _nCommandType, const ::rtl::OUString& _rCommand,
778     SQLExceptionInfo* _pErrorInfo ) SAL_THROW( ( ) )
779 {
780     // get the container for the fields
781     Reference< XComponent > xKeepFieldsAlive;
782     Reference< XNameAccess > xFieldContainer = getFieldsByCommandDescriptor( _rxConnection, _nCommandType, _rCommand, xKeepFieldsAlive, _pErrorInfo );
783 
784     // get the names of the fields
785     Sequence< ::rtl::OUString > aNames;
786     if ( xFieldContainer.is() )
787         aNames = xFieldContainer->getElementNames();
788 
789     // clean up any temporary objects which have been created
790     disposeComponent( xKeepFieldsAlive );
791 
792     // outta here
793     return aNames;
794 }
795 
796 //------------------------------------------------------------------------------
prependContextInfo(const SQLException & _rException,const Reference<XInterface> & _rxContext,const::rtl::OUString & _rContextDescription,const::rtl::OUString & _rContextDetails)797 SQLContext prependContextInfo(const SQLException& _rException, const Reference< XInterface >& _rxContext, const ::rtl::OUString& _rContextDescription, const ::rtl::OUString& _rContextDetails)
798 {
799     return SQLContext( _rContextDescription, _rxContext, ::rtl::OUString(), 0, makeAny( _rException ), _rContextDetails );
800 }
801 //------------------------------------------------------------------------------
prependErrorInfo(const SQLException & _rChainedException,const Reference<XInterface> & _rxContext,const::rtl::OUString & _rAdditionalError,const StandardSQLState _eSQLState,const sal_Int32 _nErrorCode)802 SQLException prependErrorInfo( const SQLException& _rChainedException, const Reference< XInterface >& _rxContext,
803     const ::rtl::OUString& _rAdditionalError, const StandardSQLState _eSQLState, const sal_Int32 _nErrorCode )
804 {
805     return SQLException( _rAdditionalError, _rxContext,
806         _eSQLState == SQL_ERROR_UNSPECIFIED ? ::rtl::OUString() : getStandardSQLState( _eSQLState ),
807         _nErrorCode, makeAny( _rChainedException ) );
808 }
809 
810 //--------------------------------------------------------------------------
811 namespace
812 {
813     struct NameComponentSupport
814     {
815         const bool  bCatalogs;
816         const bool  bSchemas;
817 
NameComponentSupportdbtools::__anon7710aac50311::NameComponentSupport818         NameComponentSupport( )
819             :bCatalogs( true )
820             ,bSchemas( true )
821         {
822         }
823 
NameComponentSupportdbtools::__anon7710aac50311::NameComponentSupport824         NameComponentSupport( const bool _bCatalogs, const bool _bSchemas )
825             :bCatalogs( _bCatalogs )
826             ,bSchemas( _bSchemas )
827         {
828         }
829     };
830 
lcl_getNameComponentSupport(const Reference<XDatabaseMetaData> & _rxMetaData,EComposeRule _eComposeRule)831     NameComponentSupport lcl_getNameComponentSupport( const Reference< XDatabaseMetaData >& _rxMetaData, EComposeRule _eComposeRule )
832     {
833         OSL_PRECOND( _rxMetaData.is(), "lcl_getNameComponentSupport: invalid meta data!" );
834 
835         FMetaDataSupport pCatalogCall = &XDatabaseMetaData::supportsCatalogsInDataManipulation;
836         FMetaDataSupport pSchemaCall = &XDatabaseMetaData::supportsSchemasInDataManipulation;
837         bool bIgnoreMetaData = false;
838 
839         switch ( _eComposeRule )
840         {
841             case eInTableDefinitions:
842                 pCatalogCall = &XDatabaseMetaData::supportsCatalogsInTableDefinitions;
843                 pSchemaCall = &XDatabaseMetaData::supportsSchemasInTableDefinitions;
844                 break;
845             case eInIndexDefinitions:
846                 pCatalogCall = &XDatabaseMetaData::supportsCatalogsInIndexDefinitions;
847                 pSchemaCall = &XDatabaseMetaData::supportsSchemasInIndexDefinitions;
848                 break;
849             case eInProcedureCalls:
850                 pCatalogCall = &XDatabaseMetaData::supportsCatalogsInProcedureCalls;
851                 pSchemaCall = &XDatabaseMetaData::supportsSchemasInProcedureCalls;
852                 break;
853             case eInPrivilegeDefinitions:
854                 pCatalogCall = &XDatabaseMetaData::supportsCatalogsInPrivilegeDefinitions;
855                 pSchemaCall = &XDatabaseMetaData::supportsSchemasInPrivilegeDefinitions;
856                 break;
857             case eComplete:
858                 bIgnoreMetaData = true;
859                 break;
860             case eInDataManipulation:
861                 // already properly set above
862                 break;
863         }
864         return NameComponentSupport(
865             bIgnoreMetaData ? true : (_rxMetaData.get()->*pCatalogCall)(),
866             bIgnoreMetaData ? true : (_rxMetaData.get()->*pSchemaCall)()
867         );
868     }
869 }
870 
871 //--------------------------------------------------------------------------
impl_doComposeTableName(const Reference<XDatabaseMetaData> & _rxMetaData,const::rtl::OUString & _rCatalog,const::rtl::OUString & _rSchema,const::rtl::OUString & _rName,sal_Bool _bQuote,EComposeRule _eComposeRule)872 static ::rtl::OUString impl_doComposeTableName( const Reference< XDatabaseMetaData >& _rxMetaData,
873                 const ::rtl::OUString& _rCatalog, const ::rtl::OUString& _rSchema, const ::rtl::OUString& _rName,
874                 sal_Bool _bQuote, EComposeRule _eComposeRule )
875 {
876     OSL_ENSURE(_rxMetaData.is(), "impl_doComposeTableName : invalid meta data !");
877     if ( !_rxMetaData.is() )
878         return ::rtl::OUString();
879     OSL_ENSURE(_rName.getLength(), "impl_doComposeTableName : at least the name should be non-empty !");
880 
881     const ::rtl::OUString sQuoteString = _rxMetaData->getIdentifierQuoteString();
882     const NameComponentSupport aNameComps( lcl_getNameComponentSupport( _rxMetaData, _eComposeRule ) );
883 
884     ::rtl::OUStringBuffer aComposedName;
885 
886     ::rtl::OUString sCatalogSep;
887     sal_Bool bCatlogAtStart = sal_True;
888     if ( _rCatalog.getLength() && aNameComps.bCatalogs )
889     {
890         sCatalogSep     = _rxMetaData->getCatalogSeparator();
891         bCatlogAtStart  = _rxMetaData->isCatalogAtStart();
892 
893         if ( bCatlogAtStart && sCatalogSep.getLength())
894         {
895             aComposedName.append( _bQuote ? quoteName( sQuoteString, _rCatalog ) : _rCatalog );
896             aComposedName.append( sCatalogSep );
897         }
898     }
899 
900     if ( _rSchema.getLength() && aNameComps.bSchemas )
901     {
902         aComposedName.append( _bQuote ? quoteName( sQuoteString, _rSchema ) : _rSchema );
903         aComposedName.appendAscii( "." );
904     }
905 
906     aComposedName.append( _bQuote ? quoteName( sQuoteString, _rName ) : _rName );
907 
908     if  (   _rCatalog.getLength()
909         &&  !bCatlogAtStart
910         &&  sCatalogSep.getLength()
911         &&  aNameComps.bCatalogs
912         )
913     {
914         aComposedName.append( sCatalogSep );
915         aComposedName.append( _bQuote ? quoteName( sQuoteString, _rCatalog ) : _rCatalog );
916     }
917 
918     return aComposedName.makeStringAndClear();
919 }
920 
921 //------------------------------------------------------------------------------
quoteTableName(const Reference<XDatabaseMetaData> & _rxMeta,const::rtl::OUString & _rName,EComposeRule _eComposeRule)922 ::rtl::OUString quoteTableName(const Reference< XDatabaseMetaData>& _rxMeta
923                                , const ::rtl::OUString& _rName
924                                , EComposeRule _eComposeRule)
925 {
926     ::rtl::OUString sCatalog, sSchema, sTable;
927     qualifiedNameComponents(_rxMeta,_rName,sCatalog,sSchema,sTable,_eComposeRule);
928     return impl_doComposeTableName( _rxMeta, sCatalog, sSchema, sTable, sal_True, _eComposeRule );
929 }
930 
931 //------------------------------------------------------------------------------
qualifiedNameComponents(const Reference<XDatabaseMetaData> & _rxConnMetaData,const::rtl::OUString & _rQualifiedName,::rtl::OUString & _rCatalog,::rtl::OUString & _rSchema,::rtl::OUString & _rName,EComposeRule _eComposeRule)932 void qualifiedNameComponents(const Reference< XDatabaseMetaData >& _rxConnMetaData, const ::rtl::OUString& _rQualifiedName, ::rtl::OUString& _rCatalog, ::rtl::OUString& _rSchema, ::rtl::OUString& _rName,EComposeRule _eComposeRule)
933 {
934     OSL_ENSURE(_rxConnMetaData.is(), "QualifiedNameComponents : invalid meta data!");
935 
936     NameComponentSupport aNameComps( lcl_getNameComponentSupport( _rxConnMetaData, _eComposeRule ) );
937 
938     ::rtl::OUString sSeparator = _rxConnMetaData->getCatalogSeparator();
939 
940     ::rtl::OUString sName(_rQualifiedName);
941     // do we have catalogs ?
942     if ( aNameComps.bCatalogs )
943     {
944         if (_rxConnMetaData->isCatalogAtStart())
945         {
946             // search for the catalog name at the beginning
947             sal_Int32 nIndex = sName.indexOf(sSeparator);
948             if (-1 != nIndex)
949             {
950                 _rCatalog = sName.copy(0, nIndex);
951                 sName = sName.copy(nIndex + 1);
952             }
953         }
954         else
955         {
956             // Katalogname am Ende
957             sal_Int32 nIndex = sName.lastIndexOf(sSeparator);
958             if (-1 != nIndex)
959             {
960                 _rCatalog = sName.copy(nIndex + 1);
961                 sName = sName.copy(0, nIndex);
962             }
963         }
964     }
965 
966     if ( aNameComps.bSchemas )
967     {
968         sal_Int32 nIndex = sName.indexOf((sal_Unicode)'.');
969         //  OSL_ENSURE(-1 != nIndex, "QualifiedNameComponents : no schema separator!");
970         if ( nIndex != -1 )
971             _rSchema = sName.copy(0, nIndex);
972         sName = sName.copy(nIndex + 1);
973     }
974 
975     _rName = sName;
976 }
977 
978 //------------------------------------------------------------------------------
getNumberFormats(const Reference<XConnection> & _rxConn,sal_Bool _bAlloweDefault,const Reference<XMultiServiceFactory> & _rxFactory)979 Reference< XNumberFormatsSupplier> getNumberFormats(
980             const Reference< XConnection>& _rxConn,
981             sal_Bool _bAlloweDefault,
982             const Reference< XMultiServiceFactory>& _rxFactory)
983 {
984     // ask the parent of the connection (should be an DatabaseAccess)
985     Reference< XNumberFormatsSupplier> xReturn;
986     Reference< XChild> xConnAsChild(_rxConn, UNO_QUERY);
987     ::rtl::OUString sPropFormatsSupplier = ::rtl::OUString::createFromAscii("NumberFormatsSupplier");
988     if (xConnAsChild.is())
989     {
990         Reference< XPropertySet> xConnParentProps(xConnAsChild->getParent(), UNO_QUERY);
991         if (xConnParentProps.is() && hasProperty(sPropFormatsSupplier, xConnParentProps))
992             xConnParentProps->getPropertyValue(sPropFormatsSupplier) >>= xReturn;
993     }
994     else if(_bAlloweDefault && _rxFactory.is())
995     {
996         xReturn = Reference< XNumberFormatsSupplier>(_rxFactory->createInstance(::rtl::OUString::createFromAscii("com.sun.star.util.NumberFormatsSupplier")),UNO_QUERY);
997     }
998     return xReturn;
999 }
1000 
1001 //==============================================================================
1002 //------------------------------------------------------------------------------
TransferFormComponentProperties(const Reference<XPropertySet> & xOldProps,const Reference<XPropertySet> & xNewProps,const Locale & _rLocale)1003 void TransferFormComponentProperties(
1004             const Reference< XPropertySet>& xOldProps,
1005             const Reference< XPropertySet>& xNewProps,
1006             const Locale& _rLocale)
1007 {
1008 try
1009 {
1010     OSL_ENSURE( xOldProps.is() && xNewProps.is(), "TransferFormComponentProperties: invalid source/dest!" );
1011     if ( !xOldProps.is() || !xNewProps.is() )
1012         return;
1013 
1014     // kopieren wir erst mal alle Props, die in Quelle und Ziel vorhanden sind und identische Beschreibungen haben
1015     Reference< XPropertySetInfo> xOldInfo( xOldProps->getPropertySetInfo());
1016     Reference< XPropertySetInfo> xNewInfo( xNewProps->getPropertySetInfo());
1017 
1018     Sequence< Property> aOldProperties = xOldInfo->getProperties();
1019     Sequence< Property> aNewProperties = xNewInfo->getProperties();
1020     int nNewLen = aNewProperties.getLength();
1021 
1022     Property* pOldProps = aOldProperties.getArray();
1023     Property* pNewProps = aNewProperties.getArray();
1024 
1025     ::rtl::OUString sPropDefaultControl(::rtl::OUString::createFromAscii("DefaultControl"));
1026     ::rtl::OUString sPropLabelControl(::rtl::OUString::createFromAscii("LabelControl"));
1027     ::rtl::OUString sPropFormatsSupplier(::rtl::OUString::createFromAscii("FormatsSupplier"));
1028     ::rtl::OUString sPropCurrencySymbol(::rtl::OUString::createFromAscii("CurrencySymbol"));
1029     ::rtl::OUString sPropDecimals(::rtl::OUString::createFromAscii("Decimals"));
1030     ::rtl::OUString sPropEffectiveMin(::rtl::OUString::createFromAscii("EffectiveMin"));
1031     ::rtl::OUString sPropEffectiveMax(::rtl::OUString::createFromAscii("EffectiveMax"));
1032     ::rtl::OUString sPropEffectiveDefault(::rtl::OUString::createFromAscii("EffectiveDefault"));
1033     ::rtl::OUString sPropDefaultText(::rtl::OUString::createFromAscii("DefaultText"));
1034     ::rtl::OUString sPropDefaultDate(::rtl::OUString::createFromAscii("DefaultDate"));
1035     ::rtl::OUString sPropDefaultTime(::rtl::OUString::createFromAscii("DefaultTime"));
1036     ::rtl::OUString sPropValueMin(::rtl::OUString::createFromAscii("ValueMin"));
1037     ::rtl::OUString sPropValueMax(::rtl::OUString::createFromAscii("ValueMax"));
1038     ::rtl::OUString sPropDecimalAccuracy(::rtl::OUString::createFromAscii("DecimalAccuracy"));
1039     ::rtl::OUString sPropClassId(::rtl::OUString::createFromAscii("ClassId"));
1040     ::rtl::OUString sFormattedServiceName( ::rtl::OUString::createFromAscii( "com.sun.star.form.component.FormattedField" ) );
1041 
1042     for (sal_Int16 i=0; i<aOldProperties.getLength(); ++i)
1043     {
1044         if  (   (!pOldProps[i].Name.equals(sPropDefaultControl))
1045             &&  (!pOldProps[i].Name.equals(sPropLabelControl))
1046             )
1047         {
1048             // binaere Suche
1049             Property* pResult = ::std::lower_bound(pNewProps, pNewProps + nNewLen,pOldProps[i].Name, ::comphelper::PropertyStringLessFunctor());
1050             if (    pResult
1051                 && ( pResult != pNewProps + nNewLen && pResult->Name == pOldProps[i].Name )
1052                 && ( (pResult->Attributes & PropertyAttribute::READONLY) == 0 )
1053                 && ( pResult->Type.equals(pOldProps[i].Type)) )
1054             {   // Attribute stimmen ueberein und Property ist nicht read-only
1055                 try
1056                 {
1057                     xNewProps->setPropertyValue(pResult->Name, xOldProps->getPropertyValue(pResult->Name));
1058                 }
1059                 catch(IllegalArgumentException& e)
1060                 {
1061                     OSL_UNUSED( e );
1062 #ifdef DBG_UTIL
1063                     ::rtl::OUString sMessage = ::rtl::OUString::createFromAscii("TransferFormComponentProperties : could not transfer the value for property \"");
1064                     sMessage += pResult->Name;
1065                     sMessage += ::rtl::OUString::createFromAscii("\"");
1066                     OSL_ENSURE(sal_False, ::rtl::OUStringToOString(sMessage, RTL_TEXTENCODING_ASCII_US));
1067 #endif
1068                 }
1069             }
1070         }
1071     }
1072 
1073 
1074     // fuer formatierte Felder (entweder alt oder neu) haben wir ein paar Sonderbehandlungen
1075     Reference< XServiceInfo > xSI( xOldProps, UNO_QUERY );
1076     sal_Bool bOldIsFormatted = xSI.is() && xSI->supportsService( sFormattedServiceName );
1077     xSI = Reference< XServiceInfo >( xNewProps, UNO_QUERY );
1078     sal_Bool bNewIsFormatted = xSI.is() && xSI->supportsService( sFormattedServiceName );
1079 
1080     if (!bOldIsFormatted && !bNewIsFormatted)
1081         return; // nothing to do
1082 
1083     if (bOldIsFormatted && bNewIsFormatted)
1084         // nein, wenn beide formatierte Felder sind, dann machen wir keinerlei Konvertierungen
1085         // Das geht zu weit ;)
1086         return;
1087 
1088     if (bOldIsFormatted)
1089     {
1090         // aus dem eingestellten Format ein paar Properties rausziehen und zum neuen Set durchschleifen
1091         Any aFormatKey( xOldProps->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FORMATKEY)) );
1092         if (aFormatKey.hasValue())
1093         {
1094             Reference< XNumberFormatsSupplier> xSupplier;
1095             xOldProps->getPropertyValue(sPropFormatsSupplier) >>= xSupplier;
1096             if (xSupplier.is())
1097             {
1098                 Reference< XNumberFormats> xFormats(xSupplier->getNumberFormats());
1099                 Reference< XPropertySet> xFormat(xFormats->getByKey(getINT32(aFormatKey)));
1100                 if (hasProperty(sPropCurrencySymbol, xFormat))
1101                 {
1102                     Any aVal( xFormat->getPropertyValue(sPropCurrencySymbol) );
1103                     if (aVal.hasValue() && hasProperty(sPropCurrencySymbol, xNewProps))
1104                         // (wenn die Quelle das nicht gesetzt hat, dann auch nicht kopieren, um den
1105                         // Default-Wert nicht zu ueberschreiben
1106                         xNewProps->setPropertyValue(sPropCurrencySymbol, aVal);
1107                 }
1108                 if (hasProperty(sPropDecimals, xFormat) && hasProperty(sPropDecimals, xNewProps))
1109                     xNewProps->setPropertyValue(sPropDecimals, xFormat->getPropertyValue(sPropDecimals));
1110             }
1111         }
1112 
1113         // eine eventuelle-Min-Max-Konvertierung
1114         Any aEffectiveMin( xOldProps->getPropertyValue(sPropEffectiveMin) );
1115         if (aEffectiveMin.hasValue())
1116         {   // im Gegensatz zu ValueMin kann EffectiveMin void sein
1117             if (hasProperty(sPropValueMin, xNewProps))
1118             {
1119                 OSL_ENSURE(aEffectiveMin.getValueType().getTypeClass() == TypeClass_DOUBLE,
1120                     "TransferFormComponentProperties : invalid property type !");
1121                 xNewProps->setPropertyValue(sPropValueMin, aEffectiveMin);
1122             }
1123         }
1124         Any aEffectiveMax( xOldProps->getPropertyValue(sPropEffectiveMax) );
1125         if (aEffectiveMax.hasValue())
1126         {   // analog
1127             if (hasProperty(sPropValueMax, xNewProps))
1128             {
1129                 OSL_ENSURE(aEffectiveMax.getValueType().getTypeClass() == TypeClass_DOUBLE,
1130                     "TransferFormComponentProperties : invalid property type !");
1131                 xNewProps->setPropertyValue(sPropValueMax, aEffectiveMax);
1132             }
1133         }
1134 
1135         // dann koennen wir noch Default-Werte konvertieren und uebernehmen
1136         Any aEffectiveDefault( xOldProps->getPropertyValue(sPropEffectiveDefault) );
1137         if (aEffectiveDefault.hasValue())
1138         {
1139             sal_Bool bIsString = aEffectiveDefault.getValueType().getTypeClass() == TypeClass_STRING;
1140             OSL_ENSURE(bIsString || aEffectiveDefault.getValueType().getTypeClass() == TypeClass_DOUBLE,
1141                 "TransferFormComponentProperties : invalid property type !");
1142                 // die Effective-Properties sollten immer void oder string oder double sein ....
1143 
1144             if (hasProperty(sPropDefaultDate, xNewProps) && !bIsString)
1145             {   // (einen ::rtl::OUString in ein Datum zu konvertieren muss nicht immer klappen, denn das ganze kann ja an
1146                 // eine Textspalte gebunden gewesen sein, aber mit einem double koennen wir was anfangen)
1147                 Date aDate = DBTypeConversion::toDate(getDouble(aEffectiveDefault));
1148                 xNewProps->setPropertyValue(sPropDefaultDate, makeAny(aDate));
1149             }
1150 
1151             if (hasProperty(sPropDefaultTime, xNewProps) && !bIsString)
1152             {   // voellig analog mit Zeit
1153                 Time aTime = DBTypeConversion::toTime(getDouble(aEffectiveDefault));
1154                 xNewProps->setPropertyValue(sPropDefaultTime, makeAny(aTime));
1155             }
1156 
1157             if (hasProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE), xNewProps) && !bIsString)
1158             {   // hier koennen wir einfach das double durchreichen
1159                 xNewProps->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE), aEffectiveDefault);
1160             }
1161 
1162             if (hasProperty(sPropDefaultText, xNewProps) && bIsString)
1163             {   // und hier den ::rtl::OUString
1164                 xNewProps->setPropertyValue(sPropDefaultText, aEffectiveDefault);
1165             }
1166 
1167             // nyi: die Uebersetzung zwischen doubles und ::rtl::OUString wuerde noch mehr Moeglichkeien eroeffnen
1168         }
1169     }
1170 
1171     // die andere Richtung : das neu Control soll formatiert sein
1172     if (bNewIsFormatted)
1173     {
1174         // zuerst die Formatierung
1175         // einen Supplier koennen wir nicht setzen, also muss das neue Set schon einen mitbringen
1176         Reference< XNumberFormatsSupplier> xSupplier;
1177         xNewProps->getPropertyValue(sPropFormatsSupplier) >>= xSupplier;
1178         if (xSupplier.is())
1179         {
1180             Reference< XNumberFormats> xFormats(xSupplier->getNumberFormats());
1181 
1182             // Dezimal-Stellen
1183             sal_Int16 nDecimals = 2;
1184             if (hasProperty(sPropDecimalAccuracy, xOldProps))
1185                 xOldProps->getPropertyValue(sPropDecimalAccuracy) >>= nDecimals;
1186 
1187             // Grund-Format (je nach ClassId des alten Sets)
1188             sal_Int32 nBaseKey = 0;
1189             if (hasProperty(sPropClassId, xOldProps))
1190             {
1191                 Reference< XNumberFormatTypes> xTypeList(xFormats, UNO_QUERY);
1192                 if (xTypeList.is())
1193                 {
1194                     sal_Int16 nClassId = 0;
1195                     xOldProps->getPropertyValue(sPropClassId) >>= nClassId;
1196                     switch (nClassId)
1197                     {
1198                         case FormComponentType::DATEFIELD :
1199                             nBaseKey = xTypeList->getStandardFormat(NumberFormat::DATE, _rLocale);
1200                             break;
1201 
1202                         case FormComponentType::TIMEFIELD :
1203                             nBaseKey = xTypeList->getStandardFormat(NumberFormat::TIME, _rLocale);
1204                             break;
1205 
1206                         case FormComponentType::CURRENCYFIELD :
1207                             nBaseKey = xTypeList->getStandardFormat(NumberFormat::CURRENCY, _rLocale);
1208                             break;
1209                     }
1210                 }
1211             }
1212 
1213             // damit koennen wir ein neues Format basteln ...
1214             ::rtl::OUString sNewFormat = xFormats->generateFormat(nBaseKey, _rLocale, sal_False, sal_False, nDecimals, 0);
1215                 // kein Tausender-Trennzeichen, negative Zahlen nicht in Rot, keine fuehrenden Nullen
1216 
1217             // ... und zum FormatsSupplier hinzufuegen (wenn noetig)
1218             sal_Int32 nKey = xFormats->queryKey(sNewFormat, _rLocale, sal_False);
1219             if (nKey == (sal_Int32)-1)
1220             {   // noch nicht vorhanden in meinem Formatter ...
1221                 nKey = xFormats->addNew(sNewFormat, _rLocale);
1222             }
1223 
1224             xNewProps->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FORMATKEY), makeAny((sal_Int32)nKey));
1225         }
1226 
1227         // min-/max-Werte
1228         Any aNewMin, aNewMax;
1229         if (hasProperty(sPropValueMin, xOldProps))
1230             aNewMin = xOldProps->getPropertyValue(sPropValueMin);
1231         if (hasProperty(sPropValueMax, xOldProps))
1232             aNewMax = xOldProps->getPropertyValue(sPropValueMax);
1233         xNewProps->setPropertyValue(sPropEffectiveMin, aNewMin);
1234         xNewProps->setPropertyValue(sPropEffectiveMax, aNewMax);
1235 
1236         // Default-Wert
1237         Any aNewDefault;
1238         if (hasProperty(sPropDefaultDate, xOldProps))
1239         {
1240             Any aDate( xOldProps->getPropertyValue(sPropDefaultDate) );
1241             if (aDate.hasValue())
1242                 aNewDefault <<= DBTypeConversion::toDouble(*(Date*)aDate.getValue());
1243         }
1244 
1245         if (hasProperty(sPropDefaultTime, xOldProps))
1246         {
1247             Any aTime( xOldProps->getPropertyValue(sPropDefaultTime) );
1248             if (aTime.hasValue())
1249                 aNewDefault <<= DBTypeConversion::toDouble(*(Time*)aTime.getValue());
1250         }
1251 
1252         // double oder ::rtl::OUString werden direkt uebernommen
1253         if (hasProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE), xOldProps))
1254             aNewDefault = xOldProps->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE));
1255         if (hasProperty(sPropDefaultText, xOldProps))
1256             aNewDefault = xOldProps->getPropertyValue(sPropDefaultText);
1257 
1258         if (aNewDefault.hasValue())
1259             xNewProps->setPropertyValue(sPropEffectiveDefault, aNewDefault);
1260     }
1261 }
1262 catch(const Exception&)
1263 {
1264     OSL_ENSURE( sal_False, "TransferFormComponentProperties: caught an exception!" );
1265 }
1266 }
1267 
1268 //------------------------------------------------------------------------------
canInsert(const Reference<XPropertySet> & _rxCursorSet)1269 sal_Bool canInsert(const Reference< XPropertySet>& _rxCursorSet)
1270 {
1271     return ((_rxCursorSet.is() && (getINT32(_rxCursorSet->getPropertyValue(::rtl::OUString::createFromAscii("Privileges"))) & Privilege::INSERT) != 0));
1272 }
1273 
1274 //------------------------------------------------------------------------------
canUpdate(const Reference<XPropertySet> & _rxCursorSet)1275 sal_Bool canUpdate(const Reference< XPropertySet>& _rxCursorSet)
1276 {
1277     return ((_rxCursorSet.is() && (getINT32(_rxCursorSet->getPropertyValue(::rtl::OUString::createFromAscii("Privileges"))) & Privilege::UPDATE) != 0));
1278 }
1279 
1280 //------------------------------------------------------------------------------
canDelete(const Reference<XPropertySet> & _rxCursorSet)1281 sal_Bool canDelete(const Reference< XPropertySet>& _rxCursorSet)
1282 {
1283     return ((_rxCursorSet.is() && (getINT32(_rxCursorSet->getPropertyValue(::rtl::OUString::createFromAscii("Privileges"))) & Privilege::DELETE) != 0));
1284 }
1285 // -----------------------------------------------------------------------------
findDataSource(const Reference<XInterface> & _xParent)1286 Reference< XDataSource> findDataSource(const Reference< XInterface >& _xParent)
1287 {
1288     Reference< XOfficeDatabaseDocument> xDatabaseDocument(_xParent, UNO_QUERY);
1289     Reference< XDataSource> xDataSource;
1290     if ( xDatabaseDocument.is() )
1291         xDataSource = xDatabaseDocument->getDataSource();
1292     if ( !xDataSource.is() )
1293         xDataSource.set(_xParent, UNO_QUERY);
1294     if (!xDataSource.is())
1295     {
1296         Reference< XChild> xChild(_xParent, UNO_QUERY);
1297         if ( xChild.is() )
1298             xDataSource = findDataSource(xChild->getParent());
1299     }
1300     return xDataSource;
1301 }
1302 
1303 //------------------------------------------------------------------------------
getComposedRowSetStatement(const Reference<XPropertySet> & _rxRowSet,const Reference<XMultiServiceFactory> & _rxFactory,sal_Bool _bUseRowSetFilter,sal_Bool _bUseRowSetOrder,Reference<XSingleSelectQueryComposer> * _pxComposer)1304 ::rtl::OUString getComposedRowSetStatement( const Reference< XPropertySet >& _rxRowSet, const Reference< XMultiServiceFactory>& _rxFactory,
1305                                    sal_Bool _bUseRowSetFilter, sal_Bool _bUseRowSetOrder, Reference< XSingleSelectQueryComposer >* _pxComposer )
1306 {
1307     ::rtl::OUString sStatement;
1308     try
1309     {
1310         Reference< XConnection> xConn = connectRowset( Reference< XRowSet >( _rxRowSet, UNO_QUERY ), _rxFactory, sal_True );
1311         if ( xConn.is() )       // implies _rxRowSet.is()
1312         {
1313             // build the statement the row set is based on (can't use the ActiveCommand property of the set
1314             // as this reflects the status after the last execute, not the currently set properties)
1315 
1316             sal_Int32 nCommandType = CommandType::COMMAND;
1317             ::rtl::OUString sCommand;
1318             sal_Bool bEscapeProcessing = sal_False;
1319 
1320             OSL_VERIFY( _rxRowSet->getPropertyValue( ::rtl::OUString::createFromAscii( "CommandType" )      ) >>= nCommandType      );
1321             OSL_VERIFY( _rxRowSet->getPropertyValue( ::rtl::OUString::createFromAscii( "Command" )          ) >>= sCommand          );
1322             OSL_VERIFY( _rxRowSet->getPropertyValue( ::rtl::OUString::createFromAscii( "EscapeProcessing" ) ) >>= bEscapeProcessing );
1323 
1324             StatementComposer aComposer( xConn, sCommand, nCommandType, bEscapeProcessing );
1325             // append sort
1326             if ( _bUseRowSetOrder )
1327                 aComposer.setOrder( getString( _rxRowSet->getPropertyValue( ::rtl::OUString::createFromAscii( "Order" ) ) ) );
1328 
1329             // append filter
1330             if ( _bUseRowSetFilter )
1331             {
1332                 sal_Bool bApplyFilter = sal_True;
1333                 _rxRowSet->getPropertyValue( ::rtl::OUString::createFromAscii( "ApplyFilter" ) ) >>= bApplyFilter;
1334                 if ( bApplyFilter )
1335                     aComposer.setFilter( getString( _rxRowSet->getPropertyValue( ::rtl::OUString::createFromAscii( "Filter" ) ) ) );
1336             }
1337 
1338             sStatement = aComposer.getQuery();
1339 
1340             if ( _pxComposer )
1341             {
1342                 *_pxComposer = aComposer.getComposer();
1343                 aComposer.setDisposeComposer( false );
1344             }
1345         }
1346     }
1347     catch( const SQLException& )
1348     {
1349         throw;
1350     }
1351     catch( const Exception& )
1352     {
1353         DBG_UNHANDLED_EXCEPTION();
1354     }
1355 
1356     return sStatement;
1357 }
1358 
1359 //------------------------------------------------------------------------------
getComposedRowSetStatement(const Reference<XPropertySet> & _rxRowSet,const Reference<XMultiServiceFactory> & _rxFactory,sal_Bool _bUseRowSetFilter,sal_Bool _bUseRowSetOrder)1360 ::rtl::OUString getComposedRowSetStatement(
1361                     const Reference< XPropertySet >& _rxRowSet, const Reference< XMultiServiceFactory>& _rxFactory,
1362                     sal_Bool _bUseRowSetFilter, sal_Bool _bUseRowSetOrder )
1363 {
1364     return getComposedRowSetStatement( _rxRowSet, _rxFactory, _bUseRowSetFilter, _bUseRowSetOrder, NULL );
1365 }
1366 
1367 //------------------------------------------------------------------------------
getCurrentSettingsComposer(const Reference<XPropertySet> & _rxRowSetProps,const Reference<XMultiServiceFactory> & _rxFactory)1368 Reference< XSingleSelectQueryComposer > getCurrentSettingsComposer(
1369                 const Reference< XPropertySet>& _rxRowSetProps,
1370                 const Reference< XMultiServiceFactory>& _rxFactory)
1371 {
1372     Reference< XSingleSelectQueryComposer > xReturn;
1373     try
1374     {
1375         getComposedRowSetStatement( _rxRowSetProps, _rxFactory, sal_True, sal_True, &xReturn );
1376     }
1377     catch( const SQLException& )
1378     {
1379         throw;
1380     }
1381     catch( const Exception& )
1382     {
1383         OSL_ENSURE( sal_False, "::getCurrentSettingsComposer : caught an exception !" );
1384     }
1385 
1386     return xReturn;
1387 }
1388 //--------------------------------------------------------------------------
composeTableName(const Reference<XDatabaseMetaData> & _rxMetaData,const::rtl::OUString & _rCatalog,const::rtl::OUString & _rSchema,const::rtl::OUString & _rName,sal_Bool _bQuote,EComposeRule _eComposeRule)1389 ::rtl::OUString composeTableName( const Reference< XDatabaseMetaData >& _rxMetaData,
1390                         const ::rtl::OUString& _rCatalog,
1391                         const ::rtl::OUString& _rSchema,
1392                         const ::rtl::OUString& _rName,
1393                         sal_Bool _bQuote,
1394                         EComposeRule _eComposeRule)
1395 {
1396     return impl_doComposeTableName( _rxMetaData, _rCatalog, _rSchema, _rName, _bQuote, _eComposeRule );
1397 }
1398 
1399 // -----------------------------------------------------------------------------
composeTableNameForSelect(const Reference<XConnection> & _rxConnection,const::rtl::OUString & _rCatalog,const::rtl::OUString & _rSchema,const::rtl::OUString & _rName)1400 ::rtl::OUString composeTableNameForSelect( const Reference< XConnection >& _rxConnection,
1401     const ::rtl::OUString& _rCatalog, const ::rtl::OUString& _rSchema, const ::rtl::OUString& _rName )
1402 {
1403     sal_Bool bUseCatalogInSelect = isDataSourcePropertyEnabled( _rxConnection, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseCatalogInSelect" ) ), sal_True );
1404     sal_Bool bUseSchemaInSelect = isDataSourcePropertyEnabled( _rxConnection, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseSchemaInSelect" ) ), sal_True );
1405 
1406     return impl_doComposeTableName(
1407         _rxConnection->getMetaData(),
1408         bUseCatalogInSelect ? _rCatalog : ::rtl::OUString(),
1409         bUseSchemaInSelect ? _rSchema : ::rtl::OUString(),
1410         _rName,
1411         true,
1412         eInDataManipulation
1413     );
1414 }
1415 
1416 // -----------------------------------------------------------------------------
1417 namespace
1418 {
lcl_getTableNameComponents(const Reference<XPropertySet> & _xTable,::rtl::OUString & _out_rCatalog,::rtl::OUString & _out_rSchema,::rtl::OUString & _out_rName)1419     static void lcl_getTableNameComponents( const Reference<XPropertySet>& _xTable,
1420         ::rtl::OUString& _out_rCatalog, ::rtl::OUString& _out_rSchema, ::rtl::OUString& _out_rName )
1421     {
1422         ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap();
1423         Reference< XPropertySetInfo > xInfo = _xTable->getPropertySetInfo();
1424         if (    xInfo.is()
1425             &&  xInfo->hasPropertyByName(rPropMap.getNameByIndex(PROPERTY_ID_NAME)) )
1426         {
1427 
1428             ::rtl::OUString aCatalog;
1429             ::rtl::OUString aSchema;
1430             ::rtl::OUString aTable;
1431             if (    xInfo->hasPropertyByName(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME))
1432                 &&  xInfo->hasPropertyByName(rPropMap.getNameByIndex(PROPERTY_ID_SCHEMANAME)) )
1433             {
1434                 _xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME)) >>= _out_rCatalog;
1435                 _xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_SCHEMANAME))  >>= _out_rSchema;
1436             }
1437             _xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME))        >>= _out_rName;
1438         }
1439         else
1440             OSL_ENSURE( false, "::dbtools::lcl_getTableNameComponents: this is no table object!" );
1441     }
1442 }
1443 
1444 // -----------------------------------------------------------------------------
composeTableNameForSelect(const Reference<XConnection> & _rxConnection,const Reference<XPropertySet> & _xTable)1445 ::rtl::OUString composeTableNameForSelect( const Reference< XConnection >& _rxConnection, const Reference<XPropertySet>& _xTable )
1446 {
1447     ::rtl::OUString sCatalog, sSchema, sName;
1448     lcl_getTableNameComponents( _xTable, sCatalog, sSchema, sName );
1449 
1450     return composeTableNameForSelect( _rxConnection, sCatalog, sSchema, sName );
1451 }
1452 
1453 // -----------------------------------------------------------------------------
composeTableName(const Reference<XDatabaseMetaData> & _xMetaData,const Reference<XPropertySet> & _xTable,EComposeRule _eComposeRule,bool _bSuppressCatalog,bool _bSuppressSchema,bool _bQuote)1454 ::rtl::OUString composeTableName(const Reference<XDatabaseMetaData>& _xMetaData,
1455                                  const Reference<XPropertySet>& _xTable,
1456                                  EComposeRule _eComposeRule,
1457                                  bool _bSuppressCatalog,
1458                                  bool _bSuppressSchema,
1459                                  bool _bQuote )
1460 {
1461     ::rtl::OUString sCatalog, sSchema, sName;
1462     lcl_getTableNameComponents( _xTable, sCatalog, sSchema, sName );
1463 
1464     return impl_doComposeTableName(
1465             _xMetaData,
1466             _bSuppressCatalog ? ::rtl::OUString() : sCatalog,
1467             _bSuppressSchema ? ::rtl::OUString() : sSchema,
1468             sName,
1469             _bQuote,
1470             _eComposeRule
1471         );
1472 }
1473 // -----------------------------------------------------------------------------
getSearchColumnFlag(const Reference<XConnection> & _rxConn,sal_Int32 _nDataType)1474 sal_Int32 getSearchColumnFlag( const Reference< XConnection>& _rxConn,sal_Int32 _nDataType)
1475 {
1476     sal_Int32 nSearchFlag = 0;
1477     Reference<XResultSet> xSet = _rxConn->getMetaData()->getTypeInfo();
1478     if(xSet.is())
1479     {
1480         Reference<XRow> xRow(xSet,UNO_QUERY);
1481         while(xSet->next())
1482         {
1483             if(xRow->getInt(2) == _nDataType)
1484             {
1485                 nSearchFlag = xRow->getInt(9);
1486                 break;
1487             }
1488         }
1489     }
1490     return nSearchFlag;
1491 }
1492 
1493 // -----------------------------------------------------------------------------
createUniqueName(const Sequence<::rtl::OUString> & _rNames,const::rtl::OUString & _rBaseName,sal_Bool _bStartWithNumber)1494 ::rtl::OUString createUniqueName( const Sequence< ::rtl::OUString >& _rNames, const ::rtl::OUString& _rBaseName, sal_Bool _bStartWithNumber )
1495 {
1496     ::std::set< ::rtl::OUString > aUsedNames;
1497     ::std::copy(
1498         _rNames.getConstArray(),
1499         _rNames.getConstArray() + _rNames.getLength(),
1500         ::std::insert_iterator< ::std::set< ::rtl::OUString > >( aUsedNames, aUsedNames.end() )
1501     );
1502 
1503     ::rtl::OUString sName( _rBaseName );
1504     sal_Int32 nPos = 1;
1505     if ( _bStartWithNumber )
1506         sName += ::rtl::OUString::valueOf( nPos );
1507 
1508     while ( aUsedNames.find( sName ) != aUsedNames.end() )
1509     {
1510         sName = _rBaseName;
1511         sName += ::rtl::OUString::valueOf( ++nPos );
1512     }
1513     return sName;
1514 }
1515 
1516 // -----------------------------------------------------------------------------
createUniqueName(const Reference<XNameAccess> & _rxContainer,const::rtl::OUString & _rBaseName,sal_Bool _bStartWithNumber)1517 ::rtl::OUString createUniqueName(const Reference<XNameAccess>& _rxContainer,const ::rtl::OUString& _rBaseName,sal_Bool _bStartWithNumber)
1518 {
1519     Sequence< ::rtl::OUString > aElementNames;
1520 
1521     OSL_ENSURE( _rxContainer.is(), "createUniqueName: invalid container!" );
1522     if ( _rxContainer.is() )
1523         aElementNames = _rxContainer->getElementNames();
1524 
1525     return createUniqueName( aElementNames, _rBaseName, _bStartWithNumber );
1526 }
1527 
1528 // -----------------------------------------------------------------------------
showError(const SQLExceptionInfo & _rInfo,const Reference<XWindow> & _xParent,const Reference<XMultiServiceFactory> & _xFactory)1529 void showError(const SQLExceptionInfo& _rInfo,
1530                const Reference< XWindow>& _xParent,
1531                const Reference< XMultiServiceFactory >& _xFactory)
1532 {
1533     if (_rInfo.isValid())
1534     {
1535         try
1536         {
1537             Sequence< Any > aArgs(2);
1538             aArgs[0] <<= PropertyValue(::rtl::OUString::createFromAscii("SQLException"), 0, _rInfo.get(), PropertyState_DIRECT_VALUE);
1539             aArgs[1] <<= PropertyValue(::rtl::OUString::createFromAscii("ParentWindow"), 0, makeAny(_xParent), PropertyState_DIRECT_VALUE);
1540 
1541             static ::rtl::OUString s_sDialogServiceName = ::rtl::OUString::createFromAscii("com.sun.star.sdb.ErrorMessageDialog");
1542             Reference< XExecutableDialog > xErrorDialog(
1543                 _xFactory->createInstanceWithArguments(s_sDialogServiceName, aArgs), UNO_QUERY);
1544             if (xErrorDialog.is())
1545                 xErrorDialog->execute();
1546             else
1547             {
1548                 OSL_ENSURE(0,"dbtools::showError: no XExecutableDialog found!");
1549             }
1550         }
1551         catch(Exception&)
1552         {
1553             OSL_ENSURE(0,"showError: could not display the error message!");
1554         }
1555     }
1556 }
1557 
1558 // -------------------------------------------------------------------------
implUpdateObject(const Reference<XRowUpdate> & _rxUpdatedObject,const sal_Int32 _nColumnIndex,const Any & _rValue)1559 sal_Bool implUpdateObject(const Reference< XRowUpdate >& _rxUpdatedObject,
1560     const sal_Int32 _nColumnIndex, const Any& _rValue)
1561 {
1562     sal_Bool bSuccessfullyReRouted = sal_True;
1563     switch (_rValue.getValueTypeClass())
1564     {
1565         case TypeClass_ANY:
1566         {
1567             Any aInnerValue;
1568             _rValue >>= aInnerValue;
1569             bSuccessfullyReRouted = implUpdateObject(_rxUpdatedObject, _nColumnIndex, aInnerValue);
1570         }
1571         break;
1572 
1573         case TypeClass_VOID:
1574             _rxUpdatedObject->updateNull(_nColumnIndex);
1575             break;
1576 
1577         case TypeClass_STRING:
1578             _rxUpdatedObject->updateString(_nColumnIndex, *(rtl::OUString*)_rValue.getValue());
1579             break;
1580 
1581         case TypeClass_BOOLEAN:
1582             _rxUpdatedObject->updateBoolean(_nColumnIndex, *(sal_Bool *)_rValue.getValue());
1583             break;
1584 
1585         case TypeClass_BYTE:
1586             _rxUpdatedObject->updateByte(_nColumnIndex, *(sal_Int8 *)_rValue.getValue());
1587             break;
1588 
1589         case TypeClass_UNSIGNED_SHORT:
1590         case TypeClass_SHORT:
1591             _rxUpdatedObject->updateShort(_nColumnIndex, *(sal_Int16*)_rValue.getValue());
1592             break;
1593 
1594         case TypeClass_CHAR:
1595             _rxUpdatedObject->updateString(_nColumnIndex,::rtl::OUString((sal_Unicode *)_rValue.getValue(),1));
1596             break;
1597 
1598         case TypeClass_UNSIGNED_LONG:
1599         case TypeClass_LONG:
1600             _rxUpdatedObject->updateInt(_nColumnIndex, *(sal_Int32*)_rValue.getValue());
1601             break;
1602 
1603         case TypeClass_HYPER:
1604         {
1605             sal_Int64 nValue = 0;
1606             OSL_VERIFY( _rValue >>= nValue );
1607             _rxUpdatedObject->updateLong( _nColumnIndex, nValue );
1608         }
1609         break;
1610 
1611         case TypeClass_FLOAT:
1612             _rxUpdatedObject->updateFloat(_nColumnIndex, *(float*)_rValue.getValue());
1613             break;
1614 
1615         case TypeClass_DOUBLE:
1616             _rxUpdatedObject->updateDouble(_nColumnIndex, *(double*)_rValue.getValue());
1617             break;
1618 
1619         case TypeClass_SEQUENCE:
1620             if (_rValue.getValueType() == ::getCppuType((const Sequence< sal_Int8 > *)0))
1621                 _rxUpdatedObject->updateBytes(_nColumnIndex, *(Sequence<sal_Int8>*)_rValue.getValue());
1622             else
1623                 bSuccessfullyReRouted = sal_False;
1624             break;
1625         case TypeClass_STRUCT:
1626             if (_rValue.getValueType() == ::getCppuType((const DateTime*)0))
1627                 _rxUpdatedObject->updateTimestamp(_nColumnIndex, *(DateTime*)_rValue.getValue());
1628             else if (_rValue.getValueType() == ::getCppuType((const Date*)0))
1629                 _rxUpdatedObject->updateDate(_nColumnIndex, *(Date*)_rValue.getValue());
1630             else if (_rValue.getValueType() == ::getCppuType((const Time*)0))
1631                 _rxUpdatedObject->updateTime(_nColumnIndex, *(Time*)_rValue.getValue());
1632             else
1633                 bSuccessfullyReRouted = sal_False;
1634             break;
1635 
1636         case TypeClass_INTERFACE:
1637             if (_rValue.getValueType() == ::getCppuType(static_cast<Reference< XInputStream>*>(NULL)))
1638             {
1639                 Reference< XInputStream >  xStream;
1640                 _rValue >>= xStream;
1641                 _rxUpdatedObject->updateBinaryStream(_nColumnIndex, xStream, xStream->available());
1642                 break;
1643             }
1644             // run through
1645         default:
1646             bSuccessfullyReRouted = sal_False;
1647     }
1648 
1649     return bSuccessfullyReRouted;
1650 }
1651 // -------------------------------------------------------------------------
implSetObject(const Reference<XParameters> & _rxParameters,const sal_Int32 _nColumnIndex,const Any & _rValue)1652 sal_Bool implSetObject( const Reference< XParameters >& _rxParameters,
1653                         const sal_Int32 _nColumnIndex, const Any& _rValue)
1654 {
1655     sal_Bool bSuccessfullyReRouted = sal_True;
1656     switch (_rValue.getValueTypeClass())
1657     {
1658         case TypeClass_HYPER:
1659         {
1660             sal_Int64 nValue = 0;
1661             OSL_VERIFY( _rValue >>= nValue );
1662             _rxParameters->setLong( _nColumnIndex, nValue );
1663         }
1664         break;
1665 
1666         case TypeClass_ANY:
1667         {
1668             Any aInnerValue;
1669             _rValue >>= aInnerValue;
1670             bSuccessfullyReRouted = implSetObject(_rxParameters, _nColumnIndex, aInnerValue);
1671         }
1672         break;
1673 
1674         case TypeClass_VOID:
1675             _rxParameters->setNull(_nColumnIndex,DataType::VARCHAR);
1676             break;
1677 
1678         case TypeClass_STRING:
1679             _rxParameters->setString(_nColumnIndex, *(rtl::OUString*)_rValue.getValue());
1680             break;
1681 
1682         case TypeClass_BOOLEAN:
1683             _rxParameters->setBoolean(_nColumnIndex, *(sal_Bool *)_rValue.getValue());
1684             break;
1685 
1686         case TypeClass_BYTE:
1687             _rxParameters->setByte(_nColumnIndex, *(sal_Int8 *)_rValue.getValue());
1688             break;
1689 
1690         case TypeClass_UNSIGNED_SHORT:
1691         case TypeClass_SHORT:
1692             _rxParameters->setShort(_nColumnIndex, *(sal_Int16*)_rValue.getValue());
1693             break;
1694 
1695         case TypeClass_CHAR:
1696             _rxParameters->setString(_nColumnIndex, ::rtl::OUString((sal_Unicode *)_rValue.getValue(),1));
1697             break;
1698 
1699         case TypeClass_UNSIGNED_LONG:
1700         case TypeClass_LONG:
1701             _rxParameters->setInt(_nColumnIndex, *(sal_Int32*)_rValue.getValue());
1702             break;
1703 
1704         case TypeClass_FLOAT:
1705             _rxParameters->setFloat(_nColumnIndex, *(float*)_rValue.getValue());
1706             break;
1707 
1708         case TypeClass_DOUBLE:
1709             _rxParameters->setDouble(_nColumnIndex, *(double*)_rValue.getValue());
1710             break;
1711 
1712         case TypeClass_SEQUENCE:
1713             if (_rValue.getValueType() == ::getCppuType((const Sequence< sal_Int8 > *)0))
1714             {
1715                 _rxParameters->setBytes(_nColumnIndex, *(Sequence<sal_Int8>*)_rValue.getValue());
1716             }
1717             else
1718                 bSuccessfullyReRouted = sal_False;
1719             break;
1720         case TypeClass_STRUCT:
1721             if (_rValue.getValueType() == ::getCppuType((const DateTime*)0))
1722                 _rxParameters->setTimestamp(_nColumnIndex, *(DateTime*)_rValue.getValue());
1723             else if (_rValue.getValueType() == ::getCppuType((const Date*)0))
1724                 _rxParameters->setDate(_nColumnIndex, *(Date*)_rValue.getValue());
1725             else if (_rValue.getValueType() == ::getCppuType((const Time*)0))
1726                 _rxParameters->setTime(_nColumnIndex, *(Time*)_rValue.getValue());
1727             else
1728                 bSuccessfullyReRouted = sal_False;
1729             break;
1730 
1731         case TypeClass_INTERFACE:
1732             if (_rValue.getValueType() == ::getCppuType(static_cast<Reference< XInputStream>*>(NULL)))
1733             {
1734                 Reference< XInputStream >  xStream;
1735                 _rValue >>= xStream;
1736                 _rxParameters->setBinaryStream(_nColumnIndex, xStream, xStream->available());
1737                 break;
1738             }
1739             // run through
1740         default:
1741             bSuccessfullyReRouted = sal_False;
1742 
1743     }
1744 
1745     return bSuccessfullyReRouted;
1746 }
1747 
1748 //..................................................................
1749 namespace
1750 {
1751     class OParameterWrapper : public ::cppu::WeakImplHelper1< XIndexAccess >
1752     {
1753         ::std::bit_vector       m_aSet;
1754         Reference<XIndexAccess> m_xSource;
1755     public:
OParameterWrapper(const::std::bit_vector & _aSet,const Reference<XIndexAccess> & _xSource)1756         OParameterWrapper(const ::std::bit_vector& _aSet,const Reference<XIndexAccess>& _xSource) : m_aSet(_aSet),m_xSource(_xSource){}
1757     private:
1758         // ::com::sun::star::container::XElementAccess
getElementType()1759         virtual Type SAL_CALL getElementType()
1760         {
1761             return m_xSource->getElementType();
1762         }
hasElements()1763         virtual sal_Bool SAL_CALL hasElements(  )
1764         {
1765             if ( m_aSet.empty() )
1766                 return m_xSource->hasElements();
1767             return (::std::find(m_aSet.begin(),m_aSet.end(),false) != m_aSet.end());
1768         }
1769         // ::com::sun::star::container::XIndexAccess
getCount()1770         virtual sal_Int32 SAL_CALL getCount(  )
1771         {
1772             if ( m_aSet.empty() )
1773                 return m_xSource->getCount();
1774             return std_bitset_count(m_aSet.begin(),m_aSet.end(),false);
1775         }
getByIndex(sal_Int32 Index)1776         virtual Any SAL_CALL getByIndex( sal_Int32 Index )
1777         {
1778             if ( m_aSet.empty() )
1779                 return m_xSource->getByIndex(Index);
1780             if ( m_aSet.size() < (size_t)Index )
1781                 throw IndexOutOfBoundsException();
1782 
1783             ::std::bit_vector::iterator aIter = m_aSet.begin();
1784             ::std::bit_vector::iterator aEnd = m_aSet.end();
1785             sal_Int32 i = 0;
1786             sal_Int32 nParamPos = -1;
1787             for(; aIter != aEnd && i <= Index; ++aIter)
1788             {
1789                 ++nParamPos;
1790                 if ( !*aIter )
1791                 {
1792                     ++i;
1793                 }
1794             }
1795             return m_xSource->getByIndex(nParamPos);
1796         }
1797     };
1798 }
1799 
1800 // -----------------------------------------------------------------------------
askForParameters(const Reference<XSingleSelectQueryComposer> & _xComposer,const Reference<XParameters> & _xParameters,const Reference<XConnection> & _xConnection,const Reference<XInteractionHandler> & _rxHandler,const::std::bit_vector & _aParametersSet)1801 void askForParameters(const Reference< XSingleSelectQueryComposer >& _xComposer,
1802                       const Reference<XParameters>& _xParameters,
1803                       const Reference< XConnection>& _xConnection,
1804                       const Reference< XInteractionHandler >& _rxHandler,
1805                       const ::std::bit_vector& _aParametersSet)
1806 {
1807     OSL_ENSURE(_xComposer.is(),"dbtools::askForParameters XSQLQueryComposer is null!");
1808     OSL_ENSURE(_xParameters.is(),"dbtools::askForParameters XParameters is null!");
1809     OSL_ENSURE(_xConnection.is(),"dbtools::askForParameters XConnection is null!");
1810     OSL_ENSURE(_rxHandler.is(),"dbtools::askForParameters XInteractionHandler is null!");
1811 
1812     // we have to set this here again because getCurrentSettingsComposer can force a setpropertyvalue
1813     Reference<XParametersSupplier>  xParameters = Reference<XParametersSupplier> (_xComposer, UNO_QUERY);
1814 
1815     Reference<XIndexAccess>  xParamsAsIndicies = xParameters.is() ? xParameters->getParameters() : Reference<XIndexAccess>();
1816     Reference<XNameAccess>   xParamsAsNames(xParamsAsIndicies, UNO_QUERY);
1817     sal_Int32 nParamCount = xParamsAsIndicies.is() ? xParamsAsIndicies->getCount() : 0;
1818     ::std::bit_vector aNewParameterSet( _aParametersSet );
1819     if ( nParamCount || std_bitset_count(aNewParameterSet.begin(),aNewParameterSet.end(),true) != nParamCount )
1820     {
1821         static const ::rtl::OUString PROPERTY_NAME(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME));
1822         aNewParameterSet.resize(nParamCount ,false);
1823         typedef ::std::map< ::rtl::OUString, ::std::vector<sal_Int32> > TParameterPositions;
1824         TParameterPositions aParameterNames;
1825         for(sal_Int32 i = 0; i < nParamCount; ++i)
1826         {
1827             Reference<XPropertySet> xParam(xParamsAsIndicies->getByIndex(i),UNO_QUERY);
1828             ::rtl::OUString sName;
1829             xParam->getPropertyValue(PROPERTY_NAME) >>= sName;
1830 
1831             TParameterPositions::iterator aFind = aParameterNames.find(sName);
1832             if ( aFind != aParameterNames.end() )
1833                 aNewParameterSet[i] = true;
1834             aParameterNames[sName].push_back(i+1);
1835         }
1836         // build an interaction request
1837         // two continuations (Ok and Cancel)
1838         OInteractionAbort* pAbort = new OInteractionAbort;
1839         OParameterContinuation* pParams = new OParameterContinuation;
1840         // the request
1841         ParametersRequest aRequest;
1842         Reference<XIndexAccess> xWrappedParameters = new OParameterWrapper(aNewParameterSet,xParamsAsIndicies);
1843         aRequest.Parameters = xWrappedParameters;
1844         aRequest.Connection = _xConnection;
1845         OInteractionRequest* pRequest = new OInteractionRequest(makeAny(aRequest));
1846         Reference< XInteractionRequest > xRequest(pRequest);
1847         // some knittings
1848         pRequest->addContinuation(pAbort);
1849         pRequest->addContinuation(pParams);
1850 
1851         // execute the request
1852         _rxHandler->handle(xRequest);
1853 
1854         if (!pParams->wasSelected())
1855         {
1856             // canceled by the user (i.e. (s)he canceled the dialog)
1857             RowSetVetoException e;
1858             e.ErrorCode = ParameterInteractionCancelled;
1859             throw e;
1860         }
1861 
1862         // now transfer the values from the continuation object to the parameter columns
1863         Sequence< PropertyValue > aFinalValues = pParams->getValues();
1864         const PropertyValue* pFinalValues = aFinalValues.getConstArray();
1865         for (sal_Int32 i=0; i<aFinalValues.getLength(); ++i, ++pFinalValues)
1866         {
1867             Reference< XPropertySet > xParamColumn(xWrappedParameters->getByIndex(i),UNO_QUERY);
1868             if (xParamColumn.is())
1869             {
1870                 ::rtl::OUString sName;
1871                 xParamColumn->getPropertyValue(PROPERTY_NAME) >>= sName;
1872                 OSL_ENSURE(sName.equals(pFinalValues->Name), "::dbaui::askForParameters: inconsistent parameter names!");
1873 
1874                 // determine the field type and ...
1875                 sal_Int32 nParamType = 0;
1876                 xParamColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)) >>= nParamType;
1877                 // ... the scale of the parameter column
1878                 sal_Int32 nScale = 0;
1879                 if (hasProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE), xParamColumn))
1880                     xParamColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE)) >>= nScale;
1881                     // (the index of the parameters is one-based)
1882                 TParameterPositions::iterator aFind = aParameterNames.find(pFinalValues->Name);
1883                 ::std::vector<sal_Int32>::iterator aIterPos = aFind->second.begin();
1884                 ::std::vector<sal_Int32>::iterator aEndPos = aFind->second.end();
1885                 for(;aIterPos != aEndPos;++aIterPos)
1886                 {
1887                     if ( _aParametersSet.empty() || !_aParametersSet[(*aIterPos)-1] )
1888                     {
1889                         _xParameters->setObjectWithInfo(*aIterPos, pFinalValues->Value, nParamType, nScale);
1890                     }
1891                 }
1892             }
1893         }
1894     }
1895 }
1896 // -----------------------------------------------------------------------------
setObjectWithInfo(const Reference<XParameters> & _xParams,sal_Int32 parameterIndex,const Any & x,sal_Int32 sqlType,sal_Int32 scale)1897 void setObjectWithInfo(const Reference<XParameters>& _xParams,
1898                        sal_Int32 parameterIndex,
1899                        const Any& x,
1900                        sal_Int32 sqlType,
1901                        sal_Int32 scale)
1902 {
1903     ORowSetValue aVal;
1904     aVal.fill(x);
1905     setObjectWithInfo(_xParams,parameterIndex,aVal,sqlType,scale);
1906 }
1907 // -----------------------------------------------------------------------------
setObjectWithInfo(const Reference<XParameters> & _xParams,sal_Int32 parameterIndex,const::connectivity::ORowSetValue & _rValue,sal_Int32 sqlType,sal_Int32 scale)1908 void setObjectWithInfo(const Reference<XParameters>& _xParams,
1909                        sal_Int32 parameterIndex,
1910                        const ::connectivity::ORowSetValue& _rValue,
1911                        sal_Int32 sqlType,
1912                        sal_Int32 scale)
1913 {
1914     if ( _rValue.isNull() )
1915         _xParams->setNull(parameterIndex,sqlType);
1916     else
1917     {
1918         switch(sqlType)
1919         {
1920             case DataType::DECIMAL:
1921             case DataType::NUMERIC:
1922                 _xParams->setObjectWithInfo(parameterIndex,_rValue.makeAny(),sqlType,scale);
1923                 break;
1924             case DataType::CHAR:
1925             case DataType::VARCHAR:
1926             case DataType::LONGVARCHAR:
1927                 _xParams->setString(parameterIndex,_rValue);
1928                 break;
1929             case DataType::CLOB:
1930                 {
1931                     Any x(_rValue.makeAny());
1932                     ::rtl::OUString sValue;
1933                     if ( x >>= sValue )
1934                         _xParams->setString(parameterIndex,sValue);
1935                     else
1936                     {
1937                         Reference< XClob > xClob;
1938                         if(x >>= xClob)
1939                             _xParams->setClob(parameterIndex,xClob);
1940                         else
1941                         {
1942                             Reference< ::com::sun::star::io::XInputStream > xStream;
1943                             if(x >>= xStream)
1944                                 _xParams->setCharacterStream(parameterIndex,xStream,xStream->available());
1945                         }
1946                     }
1947                 }
1948                 break;
1949             case DataType::BIGINT:
1950                 if ( _rValue.isSigned() )
1951                     _xParams->setLong(parameterIndex,_rValue);
1952                 else
1953                     _xParams->setString(parameterIndex,_rValue);
1954                 break;
1955 
1956             case DataType::FLOAT:
1957                 _xParams->setFloat(parameterIndex,_rValue);
1958                 break;
1959             case DataType::REAL:
1960             case DataType::DOUBLE:
1961                 _xParams->setDouble(parameterIndex,_rValue);
1962                 break;
1963             case DataType::DATE:
1964                 _xParams->setDate(parameterIndex,_rValue);
1965                 break;
1966             case DataType::TIME:
1967                 _xParams->setTime(parameterIndex,_rValue);
1968                 break;
1969             case DataType::TIMESTAMP:
1970                 _xParams->setTimestamp(parameterIndex,_rValue);
1971                 break;
1972             case DataType::BINARY:
1973             case DataType::VARBINARY:
1974             case DataType::LONGVARBINARY:
1975             case DataType::BLOB:
1976                 {
1977                     Any x(_rValue.makeAny());
1978                     Sequence< sal_Int8> aBytes;
1979                     if(x >>= aBytes)
1980                         _xParams->setBytes(parameterIndex,aBytes);
1981                     else
1982                     {
1983                         Reference< XBlob > xBlob;
1984                         if(x >>= xBlob)
1985                             _xParams->setBlob(parameterIndex,xBlob);
1986                         else
1987                         {
1988                             Reference< XClob > xClob;
1989                             if(x >>= xClob)
1990                                 _xParams->setClob(parameterIndex,xClob);
1991                             else
1992                             {
1993                                 Reference< ::com::sun::star::io::XInputStream > xBinStream;
1994                                 if(x >>= xBinStream)
1995                                     _xParams->setBinaryStream(parameterIndex,xBinStream,xBinStream->available());
1996                             }
1997                         }
1998                     }
1999                 }
2000                 break;
2001             case DataType::BIT:
2002             case DataType::BOOLEAN:
2003                 _xParams->setBoolean(parameterIndex,_rValue);
2004                 break;
2005             case DataType::TINYINT:
2006                 if ( _rValue.isSigned() )
2007                     _xParams->setByte(parameterIndex,_rValue);
2008                 else
2009                     _xParams->setShort(parameterIndex,_rValue);
2010                 break;
2011             case DataType::SMALLINT:
2012                 if ( _rValue.isSigned() )
2013                     _xParams->setShort(parameterIndex,_rValue);
2014                 else
2015                     _xParams->setInt(parameterIndex,_rValue);
2016                 break;
2017             case DataType::INTEGER:
2018                 if ( _rValue.isSigned() )
2019                     _xParams->setInt(parameterIndex,_rValue);
2020                 else
2021                     _xParams->setLong(parameterIndex,_rValue);
2022                 break;
2023             default:
2024                 {
2025                     ::connectivity::SharedResources aResources;
2026                     const ::rtl::OUString sError( aResources.getResourceStringWithSubstitution(
2027                             STR_UNKNOWN_PARA_TYPE,
2028                             "$position$", ::rtl::OUString::valueOf(parameterIndex)
2029                          ) );
2030                     ::dbtools::throwGenericSQLException(sError,NULL);
2031                 }
2032         }
2033     }
2034 }
2035 
2036 // --------------------------------------------------------------------
getBoleanComparisonPredicate(const::rtl::OUString & _rExpression,const sal_Bool _bValue,const sal_Int32 _nBooleanComparisonMode,::rtl::OUStringBuffer & _out_rSQLPredicate)2037 void getBoleanComparisonPredicate( const ::rtl::OUString& _rExpression, const sal_Bool _bValue, const sal_Int32 _nBooleanComparisonMode,
2038     ::rtl::OUStringBuffer& _out_rSQLPredicate )
2039 {
2040     switch ( _nBooleanComparisonMode )
2041     {
2042     case BooleanComparisonMode::IS_LITERAL:
2043         _out_rSQLPredicate.append( _rExpression );
2044         if ( _bValue )
2045             _out_rSQLPredicate.appendAscii( " IS TRUE" );
2046         else
2047             _out_rSQLPredicate.appendAscii( " IS FALSE" );
2048         break;
2049 
2050     case BooleanComparisonMode::EQUAL_LITERAL:
2051         _out_rSQLPredicate.append( _rExpression );
2052         _out_rSQLPredicate.appendAscii( _bValue ? " = TRUE" : " = FALSE" );
2053         break;
2054 
2055     case BooleanComparisonMode::ACCESS_COMPAT:
2056         if ( _bValue )
2057         {
2058             _out_rSQLPredicate.appendAscii( " NOT ( ( " );
2059             _out_rSQLPredicate.append( _rExpression );
2060             _out_rSQLPredicate.appendAscii( " = 0 ) OR ( " );
2061             _out_rSQLPredicate.append( _rExpression );
2062             _out_rSQLPredicate.appendAscii( " IS NULL ) )" );
2063         }
2064         else
2065         {
2066             _out_rSQLPredicate.append( _rExpression );
2067             _out_rSQLPredicate.appendAscii( " = 0" );
2068         }
2069         break;
2070 
2071     case BooleanComparisonMode::EQUAL_INTEGER:
2072         // fall through
2073     default:
2074         _out_rSQLPredicate.append( _rExpression );
2075         _out_rSQLPredicate.appendAscii( _bValue ? " = 1" : " = 0" );
2076         break;
2077     }
2078 }
2079 
2080 //.........................................................................
2081 }   // namespace dbtools
2082 //.........................................................................
2083 
2084 //.........................................................................
2085 namespace connectivity
2086 {
2087 //.........................................................................
2088 
release(oslInterlockedCount & _refCount,::cppu::OBroadcastHelper & rBHelper,Reference<XInterface> & _xInterface,::com::sun::star::lang::XComponent * _pObject)2089 void release(oslInterlockedCount& _refCount,
2090              ::cppu::OBroadcastHelper& rBHelper,
2091              Reference< XInterface >& _xInterface,
2092              ::com::sun::star::lang::XComponent* _pObject)
2093 {
2094     if (osl_decrementInterlockedCount( &_refCount ) == 0)
2095     {
2096         osl_incrementInterlockedCount( &_refCount );
2097 
2098         if (!rBHelper.bDisposed && !rBHelper.bInDispose)
2099         {
2100             // remember the parent
2101             Reference< XInterface > xParent;
2102             {
2103                 ::osl::MutexGuard aGuard( rBHelper.rMutex );
2104                 xParent = _xInterface;
2105                 _xInterface = NULL;
2106             }
2107 
2108             // First dispose
2109             _pObject->dispose();
2110 
2111             // only the alive ref holds the object
2112             OSL_ASSERT( _refCount == 1 );
2113 
2114             // release the parent in the ~
2115             if (xParent.is())
2116             {
2117                 ::osl::MutexGuard aGuard( rBHelper.rMutex );
2118                 _xInterface = xParent;
2119             }
2120 
2121 //                  // destroy the object if xHoldAlive decrement the refcount to 0
2122 //                  m_pDerivedImplementation->WEAK::release();
2123         }
2124     }
2125     else
2126         osl_incrementInterlockedCount( &_refCount );
2127 }
2128 
checkDisposed(sal_Bool _bThrow)2129 void checkDisposed(sal_Bool _bThrow)
2130 {
2131     if (_bThrow)
2132         throw DisposedException();
2133 
2134 }
2135 // -------------------------------------------------------------------------
find(OSQLColumns::Vector::const_iterator __first,OSQLColumns::Vector::const_iterator __last,const::rtl::OUString & _rVal,const::comphelper::UStringMixEqual & _rCase)2136     OSQLColumns::Vector::const_iterator find(   OSQLColumns::Vector::const_iterator __first,
2137                                         OSQLColumns::Vector::const_iterator __last,
2138                                         const ::rtl::OUString& _rVal,
2139                                         const ::comphelper::UStringMixEqual& _rCase)
2140     {
2141         ::rtl::OUString sName = OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME);
2142         return find(__first,__last,sName,_rVal,_rCase);
2143     }
2144     // -------------------------------------------------------------------------
findRealName(OSQLColumns::Vector::const_iterator __first,OSQLColumns::Vector::const_iterator __last,const::rtl::OUString & _rVal,const::comphelper::UStringMixEqual & _rCase)2145     OSQLColumns::Vector::const_iterator findRealName(   OSQLColumns::Vector::const_iterator __first,
2146                                         OSQLColumns::Vector::const_iterator __last,
2147                                         const ::rtl::OUString& _rVal,
2148                                         const ::comphelper::UStringMixEqual& _rCase)
2149     {
2150         ::rtl::OUString sRealName = OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_REALNAME);
2151         return find(__first,__last,sRealName,_rVal,_rCase);
2152     }
2153     // -------------------------------------------------------------------------
find(OSQLColumns::Vector::const_iterator __first,OSQLColumns::Vector::const_iterator __last,const::rtl::OUString & _rProp,const::rtl::OUString & _rVal,const::comphelper::UStringMixEqual & _rCase)2154     OSQLColumns::Vector::const_iterator find(   OSQLColumns::Vector::const_iterator __first,
2155                                         OSQLColumns::Vector::const_iterator __last,
2156                                         const ::rtl::OUString& _rProp,
2157                                         const ::rtl::OUString& _rVal,
2158                                         const ::comphelper::UStringMixEqual& _rCase)
2159     {
2160         while (__first != __last && !_rCase(getString((*__first)->getPropertyValue(_rProp)),_rVal))
2161             ++__first;
2162         return __first;
2163     }
2164 
2165 // -----------------------------------------------------------------------------
2166 } //namespace connectivity
2167 // -----------------------------------------------------------------------------
2168