Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / connectivity / source / commontools / dbtools.cxx
blob514b026b26c97b092df60c68f3cd0157dd759440
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <connectivity/CommonTools.hxx>
21 #include <TConnection.hxx>
22 #include <connectivity/ParameterCont.hxx>
24 #include <com/sun/star/awt/XWindow.hpp>
25 #include <com/sun/star/beans/NamedValue.hpp>
26 #include <com/sun/star/beans/PropertyAttribute.hpp>
27 #include <com/sun/star/container/XChild.hpp>
28 #include <com/sun/star/form/FormComponentType.hpp>
29 #include <com/sun/star/io/XInputStream.hpp>
30 #include <com/sun/star/lang/DisposedException.hpp>
31 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
32 #include <com/sun/star/lang/XInitialization.hpp>
33 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
34 #include <com/sun/star/sdb/DatabaseContext.hpp>
35 #include <com/sun/star/sdb/BooleanComparisonMode.hpp>
36 #include <com/sun/star/sdb/CommandType.hpp>
37 #include <com/sun/star/sdb/ErrorMessageDialog.hpp>
38 #include <com/sun/star/sdb/ParametersRequest.hpp>
39 #include <com/sun/star/sdb/RowSetVetoException.hpp>
40 #include <com/sun/star/sdb/SQLContext.hpp>
41 #include <com/sun/star/sdb/XCompletedConnection.hpp>
42 #include <com/sun/star/sdb/XInteractionSupplyParameters.hpp>
43 #include <com/sun/star/sdb/XOfficeDatabaseDocument.hpp>
44 #include <com/sun/star/sdb/XParametersSupplier.hpp>
45 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
46 #include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
47 #include <com/sun/star/sdbc/ConnectionPool.hpp>
48 #include <com/sun/star/sdbc/DataType.hpp>
49 #include <com/sun/star/sdbc/XConnection.hpp>
50 #include <com/sun/star/sdbc/XDataSource.hpp>
51 #include <com/sun/star/sdbc/XDriverManager.hpp>
52 #include <com/sun/star/sdbc/XParameters.hpp>
53 #include <com/sun/star/sdbc/XRow.hpp>
54 #include <com/sun/star/sdbc/XRowSet.hpp>
55 #include <com/sun/star/sdbc/XRowUpdate.hpp>
56 #include <com/sun/star/sdbcx/KeyType.hpp>
57 #include <com/sun/star/sdbcx/Privilege.hpp>
58 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
59 #include <com/sun/star/sdbcx/XKeysSupplier.hpp>
60 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
61 #include <com/sun/star/task/InteractionHandler.hpp>
62 #include <com/sun/star/task/XInteractionRequest.hpp>
63 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
64 #include <com/sun/star/uno/XNamingService.hpp>
65 #include <com/sun/star/util/NumberFormat.hpp>
66 #include <com/sun/star/util/NumberFormatsSupplier.hpp>
67 #include <com/sun/star/util/XNumberFormatTypes.hpp>
69 #include <comphelper/extract.hxx>
70 #include <comphelper/interaction.hxx>
71 #include <comphelper/property.hxx>
72 #include <comphelper/propertysequence.hxx>
73 #include <comphelper/types.hxx>
74 #include <connectivity/conncleanup.hxx>
75 #include <connectivity/dbconversion.hxx>
76 #include <connectivity/dbexception.hxx>
77 #include <connectivity/dbtools.hxx>
78 #include <connectivity/statementcomposer.hxx>
79 #include <o3tl/any.hxx>
80 #include <osl/diagnose.h>
81 #include <rtl/ustrbuf.hxx>
82 #include <sal/log.hxx>
83 #include <tools/diagnose_ex.h>
84 #include <tools/stream.hxx>
85 #include <cppuhelper/implbase.hxx>
86 #include <strings.hrc>
87 #include <resource/sharedresources.hxx>
89 #include <algorithm>
90 #include <iterator>
91 #include <set>
93 using namespace ::comphelper;
94 using namespace ::com::sun::star::uno;
95 using namespace ::com::sun::star::io;
96 using namespace ::com::sun::star::awt;
97 using namespace ::com::sun::star::ui::dialogs;
98 using namespace ::com::sun::star::util;
99 using namespace ::com::sun::star::lang;
100 using namespace ::com::sun::star::beans;
101 using namespace ::com::sun::star::container;
102 using namespace ::com::sun::star::sdb;
103 using namespace ::com::sun::star::sdbc;
104 using namespace ::com::sun::star::sdbcx;
105 using namespace ::com::sun::star::task;
106 using namespace ::com::sun::star::form;
107 using namespace connectivity;
109 namespace dbtools
112 namespace
114 typedef sal_Bool (SAL_CALL XDatabaseMetaData::*FMetaDataSupport)();
117 sal_Int32 getDefaultNumberFormat(const Reference< XPropertySet >& _xColumn,
118 const Reference< XNumberFormatTypes >& _xTypes,
119 const Locale& _rLocale)
121 OSL_ENSURE(_xTypes.is() && _xColumn.is(), "dbtools::getDefaultNumberFormat: invalid arg !");
122 if (!_xTypes.is() || !_xColumn.is())
123 return NumberFormat::UNDEFINED;
125 sal_Int32 nDataType = 0;
126 sal_Int32 nScale = 0;
129 // determine the datatype of the column
130 _xColumn->getPropertyValue("Type") >>= nDataType;
132 if (DataType::NUMERIC == nDataType || DataType::DECIMAL == nDataType)
133 _xColumn->getPropertyValue("Scale") >>= nScale;
135 catch (Exception&)
137 return NumberFormat::UNDEFINED;
139 return getDefaultNumberFormat(nDataType,
140 nScale,
141 ::cppu::any2bool(_xColumn->getPropertyValue("IsCurrency")),
142 _xTypes,
143 _rLocale);
146 sal_Int32 getDefaultNumberFormat(sal_Int32 _nDataType,
147 sal_Int32 _nScale,
148 bool _bIsCurrency,
149 const Reference< XNumberFormatTypes >& _xTypes,
150 const Locale& _rLocale)
152 OSL_ENSURE(_xTypes.is() , "dbtools::getDefaultNumberFormat: invalid arg !");
153 if (!_xTypes.is())
154 return NumberFormat::UNDEFINED;
156 sal_Int32 nFormat = 0;
157 sal_Int32 nNumberType = _bIsCurrency ? NumberFormat::CURRENCY : NumberFormat::NUMBER;
158 switch (_nDataType)
160 case DataType::BIT:
161 case DataType::BOOLEAN:
162 nFormat = _xTypes->getStandardFormat(NumberFormat::LOGICAL, _rLocale);
163 break;
164 case DataType::TINYINT:
165 case DataType::SMALLINT:
166 case DataType::INTEGER:
167 case DataType::BIGINT:
168 case DataType::FLOAT:
169 case DataType::REAL:
170 case DataType::DOUBLE:
171 case DataType::NUMERIC:
172 case DataType::DECIMAL:
176 nFormat = _xTypes->getStandardFormat(static_cast<sal_Int16>(nNumberType), _rLocale);
177 if(_nScale > 0)
179 // generate a new format if necessary
180 Reference< XNumberFormats > xFormats(_xTypes, UNO_QUERY);
181 OUString sNewFormat = xFormats->generateFormat( 0, _rLocale, false, false, static_cast<sal_Int16>(_nScale), 1);
183 // and add it to the formatter if necessary
184 nFormat = xFormats->queryKey(sNewFormat, _rLocale, false);
185 if (nFormat == sal_Int32(-1))
186 nFormat = xFormats->addNew(sNewFormat, _rLocale);
189 catch (Exception&)
191 nFormat = _xTypes->getStandardFormat(static_cast<sal_Int16>(nNumberType), _rLocale);
193 } break;
194 case DataType::CHAR:
195 case DataType::VARCHAR:
196 case DataType::LONGVARCHAR:
197 case DataType::CLOB:
198 nFormat = _xTypes->getStandardFormat(NumberFormat::TEXT, _rLocale);
199 break;
200 case DataType::DATE:
201 nFormat = _xTypes->getStandardFormat(NumberFormat::DATE, _rLocale);
202 break;
203 case DataType::TIME:
204 nFormat = _xTypes->getStandardFormat(NumberFormat::TIME, _rLocale);
205 break;
206 case DataType::TIMESTAMP:
207 nFormat = _xTypes->getStandardFormat(NumberFormat::DATETIME, _rLocale);
208 break;
209 case DataType::BINARY:
210 case DataType::VARBINARY:
211 case DataType::LONGVARBINARY:
212 case DataType::SQLNULL:
213 case DataType::OTHER:
214 case DataType::OBJECT:
215 case DataType::DISTINCT:
216 case DataType::STRUCT:
217 case DataType::ARRAY:
218 case DataType::BLOB:
219 case DataType::REF:
220 default:
221 nFormat = _xTypes->getStandardFormat(NumberFormat::UNDEFINED, _rLocale);
223 return nFormat;
226 static Reference< XConnection> findConnection(const Reference< XInterface >& xParent)
228 Reference< XConnection> xConnection(xParent, UNO_QUERY);
229 if (!xConnection.is())
231 Reference< XChild> xChild(xParent, UNO_QUERY);
232 if (xChild.is())
233 xConnection = findConnection(xChild->getParent());
235 return xConnection;
238 static Reference< XDataSource> getDataSource_allowException(
239 const OUString& _rsTitleOrPath,
240 const Reference< XComponentContext >& _rxContext )
242 ENSURE_OR_RETURN( !_rsTitleOrPath.isEmpty(), "getDataSource_allowException: invalid arg !", nullptr );
244 Reference< XDatabaseContext> xDatabaseContext = DatabaseContext::create(_rxContext);
246 return Reference< XDataSource >( xDatabaseContext->getByName( _rsTitleOrPath ), UNO_QUERY );
249 Reference< XDataSource > getDataSource(
250 const OUString& _rsTitleOrPath,
251 const Reference< XComponentContext >& _rxContext )
253 Reference< XDataSource > xDS;
256 xDS = getDataSource_allowException( _rsTitleOrPath, _rxContext );
258 catch( const Exception& )
260 DBG_UNHANDLED_EXCEPTION("connectivity.commontools");
263 return xDS;
266 static Reference< XConnection > getConnection_allowException(
267 const OUString& _rsTitleOrPath,
268 const OUString& _rsUser,
269 const OUString& _rsPwd,
270 const Reference< XComponentContext>& _rxContext,
271 const Reference< XWindow >& _rxParent)
273 Reference< XDataSource> xDataSource( getDataSource_allowException(_rsTitleOrPath, _rxContext) );
274 Reference<XConnection> xConnection;
275 if (xDataSource.is())
278 //set ParentWindow for dialog, but just for the duration of this
279 //call, undo at end of scope
280 Reference<XInitialization> xIni(xDataSource, UNO_QUERY);
281 if (xIni.is())
283 Sequence< Any > aArgs(1);
284 NamedValue aParam( "ParentWindow", makeAny(_rxParent) );
285 aArgs[0] <<= aParam;
286 xIni->initialize(aArgs);
289 // do it with interaction handler
290 if(_rsUser.isEmpty() || _rsPwd.isEmpty())
292 Reference<XPropertySet> xProp(xDataSource,UNO_QUERY);
293 OUString sPwd, sUser;
294 bool bPwdReq = false;
297 xProp->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PASSWORD)) >>= sPwd;
298 bPwdReq = ::cppu::any2bool(xProp->getPropertyValue("IsPasswordRequired"));
299 xProp->getPropertyValue("User") >>= sUser;
301 catch(Exception&)
303 OSL_FAIL("dbtools::getConnection: error while retrieving data source properties!");
305 if(bPwdReq && sPwd.isEmpty())
306 { // password required, but empty -> connect using an interaction handler
307 Reference<XCompletedConnection> xConnectionCompletion(xProp, UNO_QUERY);
308 if (xConnectionCompletion.is())
309 { // instantiate the default SDB interaction handler
310 Reference< XInteractionHandler > xHandler =
311 InteractionHandler::createWithParent(_rxContext, _rxParent);
312 xConnection = xConnectionCompletion->connectWithCompletion(xHandler);
315 else
316 xConnection = xDataSource->getConnection(sUser, sPwd);
318 if(!xConnection.is()) // try to get one if not already have one, just to make sure
319 xConnection = xDataSource->getConnection(_rsUser, _rsPwd);
321 if (xIni.is())
323 Sequence< Any > aArgs(1);
324 NamedValue aParam( "ParentWindow", makeAny(Reference<XWindow>()) );
325 aArgs[0] <<= aParam;
326 xIni->initialize(aArgs);
330 return xConnection;
333 Reference< XConnection> getConnection_withFeedback(const OUString& _rDataSourceName,
334 const OUString& _rUser, const OUString& _rPwd, const Reference< XComponentContext>& _rxContext,
335 const Reference< XWindow >& _rxParent)
337 Reference< XConnection > xReturn;
340 xReturn = getConnection_allowException(_rDataSourceName, _rUser, _rPwd, _rxContext, _rxParent);
342 catch(SQLException&)
344 // allowed to pass
345 throw;
347 catch(Exception&)
349 OSL_FAIL("::dbtools::getConnection_withFeedback: unexpected (non-SQL) exception caught!");
351 return xReturn;
354 Reference< XConnection> getConnection(const Reference< XRowSet>& _rxRowSet)
356 Reference< XConnection> xReturn;
357 Reference< XPropertySet> xRowSetProps(_rxRowSet, UNO_QUERY);
358 if (xRowSetProps.is())
359 xRowSetProps->getPropertyValue("ActiveConnection") >>= xReturn;
360 return xReturn;
363 // helper function which allows to implement both the connectRowset and the ensureRowSetConnection semantics
364 // if connectRowset (which is deprecated) is removed, this function and one of its parameters are
365 // not needed anymore, the whole implementation can be moved into ensureRowSetConnection then)
366 static SharedConnection lcl_connectRowSet(const Reference< XRowSet>& _rxRowSet, const Reference< XComponentContext >& _rxContext,
367 bool _bAttachAutoDisposer, const Reference< XWindow >& _rxParent)
369 SharedConnection xConnection;
373 Reference< XPropertySet> xRowSetProps(_rxRowSet, UNO_QUERY);
374 if ( !xRowSetProps.is() )
375 break;
377 // 1. already connected?
378 Reference< XConnection > xExistingConn(
379 xRowSetProps->getPropertyValue("ActiveConnection"),
380 UNO_QUERY );
382 if ( xExistingConn.is()
383 // 2. embedded in a database?
384 || isEmbeddedInDatabase( _rxRowSet, xExistingConn )
385 // 3. is there a connection in the parent hierarchy?
386 || ( xExistingConn = findConnection( _rxRowSet ) ).is()
389 xRowSetProps->setPropertyValue("ActiveConnection", makeAny( xExistingConn ) );
390 // no auto disposer needed, since we did not create the connection
392 xConnection.reset( xExistingConn, SharedConnection::NoTakeOwnership );
393 break;
396 // build a connection with its current settings (4. data source name, or 5. URL)
398 const OUString sUserProp( "User" );
399 OUString sDataSourceName;
400 xRowSetProps->getPropertyValue("DataSourceName") >>= sDataSourceName;
401 OUString sURL;
402 xRowSetProps->getPropertyValue("URL") >>= sURL;
404 Reference< XConnection > xPureConnection;
405 if (!sDataSourceName.isEmpty())
406 { // the row set's data source property is set
407 // -> try to connect, get user and pwd setting for that
408 OUString sUser, sPwd;
410 if (hasProperty(sUserProp, xRowSetProps))
411 xRowSetProps->getPropertyValue(sUserProp) >>= sUser;
412 if (hasProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PASSWORD), xRowSetProps))
413 xRowSetProps->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PASSWORD)) >>= sPwd;
415 xPureConnection = getConnection_allowException( sDataSourceName, sUser, sPwd, _rxContext, _rxParent );
417 else if (!sURL.isEmpty())
418 { // the row set has no data source, but a connection url set
419 // -> try to connection with that url
420 Reference< XConnectionPool > xDriverManager;
421 try {
422 xDriverManager = ConnectionPool::create( _rxContext );
423 } catch( const Exception& ) { }
424 if (xDriverManager.is())
426 OUString sUser, sPwd;
427 if (hasProperty(sUserProp, xRowSetProps))
428 xRowSetProps->getPropertyValue(sUserProp) >>= sUser;
429 if (hasProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PASSWORD), xRowSetProps))
430 xRowSetProps->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PASSWORD)) >>= sPwd;
431 if (!sUser.isEmpty())
432 { // use user and pwd together with the url
433 auto aInfo(::comphelper::InitPropertySequence({
434 { "user", makeAny(sUser) },
435 { "password", makeAny(sPwd) }
436 }));
437 xPureConnection = xDriverManager->getConnectionWithInfo( sURL, aInfo );
439 else
440 // just use the url
441 xPureConnection = xDriverManager->getConnection( sURL );
444 xConnection.reset(
445 xPureConnection,
446 _bAttachAutoDisposer ? SharedConnection::NoTakeOwnership : SharedConnection::TakeOwnership
447 /* take ownership if and only if we're *not* going to auto-dispose the connection */
450 // now if we created a connection, forward it to the row set
451 if ( xConnection.is() )
455 if ( _bAttachAutoDisposer )
457 rtl::Reference<OAutoConnectionDisposer> pAutoDispose = new OAutoConnectionDisposer( _rxRowSet, xConnection );
459 else
460 xRowSetProps->setPropertyValue(
461 "ActiveConnection",
462 makeAny( xConnection.getTyped() )
465 catch(Exception&)
467 OSL_FAIL("EXception when we set the new active connection!");
471 while ( false );
473 return xConnection;
476 Reference< XConnection> connectRowset(const Reference< XRowSet>& _rxRowSet, const Reference< XComponentContext >& _rxContext, const Reference< XWindow >& _rxParent)
478 SharedConnection xConnection = lcl_connectRowSet( _rxRowSet, _rxContext, true, _rxParent );
479 return xConnection.getTyped();
482 SharedConnection ensureRowSetConnection(const Reference< XRowSet>& _rxRowSet, const Reference< XComponentContext>& _rxContext, const Reference< XWindow >& _rxParent)
484 return lcl_connectRowSet( _rxRowSet, _rxContext, false/*bUseAutoConnectionDisposer*/, _rxParent );
487 Reference< XNameAccess> getTableFields(const Reference< XConnection>& _rxConn,const OUString& _rName)
489 Reference< XComponent > xDummy;
490 return getFieldsByCommandDescriptor( _rxConn, CommandType::TABLE, _rName, xDummy );
493 Reference< XNameAccess> getPrimaryKeyColumns_throw(const Any& i_aTable)
495 const Reference< XPropertySet > xTable(i_aTable,UNO_QUERY_THROW);
496 return getPrimaryKeyColumns_throw(xTable);
499 Reference< XNameAccess> getPrimaryKeyColumns_throw(const Reference< XPropertySet >& i_xTable)
501 Reference<XNameAccess> xKeyColumns;
502 const Reference<XKeysSupplier> xKeySup(i_xTable,UNO_QUERY);
503 if ( xKeySup.is() )
505 const Reference<XIndexAccess> xKeys = xKeySup->getKeys();
506 if ( xKeys.is() )
508 ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap();
509 const OUString& sPropName = rPropMap.getNameByIndex(PROPERTY_ID_TYPE);
510 Reference<XPropertySet> xProp;
511 const sal_Int32 nCount = xKeys->getCount();
512 for(sal_Int32 i = 0;i< nCount;++i)
514 xProp.set(xKeys->getByIndex(i),UNO_QUERY_THROW);
515 sal_Int32 nKeyType = 0;
516 xProp->getPropertyValue(sPropName) >>= nKeyType;
517 if(KeyType::PRIMARY == nKeyType)
519 const Reference<XColumnsSupplier> xKeyColsSup(xProp,UNO_QUERY_THROW);
520 xKeyColumns = xKeyColsSup->getColumns();
521 break;
527 return xKeyColumns;
530 namespace
532 enum FieldLookupState
534 HANDLE_TABLE, HANDLE_QUERY, HANDLE_SQL, RETRIEVE_OBJECT, RETRIEVE_COLUMNS, DONE, FAILED
538 Reference< XNameAccess > getFieldsByCommandDescriptor( const Reference< XConnection >& _rxConnection,
539 const sal_Int32 _nCommandType, const OUString& _rCommand,
540 Reference< XComponent >& _rxKeepFieldsAlive, SQLExceptionInfo* _pErrorInfo )
542 OSL_PRECOND( _rxConnection.is(), "::dbtools::getFieldsByCommandDescriptor: invalid connection!" );
543 OSL_PRECOND( ( CommandType::TABLE == _nCommandType ) || ( CommandType::QUERY == _nCommandType ) || ( CommandType::COMMAND == _nCommandType ),
544 "::dbtools::getFieldsByCommandDescriptor: invalid command type!" );
545 OSL_PRECOND( !_rCommand.isEmpty(), "::dbtools::getFieldsByCommandDescriptor: invalid command (empty)!" );
547 Reference< XNameAccess > xFields;
549 // reset the error
550 if ( _pErrorInfo )
551 *_pErrorInfo = SQLExceptionInfo();
552 // reset the ownership holder
553 _rxKeepFieldsAlive.clear();
555 // go for the fields
558 // some kind of state machine to ease the sharing of code
559 FieldLookupState eState = FAILED;
560 switch ( _nCommandType )
562 case CommandType::TABLE:
563 eState = HANDLE_TABLE;
564 break;
565 case CommandType::QUERY:
566 eState = HANDLE_QUERY;
567 break;
568 case CommandType::COMMAND:
569 eState = HANDLE_SQL;
570 break;
573 // needed in various states:
574 Reference< XNameAccess > xObjectCollection;
575 Reference< XColumnsSupplier > xSupplyColumns;
577 // go!
578 while ( ( DONE != eState ) && ( FAILED != eState ) )
580 switch ( eState )
582 case HANDLE_TABLE:
584 // initial state for handling the tables
586 // get the table objects
587 Reference< XTablesSupplier > xSupplyTables( _rxConnection, UNO_QUERY );
588 if ( xSupplyTables.is() )
589 xObjectCollection = xSupplyTables->getTables();
590 // if something went wrong 'til here, then this will be handled in the next state
592 // next state: get the object
593 eState = RETRIEVE_OBJECT;
595 break;
597 case HANDLE_QUERY:
599 // initial state for handling the tables
601 // get the table objects
602 Reference< XQueriesSupplier > xSupplyQueries( _rxConnection, UNO_QUERY );
603 if ( xSupplyQueries.is() )
604 xObjectCollection = xSupplyQueries->getQueries();
605 // if something went wrong 'til here, then this will be handled in the next state
607 // next state: get the object
608 eState = RETRIEVE_OBJECT;
610 break;
612 case RETRIEVE_OBJECT:
613 // here we should have an object (aka query or table) collection, and are going
614 // to retrieve the desired object
616 // next state: default to FAILED
617 eState = FAILED;
619 OSL_ENSURE( xObjectCollection.is(), "::dbtools::getFieldsByCommandDescriptor: invalid connection (no sdb.Connection, or no Tables-/QueriesSupplier)!");
620 if ( xObjectCollection.is() && xObjectCollection->hasByName( _rCommand ) )
622 xObjectCollection->getByName( _rCommand ) >>= xSupplyColumns;
623 // (xSupplyColumns being NULL will be handled in the next state)
625 // next: go for the columns
626 eState = RETRIEVE_COLUMNS;
628 break;
630 case RETRIEVE_COLUMNS:
631 OSL_ENSURE( xSupplyColumns.is(), "::dbtools::getFieldsByCommandDescriptor: could not retrieve the columns supplier!" );
633 // next state: default to FAILED
634 eState = FAILED;
636 if ( xSupplyColumns.is() )
638 xFields = xSupplyColumns->getColumns();
639 // that's it
640 eState = DONE;
642 break;
644 case HANDLE_SQL:
646 OUString sStatementToExecute( _rCommand );
648 // well, the main problem here is to handle statements which contain a parameter
649 // If we would simply execute a parametrized statement, then this will fail because
650 // we cannot supply any parameter values.
651 // Thus, we try to analyze the statement, and to append a WHERE 0=1 filter criterion
652 // This should cause every driver to not really execute the statement, but to return
653 // an empty result set with the proper structure. We then can use this result set
654 // to retrieve the columns.
658 Reference< XMultiServiceFactory > xComposerFac( _rxConnection, UNO_QUERY );
660 if ( xComposerFac.is() )
662 Reference< XSingleSelectQueryComposer > xComposer(xComposerFac->createInstance("com.sun.star.sdb.SingleSelectQueryComposer"),UNO_QUERY);
663 if ( xComposer.is() )
665 xComposer->setQuery( sStatementToExecute );
667 // Now set the filter to a dummy restriction which will result in an empty
668 // result set.
669 xComposer->setFilter( "0=1" );
670 sStatementToExecute = xComposer->getQuery( );
674 catch( const Exception& )
676 // silent this error, this was just a try. If we're here, we did not change sStatementToExecute,
677 // so it will still be _rCommand, which then will be executed without being touched
680 // now execute
681 Reference< XPreparedStatement > xStatement = _rxConnection->prepareStatement( sStatementToExecute );
682 // transfer ownership of this temporary object to the caller
683 _rxKeepFieldsAlive.set(xStatement, css::uno::UNO_QUERY);
685 // set the "MaxRows" to 0. This is just in case our attempt to append a 0=1 filter
686 // failed - in this case, the MaxRows restriction should at least ensure that there
687 // is no data returned (which would be potentially expensive)
688 Reference< XPropertySet > xStatementProps( xStatement,UNO_QUERY );
691 if ( xStatementProps.is() )
692 xStatementProps->setPropertyValue( "MaxRows", makeAny( sal_Int32( 0 ) ) );
694 catch( const Exception& )
696 OSL_FAIL( "::dbtools::getFieldsByCommandDescriptor: could not set the MaxRows!" );
697 // oh damn. Not much of a chance to recover, we will no retrieve the complete
698 // full blown result set
701 xSupplyColumns.set(xStatement->executeQuery(), css::uno::UNO_QUERY);
702 // this should have given us a result set which does not contain any data, but
703 // the structural information we need
705 // so the next state is to get the columns
706 eState = RETRIEVE_COLUMNS;
708 break;
710 default:
711 OSL_FAIL( "::dbtools::getFieldsByCommandDescriptor: oops! unhandled state here!" );
712 eState = FAILED;
716 catch( const SQLContext& e ) { if ( _pErrorInfo ) *_pErrorInfo = SQLExceptionInfo( e ); }
717 catch( const SQLWarning& e ) { if ( _pErrorInfo ) *_pErrorInfo = SQLExceptionInfo( e ); }
718 catch( const SQLException& e ) { if ( _pErrorInfo ) *_pErrorInfo = SQLExceptionInfo( e ); }
719 catch( const Exception& )
721 OSL_FAIL( "::dbtools::getFieldsByCommandDescriptor: caught an exception while retrieving the fields!" );
724 return xFields;
727 Sequence< OUString > getFieldNamesByCommandDescriptor( const Reference< XConnection >& _rxConnection,
728 const sal_Int32 _nCommandType, const OUString& _rCommand,
729 SQLExceptionInfo* _pErrorInfo )
731 // get the container for the fields
732 Reference< XComponent > xKeepFieldsAlive;
733 Reference< XNameAccess > xFieldContainer = getFieldsByCommandDescriptor( _rxConnection, _nCommandType, _rCommand, xKeepFieldsAlive, _pErrorInfo );
735 // get the names of the fields
736 Sequence< OUString > aNames;
737 if ( xFieldContainer.is() )
738 aNames = xFieldContainer->getElementNames();
740 // clean up any temporary objects which have been created
741 disposeComponent( xKeepFieldsAlive );
743 // outta here
744 return aNames;
747 SQLException prependErrorInfo( const SQLException& _rChainedException, const Reference< XInterface >& _rxContext,
748 const OUString& _rAdditionalError, const StandardSQLState _eSQLState )
750 return SQLException( _rAdditionalError, _rxContext,
751 _eSQLState == StandardSQLState::ERROR_UNSPECIFIED ? OUString() : getStandardSQLState( _eSQLState ),
752 0, makeAny( _rChainedException ) );
755 namespace
757 struct NameComponentSupport
759 const bool bCatalogs;
760 const bool bSchemas;
762 NameComponentSupport( const bool _bCatalogs, const bool _bSchemas )
763 :bCatalogs( _bCatalogs )
764 ,bSchemas( _bSchemas )
769 NameComponentSupport lcl_getNameComponentSupport( const Reference< XDatabaseMetaData >& _rxMetaData, EComposeRule _eComposeRule )
771 OSL_PRECOND( _rxMetaData.is(), "lcl_getNameComponentSupport: invalid meta data!" );
773 FMetaDataSupport pCatalogCall = &XDatabaseMetaData::supportsCatalogsInDataManipulation;
774 FMetaDataSupport pSchemaCall = &XDatabaseMetaData::supportsSchemasInDataManipulation;
775 bool bIgnoreMetaData = false;
777 switch ( _eComposeRule )
779 case EComposeRule::InTableDefinitions:
780 pCatalogCall = &XDatabaseMetaData::supportsCatalogsInTableDefinitions;
781 pSchemaCall = &XDatabaseMetaData::supportsSchemasInTableDefinitions;
782 break;
783 case EComposeRule::InIndexDefinitions:
784 pCatalogCall = &XDatabaseMetaData::supportsCatalogsInIndexDefinitions;
785 pSchemaCall = &XDatabaseMetaData::supportsSchemasInIndexDefinitions;
786 break;
787 case EComposeRule::InProcedureCalls:
788 pCatalogCall = &XDatabaseMetaData::supportsCatalogsInProcedureCalls;
789 pSchemaCall = &XDatabaseMetaData::supportsSchemasInProcedureCalls;
790 break;
791 case EComposeRule::InPrivilegeDefinitions:
792 pCatalogCall = &XDatabaseMetaData::supportsCatalogsInPrivilegeDefinitions;
793 pSchemaCall = &XDatabaseMetaData::supportsSchemasInPrivilegeDefinitions;
794 break;
795 case EComposeRule::Complete:
796 bIgnoreMetaData = true;
797 break;
798 case EComposeRule::InDataManipulation:
799 // already properly set above
800 break;
802 return NameComponentSupport(
803 bIgnoreMetaData || (_rxMetaData.get()->*pCatalogCall)(),
804 bIgnoreMetaData || (_rxMetaData.get()->*pSchemaCall)()
809 static OUString impl_doComposeTableName( const Reference< XDatabaseMetaData >& _rxMetaData,
810 const OUString& _rCatalog, const OUString& _rSchema, const OUString& _rName,
811 bool _bQuote, EComposeRule _eComposeRule )
813 OSL_ENSURE(_rxMetaData.is(), "impl_doComposeTableName : invalid meta data !");
814 if ( !_rxMetaData.is() )
815 return OUString();
816 OSL_ENSURE(!_rName.isEmpty(), "impl_doComposeTableName : at least the name should be non-empty !");
818 const OUString sQuoteString = _rxMetaData->getIdentifierQuoteString();
819 const NameComponentSupport aNameComps( lcl_getNameComponentSupport( _rxMetaData, _eComposeRule ) );
821 OUStringBuffer aComposedName;
823 OUString sCatalogSep;
824 bool bCatlogAtStart = true;
825 if ( !_rCatalog.isEmpty() && aNameComps.bCatalogs )
827 sCatalogSep = _rxMetaData->getCatalogSeparator();
828 bCatlogAtStart = _rxMetaData->isCatalogAtStart();
830 if ( bCatlogAtStart && !sCatalogSep.isEmpty())
832 aComposedName.append( _bQuote ? quoteName( sQuoteString, _rCatalog ) : _rCatalog );
833 aComposedName.append( sCatalogSep );
837 if ( !_rSchema.isEmpty() && aNameComps.bSchemas )
839 aComposedName.append( _bQuote ? quoteName( sQuoteString, _rSchema ) : _rSchema );
840 aComposedName.append( "." );
843 aComposedName.append( _bQuote ? quoteName( sQuoteString, _rName ) : _rName );
845 if ( !_rCatalog.isEmpty()
846 && !bCatlogAtStart
847 && !sCatalogSep.isEmpty()
848 && aNameComps.bCatalogs
851 aComposedName.append( sCatalogSep );
852 aComposedName.append( _bQuote ? quoteName( sQuoteString, _rCatalog ) : _rCatalog );
855 return aComposedName.makeStringAndClear();
858 OUString quoteTableName(const Reference< XDatabaseMetaData>& _rxMeta
859 , const OUString& _rName
860 , EComposeRule _eComposeRule)
862 OUString sCatalog, sSchema, sTable;
863 qualifiedNameComponents(_rxMeta,_rName,sCatalog,sSchema,sTable,_eComposeRule);
864 return impl_doComposeTableName( _rxMeta, sCatalog, sSchema, sTable, true, _eComposeRule );
867 void qualifiedNameComponents(const Reference< XDatabaseMetaData >& _rxConnMetaData, const OUString& _rQualifiedName, OUString& _rCatalog, OUString& _rSchema, OUString& _rName,EComposeRule _eComposeRule)
869 OSL_ENSURE(_rxConnMetaData.is(), "QualifiedNameComponents : invalid meta data!");
871 NameComponentSupport aNameComps( lcl_getNameComponentSupport( _rxConnMetaData, _eComposeRule ) );
873 OUString sSeparator = _rxConnMetaData->getCatalogSeparator();
875 OUString sName(_rQualifiedName);
876 // do we have catalogs?
877 if ( aNameComps.bCatalogs )
879 if (_rxConnMetaData->isCatalogAtStart())
881 // search for the catalog name at the beginning
882 sal_Int32 nIndex = sName.indexOf(sSeparator);
883 if (-1 != nIndex)
885 _rCatalog = sName.copy(0, nIndex);
886 sName = sName.copy(nIndex + 1);
889 else
891 // Catalog name at the end
892 sal_Int32 nIndex = sName.lastIndexOf(sSeparator);
893 if (-1 != nIndex)
895 _rCatalog = sName.copy(nIndex + 1);
896 sName = sName.copy(0, nIndex);
901 if ( aNameComps.bSchemas )
903 sal_Int32 nIndex = sName.indexOf('.');
904 // OSL_ENSURE(-1 != nIndex, "QualifiedNameComponents: no schema separator!");
905 if ( nIndex != -1 )
906 _rSchema = sName.copy(0, nIndex);
907 sName = sName.copy(nIndex + 1);
910 _rName = sName;
913 Reference< XNumberFormatsSupplier> getNumberFormats(
914 const Reference< XConnection>& _rxConn,
915 bool _bAlloweDefault,
916 const Reference< XComponentContext>& _rxContext)
918 // ask the parent of the connection (should be a DatabaseAccess)
919 Reference< XNumberFormatsSupplier> xReturn;
920 Reference< XChild> xConnAsChild(_rxConn, UNO_QUERY);
921 OUString sPropFormatsSupplier( "NumberFormatsSupplier" );
922 if (xConnAsChild.is())
924 Reference< XPropertySet> xConnParentProps(xConnAsChild->getParent(), UNO_QUERY);
925 if (xConnParentProps.is() && hasProperty(sPropFormatsSupplier, xConnParentProps))
926 xConnParentProps->getPropertyValue(sPropFormatsSupplier) >>= xReturn;
928 else if(_bAlloweDefault && _rxContext.is())
930 xReturn = NumberFormatsSupplier::createWithDefaultLocale( _rxContext );
932 return xReturn;
935 void TransferFormComponentProperties(
936 const Reference< XPropertySet>& xOldProps,
937 const Reference< XPropertySet>& xNewProps,
938 const Locale& _rLocale)
942 OSL_ENSURE( xOldProps.is() && xNewProps.is(), "TransferFormComponentProperties: invalid source/dest!" );
943 if ( !xOldProps.is() || !xNewProps.is() )
944 return;
946 // First we copy all the Props, that are available in source and target and have the same description
947 Reference< XPropertySetInfo> xOldInfo( xOldProps->getPropertySetInfo());
948 Reference< XPropertySetInfo> xNewInfo( xNewProps->getPropertySetInfo());
950 Sequence< Property> aOldProperties = xOldInfo->getProperties();
951 Sequence< Property> aNewProperties = xNewInfo->getProperties();
952 int nNewLen = aNewProperties.getLength();
954 Property* pOldProps = aOldProperties.getArray();
955 Property* pNewProps = aNewProperties.getArray();
957 OUString sPropFormatsSupplier("FormatsSupplier");
958 OUString sPropCurrencySymbol("CurrencySymbol");
959 OUString sPropDecimals("Decimals");
960 OUString sPropEffectiveMin("EffectiveMin");
961 OUString sPropEffectiveMax("EffectiveMax");
962 OUString sPropEffectiveDefault("EffectiveDefault");
963 OUString sPropDefaultText("DefaultText");
964 OUString sPropDefaultDate("DefaultDate");
965 OUString sPropDefaultTime("DefaultTime");
966 OUString sPropValueMin("ValueMin");
967 OUString sPropValueMax("ValueMax");
968 OUString sPropDecimalAccuracy("DecimalAccuracy");
969 OUString sPropClassId("ClassId");
970 OUString sFormattedServiceName( "com.sun.star.form.component.FormattedField" );
972 for (sal_Int32 i=0; i<aOldProperties.getLength(); ++i)
974 if ( pOldProps[i].Name != "DefaultControl" && pOldProps[i].Name != "LabelControl" )
976 // binary search
977 Property* pResult = std::lower_bound(
978 pNewProps, pNewProps + nNewLen, pOldProps[i], ::comphelper::PropertyCompareByName());
980 if ( ( pResult != aNewProperties.end() )
981 && ( pResult->Name == pOldProps[i].Name )
982 && ( (pResult->Attributes & PropertyAttribute::READONLY) == 0 )
983 && ( pResult->Type.equals(pOldProps[i].Type)) )
984 { // Attributes match and the property is not read-only
987 xNewProps->setPropertyValue(pResult->Name, xOldProps->getPropertyValue(pResult->Name));
989 catch(IllegalArgumentException const &)
991 TOOLS_WARN_EXCEPTION( "connectivity.commontools", "TransferFormComponentProperties : could not transfer the value for property \""
992 << pResult->Name << "\"");
998 // for formatted fields (either old or new) we have some special treatments
999 Reference< XServiceInfo > xSI( xOldProps, UNO_QUERY );
1000 bool bOldIsFormatted = xSI.is() && xSI->supportsService( sFormattedServiceName );
1001 xSI.set( xNewProps, UNO_QUERY );
1002 bool bNewIsFormatted = xSI.is() && xSI->supportsService( sFormattedServiceName );
1004 if (!bOldIsFormatted && !bNewIsFormatted)
1005 return; // nothing to do
1007 if (bOldIsFormatted && bNewIsFormatted)
1008 // if both fields are formatted we do no conversions
1009 return;
1011 if (bOldIsFormatted)
1013 // get some properties from the selected format and put them in the new Set
1014 Any aFormatKey( xOldProps->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FORMATKEY)) );
1015 if (aFormatKey.hasValue())
1017 Reference< XNumberFormatsSupplier> xSupplier;
1018 xOldProps->getPropertyValue(sPropFormatsSupplier) >>= xSupplier;
1019 if (xSupplier.is())
1021 Reference< XNumberFormats> xFormats(xSupplier->getNumberFormats());
1022 Reference< XPropertySet> xFormat(xFormats->getByKey(getINT32(aFormatKey)));
1023 if (hasProperty(sPropCurrencySymbol, xFormat))
1025 Any aVal( xFormat->getPropertyValue(sPropCurrencySymbol) );
1026 if (aVal.hasValue() && hasProperty(sPropCurrencySymbol, xNewProps))
1027 // If the source value hasn't been set then don't copy it
1028 // so we don't overwrite the default value
1029 xNewProps->setPropertyValue(sPropCurrencySymbol, aVal);
1031 if (hasProperty(sPropDecimals, xFormat) && hasProperty(sPropDecimals, xNewProps))
1032 xNewProps->setPropertyValue(sPropDecimals, xFormat->getPropertyValue(sPropDecimals));
1036 // a potential Min-Max-Conversion
1037 Any aEffectiveMin( xOldProps->getPropertyValue(sPropEffectiveMin) );
1038 if (aEffectiveMin.hasValue())
1039 { // Unlike the ValueMin the EffectiveMin can be void
1040 if (hasProperty(sPropValueMin, xNewProps))
1042 OSL_ENSURE(aEffectiveMin.getValueType().getTypeClass() == TypeClass_DOUBLE,
1043 "TransferFormComponentProperties : invalid property type !");
1044 xNewProps->setPropertyValue(sPropValueMin, aEffectiveMin);
1047 Any aEffectiveMax( xOldProps->getPropertyValue(sPropEffectiveMax) );
1048 if (aEffectiveMax.hasValue())
1049 { // analog
1050 if (hasProperty(sPropValueMax, xNewProps))
1052 OSL_ENSURE(aEffectiveMax.getValueType().getTypeClass() == TypeClass_DOUBLE,
1053 "TransferFormComponentProperties : invalid property type !");
1054 xNewProps->setPropertyValue(sPropValueMax, aEffectiveMax);
1058 // then we can still convert and copy the default values
1059 Any aEffectiveDefault( xOldProps->getPropertyValue(sPropEffectiveDefault) );
1060 if (aEffectiveDefault.hasValue())
1062 bool bIsString = aEffectiveDefault.getValueType().getTypeClass() == TypeClass_STRING;
1063 OSL_ENSURE(bIsString || aEffectiveDefault.getValueType().getTypeClass() == TypeClass_DOUBLE,
1064 "TransferFormComponentProperties : invalid property type !");
1065 // The Effective-Properties should always be void or string or double...
1067 if (hasProperty(sPropDefaultDate, xNewProps) && !bIsString)
1068 { // (to convert an OUString into a date will not always succeed, because it might be bound to a text-column,
1069 // but we can work with a double)
1070 Date aDate = DBTypeConversion::toDate(getDouble(aEffectiveDefault));
1071 xNewProps->setPropertyValue(sPropDefaultDate, makeAny(aDate));
1074 if (hasProperty(sPropDefaultTime, xNewProps) && !bIsString)
1075 { // Completely analogous to time
1076 css::util::Time aTime = DBTypeConversion::toTime(getDouble(aEffectiveDefault));
1077 xNewProps->setPropertyValue(sPropDefaultTime, makeAny(aTime));
1080 if (hasProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE), xNewProps) && !bIsString)
1081 { // Here we can simply pass the double
1082 xNewProps->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE), aEffectiveDefault);
1085 if (hasProperty(sPropDefaultText, xNewProps) && bIsString)
1086 { // and here the OUString
1087 xNewProps->setPropertyValue(sPropDefaultText, aEffectiveDefault);
1090 // nyi: The translation between doubles and OUString would offer more alternatives
1094 // The other direction: the new Control shall be formatted
1095 if (bNewIsFormatted)
1097 // first the formatting
1098 // we can't set a Supplier, so the new Set must bring one in
1099 Reference< XNumberFormatsSupplier> xSupplier;
1100 xNewProps->getPropertyValue(sPropFormatsSupplier) >>= xSupplier;
1101 if (xSupplier.is())
1103 Reference< XNumberFormats> xFormats(xSupplier->getNumberFormats());
1105 // Set number of decimals
1106 sal_Int16 nDecimals = 2;
1107 if (hasProperty(sPropDecimalAccuracy, xOldProps))
1108 xOldProps->getPropertyValue(sPropDecimalAccuracy) >>= nDecimals;
1110 // base format (depending on the ClassId of the old Set)
1111 sal_Int32 nBaseKey = 0;
1112 if (hasProperty(sPropClassId, xOldProps))
1114 Reference< XNumberFormatTypes> xTypeList(xFormats, UNO_QUERY);
1115 if (xTypeList.is())
1117 sal_Int16 nClassId = 0;
1118 xOldProps->getPropertyValue(sPropClassId) >>= nClassId;
1119 switch (nClassId)
1121 case FormComponentType::DATEFIELD :
1122 nBaseKey = xTypeList->getStandardFormat(NumberFormat::DATE, _rLocale);
1123 break;
1125 case FormComponentType::TIMEFIELD :
1126 nBaseKey = xTypeList->getStandardFormat(NumberFormat::TIME, _rLocale);
1127 break;
1129 case FormComponentType::CURRENCYFIELD :
1130 nBaseKey = xTypeList->getStandardFormat(NumberFormat::CURRENCY, _rLocale);
1131 break;
1136 // With this we can generate a new format ...
1137 OUString sNewFormat = xFormats->generateFormat(nBaseKey, _rLocale, false, false, nDecimals, 0);
1138 // No thousands separator, negative numbers are not in red, no leading zeros
1140 // ... and add at FormatsSupplier (if needed)
1141 sal_Int32 nKey = xFormats->queryKey(sNewFormat, _rLocale, false);
1142 if (nKey == sal_Int32(-1))
1143 { // not added yet in my formatter ...
1144 nKey = xFormats->addNew(sNewFormat, _rLocale);
1147 xNewProps->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FORMATKEY), makeAny(nKey));
1150 // min-/max-Value
1151 Any aNewMin, aNewMax;
1152 if (hasProperty(sPropValueMin, xOldProps))
1153 aNewMin = xOldProps->getPropertyValue(sPropValueMin);
1154 if (hasProperty(sPropValueMax, xOldProps))
1155 aNewMax = xOldProps->getPropertyValue(sPropValueMax);
1156 xNewProps->setPropertyValue(sPropEffectiveMin, aNewMin);
1157 xNewProps->setPropertyValue(sPropEffectiveMax, aNewMax);
1159 // Default-Value
1160 Any aNewDefault;
1161 if (hasProperty(sPropDefaultDate, xOldProps))
1163 Any aDate( xOldProps->getPropertyValue(sPropDefaultDate) );
1164 if (aDate.hasValue())
1165 aNewDefault <<= DBTypeConversion::toDouble(*o3tl::doAccess<Date>(aDate));
1168 if (hasProperty(sPropDefaultTime, xOldProps))
1170 Any aTime( xOldProps->getPropertyValue(sPropDefaultTime) );
1171 if (aTime.hasValue())
1172 aNewDefault <<= DBTypeConversion::toDouble(*o3tl::doAccess<Time>(aTime));
1175 // double or OUString will be copied directly
1176 if (hasProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE), xOldProps))
1177 aNewDefault = xOldProps->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE));
1178 if (hasProperty(sPropDefaultText, xOldProps))
1179 aNewDefault = xOldProps->getPropertyValue(sPropDefaultText);
1181 if (aNewDefault.hasValue())
1182 xNewProps->setPropertyValue(sPropEffectiveDefault, aNewDefault);
1185 catch(const Exception&)
1187 OSL_FAIL( "TransferFormComponentProperties: caught an exception!" );
1191 bool canInsert(const Reference< XPropertySet>& _rxCursorSet)
1193 return (_rxCursorSet.is() && (getINT32(_rxCursorSet->getPropertyValue("Privileges")) & Privilege::INSERT) != 0);
1196 bool canUpdate(const Reference< XPropertySet>& _rxCursorSet)
1198 return (_rxCursorSet.is() && (getINT32(_rxCursorSet->getPropertyValue("Privileges")) & Privilege::UPDATE) != 0);
1201 bool canDelete(const Reference< XPropertySet>& _rxCursorSet)
1203 return (_rxCursorSet.is() && (getINT32(_rxCursorSet->getPropertyValue("Privileges")) & Privilege::DELETE) != 0);
1206 Reference< XDataSource> findDataSource(const Reference< XInterface >& _xParent)
1208 Reference< XOfficeDatabaseDocument> xDatabaseDocument(_xParent, UNO_QUERY);
1209 Reference< XDataSource> xDataSource;
1210 if ( xDatabaseDocument.is() )
1211 xDataSource = xDatabaseDocument->getDataSource();
1212 if ( !xDataSource.is() )
1213 xDataSource.set(_xParent, UNO_QUERY);
1214 if (!xDataSource.is())
1216 Reference< XChild> xChild(_xParent, UNO_QUERY);
1217 if ( xChild.is() )
1218 xDataSource = findDataSource(xChild->getParent());
1220 return xDataSource;
1223 static Reference< XSingleSelectQueryComposer > getComposedRowSetStatement( const Reference< XPropertySet >& _rxRowSet, const Reference< XComponentContext >& _rxContext, const Reference< XWindow >& _rxParent )
1225 Reference< XSingleSelectQueryComposer > xComposer;
1228 Reference< XConnection> xConn = connectRowset( Reference< XRowSet >( _rxRowSet, UNO_QUERY ), _rxContext, _rxParent );
1229 if ( xConn.is() ) // implies _rxRowSet.is()
1231 // build the statement the row set is based on (can't use the ActiveCommand property of the set
1232 // as this reflects the status after the last execute, not the currently set properties)
1234 sal_Int32 nCommandType = CommandType::COMMAND;
1235 OUString sCommand;
1236 bool bEscapeProcessing = false;
1238 OSL_VERIFY( _rxRowSet->getPropertyValue("CommandType") >>= nCommandType );
1239 OSL_VERIFY( _rxRowSet->getPropertyValue("Command") >>= sCommand );
1240 OSL_VERIFY( _rxRowSet->getPropertyValue("EscapeProcessing") >>= bEscapeProcessing );
1242 StatementComposer aComposer( xConn, sCommand, nCommandType, bEscapeProcessing );
1243 // append sort
1244 aComposer.setOrder( getString( _rxRowSet->getPropertyValue("Order") ) );
1246 // append filter
1247 bool bApplyFilter = true;
1248 _rxRowSet->getPropertyValue("ApplyFilter") >>= bApplyFilter;
1249 if ( bApplyFilter )
1250 aComposer.setFilter( getString( _rxRowSet->getPropertyValue("Filter") ) );
1252 aComposer.getQuery();
1254 xComposer = aComposer.getComposer();
1255 aComposer.setDisposeComposer( false );
1258 catch( const SQLException& )
1260 throw;
1262 catch( const Exception& )
1264 DBG_UNHANDLED_EXCEPTION("connectivity.commontools");
1267 return xComposer;
1270 Reference< XSingleSelectQueryComposer > getCurrentSettingsComposer(
1271 const Reference< XPropertySet>& _rxRowSetProps,
1272 const Reference< XComponentContext>& _rxContext,
1273 const Reference< XWindow >& _rxParent)
1275 Reference< XSingleSelectQueryComposer > xReturn;
1278 xReturn = getComposedRowSetStatement( _rxRowSetProps, _rxContext, _rxParent );
1280 catch( const SQLException& )
1282 throw;
1284 catch( const Exception& )
1286 OSL_FAIL( "::getCurrentSettingsComposer : caught an exception !" );
1289 return xReturn;
1292 OUString composeTableName( const Reference< XDatabaseMetaData >& _rxMetaData,
1293 const OUString& _rCatalog,
1294 const OUString& _rSchema,
1295 const OUString& _rName,
1296 bool _bQuote,
1297 EComposeRule _eComposeRule)
1299 return impl_doComposeTableName( _rxMetaData, _rCatalog, _rSchema, _rName, _bQuote, _eComposeRule );
1302 OUString composeTableNameForSelect( const Reference< XConnection >& _rxConnection,
1303 const OUString& _rCatalog, const OUString& _rSchema, const OUString& _rName )
1305 bool bUseCatalogInSelect = isDataSourcePropertyEnabled( _rxConnection, "UseCatalogInSelect", true );
1306 bool bUseSchemaInSelect = isDataSourcePropertyEnabled( _rxConnection, "UseSchemaInSelect", true );
1308 return impl_doComposeTableName(
1309 _rxConnection->getMetaData(),
1310 bUseCatalogInSelect ? _rCatalog : OUString(),
1311 bUseSchemaInSelect ? _rSchema : OUString(),
1312 _rName,
1313 true,
1314 EComposeRule::InDataManipulation
1318 namespace
1320 void lcl_getTableNameComponents( const Reference<XPropertySet>& _xTable,
1321 OUString& _out_rCatalog, OUString& _out_rSchema, OUString& _out_rName )
1323 ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap();
1324 Reference< XPropertySetInfo > xInfo;
1325 if (_xTable.is())
1326 xInfo = _xTable->getPropertySetInfo();
1327 if ( xInfo.is()
1328 && xInfo->hasPropertyByName(rPropMap.getNameByIndex(PROPERTY_ID_NAME)) )
1330 if ( xInfo->hasPropertyByName(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME))
1331 && xInfo->hasPropertyByName(rPropMap.getNameByIndex(PROPERTY_ID_SCHEMANAME)) )
1333 _xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME)) >>= _out_rCatalog;
1334 _xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_SCHEMANAME)) >>= _out_rSchema;
1336 _xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME)) >>= _out_rName;
1338 else
1339 OSL_FAIL( "::dbtools::lcl_getTableNameComponents: this is no table object!" );
1343 OUString composeTableNameForSelect( const Reference< XConnection >& _rxConnection, const Reference<XPropertySet>& _xTable )
1345 OUString sCatalog, sSchema, sName;
1346 lcl_getTableNameComponents( _xTable, sCatalog, sSchema, sName );
1348 return composeTableNameForSelect( _rxConnection, sCatalog, sSchema, sName );
1351 OUString composeTableName(const Reference<XDatabaseMetaData>& _xMetaData,
1352 const Reference<XPropertySet>& _xTable,
1353 EComposeRule _eComposeRule,
1354 bool _bQuote )
1356 OUString sCatalog, sSchema, sName;
1357 lcl_getTableNameComponents( _xTable, sCatalog, sSchema, sName );
1359 return impl_doComposeTableName(
1360 _xMetaData,
1361 sCatalog,
1362 sSchema,
1363 sName,
1364 _bQuote,
1365 _eComposeRule
1369 sal_Int32 getSearchColumnFlag( const Reference< XConnection>& _rxConn,sal_Int32 _nDataType)
1371 sal_Int32 nSearchFlag = 0;
1372 Reference<XResultSet> xSet = _rxConn->getMetaData()->getTypeInfo();
1373 if(xSet.is())
1375 Reference<XRow> xRow(xSet,UNO_QUERY);
1376 while(xSet->next())
1378 if(xRow->getInt(2) == _nDataType)
1380 nSearchFlag = xRow->getInt(9);
1381 break;
1385 return nSearchFlag;
1388 OUString createUniqueName( const Sequence< OUString >& _rNames, const OUString& _rBaseName, bool _bStartWithNumber )
1390 std::set< OUString > aUsedNames;
1391 std::copy(
1392 _rNames.begin(),
1393 _rNames.end(),
1394 std::insert_iterator< std::set< OUString > >( aUsedNames, aUsedNames.end() )
1397 OUString sName( _rBaseName );
1398 sal_Int32 nPos = 1;
1399 if ( _bStartWithNumber )
1400 sName += OUString::number( nPos );
1402 while ( aUsedNames.find( sName ) != aUsedNames.end() )
1404 sName = _rBaseName + OUString::number( ++nPos );
1406 return sName;
1409 OUString createUniqueName(const Reference<XNameAccess>& _rxContainer,const OUString& _rBaseName, bool _bStartWithNumber)
1411 Sequence< OUString > aElementNames;
1413 OSL_ENSURE( _rxContainer.is(), "createUniqueName: invalid container!" );
1414 if ( _rxContainer.is() )
1415 aElementNames = _rxContainer->getElementNames();
1417 return createUniqueName( aElementNames, _rBaseName, _bStartWithNumber );
1420 void showError(const SQLExceptionInfo& _rInfo,
1421 const Reference< XWindow>& _xParent,
1422 const Reference< XComponentContext >& _rxContext)
1424 if (_rInfo.isValid())
1428 Reference< XExecutableDialog > xErrorDialog = ErrorMessageDialog::create( _rxContext, "", _xParent, _rInfo.get() );
1429 xErrorDialog->execute();
1431 catch(const Exception&)
1433 OSL_FAIL("showError: could not display the error message!");
1438 bool implUpdateObject(const Reference< XRowUpdate >& _rxUpdatedObject,
1439 const sal_Int32 _nColumnIndex, const Any& _rValue)
1441 bool bSuccessfullyReRouted = true;
1442 switch (_rValue.getValueTypeClass())
1444 case TypeClass_ANY:
1446 bSuccessfullyReRouted = implUpdateObject(_rxUpdatedObject, _nColumnIndex, _rValue);
1448 break;
1450 case TypeClass_VOID:
1451 _rxUpdatedObject->updateNull(_nColumnIndex);
1452 break;
1454 case TypeClass_STRING:
1455 _rxUpdatedObject->updateString(_nColumnIndex, *o3tl::forceAccess<OUString>(_rValue));
1456 break;
1458 case TypeClass_BOOLEAN:
1459 _rxUpdatedObject->updateBoolean(_nColumnIndex, *o3tl::forceAccess<bool>(_rValue));
1460 break;
1462 case TypeClass_BYTE:
1463 _rxUpdatedObject->updateByte(_nColumnIndex, *o3tl::forceAccess<sal_Int8>(_rValue));
1464 break;
1466 case TypeClass_UNSIGNED_SHORT:
1467 case TypeClass_SHORT:
1468 _rxUpdatedObject->updateShort(_nColumnIndex, *o3tl::forceAccess<sal_Int16>(_rValue));
1469 break;
1471 case TypeClass_CHAR:
1472 _rxUpdatedObject->updateString(_nColumnIndex,OUString(*o3tl::forceAccess<sal_Unicode>(_rValue)));
1473 break;
1475 case TypeClass_UNSIGNED_LONG:
1476 case TypeClass_LONG:
1477 _rxUpdatedObject->updateInt(_nColumnIndex, *o3tl::forceAccess<sal_Int32>(_rValue));
1478 break;
1480 case TypeClass_HYPER:
1482 sal_Int64 nValue = 0;
1483 OSL_VERIFY( _rValue >>= nValue );
1484 _rxUpdatedObject->updateLong( _nColumnIndex, nValue );
1486 break;
1488 case TypeClass_FLOAT:
1489 _rxUpdatedObject->updateFloat(_nColumnIndex, *o3tl::forceAccess<float>(_rValue));
1490 break;
1492 case TypeClass_DOUBLE:
1493 _rxUpdatedObject->updateDouble(_nColumnIndex, *o3tl::forceAccess<double>(_rValue));
1494 break;
1496 case TypeClass_SEQUENCE:
1497 if (auto s = o3tl::tryAccess<Sequence< sal_Int8 >>(_rValue))
1498 _rxUpdatedObject->updateBytes(_nColumnIndex, *s);
1499 else
1500 bSuccessfullyReRouted = false;
1501 break;
1502 case TypeClass_STRUCT:
1503 if (auto s1 = o3tl::tryAccess<DateTime>(_rValue))
1504 _rxUpdatedObject->updateTimestamp(_nColumnIndex, *s1);
1505 else if (auto s2 = o3tl::tryAccess<Date>(_rValue))
1506 _rxUpdatedObject->updateDate(_nColumnIndex, *s2);
1507 else if (auto s3 = o3tl::tryAccess<Time>(_rValue))
1508 _rxUpdatedObject->updateTime(_nColumnIndex, *s3);
1509 else
1510 bSuccessfullyReRouted = false;
1511 break;
1513 case TypeClass_INTERFACE:
1514 if (auto xStream = o3tl::tryAccess<Reference<XInputStream>>(_rValue))
1516 _rxUpdatedObject->updateBinaryStream(_nColumnIndex, *xStream, (*xStream)->available());
1517 break;
1519 [[fallthrough]];
1520 default:
1521 bSuccessfullyReRouted = false;
1524 return bSuccessfullyReRouted;
1527 bool implSetObject( const Reference< XParameters >& _rxParameters,
1528 const sal_Int32 _nColumnIndex, const Any& _rValue)
1530 bool bSuccessfullyReRouted = true;
1531 switch (_rValue.getValueTypeClass())
1533 case TypeClass_UNSIGNED_HYPER:
1535 sal_uInt64 nValue = 0;
1536 OSL_VERIFY( _rValue >>= nValue );
1537 _rxParameters->setString(_nColumnIndex, OUString::number(nValue));
1539 break;
1541 case TypeClass_UNSIGNED_LONG:
1542 case TypeClass_HYPER:
1544 sal_Int64 nValue = 0;
1545 OSL_VERIFY( _rValue >>= nValue );
1546 _rxParameters->setLong( _nColumnIndex, nValue );
1548 break;
1550 case TypeClass_ANY:
1552 bSuccessfullyReRouted = implSetObject(_rxParameters, _nColumnIndex, _rValue);
1554 break;
1556 case TypeClass_VOID:
1557 _rxParameters->setNull(_nColumnIndex,DataType::VARCHAR);
1558 break;
1560 case TypeClass_STRING:
1561 _rxParameters->setString(_nColumnIndex, *o3tl::forceAccess<OUString>(_rValue));
1562 break;
1564 case TypeClass_BOOLEAN:
1565 _rxParameters->setBoolean(_nColumnIndex, *o3tl::forceAccess<bool>(_rValue));
1566 break;
1568 case TypeClass_BYTE:
1569 _rxParameters->setByte(_nColumnIndex, *o3tl::forceAccess<sal_Int8>(_rValue));
1570 break;
1572 case TypeClass_SHORT:
1573 _rxParameters->setShort(_nColumnIndex, *o3tl::forceAccess<sal_Int16>(_rValue));
1574 break;
1576 case TypeClass_CHAR:
1577 _rxParameters->setString(_nColumnIndex, OUString(*o3tl::forceAccess<sal_Unicode>(_rValue)));
1578 break;
1580 case TypeClass_UNSIGNED_SHORT:
1581 case TypeClass_LONG:
1583 sal_Int32 nValue = 0;
1584 OSL_VERIFY( _rValue >>= nValue );
1585 _rxParameters->setInt(_nColumnIndex, nValue);
1586 break;
1589 case TypeClass_FLOAT:
1590 _rxParameters->setFloat(_nColumnIndex, *o3tl::forceAccess<float>(_rValue));
1591 break;
1593 case TypeClass_DOUBLE:
1594 _rxParameters->setDouble(_nColumnIndex, *o3tl::forceAccess<double>(_rValue));
1595 break;
1597 case TypeClass_SEQUENCE:
1598 if (auto s = o3tl::tryAccess<Sequence< sal_Int8 >>(_rValue))
1600 _rxParameters->setBytes(_nColumnIndex, *s);
1602 else
1603 bSuccessfullyReRouted = false;
1604 break;
1605 case TypeClass_STRUCT:
1606 if (auto s1 = o3tl::tryAccess<DateTime>(_rValue))
1607 _rxParameters->setTimestamp(_nColumnIndex, *s1);
1608 else if (auto s2 = o3tl::tryAccess<Date>(_rValue))
1609 _rxParameters->setDate(_nColumnIndex, *s2);
1610 else if (auto s3 = o3tl::tryAccess<Time>(_rValue))
1611 _rxParameters->setTime(_nColumnIndex, *s3);
1612 else
1613 bSuccessfullyReRouted = false;
1614 break;
1616 case TypeClass_INTERFACE:
1617 if (_rValue.getValueType() == cppu::UnoType<XInputStream>::get())
1619 Reference< XInputStream > xStream;
1620 _rValue >>= xStream;
1621 _rxParameters->setBinaryStream(_nColumnIndex, xStream, xStream->available());
1622 break;
1624 [[fallthrough]];
1625 default:
1626 bSuccessfullyReRouted = false;
1630 return bSuccessfullyReRouted;
1633 namespace
1635 class OParameterWrapper : public ::cppu::WeakImplHelper< XIndexAccess >
1637 std::vector<bool, std::allocator<bool> > m_aSet;
1638 Reference<XIndexAccess> m_xSource;
1639 public:
1640 OParameterWrapper(const std::vector<bool, std::allocator<bool> >& _aSet,const Reference<XIndexAccess>& _xSource) : m_aSet(_aSet),m_xSource(_xSource){}
1641 private:
1642 // css::container::XElementAccess
1643 virtual Type SAL_CALL getElementType() override
1645 return m_xSource->getElementType();
1647 virtual sal_Bool SAL_CALL hasElements( ) override
1649 if ( m_aSet.empty() )
1650 return m_xSource->hasElements();
1651 return std::count(m_aSet.begin(),m_aSet.end(),false) != 0;
1653 // css::container::XIndexAccess
1654 virtual sal_Int32 SAL_CALL getCount( ) override
1656 if ( m_aSet.empty() )
1657 return m_xSource->getCount();
1658 return std::count(m_aSet.begin(),m_aSet.end(),false);
1660 virtual Any SAL_CALL getByIndex( sal_Int32 Index ) override
1662 if ( m_aSet.empty() )
1663 return m_xSource->getByIndex(Index);
1664 if ( m_aSet.size() < static_cast<size_t>(Index) )
1665 throw IndexOutOfBoundsException();
1667 std::vector<bool, std::allocator<bool> >::const_iterator aIter = m_aSet.begin();
1668 std::vector<bool, std::allocator<bool> >::const_iterator aEnd = m_aSet.end();
1669 sal_Int32 i = 0;
1670 for(; aIter != aEnd && i <= Index; ++aIter)
1672 if ( !*aIter )
1674 ++i;
1677 auto nParamPos = static_cast<sal_Int32>(std::distance(m_aSet.cbegin(), aIter)) - 1;
1678 return m_xSource->getByIndex(nParamPos);
1683 void askForParameters(const Reference< XSingleSelectQueryComposer >& _xComposer,
1684 const Reference<XParameters>& _xParameters,
1685 const Reference< XConnection>& _xConnection,
1686 const Reference< XInteractionHandler >& _rxHandler,
1687 const std::vector<bool, std::allocator<bool> >& _aParametersSet)
1689 OSL_ENSURE(_xComposer.is(),"dbtools::askForParameters XSQLQueryComposer is null!");
1690 OSL_ENSURE(_xParameters.is(),"dbtools::askForParameters XParameters is null!");
1691 OSL_ENSURE(_xConnection.is(),"dbtools::askForParameters XConnection is null!");
1692 OSL_ENSURE(_rxHandler.is(),"dbtools::askForParameters XInteractionHandler is null!");
1694 // we have to set this here again because getCurrentSettingsComposer can force a setpropertyvalue
1695 Reference<XParametersSupplier> xParameters(_xComposer, UNO_QUERY);
1697 Reference<XIndexAccess> xParamsAsIndicies = xParameters.is() ? xParameters->getParameters() : Reference<XIndexAccess>();
1698 sal_Int32 nParamCount = xParamsAsIndicies.is() ? xParamsAsIndicies->getCount() : 0;
1699 std::vector<bool, std::allocator<bool> > aNewParameterSet( _aParametersSet );
1700 if ( nParamCount && std::count(aNewParameterSet.begin(),aNewParameterSet.end(),true) != nParamCount )
1702 static const OUString PROPERTY_NAME(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME));
1703 aNewParameterSet.resize(nParamCount ,false);
1704 typedef std::map< OUString, std::vector<sal_Int32> > TParameterPositions;
1705 TParameterPositions aParameterNames;
1706 for(sal_Int32 i = 0; i < nParamCount; ++i)
1708 Reference<XPropertySet> xParam(xParamsAsIndicies->getByIndex(i),UNO_QUERY);
1709 OUString sName;
1710 xParam->getPropertyValue(PROPERTY_NAME) >>= sName;
1712 TParameterPositions::const_iterator aFind = aParameterNames.find(sName);
1713 if ( aFind != aParameterNames.end() )
1714 aNewParameterSet[i] = true;
1715 aParameterNames[sName].push_back(i+1);
1717 // build an interaction request
1718 // two continuations (Ok and Cancel)
1719 OInteractionAbort* pAbort = new OInteractionAbort;
1720 OParameterContinuation* pParams = new OParameterContinuation;
1721 // the request
1722 ParametersRequest aRequest;
1723 Reference<XIndexAccess> xWrappedParameters = new OParameterWrapper(aNewParameterSet,xParamsAsIndicies);
1724 aRequest.Parameters = xWrappedParameters;
1725 aRequest.Connection = _xConnection;
1726 OInteractionRequest* pRequest = new OInteractionRequest(makeAny(aRequest));
1727 Reference< XInteractionRequest > xRequest(pRequest);
1728 // some knittings
1729 pRequest->addContinuation(pAbort);
1730 pRequest->addContinuation(pParams);
1732 // execute the request
1733 _rxHandler->handle(xRequest);
1735 if (!pParams->wasSelected())
1737 // canceled by the user (i.e. (s)he canceled the dialog)
1738 RowSetVetoException e;
1739 e.ErrorCode = ParameterInteractionCancelled;
1740 throw e;
1743 // now transfer the values from the continuation object to the parameter columns
1744 Sequence< PropertyValue > aFinalValues = pParams->getValues();
1745 const PropertyValue* pFinalValues = aFinalValues.getConstArray();
1746 for (sal_Int32 i=0; i<aFinalValues.getLength(); ++i, ++pFinalValues)
1748 Reference< XPropertySet > xParamColumn(xWrappedParameters->getByIndex(i),UNO_QUERY);
1749 if (xParamColumn.is())
1751 OUString sName;
1752 xParamColumn->getPropertyValue(PROPERTY_NAME) >>= sName;
1753 OSL_ENSURE(sName == pFinalValues->Name, "::dbaui::askForParameters: inconsistent parameter names!");
1755 // determine the field type and ...
1756 sal_Int32 nParamType = 0;
1757 xParamColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)) >>= nParamType;
1758 // ... the scale of the parameter column
1759 sal_Int32 nScale = 0;
1760 if (hasProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE), xParamColumn))
1761 xParamColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE)) >>= nScale;
1762 // (the index of the parameters is one-based)
1763 TParameterPositions::const_iterator aFind = aParameterNames.find(pFinalValues->Name);
1764 for(const auto& rItem : aFind->second)
1766 if ( _aParametersSet.empty() || !_aParametersSet[rItem-1] )
1768 _xParameters->setObjectWithInfo(rItem, pFinalValues->Value, nParamType, nScale);
1776 void setObjectWithInfo(const Reference<XParameters>& _xParams,
1777 sal_Int32 parameterIndex,
1778 const Any& x,
1779 sal_Int32 sqlType,
1780 sal_Int32 scale)
1782 ORowSetValue aVal;
1783 aVal.fill(x);
1784 setObjectWithInfo(_xParams,parameterIndex,aVal,sqlType,scale);
1787 void setObjectWithInfo(const Reference<XParameters>& _xParams,
1788 sal_Int32 parameterIndex,
1789 const ::connectivity::ORowSetValue& _rValue,
1790 sal_Int32 sqlType,
1791 sal_Int32 scale)
1793 if ( _rValue.isNull() )
1794 _xParams->setNull(parameterIndex,sqlType);
1795 else
1797 switch(sqlType)
1799 case DataType::DECIMAL:
1800 case DataType::NUMERIC:
1801 _xParams->setObjectWithInfo(parameterIndex,_rValue.makeAny(),sqlType,scale);
1802 break;
1803 case DataType::CHAR:
1804 case DataType::VARCHAR:
1805 case DataType::LONGVARCHAR:
1806 _xParams->setString(parameterIndex,_rValue);
1807 break;
1808 case DataType::CLOB:
1810 Any x(_rValue.makeAny());
1811 OUString sValue;
1812 if ( x >>= sValue )
1813 _xParams->setString(parameterIndex,sValue);
1814 else
1816 Reference< XClob > xClob;
1817 if(x >>= xClob)
1818 _xParams->setClob(parameterIndex,xClob);
1819 else
1821 Reference< css::io::XInputStream > xStream;
1822 if(x >>= xStream)
1823 _xParams->setCharacterStream(parameterIndex,xStream,xStream->available());
1827 break;
1828 case DataType::BIGINT:
1829 if ( _rValue.isSigned() )
1830 _xParams->setLong(parameterIndex,_rValue);
1831 else
1832 _xParams->setString(parameterIndex,_rValue);
1833 break;
1835 case DataType::FLOAT:
1836 _xParams->setFloat(parameterIndex,_rValue);
1837 break;
1838 case DataType::REAL:
1839 case DataType::DOUBLE:
1840 _xParams->setDouble(parameterIndex,_rValue);
1841 break;
1842 case DataType::DATE:
1843 _xParams->setDate(parameterIndex,_rValue);
1844 break;
1845 case DataType::TIME:
1846 _xParams->setTime(parameterIndex,_rValue);
1847 break;
1848 case DataType::TIMESTAMP:
1849 _xParams->setTimestamp(parameterIndex,_rValue);
1850 break;
1851 case DataType::BINARY:
1852 case DataType::VARBINARY:
1853 case DataType::LONGVARBINARY:
1854 case DataType::BLOB:
1856 Any x(_rValue.makeAny());
1857 Sequence< sal_Int8> aBytes;
1858 if(x >>= aBytes)
1859 _xParams->setBytes(parameterIndex,aBytes);
1860 else
1862 Reference< XBlob > xBlob;
1863 if(x >>= xBlob)
1864 _xParams->setBlob(parameterIndex,xBlob);
1865 else
1867 Reference< XClob > xClob;
1868 if(x >>= xClob)
1869 _xParams->setClob(parameterIndex,xClob);
1870 else
1872 Reference< css::io::XInputStream > xBinStream;
1873 if(x >>= xBinStream)
1874 _xParams->setBinaryStream(parameterIndex,xBinStream,xBinStream->available());
1879 break;
1880 case DataType::BIT:
1881 case DataType::BOOLEAN:
1882 _xParams->setBoolean(parameterIndex,static_cast<bool>(_rValue));
1883 break;
1884 case DataType::TINYINT:
1885 if ( _rValue.isSigned() )
1886 _xParams->setByte(parameterIndex,_rValue);
1887 else
1888 _xParams->setShort(parameterIndex,_rValue);
1889 break;
1890 case DataType::SMALLINT:
1891 if ( _rValue.isSigned() )
1892 _xParams->setShort(parameterIndex,_rValue);
1893 else
1894 _xParams->setInt(parameterIndex,_rValue);
1895 break;
1896 case DataType::INTEGER:
1897 if ( _rValue.isSigned() )
1898 _xParams->setInt(parameterIndex,_rValue);
1899 else
1900 _xParams->setLong(parameterIndex,_rValue);
1901 break;
1902 default:
1904 ::connectivity::SharedResources aResources;
1905 const OUString sError( aResources.getResourceStringWithSubstitution(
1906 STR_UNKNOWN_PARA_TYPE,
1907 "$position$", OUString::number(parameterIndex)
1908 ) );
1909 ::dbtools::throwGenericSQLException(sError,nullptr);
1915 void getBooleanComparisonPredicate( const OUString& _rExpression, const bool _bValue, const sal_Int32 _nBooleanComparisonMode,
1916 OUStringBuffer& _out_rSQLPredicate )
1918 switch ( _nBooleanComparisonMode )
1920 case BooleanComparisonMode::IS_LITERAL:
1921 _out_rSQLPredicate.append( _rExpression );
1922 if ( _bValue )
1923 _out_rSQLPredicate.append( " IS TRUE" );
1924 else
1925 _out_rSQLPredicate.append( " IS FALSE" );
1926 break;
1928 case BooleanComparisonMode::EQUAL_LITERAL:
1929 _out_rSQLPredicate.append( _rExpression );
1930 _out_rSQLPredicate.appendAscii( _bValue ? " = TRUE" : " = FALSE" );
1931 break;
1933 case BooleanComparisonMode::ACCESS_COMPAT:
1934 if ( _bValue )
1936 _out_rSQLPredicate.append( " NOT ( ( " );
1937 _out_rSQLPredicate.append( _rExpression );
1938 _out_rSQLPredicate.append( " = 0 ) OR ( " );
1939 _out_rSQLPredicate.append( _rExpression );
1940 _out_rSQLPredicate.append( " IS NULL ) )" );
1942 else
1944 _out_rSQLPredicate.append( _rExpression );
1945 _out_rSQLPredicate.append( " = 0" );
1947 break;
1949 case BooleanComparisonMode::EQUAL_INTEGER:
1950 // fall through
1951 default:
1952 _out_rSQLPredicate.append( _rExpression );
1953 _out_rSQLPredicate.appendAscii( _bValue ? " = 1" : " = 0" );
1954 break;
1958 } // namespace dbtools
1960 namespace connectivity
1962 void checkDisposed(bool _bThrow)
1964 if (_bThrow)
1965 throw DisposedException();
1969 OSQLColumns::Vector::const_iterator find(const OSQLColumns::Vector::const_iterator& first,
1970 const OSQLColumns::Vector::const_iterator& last,
1971 const OUString& _rVal,
1972 const ::comphelper::UStringMixEqual& _rCase)
1974 OUString sName = OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME);
1975 return find(first,last,sName,_rVal,_rCase);
1978 OSQLColumns::Vector::const_iterator findRealName(const OSQLColumns::Vector::const_iterator& first,
1979 const OSQLColumns::Vector::const_iterator& last,
1980 const OUString& _rVal,
1981 const ::comphelper::UStringMixEqual& _rCase)
1983 OUString sRealName = OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_REALNAME);
1984 return find(first,last,sRealName,_rVal,_rCase);
1987 OSQLColumns::Vector::const_iterator find(OSQLColumns::Vector::const_iterator first,
1988 const OSQLColumns::Vector::const_iterator& last,
1989 const OUString& _rProp,
1990 const OUString& _rVal,
1991 const ::comphelper::UStringMixEqual& _rCase)
1993 while (first != last && !_rCase(getString((*first)->getPropertyValue(_rProp)),_rVal))
1994 ++first;
1995 return first;
1998 namespace dbase
2000 bool dbfDecodeCharset(rtl_TextEncoding &_out_encoding, sal_uInt8 nType, sal_uInt8 nCodepage)
2002 switch (nType)
2004 // dBaseIII header doesn't contain language driver ID
2005 // See http://dbase.free.fr/tlcharge/structure%20tables.pdf
2006 case dBaseIII:
2007 case dBaseIIIMemo:
2008 break;
2009 case dBaseIV:
2010 case dBaseV:
2011 case VisualFoxPro:
2012 case VisualFoxProAuto:
2013 case dBaseFS:
2014 case dBaseFSMemo:
2015 case dBaseIVMemoSQL:
2016 case FoxProMemo:
2018 if (nCodepage != 0x00)
2020 auto eEncoding(RTL_TEXTENCODING_DONTKNOW);
2021 switch(nCodepage)
2023 case 0x01: eEncoding = RTL_TEXTENCODING_IBM_437; break; // DOS USA code page 437
2024 case 0x02: eEncoding = RTL_TEXTENCODING_IBM_850; break; // DOS Multilingual code page 850
2025 case 0x03: eEncoding = RTL_TEXTENCODING_MS_1252; break; // Windows ANSI code page 1252
2026 case 0x04: eEncoding = RTL_TEXTENCODING_APPLE_ROMAN; break; // Standard Macintosh
2027 case 0x64: eEncoding = RTL_TEXTENCODING_IBM_852; break; // EE MS-DOS code page 852
2028 case 0x65: eEncoding = RTL_TEXTENCODING_IBM_866; break; // Russian MS-DOS code page 866
2029 case 0x66: eEncoding = RTL_TEXTENCODING_IBM_865; break; // Nordic MS-DOS code page 865
2030 case 0x67: eEncoding = RTL_TEXTENCODING_IBM_861; break; // Icelandic MS-DOS
2031 //case 0x68: eEncoding = ; break; // Kamenicky (Czech) MS-DOS
2032 //case 0x69: eEncoding = ; break; // Mazovia (Polish) MS-DOS
2033 case 0x6A: eEncoding = RTL_TEXTENCODING_IBM_737; break; // Greek MS-DOS (437G)
2034 case 0x6B: eEncoding = RTL_TEXTENCODING_IBM_857; break; // Turkish MS-DOS
2035 case 0x6C: eEncoding = RTL_TEXTENCODING_IBM_863; break; // MS-DOS, Canada
2036 case 0x78: eEncoding = RTL_TEXTENCODING_MS_950; break; // Windows, Traditional Chinese
2037 case 0x79: eEncoding = RTL_TEXTENCODING_MS_949; break; // Windows, Korean (Hangul)
2038 case 0x7A: eEncoding = RTL_TEXTENCODING_MS_936; break; // Windows, Simplified Chinese
2039 case 0x7B: eEncoding = RTL_TEXTENCODING_MS_932; break; // Windows, Japanese (Shift-jis)
2040 case 0x7C: eEncoding = RTL_TEXTENCODING_MS_874; break; // Windows, Thai
2041 case 0x7D: eEncoding = RTL_TEXTENCODING_MS_1255; break; // Windows, Hebrew
2042 case 0x7E: eEncoding = RTL_TEXTENCODING_MS_1256; break; // Windows, Arabic
2043 case 0x96: eEncoding = RTL_TEXTENCODING_APPLE_CYRILLIC; break; // Russian Macintosh
2044 case 0x97: eEncoding = RTL_TEXTENCODING_APPLE_CENTEURO; break; // Eastern European Macintosh
2045 case 0x98: eEncoding = RTL_TEXTENCODING_APPLE_GREEK; break; // Greek Macintosh
2046 case 0xC8: eEncoding = RTL_TEXTENCODING_MS_1250; break; // Windows EE code page 1250
2047 case 0xC9: eEncoding = RTL_TEXTENCODING_MS_1251; break; // Russian Windows
2048 case 0xCA: eEncoding = RTL_TEXTENCODING_MS_1254; break; // Turkish Windows
2049 case 0xCB: eEncoding = RTL_TEXTENCODING_MS_1253; break; // Greek Windows
2050 case 0xCC: eEncoding = RTL_TEXTENCODING_MS_1257; break; // Windows, Baltic
2052 if(eEncoding != RTL_TEXTENCODING_DONTKNOW)
2054 _out_encoding = eEncoding;
2055 return true;
2060 return false;
2063 bool dbfReadCharset(rtl_TextEncoding &nCharSet, SvStream* dbf_Stream)
2065 sal_uInt8 nType=0;
2066 dbf_Stream->ReadUChar( nType );
2068 dbf_Stream->Seek(STREAM_SEEK_TO_BEGIN + 29);
2069 if (dbf_Stream->eof())
2071 return false;
2073 else
2075 sal_uInt8 nEncoding=0;
2076 dbf_Stream->ReadUChar( nEncoding );
2077 return dbfDecodeCharset(nCharSet, nType, nEncoding);
2083 } //namespace connectivity
2085 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */