LibreOffice Module connectivity (master) 1
dbtools2.cxx
Go to the documentation of this file.
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
26#include <strings.hrc>
27#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
28#include <com/sun/star/sdbc/SQLException.hpp>
29#include <com/sun/star/sdbc/XConnection.hpp>
30#include <com/sun/star/sdbc/XDataSource.hpp>
31#include <com/sun/star/sdbc/ColumnValue.hpp>
32#include <com/sun/star/sdbc/DataType.hpp>
33#include <com/sun/star/sdbc/DriverManager.hpp>
34#include <com/sun/star/sdbc/XRow.hpp>
35#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
36#include <com/sun/star/sdbcx/XKeysSupplier.hpp>
37#include <com/sun/star/sdbcx/XDataDefinitionSupplier.hpp>
38#include <com/sun/star/sdbcx/Privilege.hpp>
39#include <com/sun/star/container/XIndexAccess.hpp>
40#include <com/sun/star/sdbc/KeyRule.hpp>
41#include <com/sun/star/sdbcx/KeyType.hpp>
42#include <TConnection.hxx>
44#include <com/sun/star/frame/XModel.hpp>
45#include <com/sun/star/container/XChild.hpp>
46
47#include <comphelper/types.hxx>
50#include <algorithm>
51#include <string_view>
52
53namespace dbtools
54{
55
56 using namespace ::com::sun::star::uno;
57 using namespace ::com::sun::star::beans;
58 using namespace ::com::sun::star::sdb;
59 using namespace ::com::sun::star::sdbc;
60 using namespace ::com::sun::star::sdbcx;
61 using namespace ::com::sun::star::lang;
62 using namespace ::com::sun::star::container;
63 using namespace ::com::sun::star::frame;
64 using namespace connectivity;
65 using namespace comphelper;
66
67OUString createStandardTypePart(const Reference< XPropertySet >& xColProp,const Reference< XConnection>& _xConnection,std::u16string_view _sCreatePattern)
68{
69
70 Reference<XDatabaseMetaData> xMetaData = _xConnection->getMetaData();
71
73
74 OUString sTypeName;
75 sal_Int32 nDataType = 0;
76 sal_Int32 nPrecision = 0;
77 sal_Int32 nScale = 0;
78
79 nDataType = nPrecision = nScale = 0;
80
81 xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_TYPENAME)) >>= sTypeName;
82 xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_TYPE)) >>= nDataType;
83 xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_PRECISION)) >>= nPrecision;
84 xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_SCALE)) >>= nScale;
85
86 OUStringBuffer aSql;
87
88 // check if the user enter a specific string to create autoincrement values
89 OUString sAutoIncrementValue;
90 Reference<XPropertySetInfo> xPropInfo = xColProp->getPropertySetInfo();
91 if ( xPropInfo.is() && xPropInfo->hasPropertyByName(rPropMap.getNameByIndex(PROPERTY_ID_AUTOINCREMENTCREATION)) )
92 xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_AUTOINCREMENTCREATION)) >>= sAutoIncrementValue;
93 // look if we have to use precisions
94 bool bUseLiteral = false;
95 OUString sPrefix,sPostfix,sCreateParams;
96 {
97 Reference<XResultSet> xRes = xMetaData->getTypeInfo();
98 if(xRes.is())
99 {
100 Reference<XRow> xRow(xRes,UNO_QUERY);
101 while(xRes->next())
102 {
103 OUString sTypeName2Cmp = xRow->getString(1);
104 sal_Int32 nType = xRow->getShort(2);
105 sPrefix = xRow->getString (4);
106 sPostfix = xRow->getString (5);
107 sCreateParams = xRow->getString(6);
108 // first identical type will be used if typename is empty
109 if ( sTypeName.isEmpty() && nType == nDataType )
110 sTypeName = sTypeName2Cmp;
111
112 if( sTypeName.equalsIgnoreAsciiCase(sTypeName2Cmp) && nType == nDataType && !sCreateParams.isEmpty() && !xRow->wasNull())
113 {
114 bUseLiteral = true;
115 break;
116 }
117 }
118 }
119 }
120
121 if ( !sAutoIncrementValue.isEmpty() )
122 {
123 sal_Int32 nIndex = sTypeName.indexOf(sAutoIncrementValue);
124 if (nIndex != -1)
125 sTypeName = sTypeName.replaceAt(nIndex,sTypeName.getLength() - nIndex, u"");
126 }
127
128 if ( (nPrecision > 0 || nScale > 0) && bUseLiteral )
129 {
130 sal_Int32 nParenPos = sTypeName.indexOf('(');
131 if ( nParenPos == -1 )
132 {
133 aSql.append(sTypeName + "(");
134 }
135 else
136 {
137 aSql.append(sTypeName.subView(0, ++nParenPos));
138 }
139
140 if ( nPrecision > 0 && nDataType != DataType::TIMESTAMP )
141 {
142 aSql.append(nPrecision);
143 if ( (nScale > 0) || (!_sCreatePattern.empty() && sCreateParams.indexOf(_sCreatePattern) != -1) )
144 aSql.append(",");
145 }
146 if ( (nScale > 0) || ( !_sCreatePattern.empty() && sCreateParams.indexOf(_sCreatePattern) != -1 ) || nDataType == DataType::TIMESTAMP )
147 aSql.append(nScale);
148
149 if ( nParenPos == -1 )
150 aSql.append(")");
151 else
152 {
153 nParenPos = sTypeName.indexOf(')',nParenPos);
154 aSql.append(sTypeName.subView(nParenPos));
155 }
156 }
157 else
158 aSql.append(sTypeName); // simply add the type name
159
160 OUString aDefault = ::comphelper::getString(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_DEFAULTVALUE)));
161 if ( !aDefault.isEmpty() )
162 {
163 aSql.append(" DEFAULT " + sPrefix + aDefault + sPostfix);
164 } // if ( aDefault.getLength() )
165
166 return aSql.makeStringAndClear();
167}
168
169OUString createStandardColumnPart(const Reference< XPropertySet >& xColProp,const Reference< XConnection>& _xConnection,ISQLStatementHelper* _pHelper,std::u16string_view _sCreatePattern)
170{
171 Reference<XDatabaseMetaData> xMetaData = _xConnection->getMetaData();
172
174
175 bool bIsAutoIncrement = false;
176 xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_ISAUTOINCREMENT)) >>= bIsAutoIncrement;
177
178 const OUString sQuoteString = xMetaData->getIdentifierQuoteString();
179 OUStringBuffer aSql(::dbtools::quoteName(sQuoteString,::comphelper::getString(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME)))));
180
181 // check if the user enter a specific string to create autoincrement values
182 OUString sAutoIncrementValue;
183 Reference<XPropertySetInfo> xPropInfo = xColProp->getPropertySetInfo();
184 if ( xPropInfo.is() && xPropInfo->hasPropertyByName(rPropMap.getNameByIndex(PROPERTY_ID_AUTOINCREMENTCREATION)) )
185 xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_AUTOINCREMENTCREATION)) >>= sAutoIncrementValue;
186
187 aSql.append(" " + createStandardTypePart(xColProp, _xConnection, _sCreatePattern));
188
189 if(::comphelper::getINT32(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_ISNULLABLE))) == ColumnValue::NO_NULLS)
190 aSql.append(" NOT NULL");
191
192 if ( bIsAutoIncrement && !sAutoIncrementValue.isEmpty())
193 {
194 aSql.append(" " + sAutoIncrementValue);
195 }
196
197 if ( _pHelper )
198 _pHelper->addComment(xColProp,aSql);
199
200 return aSql.makeStringAndClear();
201}
202
203
204OUString createStandardCreateStatement(const Reference< XPropertySet >& descriptor,const Reference< XConnection>& _xConnection,ISQLStatementHelper* _pHelper,std::u16string_view _sCreatePattern)
205{
206 OUStringBuffer aSql("CREATE TABLE ");
207 OUString sCatalog,sSchema,sTable,sComposedName;
208
209 Reference<XDatabaseMetaData> xMetaData = _xConnection->getMetaData();
211
212 descriptor->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME)) >>= sCatalog;
213 descriptor->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_SCHEMANAME)) >>= sSchema;
214 descriptor->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME)) >>= sTable;
215
216 sComposedName = ::dbtools::composeTableName( xMetaData, sCatalog, sSchema, sTable, true, ::dbtools::EComposeRule::InTableDefinitions );
217 if ( sComposedName.isEmpty() )
219
220 aSql.append(sComposedName + " (");
221
222 // columns
223 Reference<XColumnsSupplier> xColumnSup(descriptor,UNO_QUERY);
224 Reference<XIndexAccess> xColumns(xColumnSup->getColumns(),UNO_QUERY);
225 // check if there are columns
226 if(!xColumns.is() || !xColumns->getCount())
228
229 Reference< XPropertySet > xColProp;
230
231 sal_Int32 nCount = xColumns->getCount();
232 for(sal_Int32 i=0;i<nCount;++i)
233 {
234 if ( (xColumns->getByIndex(i) >>= xColProp) && xColProp.is() )
235 {
236 aSql.append(
237 createStandardColumnPart(xColProp,_xConnection,_pHelper,_sCreatePattern)
238 + ",");
239 }
240 }
241 return aSql.makeStringAndClear();
242}
243namespace
244{
245 OUString generateColumnNames(const Reference<XIndexAccess>& _xColumns,const Reference<XDatabaseMetaData>& _xMetaData)
246 {
248
249 const OUString sQuote(_xMetaData->getIdentifierQuoteString());
250 OUStringBuffer sSql( " (" );
251 Reference< XPropertySet > xColProp;
252
253 sal_Int32 nColCount = _xColumns->getCount();
254 for(sal_Int32 i=0;i<nColCount;++i)
255 {
256 if ( (_xColumns->getByIndex(i) >>= xColProp) && xColProp.is() )
257 sSql.append( ::dbtools::quoteName(sQuote,::comphelper::getString(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME)))) +
258 ",");
259 }
260
261 if ( nColCount )
262 sSql[sSql.getLength()-1] = ')';
263 return sSql.makeStringAndClear();
264 }
265}
266
267OUString createStandardKeyStatement(const Reference< XPropertySet >& descriptor,const Reference< XConnection>& _xConnection)
268{
269 Reference<XDatabaseMetaData> xMetaData = _xConnection->getMetaData();
271
272 OUStringBuffer aSql;
273 // keys
274 Reference<XKeysSupplier> xKeySup(descriptor,UNO_QUERY);
275 Reference<XIndexAccess> xKeys = xKeySup->getKeys();
276 if ( xKeys.is() )
277 {
278 Reference< XPropertySet > xColProp;
279 Reference<XIndexAccess> xColumns;
280 Reference<XColumnsSupplier> xColumnSup;
281 OUString sCatalog,sSchema,sTable,sComposedName;
282 bool bPKey = false;
283 for(sal_Int32 i=0;i<xKeys->getCount();++i)
284 {
285 if ( (xKeys->getByIndex(i) >>= xColProp) && xColProp.is() )
286 {
287
288 sal_Int32 nKeyType = ::comphelper::getINT32(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_TYPE)));
289
290 if ( nKeyType == KeyType::PRIMARY )
291 {
292 if(bPKey)
294
295 bPKey = true;
296 xColumnSup.set(xColProp,UNO_QUERY);
297 xColumns.set(xColumnSup->getColumns(),UNO_QUERY);
298 if(!xColumns.is() || !xColumns->getCount())
300
301 aSql.append(" PRIMARY KEY " + generateColumnNames(xColumns,xMetaData));
302 }
303 else if(nKeyType == KeyType::UNIQUE)
304 {
305 xColumnSup.set(xColProp,UNO_QUERY);
306 xColumns.set(xColumnSup->getColumns(),UNO_QUERY);
307 if(!xColumns.is() || !xColumns->getCount())
309
310 aSql.append(" UNIQUE " + generateColumnNames(xColumns,xMetaData));
311 }
312 else if(nKeyType == KeyType::FOREIGN)
313 {
314 sal_Int32 nDeleteRule = getINT32(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_DELETERULE)));
315
316 xColumnSup.set(xColProp,UNO_QUERY);
317 xColumns.set(xColumnSup->getColumns(),UNO_QUERY);
318 if(!xColumns.is() || !xColumns->getCount())
320
321 aSql.append(" FOREIGN KEY ");
322 OUString sRefTable = getString(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_REFERENCEDTABLE)));
324 sRefTable,
325 sCatalog,
326 sSchema,
327 sTable,
328 ::dbtools::EComposeRule::InDataManipulation);
329 sComposedName = ::dbtools::composeTableName( xMetaData, sCatalog, sSchema, sTable, true, ::dbtools::EComposeRule::InTableDefinitions );
330
331
332 if ( sComposedName.isEmpty() )
334
335 aSql.append(generateColumnNames(xColumns,xMetaData));
336
337 switch(nDeleteRule)
338 {
339 case KeyRule::CASCADE:
340 aSql.append(" ON DELETE CASCADE ");
341 break;
342 case KeyRule::RESTRICT:
343 aSql.append(" ON DELETE RESTRICT ");
344 break;
345 case KeyRule::SET_NULL:
346 aSql.append(" ON DELETE SET NULL ");
347 break;
348 case KeyRule::SET_DEFAULT:
349 aSql.append(" ON DELETE SET DEFAULT ");
350 break;
351 default:
352 ;
353 }
354 }
355 }
356 }
357 }
358
359 if ( !aSql.isEmpty() )
360 {
361 if ( aSql[aSql.getLength() - 1] == ',' )
362 aSql[aSql.getLength() - 1] = ')';
363 else
364 aSql.append(")");
365 }
366
367 return aSql.makeStringAndClear();
368
369}
370
371OUString createSqlCreateTableStatement( const Reference< XPropertySet >& descriptor,
372 const Reference< XConnection>& _xConnection)
373{
374 OUString aSql = ::dbtools::createStandardCreateStatement(descriptor,_xConnection,nullptr,{});
375 const OUString sKeyStmt = ::dbtools::createStandardKeyStatement(descriptor,_xConnection);
376 if ( !sKeyStmt.isEmpty() )
377 aSql += sKeyStmt;
378 else
379 {
380 if ( aSql.endsWith(",") )
381 aSql = aSql.replaceAt(aSql.getLength()-1, 1, u")");
382 else
383 aSql += ")";
384 }
385 return aSql;
386}
387namespace
388{
389 Reference<XPropertySet> lcl_createSDBCXColumn(const Reference<XNameAccess>& _xPrimaryKeyColumns,
390 const Reference<XConnection>& _xConnection,
391 const Any& _aCatalog,
392 const OUString& _aSchema,
393 const OUString& _aTable,
394 const OUString& _rQueryName,
395 const OUString& _rName,
396 bool _bCase,
397 bool _bQueryForInfo,
398 bool _bIsAutoIncrement,
399 bool _bIsCurrency,
400 sal_Int32 _nDataType)
401 {
402 Reference<XPropertySet> xProp;
403 Reference<XDatabaseMetaData> xMetaData = _xConnection->getMetaData();
404 Reference< XResultSet > xResult = xMetaData->getColumns(_aCatalog, _aSchema, _aTable, _rQueryName);
405 OUString sCatalog;
406 _aCatalog >>= sCatalog;
407
408 if ( xResult.is() )
409 {
410 UStringMixEqual aMixCompare(_bCase);
411 Reference< XRow > xRow(xResult,UNO_QUERY);
412 while( xResult->next() )
413 {
414 if ( aMixCompare(xRow->getString(4),_rName) )
415 {
416 sal_Int32 nField5 = xRow->getInt(5);
417 OUString aField6 = xRow->getString(6);
418 sal_Int32 nField7 = xRow->getInt(7)
419 , nField9 = xRow->getInt(9)
420 , nField11= xRow->getInt(11);
421 OUString sField12 = xRow->getString(12),
422 sField13 = xRow->getString(13);
423 ::comphelper::disposeComponent(xRow);
424
425 bool bAutoIncrement = _bIsAutoIncrement
426 ,bIsCurrency = _bIsCurrency;
427 if ( _bQueryForInfo )
428 {
429 const OUString sQuote = xMetaData->getIdentifierQuoteString();
430 OUString sQuotedName = ::dbtools::quoteName(sQuote,_rName);
431 OUString sComposedName = composeTableNameForSelect(_xConnection, getString( _aCatalog ), _aSchema, _aTable );
432
433 ColumnInformationMap aInfo(_bCase);
434 collectColumnInformation(_xConnection,sComposedName,sQuotedName,aInfo);
435 ColumnInformationMap::const_iterator aIter = aInfo.begin();
436 if ( aIter != aInfo.end() )
437 {
438 bAutoIncrement = aIter->second.first.first;
439 bIsCurrency = aIter->second.first.second;
440 if ( DataType::OTHER == nField5 )
441 nField5 = aIter->second.second;
442 }
443 }
444 else if ( DataType::OTHER == nField5 )
445 nField5 = _nDataType;
446
447 if ( nField11 != ColumnValue::NO_NULLS )
448 {
449 try
450 {
451 if ( _xPrimaryKeyColumns.is() )
452 {
453 if ( _xPrimaryKeyColumns->hasByName(_rName) )
454 nField11 = ColumnValue::NO_NULLS;
455
456 }
457 else
458 {
459 Reference< XResultSet > xPKeys = xMetaData->getPrimaryKeys( _aCatalog, _aSchema, _aTable );
460 Reference< XRow > xPKeyRow( xPKeys, UNO_QUERY_THROW );
461 while( xPKeys->next() ) // there can be only one primary key
462 {
463 OUString sKeyColumn = xPKeyRow->getString(4);
464 if ( aMixCompare(_rName,sKeyColumn) )
465 {
466 nField11 = ColumnValue::NO_NULLS;
467 break;
468 }
469 }
470 }
471 }
472 catch(SQLException&)
473 {
474 TOOLS_WARN_EXCEPTION( "connectivity.commontools", "lcl_createSDBCXColumn" );
475 }
476 }
477
478 xProp = new connectivity::sdbcx::OColumn(_rName,
479 aField6,
480 sField13,
481 sField12,
482 nField11,
483 nField7,
484 nField9,
485 nField5,
486 bAutoIncrement,
487 false,
488 bIsCurrency,
489 _bCase,
490 sCatalog,
491 _aSchema,
492 _aTable);
493
494 break;
495 }
496 }
497 }
498
499 return xProp;
500 }
501
502 Reference< XModel> lcl_getXModel(const Reference< XInterface>& _xIface)
503 {
504 Reference< XInterface > xParent = _xIface;
505 Reference< XModel > xModel(xParent,UNO_QUERY);
506 while( xParent.is() && !xModel.is() )
507 {
508 Reference<XChild> xChild(xParent,UNO_QUERY);
509 xParent.set(xChild.is() ? xChild->getParent() : Reference< XInterface >(),UNO_QUERY);
510 xModel.set(xParent,UNO_QUERY);
511 }
512 return xModel;
513 }
514}
515
516Reference<XPropertySet> createSDBCXColumn(const Reference<XPropertySet>& _xTable,
517 const Reference<XConnection>& _xConnection,
518 const OUString& _rName,
519 bool _bCase,
520 bool _bQueryForInfo,
521 bool _bIsAutoIncrement,
522 bool _bIsCurrency,
523 sal_Int32 _nDataType)
524{
525 Reference<XPropertySet> xProp;
526 OSL_ENSURE(_xTable.is(),"Table is NULL!");
527 if ( !_xTable.is() )
528 return xProp;
529
531 Any aCatalog = _xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME));
532 OUString sCatalog;
533 aCatalog >>= sCatalog;
534
535 OUString aSchema, aTable;
536 _xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_SCHEMANAME)) >>= aSchema;
537 _xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME)) >>= aTable;
538
539 Reference<XNameAccess> xPrimaryKeyColumns = getPrimaryKeyColumns_throw(_xTable);
540
541 xProp = lcl_createSDBCXColumn(xPrimaryKeyColumns,_xConnection,aCatalog, aSchema, aTable, _rName,_rName,_bCase,_bQueryForInfo,_bIsAutoIncrement,_bIsCurrency,_nDataType);
542 if ( !xProp.is() )
543 {
544 xProp = lcl_createSDBCXColumn(xPrimaryKeyColumns,_xConnection,aCatalog, aSchema, aTable, "%",_rName,_bCase,_bQueryForInfo,_bIsAutoIncrement,_bIsCurrency,_nDataType);
545 if ( !xProp.is() )
546 xProp = new connectivity::sdbcx::OColumn(_rName,
547 OUString(),OUString(),OUString(),
548 ColumnValue::NULLABLE_UNKNOWN,
549 0,
550 0,
551 DataType::VARCHAR,
552 _bIsAutoIncrement,
553 false,
554 _bIsCurrency,
555 _bCase,
556 sCatalog,
557 aSchema,
558 aTable);
559
560 }
561
562 return xProp;
563}
564
565
566bool getBooleanDataSourceSetting( const Reference< XConnection >& _rxConnection, const char* _pAsciiSettingName )
567{
568 return getBooleanDataSourceSetting(_rxConnection, OUString::createFromAscii( _pAsciiSettingName ));
569}
570
571bool getBooleanDataSourceSetting( const Reference< XConnection >& _rxConnection, const OUString & rSettingName )
572{
573 bool bValue( false );
574 try
575 {
576 Reference< XPropertySet> xDataSourceProperties( findDataSource( _rxConnection ), UNO_QUERY );
577 OSL_ENSURE( xDataSourceProperties.is(), "::dbtools::getBooleanDataSourceSetting: somebody is using this with a non-SDB-level connection!" );
578 if ( xDataSourceProperties.is() )
579 {
580 Reference< XPropertySet > xSettings(
581 xDataSourceProperties->getPropertyValue("Settings"),
582 UNO_QUERY_THROW
583 );
584 OSL_VERIFY( xSettings->getPropertyValue( rSettingName ) >>= bValue );
585 }
586 }
587 catch( const Exception& )
588 {
589 DBG_UNHANDLED_EXCEPTION("connectivity.commontools");
590 }
591 return bValue;
592}
593
594bool getDataSourceSetting( const Reference< XInterface >& _xChild, const OUString& _sAsciiSettingsName,
595 Any& /* [out] */ _rSettingsValue )
596{
597 bool bIsPresent = false;
598 try
599 {
600 const Reference< XPropertySet> xDataSourceProperties( findDataSource( _xChild ), UNO_QUERY );
601 if ( !xDataSourceProperties.is() )
602 return false;
603
604 const Reference< XPropertySet > xSettings(
605 xDataSourceProperties->getPropertyValue("Settings"),
606 UNO_QUERY_THROW
607 );
608
609 _rSettingsValue = xSettings->getPropertyValue( _sAsciiSettingsName );
610 bIsPresent = true;
611 }
612 catch( const Exception& )
613 {
614 bIsPresent = false;
615 }
616 return bIsPresent;
617}
618
619bool getDataSourceSetting( const Reference< XInterface >& _rxDataSource, const char* _pAsciiSettingsName,
620 Any& /* [out] */ _rSettingsValue )
621{
622 OUString sAsciiSettingsName = OUString::createFromAscii(_pAsciiSettingsName);
623 return getDataSourceSetting( _rxDataSource, sAsciiSettingsName,_rSettingsValue );
624}
625
626bool isDataSourcePropertyEnabled(const Reference<XInterface>& _xProp, const OUString& _sProperty, bool _bDefault)
627{
628 bool bEnabled = _bDefault;
629 try
630 {
631 Reference< XPropertySet> xProp(findDataSource(_xProp),UNO_QUERY);
632 if ( xProp.is() )
633 {
634 Sequence< PropertyValue > aInfo;
635 xProp->getPropertyValue("Info") >>= aInfo;
636 const PropertyValue* pValue =std::find_if(std::cbegin(aInfo),
637 std::cend(aInfo),
638 [&_sProperty](const PropertyValue& lhs)
639 { return lhs.Name == _sProperty; });
640 if ( pValue != std::cend(aInfo) )
641 pValue->Value >>= bEnabled;
642 }
643 }
644 catch(SQLException&)
645 {
646 DBG_UNHANDLED_EXCEPTION("connectivity.commontools");
647 }
648 return bEnabled;
649}
650
651Reference< XTablesSupplier> getDataDefinitionByURLAndConnection(
652 const OUString& _rsUrl,
653 const Reference< XConnection>& _xConnection,
654 const Reference< XComponentContext >& _rxContext)
655{
656 Reference< XTablesSupplier> xTablesSup;
657 try
658 {
659 Reference< XDriverManager2 > xManager = DriverManager::create( _rxContext );
660 Reference< XDataDefinitionSupplier > xSupp( xManager->getDriverByURL( _rsUrl ), UNO_QUERY );
661
662 if ( xSupp.is() )
663 {
664 xTablesSup = xSupp->getDataDefinitionByConnection( _xConnection );
665 OSL_ENSURE(xTablesSup.is(),"No table supplier!");
666 }
667 }
668 catch( const Exception& )
669 {
670 DBG_UNHANDLED_EXCEPTION("connectivity.commontools");
671 }
672 return xTablesSup;
673}
674
675
676sal_Int32 getTablePrivileges(const Reference< XDatabaseMetaData>& _xMetaData,
677 const OUString& _sCatalog,
678 const OUString& _sSchema,
679 const OUString& _sTable)
680{
681 OSL_ENSURE(_xMetaData.is(),"Invalid metadata!");
682 sal_Int32 nPrivileges = 0;
683 try
684 {
685 Any aVal;
686 if(!_sCatalog.isEmpty())
687 aVal <<= _sCatalog;
688 Reference< XResultSet > xPrivileges = _xMetaData->getTablePrivileges(aVal, _sSchema, _sTable);
689 Reference< XRow > xCurrentRow(xPrivileges, UNO_QUERY);
690
691 const OUString sUserWorkingFor = _xMetaData->getUserName();
692 static const char sSELECT[] = "SELECT";
693 static const char sINSERT[] = "INSERT";
694 static const char sUPDATE[] = "UPDATE";
695 static const char sDELETE[] = "DELETE";
696 static const char sREAD[] = "READ";
697 static const char sCREATE[] = "CREATE";
698 static const char sALTER[] = "ALTER";
699 static const char sREFERENCE[] = "REFERENCE";
700 static const char sDROP[] = "DROP";
701
702 if ( xCurrentRow.is() )
703 {
704 // after creation the set is positioned before the first record, per definition
705 OUString sPrivilege, sGrantee;
706 while ( xPrivileges->next() )
707 {
708 sGrantee = xCurrentRow->getString(5);
709 sPrivilege = xCurrentRow->getString(6);
710
711 if (!sUserWorkingFor.equalsIgnoreAsciiCase(sGrantee))
712 continue;
713
714 if (sPrivilege.equalsIgnoreAsciiCase(sSELECT))
715 nPrivileges |= Privilege::SELECT;
716 else if (sPrivilege.equalsIgnoreAsciiCase(sINSERT))
717 nPrivileges |= Privilege::INSERT;
718 else if (sPrivilege.equalsIgnoreAsciiCase(sUPDATE))
719 nPrivileges |= Privilege::UPDATE;
720 else if (sPrivilege.equalsIgnoreAsciiCase(sDELETE))
721 nPrivileges |= Privilege::DELETE;
722 else if (sPrivilege.equalsIgnoreAsciiCase(sREAD))
723 nPrivileges |= Privilege::READ;
724 else if (sPrivilege.equalsIgnoreAsciiCase(sCREATE))
725 nPrivileges |= Privilege::CREATE;
726 else if (sPrivilege.equalsIgnoreAsciiCase(sALTER))
727 nPrivileges |= Privilege::ALTER;
728 else if (sPrivilege.equalsIgnoreAsciiCase(sREFERENCE))
729 nPrivileges |= Privilege::REFERENCE;
730 else if (sPrivilege.equalsIgnoreAsciiCase(sDROP))
731 nPrivileges |= Privilege::DROP;
732 }
733 }
734 disposeComponent(xPrivileges);
735
736 // Some drivers put a table privilege as soon as any column has the privilege,
737 // some drivers only if all columns have the privilege.
738 // To unify the situation, collect column privileges here, too.
739 Reference< XResultSet > xColumnPrivileges = _xMetaData->getColumnPrivileges(aVal, _sSchema, _sTable, "%");
740 Reference< XRow > xColumnCurrentRow(xColumnPrivileges, UNO_QUERY);
741 if ( xColumnCurrentRow.is() )
742 {
743 // after creation the set is positioned before the first record, per definition
744 OUString sPrivilege, sGrantee;
745 while ( xColumnPrivileges->next() )
746 {
747 sGrantee = xColumnCurrentRow->getString(6);
748 sPrivilege = xColumnCurrentRow->getString(7);
749
750 if (!sUserWorkingFor.equalsIgnoreAsciiCase(sGrantee))
751 continue;
752
753 if (sPrivilege.equalsIgnoreAsciiCase(sSELECT))
754 nPrivileges |= Privilege::SELECT;
755 else if (sPrivilege.equalsIgnoreAsciiCase(sINSERT))
756 nPrivileges |= Privilege::INSERT;
757 else if (sPrivilege.equalsIgnoreAsciiCase(sUPDATE))
758 nPrivileges |= Privilege::UPDATE;
759 else if (sPrivilege.equalsIgnoreAsciiCase(sDELETE))
760 nPrivileges |= Privilege::DELETE;
761 else if (sPrivilege.equalsIgnoreAsciiCase(sREAD))
762 nPrivileges |= Privilege::READ;
763 else if (sPrivilege.equalsIgnoreAsciiCase(sCREATE))
764 nPrivileges |= Privilege::CREATE;
765 else if (sPrivilege.equalsIgnoreAsciiCase(sALTER))
766 nPrivileges |= Privilege::ALTER;
767 else if (sPrivilege.equalsIgnoreAsciiCase(sREFERENCE))
768 nPrivileges |= Privilege::REFERENCE;
769 else if (sPrivilege.equalsIgnoreAsciiCase(sDROP))
770 nPrivileges |= Privilege::DROP;
771 }
772 }
773 disposeComponent(xColumnPrivileges);
774 }
775 catch(const SQLException& e)
776 {
777 // some drivers don't support any privileges so we assume that we are allowed to do all we want :-)
778 if(e.SQLState == "IM001")
779 nPrivileges |= Privilege::DROP |
780 Privilege::REFERENCE |
781 Privilege::ALTER |
782 Privilege::CREATE |
783 Privilege::READ |
784 Privilege::DELETE |
785 Privilege::UPDATE |
786 Privilege::INSERT |
787 Privilege::SELECT;
788 else
789 OSL_FAIL("Could not collect the privileges !");
790 }
791 return nPrivileges;
792}
793
794// we need some more information about the column
795void collectColumnInformation(const Reference< XConnection>& _xConnection,
796 std::u16string_view _sComposedName,
797 std::u16string_view _rName,
798 ColumnInformationMap& _rInfo)
799{
800 OUString sSelect = OUString::Concat("SELECT ") + _rName +
801 " FROM " + _sComposedName +
802 " WHERE 0 = 1";
803
804 try
805 {
806 ::utl::SharedUNOComponent< XStatement > xStmt( _xConnection->createStatement() );
807 Reference< XPropertySet > xStatementProps( xStmt, UNO_QUERY_THROW );
808 xStatementProps->setPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_ESCAPEPROCESSING ), Any( false ) );
809 Reference< XResultSet > xResult( xStmt->executeQuery( sSelect ), UNO_SET_THROW );
810 Reference< XResultSetMetaDataSupplier > xSuppMeta( xResult, UNO_QUERY_THROW );
811 Reference< XResultSetMetaData > xMeta( xSuppMeta->getMetaData(), UNO_SET_THROW );
812
813 sal_Int32 nCount = xMeta->getColumnCount();
814 OSL_ENSURE( nCount != 0, "::dbtools::collectColumnInformation: result set has empty (column-less) meta data!" );
815 for (sal_Int32 i=1; i <= nCount ; ++i)
816 {
817 _rInfo.emplace( xMeta->getColumnName(i),
818 ColumnInformation(TBoolPair(xMeta->isAutoIncrement(i),xMeta->isCurrency(i)),xMeta->getColumnType(i)));
819 }
820 }
821 catch( const Exception& )
822 {
823 DBG_UNHANDLED_EXCEPTION("connectivity.commontools");
824 }
825}
826
827
828bool isEmbeddedInDatabase( const Reference< XInterface >& _rxComponent, Reference< XConnection >& _rxActualConnection )
829{
830 bool bIsEmbedded = false;
831 try
832 {
833 Reference< XModel > xModel = lcl_getXModel( _rxComponent );
834
835 if ( xModel.is() )
836 {
837 Sequence< PropertyValue > aArgs = xModel->getArgs();
838 const PropertyValue* pIter = aArgs.getConstArray();
839 const PropertyValue* pEnd = pIter + aArgs.getLength();
840 for(;pIter != pEnd;++pIter)
841 {
842 if ( pIter->Name == "ComponentData" )
843 {
844 Sequence<PropertyValue> aDocumentContext;
845 pIter->Value >>= aDocumentContext;
846 const PropertyValue* pContextIter = aDocumentContext.getConstArray();
847 const PropertyValue* pContextEnd = pContextIter + aDocumentContext.getLength();
848 for(;pContextIter != pContextEnd;++pContextIter)
849 {
850 if ( pContextIter->Name == "ActiveConnection"
851 && ( pContextIter->Value >>= _rxActualConnection )
852 )
853 {
854 bIsEmbedded = true;
855 break;
856 }
857 }
858 break;
859 }
860 }
861 }
862 }
863 catch(Exception&)
864 {
865 // not interested in
866 }
867 return bIsEmbedded;
868}
869
870namespace
871{
872 OUString lcl_getEncodingName( rtl_TextEncoding _eEncoding )
873 {
874 OUString sEncodingName;
875
876 OCharsetMap aCharsets;
877 OCharsetMap::CharsetIterator aEncodingPos = aCharsets.find( _eEncoding );
878 OSL_ENSURE( aEncodingPos != aCharsets.end(), "lcl_getEncodingName: *which* encoding?" );
879 if ( aEncodingPos != aCharsets.end() )
880 sEncodingName = (*aEncodingPos).getIanaName();
881
882 return sEncodingName;
883 }
884}
885
886
887sal_Int32 DBTypeConversion::convertUnicodeString( const OUString& _rSource, OString& _rDest, rtl_TextEncoding _eEncoding )
888{
889 if ( !rtl_convertUStringToString( &_rDest.pData, _rSource.getStr(), _rSource.getLength(),
890 _eEncoding,
891 RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
892 RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACE |
893 RTL_UNICODETOTEXT_FLAGS_PRIVATE_MAPTO0 )
894 )
895 {
896 SharedResources aResources;
897 OUString sMessage = aResources.getResourceStringWithSubstitution( STR_CANNOT_CONVERT_STRING,
898 "$string$", _rSource,
899 "$charset$", lcl_getEncodingName( _eEncoding )
900 );
901
902 throw SQLException(
903 sMessage,
904 nullptr,
905 "22018",
906 22018,
907 Any()
908 );
909 }
910
911 return _rDest.getLength();
912}
913
914
915sal_Int32 DBTypeConversion::convertUnicodeStringToLength( const OUString& _rSource, OString& _rDest,
916 sal_Int32 _nMaxLen, rtl_TextEncoding _eEncoding )
917{
918 sal_Int32 nLen = convertUnicodeString( _rSource, _rDest, _eEncoding );
919 if ( nLen > _nMaxLen )
920 {
921 SharedResources aResources;
922 OUString sMessage = aResources.getResourceStringWithSubstitution( STR_STRING_LENGTH_EXCEEDED,
923 "$string$", _rSource,
924 "$maxlen$", OUString::number( _nMaxLen ),
925 "$charset$", lcl_getEncodingName( _eEncoding )
926 );
927
928 throw SQLException(
929 sMessage,
930 nullptr,
931 "22001",
932 22001,
933 Any()
934 );
935 }
936
937 return nLen;
938}
939
940OUString getDefaultReportEngineServiceName(const Reference< XComponentContext >& _rxORB)
941{
943 _rxORB, "org.openoffice.Office.DataAccess/ReportEngines", -1, ::utl::OConfigurationTreeRoot::CM_READONLY);
944
945 if ( aReportEngines.isValid() )
946 {
947 OUString sDefaultReportEngineName;
948 aReportEngines.getNodeValue("DefaultReportEngine") >>= sDefaultReportEngineName;
949 if ( !sDefaultReportEngineName.isEmpty() )
950 {
951 ::utl::OConfigurationNode aReportEngineNames = aReportEngines.openNode("ReportEngineNames");
952 if ( aReportEngineNames.isValid() )
953 {
954 ::utl::OConfigurationNode aReportEngine = aReportEngineNames.openNode(sDefaultReportEngineName);
955 if ( aReportEngine.isValid() )
956 {
957 OUString sRet;
958 aReportEngine.getNodeValue("ServiceName") >>= sRet;
959 return sRet;
960 }
961 }
962 }
963 else
964 return "org.libreoffice.report.pentaho.SOReportJobFactory";
965 }
966 else
967 return "org.libreoffice.report.pentaho.SOReportJobFactory";
968 return OUString();
969}
970
971bool isAggregateColumn(const Reference< XSingleSelectQueryComposer > &_xParser, const Reference< XPropertySet > &_xField)
972{
973 OUString sName;
974 _xField->getPropertyValue("Name") >>= sName;
975 Reference< XColumnsSupplier > xColumnsSupplier(_xParser, UNO_QUERY);
976 Reference< css::container::XNameAccess > xCols;
977 if (xColumnsSupplier.is())
978 xCols = xColumnsSupplier->getColumns();
979
980 return isAggregateColumn(xCols, sName);
981}
982
983bool isAggregateColumn(const Reference< XNameAccess > &_xColumns, const OUString &_sName)
984{
985 if ( _xColumns.is() && _xColumns->hasByName(_sName) )
986 {
987 Reference<XPropertySet> xProp(_xColumns->getByName(_sName),UNO_QUERY);
988 assert(xProp.is());
989 return isAggregateColumn( xProp );
990 }
991 return false;
992}
993
994bool isAggregateColumn( const Reference< XPropertySet > &_xColumn )
995{
996 bool bAgg(false);
997
998 static constexpr OUStringLiteral sAgg = u"AggregateFunction";
999 if ( _xColumn->getPropertySetInfo()->hasPropertyByName(sAgg) )
1000 _xColumn->getPropertyValue(sAgg) >>= bAgg;
1001
1002 return bAgg;
1003}
1004
1005
1006} // namespace dbtools
1007
1008
1009/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_Int32 nDataType
OptionalString sSchema
OptionalString sCatalog
OptionalString sComposedName
::dbtools::OPropertyMap & getPropMap()
Definition: TConnection.cxx:68
helper class for accessing resources shared by different libraries in the connectivity module
OUString getResourceStringWithSubstitution(TranslateId pResId, const char *_pAsciiPatternToReplace, const OUString &_rStringToSubstitute) const
loads a string from the shared resource file, and replaces a given ASCII pattern with a given string
virtual void addComment(const css::uno::Reference< css::beans::XPropertySet > &descriptor, OUStringBuffer &_rOut)=0
is a class which translates between different charset representations.
Definition: dbcharset.hxx:54
CharsetIterator(const OCharsetMap *_pContainer, OCharsetMap::TextEncBag::const_iterator _aPos)
CharsetIterator find(const rtl_TextEncoding _eEncoding) const
find the given text encoding in the map.
Definition: dbcharset.cxx:89
CharsetIterator end() const
get access to the (last + 1st) element of the charset collection
Definition: dbcharset.cxx:118
const OUString & getNameByIndex(sal_Int32 _nIndex) const
Definition: propertyids.cxx:95
css::uno::Any getNodeValue(const OUString &_rPath) const noexcept
OConfigurationNode openNode(const OUString &_rPath) const noexcept
static OConfigurationTreeRoot createWithComponentContext(const css::uno::Reference< css::uno::XComponentContext > &_rxContext, const OUString &_rPath, sal_Int32 _nDepth=-1, CREATION_MODE _eMode=CM_UPDATABLE)
int nCount
#define TOOLS_WARN_EXCEPTION(area, stream)
#define DBG_UNHANDLED_EXCEPTION(...)
float u
const char sQuote[]
bool bAutoIncrement
OUString sName
OUString sPrefix
sal_Int32 nIndex
@ Exception
void disposeComponent(css::uno::Reference< TYPE > &_rxComp)
sal_Int32 getINT32(const Any &_rAny)
OUString getString(const Any &_rAny)
OOO_DLLPUBLIC_DBTOOLS sal_Int32 convertUnicodeStringToLength(const OUString &_rSource, OString &_rDest, sal_Int32 _nMaxLen, rtl_TextEncoding _eEncoding)
converts a Unicode string into a 8-bit string, using the given encoding
Definition: dbtools2.cxx:915
OOO_DLLPUBLIC_DBTOOLS sal_Int32 convertUnicodeString(const OUString &_rSource, OString &_rDest, rtl_TextEncoding _eEncoding)
converts a Unicode string into a 8-bit string, using the given encoding
Definition: dbtools2.cxx:887
sal_Int32 getTablePrivileges(const Reference< XDatabaseMetaData > &_xMetaData, const OUString &_sCatalog, const OUString &_sSchema, const OUString &_sTable)
Definition: dbtools2.cxx:676
::std::pair< bool, bool > TBoolPair
Definition: dbtools.hxx:743
OUString createSqlCreateTableStatement(const Reference< XPropertySet > &descriptor, const Reference< XConnection > &_xConnection)
Definition: dbtools2.cxx:371
OUString createStandardCreateStatement(const Reference< XPropertySet > &descriptor, const Reference< XConnection > &_xConnection, ISQLStatementHelper *_pHelper, std::u16string_view _sCreatePattern)
Definition: dbtools2.cxx:204
bool getDataSourceSetting(const Reference< XInterface > &_xChild, const OUString &_sAsciiSettingsName, Any &_rSettingsValue)
Definition: dbtools2.cxx:594
OUString composeTableName(const Reference< XDatabaseMetaData > &_rxMetaData, const OUString &_rCatalog, const OUString &_rSchema, const OUString &_rName, bool _bQuote, EComposeRule _eComposeRule)
Definition: dbtools.cxx:1286
void throwFunctionSequenceException(const Reference< XInterface > &Context, const Any &Next)
OUString createStandardTypePart(const Reference< XPropertySet > &xColProp, const Reference< XConnection > &_xConnection, std::u16string_view _sCreatePattern)
Definition: dbtools2.cxx:67
OUString createStandardColumnPart(const Reference< XPropertySet > &xColProp, const Reference< XConnection > &_xConnection, ISQLStatementHelper *_pHelper, std::u16string_view _sCreatePattern)
Definition: dbtools2.cxx:169
Reference< XTablesSupplier > getDataDefinitionByURLAndConnection(const OUString &_rsUrl, const Reference< XConnection > &_xConnection, const Reference< XComponentContext > &_rxContext)
Definition: dbtools2.cxx:651
Reference< XPropertySet > createSDBCXColumn(const Reference< XPropertySet > &_xTable, const Reference< XConnection > &_xConnection, const OUString &_rName, bool _bCase, bool _bQueryForInfo, bool _bIsAutoIncrement, bool _bIsCurrency, sal_Int32 _nDataType)
Definition: dbtools2.cxx:516
OUString createStandardKeyStatement(const Reference< XPropertySet > &descriptor, const Reference< XConnection > &_xConnection)
Definition: dbtools2.cxx:267
void qualifiedNameComponents(const Reference< XDatabaseMetaData > &_rxConnMetaData, const OUString &_rQualifiedName, OUString &_rCatalog, OUString &_rSchema, OUString &_rName, EComposeRule _eComposeRule)
Definition: dbtools.cxx:862
bool isDataSourcePropertyEnabled(const Reference< XInterface > &_xProp, const OUString &_sProperty, bool _bDefault)
Definition: dbtools2.cxx:626
bool isAggregateColumn(const Reference< XSingleSelectQueryComposer > &_xParser, const Reference< XPropertySet > &_xField)
Definition: dbtools2.cxx:971
OUString getDefaultReportEngineServiceName(const Reference< XComponentContext > &_rxORB)
Definition: dbtools2.cxx:940
OUString composeTableNameForSelect(const Reference< XConnection > &_rxConnection, const OUString &_rCatalog, const OUString &_rSchema, const OUString &_rName)
Definition: dbtools.cxx:1296
::std::multimap< OUString, ColumnInformation, ::comphelper::UStringMixLess > ColumnInformationMap
Definition: dbtools.hxx:745
OUString quoteName(std::u16string_view _rQuote, const OUString &_rName)
quote the given name with the given quote string.
void collectColumnInformation(const Reference< XConnection > &_xConnection, std::u16string_view _sComposedName, std::u16string_view _rName, ColumnInformationMap &_rInfo)
Definition: dbtools2.cxx:795
bool getBooleanDataSourceSetting(const Reference< XConnection > &_rxConnection, const char *_pAsciiSettingName)
Definition: dbtools2.cxx:566
Reference< XDataSource > findDataSource(const Reference< XInterface > &_xParent)
Definition: dbtools.cxx:1197
bool isEmbeddedInDatabase(const Reference< XInterface > &_rxComponent, Reference< XConnection > &_rxActualConnection)
Definition: dbtools2.cxx:828
Reference< XNameAccess > getPrimaryKeyColumns_throw(const Any &i_aTable)
Definition: dbtools.cxx:487
::std::pair< TBoolPair, sal_Int32 > ColumnInformation
Definition: dbtools.hxx:744
int i
#define PROPERTY_ID_NAME
Definition: propertyids.hxx:50
#define PROPERTY_ID_REFERENCEDTABLE
Definition: propertyids.hxx:61
#define PROPERTY_ID_AUTOINCREMENTCREATION
Definition: propertyids.hxx:92
#define PROPERTY_ID_TYPE
Definition: propertyids.hxx:51
#define PROPERTY_ID_CATALOGNAME
Definition: propertyids.hxx:70
#define PROPERTY_ID_ISNULLABLE
Definition: propertyids.hxx:55
#define PROPERTY_ID_PRECISION
Definition: propertyids.hxx:53
#define PROPERTY_ID_SCHEMANAME
Definition: propertyids.hxx:69
#define PROPERTY_ID_ISAUTOINCREMENT
Definition: propertyids.hxx:56
#define PROPERTY_ID_TYPENAME
Definition: propertyids.hxx:52
#define PROPERTY_ID_DELETERULE
Definition: propertyids.hxx:63
#define PROPERTY_ID_DEFAULTVALUE
Definition: propertyids.hxx:59
#define PROPERTY_ID_ESCAPEPROCESSING
Definition: propertyids.hxx:47
#define PROPERTY_ID_SCALE
Definition: propertyids.hxx:54
QPRO_FUNC_TYPE nType
OUString sMessage
Reference< XModel > xModel