Coverage Report

Created: 2026-06-30 11:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/connectivity/source/commontools/dbtools.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
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/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
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 .
18
 */
19
20
#include <connectivity/CommonTools.hxx>
21
#include <TConnection.hxx>
22
#include <ParameterCont.hxx>
23
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/XOfficeDatabaseDocument.hpp>
43
#include <com/sun/star/sdb/XParametersSupplier.hpp>
44
#include <com/sun/star/sdb/XQueriesSupplier.hpp>
45
#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
46
#include <com/sun/star/sdbc/ConnectionPool.hpp>
47
#include <com/sun/star/sdbc/DataType.hpp>
48
#include <com/sun/star/sdbc/XConnection.hpp>
49
#include <com/sun/star/sdbc/XDataSource.hpp>
50
#include <com/sun/star/sdbc/XParameters.hpp>
51
#include <com/sun/star/sdbc/XRow.hpp>
52
#include <com/sun/star/sdbc/XRowSet.hpp>
53
#include <com/sun/star/sdbc/XRowUpdate.hpp>
54
#include <com/sun/star/sdbcx/KeyType.hpp>
55
#include <com/sun/star/sdbcx/Privilege.hpp>
56
#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
57
#include <com/sun/star/sdbcx/XKeysSupplier.hpp>
58
#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
59
#include <com/sun/star/task/InteractionHandler.hpp>
60
#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
61
#include <com/sun/star/util/NumberFormat.hpp>
62
#include <com/sun/star/util/NumberFormatsSupplier.hpp>
63
#include <com/sun/star/util/XNumberFormatTypes.hpp>
64
65
#include <comphelper/extract.hxx>
66
#include <comphelper/interaction.hxx>
67
#include <comphelper/property.hxx>
68
#include <comphelper/propertysequence.hxx>
69
#include <comphelper/types.hxx>
70
#include <connectivity/conncleanup.hxx>
71
#include <connectivity/dbconversion.hxx>
72
#include <connectivity/dbexception.hxx>
73
#include <connectivity/dbtools.hxx>
74
#include <connectivity/FValue.hxx>
75
#include <connectivity/statementcomposer.hxx>
76
#include <o3tl/any.hxx>
77
#include <o3tl/safeint.hxx>
78
#include <osl/diagnose.h>
79
#include <rtl/ustrbuf.hxx>
80
#include <sal/log.hxx>
81
#include <comphelper/diagnose_ex.hxx>
82
#include <tools/stream.hxx>
83
#include <cppuhelper/implbase.hxx>
84
#include <strings.hrc>
85
#include <resource/sharedresources.hxx>
86
87
#include <algorithm>
88
#include <iterator>
89
#include <set>
90
91
using namespace ::comphelper;
92
using namespace ::com::sun::star::uno;
93
using namespace ::com::sun::star::io;
94
using namespace ::com::sun::star::awt;
95
using namespace ::com::sun::star::ui::dialogs;
96
using namespace ::com::sun::star::util;
97
using namespace ::com::sun::star::lang;
98
using namespace ::com::sun::star::beans;
99
using namespace ::com::sun::star::container;
100
using namespace ::com::sun::star::sdb;
101
using namespace ::com::sun::star::sdbc;
102
using namespace ::com::sun::star::sdbcx;
103
using namespace ::com::sun::star::task;
104
using namespace ::com::sun::star::form;
105
using namespace connectivity;
106
107
namespace dbtools
108
{
109
110
namespace
111
{
112
    typedef sal_Bool (SAL_CALL XDatabaseMetaData::*FMetaDataSupport)();
113
}
114
115
sal_Int32 getDefaultNumberFormat(const Reference< XPropertySet >& _xColumn,
116
                                 const Reference< XNumberFormatTypes >& _xTypes,
117
                                 const Locale& _rLocale)
118
0
{
119
0
    OSL_ENSURE(_xTypes.is() && _xColumn.is(), "dbtools::getDefaultNumberFormat: invalid arg !");
120
0
    if (!_xTypes.is() || !_xColumn.is())
121
0
        return NumberFormat::UNDEFINED;
122
123
0
    sal_Int32 nDataType = 0;
124
0
    sal_Int32 nScale = 0;
125
0
    try
126
0
    {
127
        // determine the datatype of the column
128
0
        _xColumn->getPropertyValue(u"Type"_ustr) >>= nDataType;
129
130
0
        if (DataType::NUMERIC == nDataType || DataType::DECIMAL == nDataType)
131
0
            _xColumn->getPropertyValue(u"Scale"_ustr) >>= nScale;
132
0
    }
133
0
    catch (Exception&)
134
0
    {
135
0
        return NumberFormat::UNDEFINED;
136
0
    }
137
0
    return getDefaultNumberFormat(nDataType,
138
0
                    nScale,
139
0
                    ::cppu::any2bool(_xColumn->getPropertyValue(u"IsCurrency"_ustr)),
140
0
                    _xTypes,
141
0
                    _rLocale);
142
0
}
143
144
sal_Int32 getDefaultNumberFormat(sal_Int32 _nDataType,
145
                                 sal_Int32 _nScale,
146
                                 bool _bIsCurrency,
147
                                 const Reference< XNumberFormatTypes >& _xTypes,
148
                                 const Locale& _rLocale)
149
0
{
150
0
    OSL_ENSURE(_xTypes.is() , "dbtools::getDefaultNumberFormat: invalid arg !");
151
0
    if (!_xTypes.is())
152
0
        return NumberFormat::UNDEFINED;
153
154
0
    sal_Int32 nFormat = 0;
155
0
    sal_Int32 nNumberType   = _bIsCurrency ? NumberFormat::CURRENCY : NumberFormat::NUMBER;
156
0
    switch (_nDataType)
157
0
    {
158
0
        case DataType::BIT:
159
0
        case DataType::BOOLEAN:
160
0
            nFormat = _xTypes->getStandardFormat(NumberFormat::LOGICAL, _rLocale);
161
0
            break;
162
0
        case DataType::TINYINT:
163
0
        case DataType::SMALLINT:
164
0
        case DataType::INTEGER:
165
0
        case DataType::BIGINT:
166
0
        case DataType::FLOAT:
167
0
        case DataType::REAL:
168
0
        case DataType::DOUBLE:
169
0
        case DataType::NUMERIC:
170
0
        case DataType::DECIMAL:
171
0
        {
172
0
            try
173
0
            {
174
0
                nFormat = _xTypes->getStandardFormat(static_cast<sal_Int16>(nNumberType), _rLocale);
175
0
                if(_nScale > 0)
176
0
                {
177
                    // generate a new format if necessary
178
0
                    Reference< XNumberFormats > xFormats(_xTypes, UNO_QUERY);
179
0
                    OUString sNewFormat = xFormats->generateFormat( 0, _rLocale, false, false, static_cast<sal_Int16>(_nScale), 1);
180
181
                    // and add it to the formatter if necessary
182
0
                    nFormat = xFormats->queryKey(sNewFormat, _rLocale, false);
183
0
                    if (nFormat == sal_Int32(-1))
184
0
                        nFormat = xFormats->addNew(sNewFormat, _rLocale);
185
0
                }
186
0
            }
187
0
            catch (Exception&)
188
0
            {
189
0
                nFormat = _xTypes->getStandardFormat(static_cast<sal_Int16>(nNumberType), _rLocale);
190
0
            }
191
0
        }   break;
192
0
        case DataType::CHAR:
193
0
        case DataType::VARCHAR:
194
0
        case DataType::LONGVARCHAR:
195
0
        case DataType::CLOB:
196
0
            nFormat = _xTypes->getStandardFormat(NumberFormat::TEXT, _rLocale);
197
0
            break;
198
0
        case DataType::DATE:
199
0
            nFormat = _xTypes->getStandardFormat(NumberFormat::DATE, _rLocale);
200
0
            break;
201
0
        case DataType::TIME:
202
0
            nFormat = _xTypes->getStandardFormat(NumberFormat::TIME, _rLocale);
203
0
            break;
204
0
        case DataType::TIMESTAMP:
205
0
            nFormat = _xTypes->getStandardFormat(NumberFormat::DATETIME, _rLocale);
206
0
            break;
207
0
        case DataType::BINARY:
208
0
        case DataType::VARBINARY:
209
0
        case DataType::LONGVARBINARY:
210
0
        case DataType::SQLNULL:
211
0
        case DataType::OTHER:
212
0
        case DataType::OBJECT:
213
0
        case DataType::DISTINCT:
214
0
        case DataType::STRUCT:
215
0
        case DataType::ARRAY:
216
0
        case DataType::BLOB:
217
0
        case DataType::REF:
218
0
        default:
219
0
            nFormat = _xTypes->getStandardFormat(NumberFormat::UNDEFINED, _rLocale);
220
0
    }
221
0
    return nFormat;
222
0
}
223
224
static Reference< XConnection> findConnection(const Reference< XInterface >& xParent)
225
0
{
226
0
    Reference< XConnection> xConnection(xParent, UNO_QUERY);
227
0
    if (!xConnection.is())
228
0
    {
229
0
        Reference< XChild> xChild(xParent, UNO_QUERY);
230
0
        if (xChild.is())
231
0
            xConnection = findConnection(xChild->getParent());
232
0
    }
233
0
    return xConnection;
234
0
}
235
236
static Reference< XDataSource> getDataSource_allowException(
237
            const OUString& _rsTitleOrPath,
238
            const Reference< XComponentContext >& _rxContext )
239
0
{
240
0
    ENSURE_OR_RETURN( !_rsTitleOrPath.isEmpty(), "getDataSource_allowException: invalid arg !", nullptr );
241
242
0
    Reference< XDatabaseContext> xDatabaseContext = DatabaseContext::create(_rxContext);
243
244
0
    return Reference< XDataSource >( xDatabaseContext->getByName( _rsTitleOrPath ), UNO_QUERY );
245
0
}
246
247
Reference< XDataSource > getDataSource(
248
            const OUString& _rsTitleOrPath,
249
            const Reference< XComponentContext >& _rxContext )
250
0
{
251
0
    Reference< XDataSource > xDS;
252
0
    try
253
0
    {
254
0
        xDS = getDataSource_allowException( _rsTitleOrPath, _rxContext );
255
0
    }
256
0
    catch( const Exception& )
257
0
    {
258
0
        DBG_UNHANDLED_EXCEPTION("connectivity.commontools");
259
0
    }
260
261
0
    return xDS;
262
0
}
263
264
static Reference< XConnection > getConnection_allowException(
265
            const OUString& _rsTitleOrPath,
266
            const OUString& _rsUser,
267
            const OUString& _rsPwd,
268
            const Reference< XComponentContext>& _rxContext,
269
            const Reference< XWindow >& _rxParent)
270
0
{
271
0
    Reference< XDataSource> xDataSource( getDataSource_allowException(_rsTitleOrPath, _rxContext) );
272
0
    Reference<XConnection> xConnection;
273
0
    if (xDataSource.is())
274
0
    {
275
276
        //set ParentWindow for dialog, but just for the duration of this
277
        //call, undo at end of scope
278
0
        Reference<XInitialization> xIni(xDataSource, UNO_QUERY);
279
0
        if (xIni.is())
280
0
        {
281
0
            Sequence< Any > aArgs{ Any(NamedValue( u"ParentWindow"_ustr, Any(_rxParent) )) };
282
0
            xIni->initialize(aArgs);
283
0
        }
284
285
        // do it with interaction handler
286
0
        if(_rsUser.isEmpty() || _rsPwd.isEmpty())
287
0
        {
288
0
            Reference<XPropertySet> xProp(xDataSource,UNO_QUERY);
289
0
            OUString sPwd, sUser;
290
0
            bool bPwdReq = false;
291
0
            try
292
0
            {
293
0
                xProp->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PASSWORD)) >>= sPwd;
294
0
                bPwdReq = ::cppu::any2bool(xProp->getPropertyValue(u"IsPasswordRequired"_ustr));
295
0
                xProp->getPropertyValue(u"User"_ustr) >>= sUser;
296
0
            }
297
0
            catch(Exception&)
298
0
            {
299
0
                OSL_FAIL("dbtools::getConnection: error while retrieving data source properties!");
300
0
            }
301
0
            if(bPwdReq && sPwd.isEmpty())
302
0
            {   // password required, but empty -> connect using an interaction handler
303
0
                Reference<XCompletedConnection> xConnectionCompletion(xProp, UNO_QUERY);
304
0
                if (xConnectionCompletion.is())
305
0
                {   // instantiate the default SDB interaction handler
306
0
                    Reference< XInteractionHandler > xHandler =
307
0
                        InteractionHandler::createWithParent(_rxContext, _rxParent);
308
0
                    xConnection = xConnectionCompletion->connectWithCompletion(xHandler);
309
0
                }
310
0
            }
311
0
            else
312
0
                xConnection = xDataSource->getConnection(sUser, sPwd);
313
0
        }
314
0
        if(!xConnection.is()) // try to get one if not already have one, just to make sure
315
0
            xConnection = xDataSource->getConnection(_rsUser, _rsPwd);
316
317
0
        if (xIni.is())
318
0
        {
319
0
            Sequence< Any > aArgs{ Any(NamedValue( u"ParentWindow"_ustr, Any(Reference<XWindow>()) )) };
320
0
            xIni->initialize(aArgs);
321
0
        }
322
323
0
    }
324
0
    return xConnection;
325
0
}
326
327
Reference< XConnection> getConnection_withFeedback(const OUString& _rDataSourceName,
328
        const OUString& _rUser, const OUString& _rPwd, const Reference< XComponentContext>& _rxContext,
329
        const Reference< XWindow >& _rxParent)
330
0
{
331
0
    Reference< XConnection > xReturn;
332
0
    try
333
0
    {
334
0
        xReturn = getConnection_allowException(_rDataSourceName, _rUser, _rPwd, _rxContext, _rxParent);
335
0
    }
336
0
    catch(SQLException&)
337
0
    {
338
        // allowed to pass
339
0
        throw;
340
0
    }
341
0
    catch(Exception&)
342
0
    {
343
0
        TOOLS_WARN_EXCEPTION( "connectivity.commontools", "::dbtools::getConnection_withFeedback: unexpected (non-SQL) exception caught!");
344
0
    }
345
0
    return xReturn;
346
0
}
347
348
Reference< XConnection> getConnection(const Reference< XRowSet>& _rxRowSet)
349
0
{
350
0
    Reference< XConnection> xReturn;
351
0
    Reference< XPropertySet> xRowSetProps(_rxRowSet, UNO_QUERY);
352
0
    if (xRowSetProps.is())
353
0
        xRowSetProps->getPropertyValue(u"ActiveConnection"_ustr) >>= xReturn;
354
0
    return xReturn;
355
0
}
356
357
// helper function which allows to implement both the connectRowset and the ensureRowSetConnection semantics
358
// if connectRowset (which is deprecated) is removed, this function and one of its parameters are
359
// not needed anymore, the whole implementation can be moved into ensureRowSetConnection then)
360
static SharedConnection lcl_connectRowSet(const Reference< XRowSet>& _rxRowSet, const Reference< XComponentContext >& _rxContext,
361
        bool _bAttachAutoDisposer, const Reference< XWindow >& _rxParent)
362
0
{
363
0
    SharedConnection xConnection;
364
365
0
    do
366
0
    {
367
0
        Reference< XPropertySet> xRowSetProps(_rxRowSet, UNO_QUERY);
368
0
        if ( !xRowSetProps.is() )
369
0
            break;
370
371
        // 1. already connected?
372
0
        Reference< XConnection > xExistingConn(
373
0
            xRowSetProps->getPropertyValue(u"ActiveConnection"_ustr),
374
0
            UNO_QUERY );
375
376
0
        if  (   xExistingConn.is()
377
            // 2. embedded in a database?
378
0
            ||  isEmbeddedInDatabase( _rxRowSet, xExistingConn )
379
            // 3. is there a connection in the parent hierarchy?
380
0
            ||  ( xExistingConn = findConnection( _rxRowSet ) ).is()
381
0
            )
382
0
        {
383
0
            xRowSetProps->setPropertyValue(u"ActiveConnection"_ustr, Any( xExistingConn ) );
384
            // no auto disposer needed, since we did not create the connection
385
386
0
            xConnection.reset( xExistingConn, SharedConnection::NoTakeOwnership );
387
0
            break;
388
0
        }
389
390
        // build a connection with its current settings (4. data source name, or 5. URL)
391
392
0
        static constexpr OUString sUserProp( u"User"_ustr );
393
0
        OUString sDataSourceName;
394
0
        xRowSetProps->getPropertyValue(u"DataSourceName"_ustr) >>= sDataSourceName;
395
0
        OUString sURL;
396
0
        xRowSetProps->getPropertyValue(u"URL"_ustr) >>= sURL;
397
398
0
        Reference< XConnection > xPureConnection;
399
0
        if (!sDataSourceName.isEmpty())
400
0
        {   // the row set's data source property is set
401
            // -> try to connect, get user and pwd setting for that
402
0
            OUString sUser, sPwd;
403
404
0
            if (hasProperty(sUserProp, xRowSetProps))
405
0
                xRowSetProps->getPropertyValue(sUserProp) >>= sUser;
406
0
            if (hasProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PASSWORD), xRowSetProps))
407
0
                xRowSetProps->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PASSWORD)) >>= sPwd;
408
409
0
            xPureConnection = getConnection_allowException( sDataSourceName, sUser, sPwd, _rxContext, _rxParent );
410
0
        }
411
0
        else if (!sURL.isEmpty())
412
0
        {   // the row set has no data source, but a connection url set
413
            // -> try to connection with that url
414
0
            Reference< XConnectionPool > xDriverManager;
415
0
            try {
416
0
                xDriverManager = ConnectionPool::create( _rxContext );
417
0
            } catch( const Exception& ) {  }
418
0
            if (xDriverManager.is())
419
0
            {
420
0
                OUString sUser, sPwd;
421
0
                if (hasProperty(sUserProp, xRowSetProps))
422
0
                    xRowSetProps->getPropertyValue(sUserProp) >>= sUser;
423
0
                if (hasProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PASSWORD), xRowSetProps))
424
0
                    xRowSetProps->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PASSWORD)) >>= sPwd;
425
0
                if (!sUser.isEmpty())
426
0
                {   // use user and pwd together with the url
427
0
                    auto aInfo(::comphelper::InitPropertySequence({
428
0
                        { "user", Any(sUser) },
429
0
                        { "password", Any(sPwd) }
430
0
                    }));
431
0
                    xPureConnection = xDriverManager->getConnectionWithInfo( sURL, aInfo );
432
0
                }
433
0
                else
434
                    // just use the url
435
0
                    xPureConnection = xDriverManager->getConnection( sURL );
436
0
            }
437
0
        }
438
0
        xConnection.reset(
439
0
            xPureConnection,
440
0
            _bAttachAutoDisposer ? SharedConnection::NoTakeOwnership : SharedConnection::TakeOwnership
441
            /* take ownership if and only if we're *not* going to auto-dispose the connection */
442
0
        );
443
444
        // now if we created a connection, forward it to the row set
445
0
        if ( xConnection.is() )
446
0
        {
447
0
            try
448
0
            {
449
0
                if ( _bAttachAutoDisposer )
450
0
                {
451
0
                    new OAutoConnectionDisposer( _rxRowSet, xConnection );
452
0
                }
453
0
                else
454
0
                    xRowSetProps->setPropertyValue(
455
0
                        u"ActiveConnection"_ustr,
456
0
                        Any( xConnection.getTyped() )
457
0
                    );
458
0
            }
459
0
            catch(Exception&)
460
0
            {
461
0
                TOOLS_WARN_EXCEPTION( "connectivity.commontools", "EXception when we set the new active connection!");
462
0
            }
463
0
        }
464
0
    }
465
0
    while ( false );
466
467
0
    return xConnection;
468
0
}
469
470
Reference< XConnection> connectRowset(const Reference< XRowSet>& _rxRowSet, const Reference< XComponentContext >& _rxContext, const Reference< XWindow >& _rxParent)
471
0
{
472
0
    SharedConnection xConnection = lcl_connectRowSet( _rxRowSet, _rxContext, true, _rxParent );
473
0
    return xConnection.getTyped();
474
0
}
475
476
SharedConnection ensureRowSetConnection(const Reference< XRowSet>& _rxRowSet, const Reference< XComponentContext>& _rxContext, const Reference< XWindow >& _rxParent)
477
0
{
478
0
    return lcl_connectRowSet( _rxRowSet, _rxContext, false/*bUseAutoConnectionDisposer*/, _rxParent );
479
0
}
480
481
Reference< XNameAccess> getTableFields(const Reference< XConnection>& _rxConn,const OUString& _rName)
482
0
{
483
0
    Reference< XComponent > xDummy;
484
0
    return getFieldsByCommandDescriptor( _rxConn, CommandType::TABLE, _rName, xDummy );
485
0
}
486
487
Reference< XNameAccess> getPrimaryKeyColumns_throw(const Any& i_aTable)
488
0
{
489
0
    const Reference< XPropertySet > xTable(i_aTable,UNO_QUERY_THROW);
490
0
    return getPrimaryKeyColumns_throw(xTable);
491
0
}
492
493
Reference< XNameAccess> getPrimaryKeyColumns_throw(const Reference< XPropertySet >& i_xTable)
494
162k
{
495
162k
    Reference<XNameAccess> xKeyColumns;
496
162k
    const Reference<XKeysSupplier> xKeySup(i_xTable,UNO_QUERY);
497
162k
    if ( xKeySup.is() )
498
162k
    {
499
162k
        const Reference<XIndexAccess> xKeys = xKeySup->getKeys();
500
162k
        if ( xKeys.is() )
501
162k
        {
502
162k
            ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap();
503
162k
            const OUString& sPropName = rPropMap.getNameByIndex(PROPERTY_ID_TYPE);
504
162k
            Reference<XPropertySet> xProp;
505
162k
            const sal_Int32 nCount = xKeys->getCount();
506
162k
            for(sal_Int32 i = 0;i< nCount;++i)
507
0
            {
508
0
                xProp.set(xKeys->getByIndex(i),UNO_QUERY_THROW);
509
0
                sal_Int32 nKeyType = 0;
510
0
                xProp->getPropertyValue(sPropName) >>= nKeyType;
511
0
                if(KeyType::PRIMARY == nKeyType)
512
0
                {
513
0
                    const Reference<XColumnsSupplier> xKeyColsSup(xProp,UNO_QUERY_THROW);
514
0
                    xKeyColumns = xKeyColsSup->getColumns();
515
0
                    break;
516
0
                }
517
0
            }
518
162k
        }
519
162k
    }
520
521
162k
    return xKeyColumns;
522
162k
}
523
524
namespace
525
{
526
    enum FieldLookupState
527
    {
528
        HANDLE_TABLE, HANDLE_QUERY, HANDLE_SQL, RETRIEVE_OBJECT, RETRIEVE_COLUMNS, DONE, FAILED
529
    };
530
}
531
532
Reference< XNameAccess > getFieldsByCommandDescriptor( const Reference< XConnection >& _rxConnection,
533
    const sal_Int32 _nCommandType, const OUString& _rCommand,
534
    Reference< XComponent >& _rxKeepFieldsAlive, SQLExceptionInfo* _pErrorInfo )
535
0
{
536
0
    OSL_PRECOND( _rxConnection.is(), "::dbtools::getFieldsByCommandDescriptor: invalid connection!" );
537
0
    OSL_PRECOND( ( CommandType::TABLE == _nCommandType ) || ( CommandType::QUERY == _nCommandType ) || ( CommandType::COMMAND == _nCommandType ),
538
0
        "::dbtools::getFieldsByCommandDescriptor: invalid command type!" );
539
0
    OSL_PRECOND( !_rCommand.isEmpty(), "::dbtools::getFieldsByCommandDescriptor: invalid command (empty)!" );
540
541
0
    Reference< XNameAccess > xFields;
542
543
    // reset the error
544
0
    if ( _pErrorInfo )
545
0
        *_pErrorInfo = SQLExceptionInfo();
546
    // reset the ownership holder
547
0
    _rxKeepFieldsAlive.clear();
548
549
    // go for the fields
550
0
    try
551
0
    {
552
        // some kind of state machine to ease the sharing of code
553
0
        FieldLookupState eState = FAILED;
554
0
        switch ( _nCommandType )
555
0
        {
556
0
            case CommandType::TABLE:
557
0
                eState = HANDLE_TABLE;
558
0
                break;
559
0
            case CommandType::QUERY:
560
0
                eState = HANDLE_QUERY;
561
0
                break;
562
0
            case CommandType::COMMAND:
563
0
                eState = HANDLE_SQL;
564
0
                break;
565
0
        }
566
567
        // needed in various states:
568
0
        Reference< XNameAccess > xObjectCollection;
569
0
        Reference< XColumnsSupplier > xSupplyColumns;
570
571
        // go!
572
0
        while ( ( DONE != eState ) && ( FAILED != eState ) )
573
0
        {
574
0
            switch ( eState )
575
0
            {
576
0
                case HANDLE_TABLE:
577
0
                {
578
                    // initial state for handling the tables
579
580
                    // get the table objects
581
0
                    Reference< XTablesSupplier > xSupplyTables( _rxConnection, UNO_QUERY );
582
0
                    if ( xSupplyTables.is() )
583
0
                        xObjectCollection = xSupplyTables->getTables();
584
                    // if something went wrong 'til here, then this will be handled in the next state
585
586
                    // next state: get the object
587
0
                    eState = RETRIEVE_OBJECT;
588
0
                }
589
0
                break;
590
591
0
                case HANDLE_QUERY:
592
0
                {
593
                    // initial state for handling the tables
594
595
                    // get the table objects
596
0
                    Reference< XQueriesSupplier > xSupplyQueries( _rxConnection, UNO_QUERY );
597
0
                    if ( xSupplyQueries.is() )
598
0
                        xObjectCollection = xSupplyQueries->getQueries();
599
                    // if something went wrong 'til here, then this will be handled in the next state
600
601
                    // next state: get the object
602
0
                    eState = RETRIEVE_OBJECT;
603
0
                }
604
0
                break;
605
606
0
                case RETRIEVE_OBJECT:
607
                    // here we should have an object (aka query or table) collection, and are going
608
                    // to retrieve the desired object
609
610
                    // next state: default to FAILED
611
0
                    eState = FAILED;
612
613
0
                    OSL_ENSURE( xObjectCollection.is(), "::dbtools::getFieldsByCommandDescriptor: invalid connection (no sdb.Connection, or no Tables-/QueriesSupplier)!");
614
0
                    if ( xObjectCollection.is() && xObjectCollection->hasByName( _rCommand ) )
615
0
                    {
616
0
                        xObjectCollection->getByName( _rCommand ) >>= xSupplyColumns;
617
                            // (xSupplyColumns being NULL will be handled in the next state)
618
619
                        // next: go for the columns
620
0
                        eState = RETRIEVE_COLUMNS;
621
0
                    }
622
0
                    break;
623
624
0
                case RETRIEVE_COLUMNS:
625
0
                    OSL_ENSURE( xSupplyColumns.is(), "::dbtools::getFieldsByCommandDescriptor: could not retrieve the columns supplier!" );
626
627
                    // next state: default to FAILED
628
0
                    eState = FAILED;
629
630
0
                    if ( xSupplyColumns.is() )
631
0
                    {
632
0
                        xFields = xSupplyColumns->getColumns();
633
                        // that's it
634
0
                        eState = DONE;
635
0
                    }
636
0
                    break;
637
638
0
                case HANDLE_SQL:
639
0
                {
640
0
                    OUString sStatementToExecute( _rCommand );
641
642
                    // well, the main problem here is to handle statements which contain a parameter
643
                    // If we would simply execute a parametrized statement, then this will fail because
644
                    // we cannot supply any parameter values.
645
                    // Thus, we try to analyze the statement, and to append a WHERE 0=1 filter criterion
646
                    // This should cause every driver to not really execute the statement, but to return
647
                    // an empty result set with the proper structure. We then can use this result set
648
                    // to retrieve the columns.
649
650
0
                    try
651
0
                    {
652
0
                        Reference< XMultiServiceFactory > xComposerFac( _rxConnection, UNO_QUERY );
653
654
0
                        if ( xComposerFac.is() )
655
0
                        {
656
0
                            Reference< XSingleSelectQueryComposer > xComposer(xComposerFac->createInstance(u"com.sun.star.sdb.SingleSelectQueryComposer"_ustr),UNO_QUERY);
657
0
                            if ( xComposer.is() )
658
0
                            {
659
0
                                xComposer->setQuery( sStatementToExecute );
660
661
                                // Now set the filter to a dummy restriction which will result in an empty
662
                                // result set.
663
0
                                xComposer->setFilter( u"0=1"_ustr );
664
0
                                sStatementToExecute = xComposer->getQuery( );
665
0
                            }
666
0
                        }
667
0
                    }
668
0
                    catch( const Exception& )
669
0
                    {
670
                        // silent this error, this was just a try. If we're here, we did not change sStatementToExecute,
671
                        // so it will still be _rCommand, which then will be executed without being touched
672
0
                    }
673
674
                    // now execute
675
0
                    Reference< XPreparedStatement > xStatement = _rxConnection->prepareStatement( sStatementToExecute );
676
                    // transfer ownership of this temporary object to the caller
677
0
                    _rxKeepFieldsAlive.set(xStatement, css::uno::UNO_QUERY);
678
679
                    // set the "MaxRows" to 0. This is just in case our attempt to append a 0=1 filter
680
                    // failed - in this case, the MaxRows restriction should at least ensure that there
681
                    // is no data returned (which would be potentially expensive)
682
0
                    Reference< XPropertySet > xStatementProps( xStatement,UNO_QUERY );
683
0
                    try
684
0
                    {
685
0
                        if ( xStatementProps.is() )
686
0
                            xStatementProps->setPropertyValue( u"MaxRows"_ustr,  Any( sal_Int32( 0 ) ) );
687
0
                    }
688
0
                    catch( const Exception& )
689
0
                    {
690
0
                        OSL_FAIL( "::dbtools::getFieldsByCommandDescriptor: could not set the MaxRows!" );
691
                        // oh damn. Not much of a chance to recover, we will no retrieve the complete
692
                        // full blown result set
693
0
                    }
694
695
0
                    xSupplyColumns.set(xStatement->executeQuery(), css::uno::UNO_QUERY);
696
                    // this should have given us a result set which does not contain any data, but
697
                    // the structural information we need
698
699
                    // so the next state is to get the columns
700
0
                    eState = RETRIEVE_COLUMNS;
701
0
                }
702
0
                break;
703
704
0
                default:
705
0
                    OSL_FAIL( "::dbtools::getFieldsByCommandDescriptor: oops! unhandled state here!" );
706
0
                    eState = FAILED;
707
0
            }
708
0
        }
709
0
    }
710
0
    catch( const SQLContext& e ) { if ( _pErrorInfo ) *_pErrorInfo = SQLExceptionInfo( e ); }
711
0
    catch( const SQLWarning& e ) { if ( _pErrorInfo ) *_pErrorInfo = SQLExceptionInfo( e ); }
712
0
    catch( const SQLException& e ) { if ( _pErrorInfo ) *_pErrorInfo = SQLExceptionInfo( e ); }
713
0
    catch( const Exception& )
714
0
    {
715
0
        TOOLS_WARN_EXCEPTION( "connectivity.commontools", "::dbtools::getFieldsByCommandDescriptor: caught an exception while retrieving the fields!" );
716
0
    }
717
718
0
    return xFields;
719
0
}
720
721
Sequence< OUString > getFieldNamesByCommandDescriptor( const Reference< XConnection >& _rxConnection,
722
    const sal_Int32 _nCommandType, const OUString& _rCommand,
723
    SQLExceptionInfo* _pErrorInfo )
724
0
{
725
    // get the container for the fields
726
0
    Reference< XComponent > xKeepFieldsAlive;
727
0
    Reference< XNameAccess > xFieldContainer = getFieldsByCommandDescriptor( _rxConnection, _nCommandType, _rCommand, xKeepFieldsAlive, _pErrorInfo );
728
729
    // get the names of the fields
730
0
    Sequence< OUString > aNames;
731
0
    if ( xFieldContainer.is() )
732
0
        aNames = xFieldContainer->getElementNames();
733
734
    // clean up any temporary objects which have been created
735
0
    disposeComponent( xKeepFieldsAlive );
736
737
    // outta here
738
0
    return aNames;
739
0
}
740
741
SQLException prependErrorInfo( const SQLException& _rChainedException, const Reference< XInterface >& _rxContext,
742
    const OUString& _rAdditionalError, const StandardSQLState _eSQLState )
743
0
{
744
0
    return SQLException( _rAdditionalError, _rxContext,
745
0
        _eSQLState == StandardSQLState::ERROR_UNSPECIFIED ? OUString() : getStandardSQLState( _eSQLState ),
746
0
        0, Any( _rChainedException ) );
747
0
}
748
749
namespace
750
{
751
    struct NameComponentSupport
752
    {
753
        const bool  bCatalogs;
754
        const bool  bSchemas;
755
756
        NameComponentSupport( const bool _bCatalogs, const bool _bSchemas )
757
142k
            :bCatalogs( _bCatalogs )
758
142k
            ,bSchemas( _bSchemas )
759
142k
        {
760
142k
        }
761
    };
762
763
    NameComponentSupport lcl_getNameComponentSupport( const Reference< XDatabaseMetaData >& _rxMetaData, EComposeRule _eComposeRule )
764
142k
    {
765
142k
        OSL_PRECOND( _rxMetaData.is(), "lcl_getNameComponentSupport: invalid meta data!" );
766
767
142k
        FMetaDataSupport pCatalogCall = &XDatabaseMetaData::supportsCatalogsInDataManipulation;
768
142k
        FMetaDataSupport pSchemaCall = &XDatabaseMetaData::supportsSchemasInDataManipulation;
769
142k
        bool bIgnoreMetaData = false;
770
771
142k
        switch ( _eComposeRule )
772
142k
        {
773
0
            case EComposeRule::InTableDefinitions:
774
0
                pCatalogCall = &XDatabaseMetaData::supportsCatalogsInTableDefinitions;
775
0
                pSchemaCall = &XDatabaseMetaData::supportsSchemasInTableDefinitions;
776
0
                break;
777
0
            case EComposeRule::InIndexDefinitions:
778
0
                pCatalogCall = &XDatabaseMetaData::supportsCatalogsInIndexDefinitions;
779
0
                pSchemaCall = &XDatabaseMetaData::supportsSchemasInIndexDefinitions;
780
0
                break;
781
0
            case EComposeRule::InProcedureCalls:
782
0
                pCatalogCall = &XDatabaseMetaData::supportsCatalogsInProcedureCalls;
783
0
                pSchemaCall = &XDatabaseMetaData::supportsSchemasInProcedureCalls;
784
0
                break;
785
0
            case EComposeRule::InPrivilegeDefinitions:
786
0
                pCatalogCall = &XDatabaseMetaData::supportsCatalogsInPrivilegeDefinitions;
787
0
                pSchemaCall = &XDatabaseMetaData::supportsSchemasInPrivilegeDefinitions;
788
0
                break;
789
0
            case EComposeRule::Complete:
790
0
                bIgnoreMetaData = true;
791
0
                break;
792
142k
            case EComposeRule::InDataManipulation:
793
                // already properly set above
794
142k
                break;
795
142k
        }
796
142k
        return NameComponentSupport(
797
142k
            bIgnoreMetaData || (_rxMetaData.get()->*pCatalogCall)(),
798
142k
            bIgnoreMetaData || (_rxMetaData.get()->*pSchemaCall)()
799
142k
        );
800
142k
    }
801
}
802
803
static OUString impl_doComposeTableName( const Reference< XDatabaseMetaData >& _rxMetaData,
804
                const OUString& _rCatalog, const OUString& _rSchema, const OUString& _rName,
805
                bool _bQuote, EComposeRule _eComposeRule )
806
81.2k
{
807
81.2k
    OSL_ENSURE(_rxMetaData.is(), "impl_doComposeTableName : invalid meta data !");
808
81.2k
    if ( !_rxMetaData.is() )
809
0
        return OUString();
810
81.2k
    OSL_ENSURE(!_rName.isEmpty(), "impl_doComposeTableName : at least the name should be non-empty !");
811
812
81.2k
    const OUString sQuoteString = _rxMetaData->getIdentifierQuoteString();
813
81.2k
    const NameComponentSupport aNameComps( lcl_getNameComponentSupport( _rxMetaData, _eComposeRule ) );
814
815
81.2k
    OUStringBuffer aComposedName;
816
817
81.2k
    OUString sCatalogSep;
818
81.2k
    bool bCatalogAtStart = true;
819
81.2k
    if ( !_rCatalog.isEmpty() && aNameComps.bCatalogs )
820
0
    {
821
0
        sCatalogSep     = _rxMetaData->getCatalogSeparator();
822
0
        bCatalogAtStart  = _rxMetaData->isCatalogAtStart();
823
824
0
        if ( bCatalogAtStart && !sCatalogSep.isEmpty())
825
0
        {
826
0
            aComposedName.append( _bQuote ? quoteName( sQuoteString, _rCatalog ) : _rCatalog );
827
0
            aComposedName.append( sCatalogSep );
828
0
        }
829
0
    }
830
831
81.2k
    if ( !_rSchema.isEmpty() && aNameComps.bSchemas )
832
0
    {
833
0
        aComposedName.append(
834
0
            (_bQuote ? quoteName( sQuoteString, _rSchema ) : _rSchema )
835
0
            + "." );
836
0
    }
837
838
81.2k
    aComposedName.append( _bQuote ? quoteName( sQuoteString, _rName ) : _rName );
839
840
81.2k
    if  (   !_rCatalog.isEmpty()
841
0
        &&  !bCatalogAtStart
842
0
        &&  !sCatalogSep.isEmpty()
843
0
        &&  aNameComps.bCatalogs
844
81.2k
        )
845
0
    {
846
0
        aComposedName.append( sCatalogSep );
847
0
        aComposedName.append( _bQuote ? quoteName( sQuoteString, _rCatalog ) : _rCatalog );
848
0
    }
849
850
81.2k
    return aComposedName.makeStringAndClear();
851
81.2k
}
852
853
OUString quoteTableName(const Reference< XDatabaseMetaData>& _rxMeta
854
                               , const OUString& _rName
855
                               , EComposeRule _eComposeRule)
856
0
{
857
0
    OUString sCatalog, sSchema, sTable;
858
0
    qualifiedNameComponents(_rxMeta,_rName,sCatalog,sSchema,sTable,_eComposeRule);
859
0
    return impl_doComposeTableName( _rxMeta, sCatalog, sSchema, sTable, true, _eComposeRule );
860
0
}
861
862
void qualifiedNameComponents(const Reference< XDatabaseMetaData >& _rxConnMetaData, const OUString& _rQualifiedName, OUString& _rCatalog, OUString& _rSchema, OUString& _rName,EComposeRule _eComposeRule)
863
61.0k
{
864
61.0k
    OSL_ENSURE(_rxConnMetaData.is(), "QualifiedNameComponents : invalid meta data!");
865
866
61.0k
    NameComponentSupport aNameComps( lcl_getNameComponentSupport( _rxConnMetaData, _eComposeRule ) );
867
868
61.0k
    OUString sSeparator = _rxConnMetaData->getCatalogSeparator();
869
870
61.0k
    OUString sName(_rQualifiedName);
871
    // do we have catalogs?
872
61.0k
    if ( aNameComps.bCatalogs )
873
0
    {
874
0
        if (_rxConnMetaData->isCatalogAtStart())
875
0
        {
876
            // search for the catalog name at the beginning
877
0
            sal_Int32 nIndex = sName.indexOf(sSeparator);
878
0
            if (-1 != nIndex)
879
0
            {
880
0
                _rCatalog = sName.copy(0, nIndex);
881
0
                sName = sName.copy(nIndex + 1);
882
0
            }
883
0
        }
884
0
        else
885
0
        {
886
            // Catalog name at the end
887
0
            sal_Int32 nIndex = sName.lastIndexOf(sSeparator);
888
0
            if (-1 != nIndex)
889
0
            {
890
0
                _rCatalog = sName.copy(nIndex + 1);
891
0
                sName = sName.copy(0, nIndex);
892
0
            }
893
0
        }
894
0
    }
895
896
61.0k
    if ( aNameComps.bSchemas )
897
0
    {
898
0
        sal_Int32 nIndex = sName.indexOf('.');
899
        //  OSL_ENSURE(-1 != nIndex, "QualifiedNameComponents: no schema separator!");
900
0
        if ( nIndex != -1 )
901
0
            _rSchema = sName.copy(0, nIndex);
902
0
        sName = sName.copy(nIndex + 1);
903
0
    }
904
905
61.0k
    _rName = sName;
906
61.0k
}
907
908
Reference< XNumberFormatsSupplier> getNumberFormats(
909
            const Reference< XConnection>& _rxConn,
910
            bool _bAlloweDefault,
911
            const Reference< XComponentContext>& _rxContext)
912
20.4k
{
913
    // ask the parent of the connection (should be a DatabaseAccess)
914
20.4k
    Reference< XNumberFormatsSupplier> xReturn;
915
20.4k
    Reference< XChild> xConnAsChild(_rxConn, UNO_QUERY);
916
20.4k
    static constexpr OUString sPropFormatsSupplier( u"NumberFormatsSupplier"_ustr );
917
20.4k
    if (xConnAsChild.is())
918
0
    {
919
0
        Reference< XPropertySet> xConnParentProps(xConnAsChild->getParent(), UNO_QUERY);
920
0
        if (xConnParentProps.is() && hasProperty(sPropFormatsSupplier, xConnParentProps))
921
0
            xConnParentProps->getPropertyValue(sPropFormatsSupplier) >>= xReturn;
922
0
    }
923
20.4k
    else if(_bAlloweDefault && _rxContext.is())
924
10.3k
    {
925
10.3k
        xReturn = NumberFormatsSupplier::createWithDefaultLocale( _rxContext );
926
10.3k
    }
927
20.4k
    return xReturn;
928
20.4k
}
929
930
void TransferFormComponentProperties(
931
            const Reference< XPropertySet>& xOldProps,
932
            const Reference< XPropertySet>& xNewProps,
933
            const Locale& _rLocale)
934
0
{
935
0
try
936
0
{
937
0
    OSL_ENSURE( xOldProps.is() && xNewProps.is(), "TransferFormComponentProperties: invalid source/dest!" );
938
0
    if ( !xOldProps.is() || !xNewProps.is() )
939
0
        return;
940
941
    // First we copy all the Props, that are available in source and target and have the same description
942
0
    Reference< XPropertySetInfo> xOldInfo( xOldProps->getPropertySetInfo());
943
0
    Reference< XPropertySetInfo> xNewInfo( xNewProps->getPropertySetInfo());
944
945
0
    const Sequence< Property> aOldProperties = xOldInfo->getProperties();
946
0
    const Sequence< Property> aNewProperties = xNewInfo->getProperties();
947
948
0
    static constexpr OUString sPropFormatsSupplier(u"FormatsSupplier"_ustr);
949
0
    static constexpr OUString sPropCurrencySymbol(u"CurrencySymbol"_ustr);
950
0
    static constexpr OUString sPropDecimals(u"Decimals"_ustr);
951
0
    static constexpr OUString sPropEffectiveMin(u"EffectiveMin"_ustr);
952
0
    static constexpr OUString sPropEffectiveMax(u"EffectiveMax"_ustr);
953
0
    static constexpr OUString sPropEffectiveDefault(u"EffectiveDefault"_ustr);
954
0
    static constexpr OUString sPropDefaultText(u"DefaultText"_ustr);
955
0
    static constexpr OUString sPropDefaultDate(u"DefaultDate"_ustr);
956
0
    static constexpr OUString sPropDefaultTime(u"DefaultTime"_ustr);
957
0
    static constexpr OUString sPropValueMin(u"ValueMin"_ustr);
958
0
    static constexpr OUString sPropValueMax(u"ValueMax"_ustr);
959
0
    static constexpr OUString sPropDecimalAccuracy(u"DecimalAccuracy"_ustr);
960
0
    static constexpr OUString sPropClassId(u"ClassId"_ustr);
961
0
    static constexpr OUString sFormattedServiceName( u"com.sun.star.form.component.FormattedField"_ustr );
962
963
0
    for (const Property& rOldProp : aOldProperties)
964
0
    {
965
0
        if ( rOldProp.Name != "DefaultControl" && rOldProp.Name != "LabelControl" )
966
0
        {
967
            // binary search
968
0
            const Property* pResult = std::lower_bound(
969
0
                aNewProperties.begin(), aNewProperties.end(), rOldProp, ::comphelper::PropertyCompareByName());
970
971
0
            if (   ( pResult != aNewProperties.end() )
972
0
                && ( pResult->Name == rOldProp.Name )
973
0
                && ( (pResult->Attributes & PropertyAttribute::READONLY) == 0 )
974
0
                && ( pResult->Type.equals(rOldProp.Type)) )
975
0
            {   // Attributes match and the property is not read-only
976
0
                try
977
0
                {
978
0
                    xNewProps->setPropertyValue(pResult->Name, xOldProps->getPropertyValue(pResult->Name));
979
0
                }
980
0
                catch(IllegalArgumentException const &)
981
0
                {
982
0
                    TOOLS_WARN_EXCEPTION( "connectivity.commontools", "TransferFormComponentProperties : could not transfer the value for property \""
983
0
                                << pResult->Name << "\"");
984
0
                }
985
0
            }
986
0
        }
987
0
    }
988
989
    // for formatted fields (either old or new) we have some special treatments
990
0
    Reference< XServiceInfo > xSI( xOldProps, UNO_QUERY );
991
0
    bool bOldIsFormatted = xSI.is() && xSI->supportsService( sFormattedServiceName );
992
0
    xSI.set( xNewProps, UNO_QUERY );
993
0
    bool bNewIsFormatted = xSI.is() && xSI->supportsService( sFormattedServiceName );
994
995
0
    if (!bOldIsFormatted && !bNewIsFormatted)
996
0
        return; // nothing to do
997
998
0
    if (bOldIsFormatted && bNewIsFormatted)
999
        // if both fields are formatted we do no conversions
1000
0
        return;
1001
1002
0
    if (bOldIsFormatted)
1003
0
    {
1004
        // get some properties from the selected format and put them in the new Set
1005
0
        Any aFormatKey( xOldProps->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FORMATKEY)) );
1006
0
        if (aFormatKey.hasValue())
1007
0
        {
1008
0
            Reference< XNumberFormatsSupplier> xSupplier;
1009
0
            xOldProps->getPropertyValue(sPropFormatsSupplier) >>= xSupplier;
1010
0
            if (xSupplier.is())
1011
0
            {
1012
0
                Reference< XNumberFormats> xFormats(xSupplier->getNumberFormats());
1013
0
                Reference< XPropertySet> xFormat(xFormats->getByKey(getINT32(aFormatKey)));
1014
0
                if (hasProperty(sPropCurrencySymbol, xFormat))
1015
0
                {
1016
0
                    Any aVal( xFormat->getPropertyValue(sPropCurrencySymbol) );
1017
0
                    if (aVal.hasValue() && hasProperty(sPropCurrencySymbol, xNewProps))
1018
                        // If the source value hasn't been set then don't copy it
1019
                        // so we don't overwrite the default value
1020
0
                        xNewProps->setPropertyValue(sPropCurrencySymbol, aVal);
1021
0
                }
1022
0
                if (hasProperty(sPropDecimals, xFormat) && hasProperty(sPropDecimals, xNewProps))
1023
0
                    xNewProps->setPropertyValue(sPropDecimals, xFormat->getPropertyValue(sPropDecimals));
1024
0
            }
1025
0
        }
1026
1027
        // a potential Min-Max-Conversion
1028
0
        Any aEffectiveMin( xOldProps->getPropertyValue(sPropEffectiveMin) );
1029
0
        if (aEffectiveMin.hasValue())
1030
0
        {   // Unlike the ValueMin the EffectiveMin can be void
1031
0
            if (hasProperty(sPropValueMin, xNewProps))
1032
0
            {
1033
0
                OSL_ENSURE(aEffectiveMin.getValueTypeClass() == TypeClass_DOUBLE,
1034
0
                    "TransferFormComponentProperties : invalid property type !");
1035
0
                xNewProps->setPropertyValue(sPropValueMin, aEffectiveMin);
1036
0
            }
1037
0
        }
1038
0
        Any aEffectiveMax( xOldProps->getPropertyValue(sPropEffectiveMax) );
1039
0
        if (aEffectiveMax.hasValue())
1040
0
        {   // analog
1041
0
            if (hasProperty(sPropValueMax, xNewProps))
1042
0
            {
1043
0
                OSL_ENSURE(aEffectiveMax.getValueTypeClass() == TypeClass_DOUBLE,
1044
0
                    "TransferFormComponentProperties : invalid property type !");
1045
0
                xNewProps->setPropertyValue(sPropValueMax, aEffectiveMax);
1046
0
            }
1047
0
        }
1048
1049
        // then we can still convert and copy the default values
1050
0
        Any aEffectiveDefault( xOldProps->getPropertyValue(sPropEffectiveDefault) );
1051
0
        if (aEffectiveDefault.hasValue())
1052
0
        {
1053
0
            bool bIsString = aEffectiveDefault.getValueTypeClass() == TypeClass_STRING;
1054
0
            OSL_ENSURE(bIsString || aEffectiveDefault.getValueTypeClass() == TypeClass_DOUBLE,
1055
0
                "TransferFormComponentProperties : invalid property type !");
1056
                // The Effective-Properties should always be void or string or double...
1057
1058
0
            if (hasProperty(sPropDefaultDate, xNewProps) && !bIsString)
1059
0
            {   // (to convert an OUString into a date will not always succeed, because it might be bound to a text-column,
1060
                // but we can work with a double)
1061
0
                Date aDate = DBTypeConversion::toDate(getDouble(aEffectiveDefault));
1062
0
                xNewProps->setPropertyValue(sPropDefaultDate, Any(aDate));
1063
0
            }
1064
1065
0
            if (hasProperty(sPropDefaultTime, xNewProps) && !bIsString)
1066
0
            {   // Completely analogous to time
1067
0
                css::util::Time aTime = DBTypeConversion::toTime(getDouble(aEffectiveDefault));
1068
0
                xNewProps->setPropertyValue(sPropDefaultTime, Any(aTime));
1069
0
            }
1070
1071
0
            if (hasProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE), xNewProps) && !bIsString)
1072
0
            {   // Here we can simply pass the double
1073
0
                xNewProps->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE), aEffectiveDefault);
1074
0
            }
1075
1076
0
            if (hasProperty(sPropDefaultText, xNewProps) && bIsString)
1077
0
            {   // and here the OUString
1078
0
                xNewProps->setPropertyValue(sPropDefaultText, aEffectiveDefault);
1079
0
            }
1080
1081
            // nyi: The translation between doubles and OUString would offer more alternatives
1082
0
        }
1083
0
    }
1084
1085
    // The other direction: the new Control shall be formatted
1086
0
    if (bNewIsFormatted)
1087
0
    {
1088
        // first the formatting
1089
        // we can't set a Supplier, so the new Set must bring one in
1090
0
        Reference< XNumberFormatsSupplier> xSupplier;
1091
0
        xNewProps->getPropertyValue(sPropFormatsSupplier) >>= xSupplier;
1092
0
        if (xSupplier.is())
1093
0
        {
1094
0
            Reference< XNumberFormats> xFormats(xSupplier->getNumberFormats());
1095
1096
            // Set number of decimals
1097
0
            sal_Int16 nDecimals = 2;
1098
0
            if (hasProperty(sPropDecimalAccuracy, xOldProps))
1099
0
                xOldProps->getPropertyValue(sPropDecimalAccuracy) >>= nDecimals;
1100
1101
            // base format (depending on the ClassId of the old Set)
1102
0
            sal_Int32 nBaseKey = 0;
1103
0
            if (hasProperty(sPropClassId, xOldProps))
1104
0
            {
1105
0
                Reference< XNumberFormatTypes> xTypeList(xFormats, UNO_QUERY);
1106
0
                if (xTypeList.is())
1107
0
                {
1108
0
                    sal_Int16 nClassId = 0;
1109
0
                    xOldProps->getPropertyValue(sPropClassId) >>= nClassId;
1110
0
                    switch (nClassId)
1111
0
                    {
1112
0
                        case FormComponentType::DATEFIELD :
1113
0
                            nBaseKey = xTypeList->getStandardFormat(NumberFormat::DATE, _rLocale);
1114
0
                            break;
1115
1116
0
                        case FormComponentType::TIMEFIELD :
1117
0
                            nBaseKey = xTypeList->getStandardFormat(NumberFormat::TIME, _rLocale);
1118
0
                            break;
1119
1120
0
                        case FormComponentType::CURRENCYFIELD :
1121
0
                            nBaseKey = xTypeList->getStandardFormat(NumberFormat::CURRENCY, _rLocale);
1122
0
                            break;
1123
0
                    }
1124
0
                }
1125
0
            }
1126
1127
            // With this we can generate a new format ...
1128
0
            OUString sNewFormat = xFormats->generateFormat(nBaseKey, _rLocale, false, false, nDecimals, 0);
1129
            // No thousands separator, negative numbers are not in red, no leading zeros
1130
1131
            // ... and add at FormatsSupplier (if needed)
1132
0
            sal_Int32 nKey = xFormats->queryKey(sNewFormat, _rLocale, false);
1133
0
            if (nKey == sal_Int32(-1))
1134
0
            {   // not added yet in my formatter ...
1135
0
                nKey = xFormats->addNew(sNewFormat, _rLocale);
1136
0
            }
1137
1138
0
            xNewProps->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FORMATKEY), Any(nKey));
1139
0
        }
1140
1141
        // min-/max-Value
1142
0
        Any aNewMin, aNewMax;
1143
0
        if (hasProperty(sPropValueMin, xOldProps))
1144
0
            aNewMin = xOldProps->getPropertyValue(sPropValueMin);
1145
0
        if (hasProperty(sPropValueMax, xOldProps))
1146
0
            aNewMax = xOldProps->getPropertyValue(sPropValueMax);
1147
0
        xNewProps->setPropertyValue(sPropEffectiveMin, aNewMin);
1148
0
        xNewProps->setPropertyValue(sPropEffectiveMax, aNewMax);
1149
1150
        // Default-Value
1151
0
        Any aNewDefault;
1152
0
        if (hasProperty(sPropDefaultDate, xOldProps))
1153
0
        {
1154
0
            Any aDate( xOldProps->getPropertyValue(sPropDefaultDate) );
1155
0
            if (aDate.hasValue())
1156
0
                aNewDefault <<= DBTypeConversion::toDouble(*o3tl::doAccess<Date>(aDate));
1157
0
        }
1158
1159
0
        if (hasProperty(sPropDefaultTime, xOldProps))
1160
0
        {
1161
0
            Any aTime( xOldProps->getPropertyValue(sPropDefaultTime) );
1162
0
            if (aTime.hasValue())
1163
0
                aNewDefault <<= DBTypeConversion::toDouble(*o3tl::doAccess<Time>(aTime));
1164
0
        }
1165
1166
        // double or OUString will be copied directly
1167
0
        if (hasProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE), xOldProps))
1168
0
            aNewDefault = xOldProps->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE));
1169
0
        if (hasProperty(sPropDefaultText, xOldProps))
1170
0
            aNewDefault = xOldProps->getPropertyValue(sPropDefaultText);
1171
1172
0
        if (aNewDefault.hasValue())
1173
0
            xNewProps->setPropertyValue(sPropEffectiveDefault, aNewDefault);
1174
0
    }
1175
0
}
1176
0
catch(const Exception&)
1177
0
{
1178
0
    TOOLS_WARN_EXCEPTION( "connectivity.commontools", "TransferFormComponentProperties" );
1179
0
}
1180
0
}
1181
1182
bool canInsert(const Reference< XPropertySet>& _rxCursorSet)
1183
0
{
1184
0
    return (_rxCursorSet.is() && (getINT32(_rxCursorSet->getPropertyValue(u"Privileges"_ustr)) & Privilege::INSERT) != 0);
1185
0
}
1186
1187
bool canUpdate(const Reference< XPropertySet>& _rxCursorSet)
1188
0
{
1189
0
    return (_rxCursorSet.is() && (getINT32(_rxCursorSet->getPropertyValue(u"Privileges"_ustr)) & Privilege::UPDATE) != 0);
1190
0
}
1191
1192
bool canDelete(const Reference< XPropertySet>& _rxCursorSet)
1193
0
{
1194
0
    return (_rxCursorSet.is() && (getINT32(_rxCursorSet->getPropertyValue(u"Privileges"_ustr)) & Privilege::DELETE) != 0);
1195
0
}
1196
1197
Reference< XDataSource> findDataSource(const Reference< XInterface >& _xParent)
1198
71.4k
{
1199
71.4k
    Reference< XOfficeDatabaseDocument> xDatabaseDocument(_xParent, UNO_QUERY);
1200
71.4k
    Reference< XDataSource> xDataSource;
1201
71.4k
    if ( xDatabaseDocument.is() )
1202
0
        xDataSource = xDatabaseDocument->getDataSource();
1203
71.4k
    if ( !xDataSource.is() )
1204
71.4k
        xDataSource.set(_xParent, UNO_QUERY);
1205
71.4k
    if (!xDataSource.is())
1206
71.4k
    {
1207
71.4k
        Reference< XChild> xChild(_xParent, UNO_QUERY);
1208
71.4k
        if ( xChild.is() )
1209
0
            xDataSource = findDataSource(xChild->getParent());
1210
71.4k
    }
1211
71.4k
    return xDataSource;
1212
71.4k
}
1213
1214
static Reference< XSingleSelectQueryComposer > getComposedRowSetStatement( const Reference< XPropertySet >& _rxRowSet, const Reference< XComponentContext >& _rxContext, const Reference< XWindow >& _rxParent )
1215
0
{
1216
0
    Reference< XSingleSelectQueryComposer > xComposer;
1217
0
    try
1218
0
    {
1219
0
        Reference< XConnection> xConn = connectRowset( Reference< XRowSet >( _rxRowSet, UNO_QUERY ), _rxContext, _rxParent );
1220
0
        if ( xConn.is() )       // implies _rxRowSet.is()
1221
0
        {
1222
            // build the statement the row set is based on (can't use the ActiveCommand property of the set
1223
            // as this reflects the status after the last execute, not the currently set properties)
1224
1225
0
            sal_Int32 nCommandType = CommandType::COMMAND;
1226
0
            OUString sCommand;
1227
0
            bool bEscapeProcessing = false;
1228
1229
0
            OSL_VERIFY( _rxRowSet->getPropertyValue(u"CommandType"_ustr) >>= nCommandType      );
1230
0
            OSL_VERIFY( _rxRowSet->getPropertyValue(u"Command"_ustr) >>= sCommand          );
1231
0
            OSL_VERIFY( _rxRowSet->getPropertyValue(u"EscapeProcessing"_ustr) >>= bEscapeProcessing );
1232
1233
0
            StatementComposer aComposer( xConn, sCommand, nCommandType, bEscapeProcessing );
1234
            // append sort
1235
0
            aComposer.setOrder( getString( _rxRowSet->getPropertyValue(u"Order"_ustr) ) );
1236
1237
            // append filter
1238
0
            bool bApplyFilter = true;
1239
0
            _rxRowSet->getPropertyValue(u"ApplyFilter"_ustr) >>= bApplyFilter;
1240
0
            if ( bApplyFilter )
1241
0
            {
1242
0
                aComposer.setFilter( getString( _rxRowSet->getPropertyValue(u"Filter"_ustr) ) );
1243
0
                aComposer.setHavingClause( getString( _rxRowSet->getPropertyValue(u"HavingClause"_ustr) ) );
1244
0
            }
1245
1246
0
            aComposer.getQuery();
1247
1248
0
            xComposer = aComposer.getComposer();
1249
0
            aComposer.setDisposeComposer( false );
1250
0
        }
1251
0
    }
1252
0
    catch( const SQLException& )
1253
0
    {
1254
0
        throw;
1255
0
    }
1256
0
    catch( const Exception& )
1257
0
    {
1258
0
        DBG_UNHANDLED_EXCEPTION("connectivity.commontools");
1259
0
    }
1260
1261
0
    return xComposer;
1262
0
}
1263
1264
Reference< XSingleSelectQueryComposer > getCurrentSettingsComposer(
1265
                const Reference< XPropertySet>& _rxRowSetProps,
1266
                const Reference< XComponentContext>& _rxContext,
1267
                const Reference< XWindow >& _rxParent)
1268
0
{
1269
0
    Reference< XSingleSelectQueryComposer > xReturn;
1270
0
    try
1271
0
    {
1272
0
        xReturn = getComposedRowSetStatement( _rxRowSetProps, _rxContext, _rxParent );
1273
0
    }
1274
0
    catch( const SQLException& )
1275
0
    {
1276
0
        throw;
1277
0
    }
1278
0
    catch( const Exception& )
1279
0
    {
1280
0
        TOOLS_WARN_EXCEPTION( "connectivity.commontools", "::getCurrentSettingsComposer : caught an exception !" );
1281
0
    }
1282
1283
0
    return xReturn;
1284
0
}
1285
1286
OUString composeTableName( const Reference< XDatabaseMetaData >& _rxMetaData,
1287
                        const OUString& _rCatalog,
1288
                        const OUString& _rSchema,
1289
                        const OUString& _rName,
1290
                        bool _bQuote,
1291
                        EComposeRule _eComposeRule)
1292
61.0k
{
1293
61.0k
    return impl_doComposeTableName( _rxMetaData, _rCatalog, _rSchema, _rName, _bQuote, _eComposeRule );
1294
61.0k
}
1295
1296
OUString composeTableNameForSelect( const Reference< XConnection >& _rxConnection,
1297
    const OUString& _rCatalog, const OUString& _rSchema, const OUString& _rName )
1298
20.2k
{
1299
20.2k
    bool bUseCatalogInSelect = isDataSourcePropertyEnabled( _rxConnection, u"UseCatalogInSelect"_ustr, true );
1300
20.2k
    bool bUseSchemaInSelect = isDataSourcePropertyEnabled( _rxConnection, u"UseSchemaInSelect"_ustr, true );
1301
1302
20.2k
    return impl_doComposeTableName(
1303
20.2k
        _rxConnection->getMetaData(),
1304
20.2k
        bUseCatalogInSelect ? _rCatalog : OUString(),
1305
20.2k
        bUseSchemaInSelect ? _rSchema : OUString(),
1306
20.2k
        _rName,
1307
20.2k
        true,
1308
20.2k
        EComposeRule::InDataManipulation
1309
20.2k
    );
1310
20.2k
}
1311
1312
namespace
1313
{
1314
    void lcl_getTableNameComponents( const Reference<XPropertySet>& _xTable,
1315
        OUString& _out_rCatalog, OUString& _out_rSchema, OUString& _out_rName )
1316
20.2k
    {
1317
20.2k
        ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap();
1318
20.2k
        Reference< XPropertySetInfo > xInfo;
1319
20.2k
        if (_xTable.is())
1320
20.2k
            xInfo = _xTable->getPropertySetInfo();
1321
20.2k
        if (    xInfo.is()
1322
20.2k
            &&  xInfo->hasPropertyByName(rPropMap.getNameByIndex(PROPERTY_ID_NAME)) )
1323
20.2k
        {
1324
20.2k
            if (    xInfo->hasPropertyByName(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME))
1325
20.2k
                &&  xInfo->hasPropertyByName(rPropMap.getNameByIndex(PROPERTY_ID_SCHEMANAME)) )
1326
20.2k
            {
1327
20.2k
                _xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME)) >>= _out_rCatalog;
1328
20.2k
                _xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_SCHEMANAME))  >>= _out_rSchema;
1329
20.2k
            }
1330
20.2k
            _xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME))        >>= _out_rName;
1331
20.2k
        }
1332
0
        else
1333
20.2k
            OSL_FAIL( "::dbtools::lcl_getTableNameComponents: this is no table object!" );
1334
20.2k
    }
1335
}
1336
1337
OUString composeTableNameForSelect( const Reference< XConnection >& _rxConnection, const Reference<XPropertySet>& _xTable )
1338
20.2k
{
1339
20.2k
    OUString sCatalog, sSchema, sName;
1340
20.2k
    lcl_getTableNameComponents( _xTable, sCatalog, sSchema, sName );
1341
1342
20.2k
    return composeTableNameForSelect( _rxConnection, sCatalog, sSchema, sName );
1343
20.2k
}
1344
1345
OUString composeTableName(const Reference<XDatabaseMetaData>& _xMetaData,
1346
                                 const Reference<XPropertySet>& _xTable,
1347
                                 EComposeRule _eComposeRule,
1348
                                 bool _bQuote )
1349
0
{
1350
0
    OUString sCatalog, sSchema, sName;
1351
0
    lcl_getTableNameComponents( _xTable, sCatalog, sSchema, sName );
1352
1353
0
    return impl_doComposeTableName(
1354
0
            _xMetaData,
1355
0
            sCatalog,
1356
0
            sSchema,
1357
0
            sName,
1358
0
            _bQuote,
1359
0
            _eComposeRule
1360
0
        );
1361
0
}
1362
1363
sal_Int32 getSearchColumnFlag( const Reference< XConnection>& _rxConn,sal_Int32 _nDataType)
1364
0
{
1365
0
    sal_Int32 nSearchFlag = 0;
1366
0
    Reference<XResultSet> xSet = _rxConn->getMetaData()->getTypeInfo();
1367
0
    if(xSet.is())
1368
0
    {
1369
0
        Reference<XRow> xRow(xSet,UNO_QUERY);
1370
0
        while(xSet->next())
1371
0
        {
1372
0
            if(xRow->getInt(2) == _nDataType)
1373
0
            {
1374
0
                nSearchFlag = xRow->getInt(9);
1375
0
                break;
1376
0
            }
1377
0
        }
1378
0
    }
1379
0
    return nSearchFlag;
1380
0
}
1381
1382
OUString createUniqueName( const Sequence< OUString >& _rNames, const OUString& _rBaseName, bool _bStartWithNumber )
1383
0
{
1384
0
    std::set< OUString > aUsedNames(_rNames.begin(), _rNames.end());
1385
1386
0
    OUString sName( _rBaseName );
1387
0
    sal_Int32 nPos = 1;
1388
0
    if ( _bStartWithNumber )
1389
0
        sName += OUString::number( nPos );
1390
1391
0
    while ( aUsedNames.contains( sName ) )
1392
0
    {
1393
0
        sName = _rBaseName + OUString::number( ++nPos );
1394
0
    }
1395
0
    return sName;
1396
0
}
1397
1398
OUString createUniqueName(const Reference<XNameAccess>& _rxContainer,const OUString& _rBaseName, bool _bStartWithNumber)
1399
0
{
1400
0
    Sequence< OUString > aElementNames;
1401
1402
0
    OSL_ENSURE( _rxContainer.is(), "createUniqueName: invalid container!" );
1403
0
    if ( _rxContainer.is() )
1404
0
        aElementNames = _rxContainer->getElementNames();
1405
1406
0
    return createUniqueName( aElementNames, _rBaseName, _bStartWithNumber );
1407
0
}
1408
1409
OUString createUniqueName(const Reference<XTablesSupplier>& _rxSupplier,const OUString& _rBaseName, bool _bStartWithNumber)
1410
0
{
1411
0
    Reference< XNameAccess > xContainer;
1412
0
    OSL_ENSURE( _rxSupplier.is(), "createUniqueName: invalid connection!" );
1413
0
    if ( _rxSupplier.is() )
1414
0
        xContainer = _rxSupplier->getTables();
1415
0
    return createUniqueName( xContainer, _rBaseName, _bStartWithNumber );
1416
0
}
1417
1418
void showError(const SQLExceptionInfo& _rInfo,
1419
               const Reference< XWindow>& _xParent,
1420
               const Reference< XComponentContext >& _rxContext)
1421
0
{
1422
0
    if (_rInfo.isValid())
1423
0
    {
1424
0
        try
1425
0
        {
1426
0
            Reference< XExecutableDialog > xErrorDialog = ErrorMessageDialog::create( _rxContext, u""_ustr, _xParent, _rInfo.get() );
1427
0
            xErrorDialog->execute();
1428
0
        }
1429
0
        catch(const Exception&)
1430
0
        {
1431
0
            OSL_FAIL("showError: could not display the error message!");
1432
0
        }
1433
0
    }
1434
0
}
1435
1436
bool implUpdateObject(const Reference< XRowUpdate >& _rxUpdatedObject,
1437
    const sal_Int32 _nColumnIndex, const Any& _rValue)
1438
0
{
1439
0
    bool bSuccessfullyReRouted = true;
1440
0
    switch (_rValue.getValueTypeClass())
1441
0
    {
1442
0
        case TypeClass_ANY:
1443
0
        {
1444
0
            bSuccessfullyReRouted = implUpdateObject(_rxUpdatedObject, _nColumnIndex, _rValue);
1445
0
        }
1446
0
        break;
1447
1448
0
        case TypeClass_VOID:
1449
0
            _rxUpdatedObject->updateNull(_nColumnIndex);
1450
0
            break;
1451
1452
0
        case TypeClass_STRING:
1453
0
            _rxUpdatedObject->updateString(_nColumnIndex, *o3tl::forceAccess<OUString>(_rValue));
1454
0
            break;
1455
1456
0
        case TypeClass_BOOLEAN:
1457
0
            _rxUpdatedObject->updateBoolean(_nColumnIndex, *o3tl::forceAccess<bool>(_rValue));
1458
0
            break;
1459
1460
0
        case TypeClass_BYTE:
1461
0
            _rxUpdatedObject->updateByte(_nColumnIndex, *o3tl::forceAccess<sal_Int8>(_rValue));
1462
0
            break;
1463
1464
0
        case TypeClass_UNSIGNED_SHORT:
1465
0
        case TypeClass_SHORT:
1466
0
            _rxUpdatedObject->updateShort(_nColumnIndex, *o3tl::forceAccess<sal_Int16>(_rValue));
1467
0
            break;
1468
1469
0
        case TypeClass_CHAR:
1470
0
            _rxUpdatedObject->updateString(_nColumnIndex,OUString(*o3tl::forceAccess<sal_Unicode>(_rValue)));
1471
0
            break;
1472
1473
0
        case TypeClass_UNSIGNED_LONG:
1474
0
        case TypeClass_LONG:
1475
0
            _rxUpdatedObject->updateInt(_nColumnIndex, *o3tl::forceAccess<sal_Int32>(_rValue));
1476
0
            break;
1477
1478
0
        case TypeClass_HYPER:
1479
0
        {
1480
0
            sal_Int64 nValue = 0;
1481
0
            OSL_VERIFY( _rValue >>= nValue );
1482
0
            _rxUpdatedObject->updateLong( _nColumnIndex, nValue );
1483
0
        }
1484
0
        break;
1485
1486
0
        case TypeClass_FLOAT:
1487
0
            _rxUpdatedObject->updateFloat(_nColumnIndex, *o3tl::forceAccess<float>(_rValue));
1488
0
            break;
1489
1490
0
        case TypeClass_DOUBLE:
1491
0
            _rxUpdatedObject->updateDouble(_nColumnIndex, *o3tl::forceAccess<double>(_rValue));
1492
0
            break;
1493
1494
0
        case TypeClass_SEQUENCE:
1495
0
            if (auto s = o3tl::tryAccess<Sequence< sal_Int8 >>(_rValue))
1496
0
                _rxUpdatedObject->updateBytes(_nColumnIndex, *s);
1497
0
            else
1498
0
                bSuccessfullyReRouted = false;
1499
0
            break;
1500
0
        case TypeClass_STRUCT:
1501
0
            if (auto s1 = o3tl::tryAccess<DateTime>(_rValue))
1502
0
                _rxUpdatedObject->updateTimestamp(_nColumnIndex, *s1);
1503
0
            else if (auto s2 = o3tl::tryAccess<Date>(_rValue))
1504
0
                _rxUpdatedObject->updateDate(_nColumnIndex, *s2);
1505
0
            else if (auto s3 = o3tl::tryAccess<Time>(_rValue))
1506
0
                _rxUpdatedObject->updateTime(_nColumnIndex, *s3);
1507
0
            else
1508
0
                bSuccessfullyReRouted = false;
1509
0
            break;
1510
1511
0
        case TypeClass_INTERFACE:
1512
0
            if (auto xStream = o3tl::tryAccess<Reference<XInputStream>>(_rValue))
1513
0
            {
1514
0
                _rxUpdatedObject->updateBinaryStream(_nColumnIndex, *xStream, (*xStream)->available());
1515
0
                break;
1516
0
            }
1517
0
            [[fallthrough]];
1518
0
        default:
1519
0
            bSuccessfullyReRouted = false;
1520
0
    }
1521
1522
0
    return bSuccessfullyReRouted;
1523
0
}
1524
1525
bool implSetObject( const Reference< XParameters >& _rxParameters,
1526
                        const sal_Int32 _nColumnIndex, const Any& _rValue)
1527
0
{
1528
0
    bool bSuccessfullyReRouted = true;
1529
0
    switch (_rValue.getValueTypeClass())
1530
0
    {
1531
0
        case TypeClass_UNSIGNED_HYPER:
1532
0
        {
1533
0
            sal_uInt64 nValue = 0;
1534
0
            OSL_VERIFY( _rValue >>= nValue );
1535
0
            _rxParameters->setString(_nColumnIndex, OUString::number(nValue));
1536
0
        }
1537
0
        break;
1538
1539
0
        case TypeClass_UNSIGNED_LONG:
1540
0
        case TypeClass_HYPER:
1541
0
        {
1542
0
            sal_Int64 nValue = 0;
1543
0
            OSL_VERIFY( _rValue >>= nValue );
1544
0
            _rxParameters->setLong( _nColumnIndex, nValue );
1545
0
        }
1546
0
        break;
1547
1548
0
        case TypeClass_ANY:
1549
0
        {
1550
0
            bSuccessfullyReRouted = implSetObject(_rxParameters, _nColumnIndex, _rValue);
1551
0
        }
1552
0
        break;
1553
1554
0
        case TypeClass_VOID:
1555
0
            _rxParameters->setNull(_nColumnIndex,DataType::VARCHAR);
1556
0
            break;
1557
1558
0
        case TypeClass_STRING:
1559
0
            _rxParameters->setString(_nColumnIndex, *o3tl::forceAccess<OUString>(_rValue));
1560
0
            break;
1561
1562
0
        case TypeClass_BOOLEAN:
1563
0
            _rxParameters->setBoolean(_nColumnIndex, *o3tl::forceAccess<bool>(_rValue));
1564
0
            break;
1565
1566
0
        case TypeClass_BYTE:
1567
0
            _rxParameters->setByte(_nColumnIndex, *o3tl::forceAccess<sal_Int8>(_rValue));
1568
0
            break;
1569
1570
0
        case TypeClass_SHORT:
1571
0
            _rxParameters->setShort(_nColumnIndex, *o3tl::forceAccess<sal_Int16>(_rValue));
1572
0
            break;
1573
1574
0
        case TypeClass_CHAR:
1575
0
            _rxParameters->setString(_nColumnIndex, OUString(*o3tl::forceAccess<sal_Unicode>(_rValue)));
1576
0
            break;
1577
1578
0
        case TypeClass_UNSIGNED_SHORT:
1579
0
        case TypeClass_LONG:
1580
0
        {
1581
0
            sal_Int32 nValue = 0;
1582
0
            OSL_VERIFY( _rValue >>= nValue );
1583
0
            _rxParameters->setInt(_nColumnIndex, nValue);
1584
0
            break;
1585
0
        }
1586
1587
0
        case TypeClass_FLOAT:
1588
0
            _rxParameters->setFloat(_nColumnIndex, *o3tl::forceAccess<float>(_rValue));
1589
0
            break;
1590
1591
0
        case TypeClass_DOUBLE:
1592
0
            _rxParameters->setDouble(_nColumnIndex, *o3tl::forceAccess<double>(_rValue));
1593
0
            break;
1594
1595
0
        case TypeClass_SEQUENCE:
1596
0
            if (auto s = o3tl::tryAccess<Sequence< sal_Int8 >>(_rValue))
1597
0
            {
1598
0
                _rxParameters->setBytes(_nColumnIndex, *s);
1599
0
            }
1600
0
            else
1601
0
                bSuccessfullyReRouted = false;
1602
0
            break;
1603
0
        case TypeClass_STRUCT:
1604
0
            if (auto s1 = o3tl::tryAccess<DateTime>(_rValue))
1605
0
                _rxParameters->setTimestamp(_nColumnIndex, *s1);
1606
0
            else if (auto s2 = o3tl::tryAccess<Date>(_rValue))
1607
0
                _rxParameters->setDate(_nColumnIndex, *s2);
1608
0
            else if (auto s3 = o3tl::tryAccess<Time>(_rValue))
1609
0
                _rxParameters->setTime(_nColumnIndex, *s3);
1610
0
            else
1611
0
                bSuccessfullyReRouted = false;
1612
0
            break;
1613
1614
0
        case TypeClass_INTERFACE:
1615
0
            if (Reference<XInputStream> xStream; _rValue >>= xStream)
1616
0
            {
1617
0
                _rxParameters->setBinaryStream(_nColumnIndex, xStream, xStream->available());
1618
0
                break;
1619
0
            }
1620
0
            [[fallthrough]];
1621
0
        default:
1622
0
            bSuccessfullyReRouted = false;
1623
1624
0
    }
1625
1626
0
    return bSuccessfullyReRouted;
1627
0
}
1628
1629
namespace
1630
{
1631
    class OParameterWrapper : public ::cppu::WeakImplHelper< XIndexAccess >
1632
    {
1633
        std::vector<bool, std::allocator<bool> >       m_aSet;
1634
        Reference<XIndexAccess> m_xSource;
1635
    public:
1636
        OParameterWrapper(std::vector<bool, std::allocator<bool> >&& _aSet,const Reference<XIndexAccess>& _xSource)
1637
0
            : m_aSet(std::move(_aSet)), m_xSource(_xSource) {}
1638
    private:
1639
        // css::container::XElementAccess
1640
        virtual Type SAL_CALL getElementType() override
1641
0
        {
1642
0
            return m_xSource->getElementType();
1643
0
        }
1644
        virtual sal_Bool SAL_CALL hasElements(  ) override
1645
0
        {
1646
0
            if ( m_aSet.empty() )
1647
0
                return m_xSource->hasElements();
1648
0
            return std::count(m_aSet.begin(),m_aSet.end(),false) != 0;
1649
0
        }
1650
        // css::container::XIndexAccess
1651
        virtual sal_Int32 SAL_CALL getCount(  ) override
1652
0
        {
1653
0
            if ( m_aSet.empty() )
1654
0
                return m_xSource->getCount();
1655
0
            return std::count(m_aSet.begin(),m_aSet.end(),false);
1656
0
        }
1657
        virtual Any SAL_CALL getByIndex( sal_Int32 Index ) override
1658
0
        {
1659
0
            if ( m_aSet.empty() )
1660
0
                return m_xSource->getByIndex(Index);
1661
0
            if ( Index < 0 || m_aSet.size() < o3tl::make_unsigned(Index) )
1662
0
                throw IndexOutOfBoundsException();
1663
1664
0
            std::vector<bool, std::allocator<bool> >::const_iterator aIter = m_aSet.begin();
1665
0
            std::vector<bool, std::allocator<bool> >::const_iterator aEnd = m_aSet.end();
1666
0
            sal_Int32 i = 0;
1667
0
            for(; aIter != aEnd && i <= Index; ++aIter)
1668
0
            {
1669
0
                if ( !*aIter )
1670
0
                {
1671
0
                    ++i;
1672
0
                }
1673
0
            }
1674
0
            auto nParamPos = static_cast<sal_Int32>(std::distance(m_aSet.cbegin(), aIter)) - 1;
1675
0
            return m_xSource->getByIndex(nParamPos);
1676
0
        }
1677
    };
1678
}
1679
1680
void askForParameters(const Reference< XSingleSelectQueryComposer >& _xComposer,
1681
                      const Reference<XParameters>& _xParameters,
1682
                      const Reference< XConnection>& _xConnection,
1683
                      const Reference< XInteractionHandler >& _rxHandler,
1684
                      const std::vector<bool, std::allocator<bool> >& _aParametersSet)
1685
0
{
1686
0
    OSL_ENSURE(_xComposer.is(),"dbtools::askForParameters XSQLQueryComposer is null!");
1687
0
    OSL_ENSURE(_xParameters.is(),"dbtools::askForParameters XParameters is null!");
1688
0
    OSL_ENSURE(_xConnection.is(),"dbtools::askForParameters XConnection is null!");
1689
0
    OSL_ENSURE(_rxHandler.is(),"dbtools::askForParameters XInteractionHandler is null!");
1690
1691
    // we have to set this here again because getCurrentSettingsComposer can force a setpropertyvalue
1692
0
    Reference<XParametersSupplier>  xParameters(_xComposer, UNO_QUERY);
1693
1694
0
    Reference<XIndexAccess>  xParamsAsIndicies = xParameters.is() ? xParameters->getParameters() : Reference<XIndexAccess>();
1695
0
    sal_Int32 nParamCount = xParamsAsIndicies.is() ? xParamsAsIndicies->getCount() : 0;
1696
0
    std::vector<bool, std::allocator<bool> > aNewParameterSet( _aParametersSet );
1697
0
    if ( !(nParamCount && std::count(aNewParameterSet.begin(),aNewParameterSet.end(),true) != nParamCount) )
1698
0
        return;
1699
1700
0
    static const OUString PROPERTY_NAME(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME));
1701
0
    aNewParameterSet.resize(nParamCount ,false);
1702
0
    typedef std::map< OUString, std::vector<sal_Int32> > TParameterPositions;
1703
0
    TParameterPositions aParameterNames;
1704
0
    for(sal_Int32 i = 0; i < nParamCount; ++i)
1705
0
    {
1706
0
        Reference<XPropertySet> xParam(xParamsAsIndicies->getByIndex(i),UNO_QUERY);
1707
0
        OUString sName;
1708
0
        xParam->getPropertyValue(PROPERTY_NAME) >>= sName;
1709
1710
0
        if ( aParameterNames.contains(sName) )
1711
0
            aNewParameterSet[i] = true;
1712
0
        aParameterNames[sName].push_back(i+1);
1713
0
    }
1714
    // build an interaction request
1715
    // two continuations (Ok and Cancel)
1716
0
    rtl::Reference<OInteractionAbort> pAbort = new OInteractionAbort;
1717
0
    rtl::Reference<OParameterContinuation> pParams = new OParameterContinuation;
1718
    // the request
1719
0
    ParametersRequest aRequest;
1720
0
    Reference<XIndexAccess> xWrappedParameters = new OParameterWrapper(std::move(aNewParameterSet),xParamsAsIndicies);
1721
0
    aRequest.Parameters = xWrappedParameters;
1722
0
    aRequest.Connection = _xConnection;
1723
0
    rtl::Reference<OInteractionRequest> pRequest = new OInteractionRequest(Any(aRequest));
1724
    // some knittings
1725
0
    pRequest->addContinuation(pAbort);
1726
0
    pRequest->addContinuation(pParams);
1727
1728
    // execute the request
1729
0
    _rxHandler->handle(pRequest);
1730
1731
0
    if (!pParams->wasSelected())
1732
0
    {
1733
        // canceled by the user (i.e. (s)he canceled the dialog)
1734
0
        RowSetVetoException e;
1735
0
        e.ErrorCode = ParameterInteractionCancelled;
1736
0
        throw e;
1737
0
    }
1738
1739
    // now transfer the values from the continuation object to the parameter columns
1740
0
    Sequence< PropertyValue > aFinalValues = pParams->getValues();
1741
0
    for (sal_Int32 i = 0; i < aFinalValues.getLength(); ++i)
1742
0
    {
1743
0
        Reference< XPropertySet > xParamColumn(xWrappedParameters->getByIndex(i),UNO_QUERY);
1744
0
        if (xParamColumn.is())
1745
0
        {
1746
0
            OUString sName;
1747
0
            xParamColumn->getPropertyValue(PROPERTY_NAME) >>= sName;
1748
0
            OSL_ENSURE(sName == aFinalValues[i].Name, "::dbaui::askForParameters: inconsistent parameter names!");
1749
1750
            // determine the field type and ...
1751
0
            sal_Int32 nParamType = 0;
1752
0
            xParamColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)) >>= nParamType;
1753
            // ... the scale of the parameter column
1754
0
            sal_Int32 nScale = 0;
1755
0
            if (hasProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE), xParamColumn))
1756
0
                xParamColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE)) >>= nScale;
1757
                // (the index of the parameters is one-based)
1758
0
            TParameterPositions::const_iterator aFind = aParameterNames.find(aFinalValues[i].Name);
1759
0
            for(const auto& rItem : aFind->second)
1760
0
            {
1761
0
                if ( _aParametersSet.empty() || !_aParametersSet[rItem-1] )
1762
0
                {
1763
0
                    _xParameters->setObjectWithInfo(rItem, aFinalValues[i].Value, nParamType, nScale);
1764
0
                }
1765
0
            }
1766
0
        }
1767
0
    }
1768
0
}
1769
1770
void setObjectWithInfo(const Reference<XParameters>& _xParams,
1771
                       sal_Int32 parameterIndex,
1772
                       const Any& x,
1773
                       sal_Int32 sqlType,
1774
                       sal_Int32 scale)
1775
0
{
1776
0
    ORowSetValue aVal;
1777
0
    aVal.fill(x);
1778
0
    setObjectWithInfo(_xParams,parameterIndex,aVal,sqlType,scale);
1779
0
}
1780
1781
void setObjectWithInfo(const Reference<XParameters>& _xParams,
1782
                       sal_Int32 parameterIndex,
1783
                       const ::connectivity::ORowSetValue& _rValue,
1784
                       sal_Int32 sqlType,
1785
                       sal_Int32 scale)
1786
0
{
1787
0
    if ( _rValue.isNull() )
1788
0
        _xParams->setNull(parameterIndex,sqlType);
1789
0
    else
1790
0
    {
1791
0
        switch(sqlType)
1792
0
        {
1793
0
            case DataType::DECIMAL:
1794
0
            case DataType::NUMERIC:
1795
0
                _xParams->setObjectWithInfo(parameterIndex,_rValue.makeAny(),sqlType,scale);
1796
0
                break;
1797
0
            case DataType::CHAR:
1798
0
            case DataType::VARCHAR:
1799
0
            case DataType::LONGVARCHAR:
1800
0
                _xParams->setString(parameterIndex,_rValue.getString());
1801
0
                break;
1802
0
            case DataType::CLOB:
1803
0
                {
1804
0
                    Any x(_rValue.makeAny());
1805
0
                    OUString sValue;
1806
0
                    if ( x >>= sValue )
1807
0
                        _xParams->setString(parameterIndex,sValue);
1808
0
                    else
1809
0
                    {
1810
0
                        Reference< XClob > xClob;
1811
0
                        if(x >>= xClob)
1812
0
                            _xParams->setClob(parameterIndex,xClob);
1813
0
                        else
1814
0
                        {
1815
0
                            Reference< css::io::XInputStream > xStream;
1816
0
                            if(x >>= xStream)
1817
0
                                _xParams->setCharacterStream(parameterIndex,xStream,xStream->available());
1818
0
                        }
1819
0
                    }
1820
0
                }
1821
0
                break;
1822
0
            case DataType::BIGINT:
1823
0
                if ( _rValue.isSigned() )
1824
0
                    _xParams->setLong(parameterIndex,_rValue.getLong());
1825
0
                else
1826
0
                    _xParams->setString(parameterIndex,_rValue.getString());
1827
0
                break;
1828
1829
0
            case DataType::FLOAT:
1830
0
                _xParams->setFloat(parameterIndex,_rValue.getFloat());
1831
0
                break;
1832
0
            case DataType::REAL:
1833
0
            case DataType::DOUBLE:
1834
0
                _xParams->setDouble(parameterIndex,_rValue.getDouble());
1835
0
                break;
1836
0
            case DataType::DATE:
1837
0
                _xParams->setDate(parameterIndex,_rValue.getDate());
1838
0
                break;
1839
0
            case DataType::TIME:
1840
0
                _xParams->setTime(parameterIndex,_rValue.getTime());
1841
0
                break;
1842
0
            case DataType::TIMESTAMP:
1843
0
                _xParams->setTimestamp(parameterIndex,_rValue.getDateTime());
1844
0
                break;
1845
0
            case DataType::BINARY:
1846
0
            case DataType::VARBINARY:
1847
0
            case DataType::LONGVARBINARY:
1848
0
            case DataType::BLOB:
1849
0
                {
1850
0
                    Any x(_rValue.makeAny());
1851
0
                    Sequence< sal_Int8> aBytes;
1852
0
                    if(x >>= aBytes)
1853
0
                        _xParams->setBytes(parameterIndex,aBytes);
1854
0
                    else
1855
0
                    {
1856
0
                        Reference< XBlob > xBlob;
1857
0
                        if(x >>= xBlob)
1858
0
                            _xParams->setBlob(parameterIndex,xBlob);
1859
0
                        else
1860
0
                        {
1861
0
                            Reference< XClob > xClob;
1862
0
                            if(x >>= xClob)
1863
0
                                _xParams->setClob(parameterIndex,xClob);
1864
0
                            else
1865
0
                            {
1866
0
                                Reference< css::io::XInputStream > xBinStream;
1867
0
                                if(x >>= xBinStream)
1868
0
                                    _xParams->setBinaryStream(parameterIndex,xBinStream,xBinStream->available());
1869
0
                            }
1870
0
                        }
1871
0
                    }
1872
0
                }
1873
0
                break;
1874
0
            case DataType::BIT:
1875
0
            case DataType::BOOLEAN:
1876
0
                _xParams->setBoolean(parameterIndex,_rValue.getBool());
1877
0
                break;
1878
0
            case DataType::TINYINT:
1879
0
                if ( _rValue.isSigned() )
1880
0
                    _xParams->setByte(parameterIndex,_rValue.getInt8());
1881
0
                else
1882
0
                    _xParams->setShort(parameterIndex,_rValue.getInt16());
1883
0
                break;
1884
0
            case DataType::SMALLINT:
1885
0
                if ( _rValue.isSigned() )
1886
0
                    _xParams->setShort(parameterIndex,_rValue.getInt16());
1887
0
                else
1888
0
                    _xParams->setInt(parameterIndex,_rValue.getInt32());
1889
0
                break;
1890
0
            case DataType::INTEGER:
1891
0
                if ( _rValue.isSigned() )
1892
0
                    _xParams->setInt(parameterIndex,_rValue.getULong());
1893
0
                else
1894
0
                    _xParams->setLong(parameterIndex,_rValue.getLong());
1895
0
                break;
1896
0
            default:
1897
0
                {
1898
0
                    ::connectivity::SharedResources aResources;
1899
0
                    const OUString sError( aResources.getResourceStringWithSubstitution(
1900
0
                            STR_UNKNOWN_PARA_TYPE,
1901
0
                            "$position$", OUString::number(parameterIndex)
1902
0
                         ) );
1903
0
                    ::dbtools::throwGenericSQLException(sError,nullptr);
1904
0
                }
1905
0
        }
1906
0
    }
1907
0
}
1908
1909
void getBooleanComparisonPredicate( std::u16string_view _rExpression, const bool _bValue, const sal_Int32 _nBooleanComparisonMode,
1910
    OUStringBuffer& _out_rSQLPredicate )
1911
0
{
1912
0
    switch ( _nBooleanComparisonMode )
1913
0
    {
1914
0
    case BooleanComparisonMode::IS_LITERAL:
1915
0
        _out_rSQLPredicate.append( _rExpression );
1916
0
        if ( _bValue )
1917
0
            _out_rSQLPredicate.append( " IS TRUE" );
1918
0
        else
1919
0
            _out_rSQLPredicate.append( " IS FALSE" );
1920
0
        break;
1921
1922
0
    case BooleanComparisonMode::EQUAL_LITERAL:
1923
0
        _out_rSQLPredicate.append( _rExpression );
1924
0
        _out_rSQLPredicate.appendAscii( _bValue ? " = TRUE" : " = FALSE" );
1925
0
        break;
1926
1927
0
    case BooleanComparisonMode::ACCESS_COMPAT:
1928
0
        if ( _bValue )
1929
0
        {
1930
0
            _out_rSQLPredicate.append( " NOT ( ( " );
1931
0
            _out_rSQLPredicate.append( _rExpression );
1932
0
            _out_rSQLPredicate.append( " = 0 ) OR ( " );
1933
0
            _out_rSQLPredicate.append( _rExpression );
1934
0
            _out_rSQLPredicate.append( " IS NULL ) )" );
1935
0
        }
1936
0
        else
1937
0
        {
1938
0
            _out_rSQLPredicate.append( _rExpression );
1939
0
            _out_rSQLPredicate.append( " = 0" );
1940
0
        }
1941
0
        break;
1942
1943
0
    case BooleanComparisonMode::EQUAL_INTEGER:
1944
        // fall through
1945
0
    default:
1946
0
        _out_rSQLPredicate.append( _rExpression );
1947
0
        _out_rSQLPredicate.appendAscii( _bValue ? " = 1" : " = 0" );
1948
0
        break;
1949
0
    }
1950
0
}
1951
1952
}   // namespace dbtools
1953
1954
namespace connectivity
1955
{
1956
void checkDisposed(bool _bThrow)
1957
50.4M
{
1958
50.4M
    if (_bThrow)
1959
0
        throw DisposedException();
1960
1961
50.4M
}
1962
1963
OSQLColumns::const_iterator find(const OSQLColumns::const_iterator& first,
1964
                                        const OSQLColumns::const_iterator& last,
1965
                                        std::u16string_view _rVal,
1966
                                        const ::comphelper::UStringMixEqual& _rCase)
1967
1.78M
{
1968
1.78M
    OUString sName = OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME);
1969
1.78M
    return find(first,last,sName,_rVal,_rCase);
1970
1.78M
}
1971
1972
OSQLColumns::const_iterator findRealName(const OSQLColumns::const_iterator& first,
1973
                                        const OSQLColumns::const_iterator& last,
1974
                                        std::u16string_view _rVal,
1975
                                        const ::comphelper::UStringMixEqual& _rCase)
1976
0
{
1977
0
    OUString sRealName = OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_REALNAME);
1978
0
    return find(first,last,sRealName,_rVal,_rCase);
1979
0
}
1980
1981
OSQLColumns::const_iterator find(OSQLColumns::const_iterator first,
1982
                                        const OSQLColumns::const_iterator& last,
1983
                                        const OUString& _rProp,
1984
                                        std::u16string_view _rVal,
1985
                                        const ::comphelper::UStringMixEqual& _rCase)
1986
1.78M
{
1987
192M
    while (first != last && !_rCase(getString((*first)->getPropertyValue(_rProp)),_rVal))
1988
190M
        ++first;
1989
1.78M
    return first;
1990
1.78M
}
1991
1992
namespace dbase
1993
{
1994
    bool dbfDecodeCharset(rtl_TextEncoding &_out_encoding, sal_uInt8 nType, sal_uInt8 nCodepage)
1995
0
    {
1996
0
        switch (nType)
1997
0
        {
1998
        // dBaseIII header doesn't contain language driver ID
1999
        // See http://dbase.free.fr/tlcharge/structure%20tables.pdf
2000
0
        case dBaseIII:
2001
0
        case dBaseIIIMemo:
2002
0
            break;
2003
0
        case dBaseIV:
2004
0
        case dBaseV:
2005
0
        case VisualFoxPro:
2006
0
        case VisualFoxProAuto:
2007
0
        case dBaseFS:
2008
0
        case dBaseFSMemo:
2009
0
        case dBaseIVMemoSQL:
2010
0
        case FoxProMemo:
2011
0
        {
2012
0
            if (nCodepage != 0x00)
2013
0
            {
2014
0
                auto eEncoding(RTL_TEXTENCODING_DONTKNOW);
2015
0
                switch(nCodepage)
2016
0
                {
2017
0
                case 0x01: eEncoding = RTL_TEXTENCODING_IBM_437; break;       // DOS USA  code page 437
2018
0
                case 0x02: eEncoding = RTL_TEXTENCODING_IBM_850; break;       // DOS Multilingual code page 850
2019
0
                case 0x03: eEncoding = RTL_TEXTENCODING_MS_1252; break;       // Windows ANSI code page 1252
2020
0
                case 0x04: eEncoding = RTL_TEXTENCODING_APPLE_ROMAN; break;   // Standard Macintosh
2021
0
                case 0x64: eEncoding = RTL_TEXTENCODING_IBM_852; break;       // EE MS-DOS    code page 852
2022
0
                case 0x65: eEncoding = RTL_TEXTENCODING_IBM_866; break;       // Russian MS-DOS   code page 866
2023
0
                case 0x66: eEncoding = RTL_TEXTENCODING_IBM_865; break;       // Nordic MS-DOS    code page 865
2024
0
                case 0x67: eEncoding = RTL_TEXTENCODING_IBM_861; break;       // Icelandic MS-DOS
2025
0
                case 0x68: eEncoding = RTL_TEXTENCODING_KAMENICKY; break;     // Kamenicky (Czech) MS-DOS
2026
0
                case 0x69: eEncoding = RTL_TEXTENCODING_MAZOVIA; break;       // Mazovia (Polish) MS-DOS
2027
0
                case 0x6A: eEncoding = RTL_TEXTENCODING_IBM_737; break;       // Greek MS-DOS (437G)
2028
0
                case 0x6B: eEncoding = RTL_TEXTENCODING_IBM_857; break;       // Turkish MS-DOS
2029
0
                case 0x6C: eEncoding = RTL_TEXTENCODING_IBM_863; break;       // MS-DOS, Canada
2030
0
                case 0x78: eEncoding = RTL_TEXTENCODING_MS_950; break;        // Windows, Traditional Chinese
2031
0
                case 0x79: eEncoding = RTL_TEXTENCODING_MS_949; break;        // Windows, Korean (Hangul)
2032
0
                case 0x7A: eEncoding = RTL_TEXTENCODING_MS_936; break;        // Windows, Simplified Chinese
2033
0
                case 0x7B: eEncoding = RTL_TEXTENCODING_MS_932; break;        // Windows, Japanese (Shift-jis)
2034
0
                case 0x7C: eEncoding = RTL_TEXTENCODING_MS_874; break;        // Windows, Thai
2035
0
                case 0x7D: eEncoding = RTL_TEXTENCODING_MS_1255; break;       // Windows, Hebrew
2036
0
                case 0x7E: eEncoding = RTL_TEXTENCODING_MS_1256; break;       // Windows, Arabic
2037
0
                case 0x96: eEncoding = RTL_TEXTENCODING_APPLE_CYRILLIC; break;    // Russian Macintosh
2038
0
                case 0x97: eEncoding = RTL_TEXTENCODING_APPLE_CENTEURO; break;    // Eastern European Macintosh
2039
0
                case 0x98: eEncoding = RTL_TEXTENCODING_APPLE_GREEK; break;   // Greek Macintosh
2040
0
                case 0xC8: eEncoding = RTL_TEXTENCODING_MS_1250; break;       // Windows EE   code page 1250
2041
0
                case 0xC9: eEncoding = RTL_TEXTENCODING_MS_1251; break;       // Russian Windows
2042
0
                case 0xCA: eEncoding = RTL_TEXTENCODING_MS_1254; break;       // Turkish Windows
2043
0
                case 0xCB: eEncoding = RTL_TEXTENCODING_MS_1253; break;       // Greek Windows
2044
0
                case 0xCC: eEncoding = RTL_TEXTENCODING_MS_1257; break;       // Windows, Baltic
2045
0
                }
2046
0
                if(eEncoding != RTL_TEXTENCODING_DONTKNOW)
2047
0
                {
2048
0
                    _out_encoding = eEncoding;
2049
0
                    return true;
2050
0
                }
2051
0
            }
2052
0
        }
2053
0
        }
2054
0
        return false;
2055
0
    }
2056
2057
    bool dbfReadCharset(rtl_TextEncoding &nCharSet, SvStream* dbf_Stream)
2058
0
    {
2059
0
        sal_uInt8 nType=0;
2060
0
        dbf_Stream->ReadUChar( nType );
2061
2062
0
        dbf_Stream->Seek(STREAM_SEEK_TO_BEGIN + 29);
2063
0
        if (dbf_Stream->eof())
2064
0
        {
2065
0
            return false;
2066
0
        }
2067
0
        else
2068
0
        {
2069
0
            sal_uInt8 nEncoding=0;
2070
0
            dbf_Stream->ReadUChar( nEncoding );
2071
0
            return dbfDecodeCharset(nCharSet, nType, nEncoding);
2072
0
        }
2073
0
    }
2074
2075
}
2076
2077
} //namespace connectivity
2078
2079
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */