bump product version to 5.0.4.1
[LibreOffice.git] / connectivity / source / commontools / dbtools2.cxx
blob13923c0a57856a9210d6f8190afbdbb5e423ecff
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <connectivity/dbtools.hxx>
21 #include <connectivity/dbconversion.hxx>
22 #include <connectivity/dbcharset.hxx>
23 #include <connectivity/SQLStatementHelper.hxx>
24 #include <unotools/confignode.hxx>
25 #include "resource/sharedresources.hxx"
26 #include "resource/common_res.hrc"
27 #include <com/sun/star/sdbc/XConnection.hpp>
28 #include <com/sun/star/sdbc/ColumnValue.hpp>
29 #include <com/sun/star/sdbc/DataType.hpp>
30 #include <com/sun/star/sdbc/DriverManager.hpp>
31 #include <com/sun/star/sdbc/XRow.hpp>
32 #include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
33 #include <com/sun/star/sdbcx/XKeysSupplier.hpp>
34 #include <com/sun/star/sdbc/XDriverAccess.hpp>
35 #include <com/sun/star/sdbcx/XDataDefinitionSupplier.hpp>
36 #include <com/sun/star/sdbcx/Privilege.hpp>
37 #include <com/sun/star/container/XIndexAccess.hpp>
38 #include <com/sun/star/container/XEnumerationAccess.hpp>
39 #include <com/sun/star/sdbc/KeyRule.hpp>
40 #include <com/sun/star/sdbcx/KeyType.hpp>
41 #include "TConnection.hxx"
42 #include <connectivity/sdbcx/VColumn.hxx>
43 #include <com/sun/star/frame/XModel.hpp>
44 #include <com/sun/star/container/XChild.hpp>
46 #include <tools/diagnose_ex.h>
47 #include <unotools/sharedunocomponent.hxx>
48 #include <algorithm>
50 namespace dbtools
53 using namespace ::com::sun::star::uno;
54 using namespace ::com::sun::star::beans;
55 using namespace ::com::sun::star::sdbc;
56 using namespace ::com::sun::star::sdbcx;
57 using namespace ::com::sun::star::lang;
58 using namespace ::com::sun::star::container;
59 using namespace ::com::sun::star::frame;
60 using namespace connectivity;
61 using namespace comphelper;
63 OUString createStandardTypePart(const Reference< XPropertySet >& xColProp,const Reference< XConnection>& _xConnection,const OUString& _sCreatePattern)
66 Reference<XDatabaseMetaData> xMetaData = _xConnection->getMetaData();
68 ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap();
70 OUString sTypeName;
71 sal_Int32 nDataType = 0;
72 sal_Int32 nPrecision = 0;
73 sal_Int32 nScale = 0;
75 nDataType = nPrecision = nScale = 0;
77 xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_TYPENAME)) >>= sTypeName;
78 xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_TYPE)) >>= nDataType;
79 xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_PRECISION)) >>= nPrecision;
80 xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_SCALE)) >>= nScale;
82 OUStringBuffer aSql;
84 // check if the user enter a specific string to create autoincrement values
85 OUString sAutoIncrementValue;
86 Reference<XPropertySetInfo> xPropInfo = xColProp->getPropertySetInfo();
87 if ( xPropInfo.is() && xPropInfo->hasPropertyByName(rPropMap.getNameByIndex(PROPERTY_ID_AUTOINCREMENTCREATION)) )
88 xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_AUTOINCREMENTCREATION)) >>= sAutoIncrementValue;
89 // look if we have to use precisions
90 bool bUseLiteral = false;
91 OUString sPrefix,sPostfix,sCreateParams;
93 Reference<XResultSet> xRes = xMetaData->getTypeInfo();
94 if(xRes.is())
96 Reference<XRow> xRow(xRes,UNO_QUERY);
97 while(xRes->next())
99 OUString sTypeName2Cmp = xRow->getString(1);
100 sal_Int32 nType = xRow->getShort(2);
101 sPrefix = xRow->getString (4);
102 sPostfix = xRow->getString (5);
103 sCreateParams = xRow->getString(6);
104 // first identical type will be used if typename is empty
105 if ( sTypeName.isEmpty() && nType == nDataType )
106 sTypeName = sTypeName2Cmp;
108 if( sTypeName.equalsIgnoreAsciiCase(sTypeName2Cmp) && nType == nDataType && !sCreateParams.isEmpty() && !xRow->wasNull())
110 bUseLiteral = true;
111 break;
117 sal_Int32 nIndex = 0;
118 if ( !sAutoIncrementValue.isEmpty() && (nIndex = sTypeName.indexOf(sAutoIncrementValue)) != -1 )
120 sTypeName = sTypeName.replaceAt(nIndex,sTypeName.getLength() - nIndex,OUString());
123 if ( (nPrecision > 0 || nScale > 0) && bUseLiteral )
125 sal_Int32 nParenPos = sTypeName.indexOf('(');
126 if ( nParenPos == -1 )
128 aSql.append(sTypeName);
129 aSql.appendAscii("(");
131 else
133 aSql.append(sTypeName.copy(0,++nParenPos));
136 if ( nPrecision > 0 && nDataType != DataType::TIMESTAMP )
138 aSql.append(nPrecision);
139 if ( (nScale > 0) || (!_sCreatePattern.isEmpty() && sCreateParams.indexOf(_sCreatePattern) != -1) )
140 aSql.appendAscii(",");
142 if ( (nScale > 0) || ( !_sCreatePattern.isEmpty() && sCreateParams.indexOf(_sCreatePattern) != -1 ) || nDataType == DataType::TIMESTAMP )
143 aSql.append(nScale);
145 if ( nParenPos == -1 )
146 aSql.appendAscii(")");
147 else
149 nParenPos = sTypeName.indexOf(')',nParenPos);
150 aSql.append(sTypeName.copy(nParenPos));
153 else
154 aSql.append(sTypeName); // simply add the type name
156 OUString aDefault = ::comphelper::getString(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_DEFAULTVALUE)));
157 if ( !aDefault.isEmpty() )
159 aSql.append(" DEFAULT ");
160 aSql.append(sPrefix);
161 aSql.append(aDefault);
162 aSql.append(sPostfix);
163 } // if ( aDefault.getLength() )
165 return aSql.makeStringAndClear();
168 OUString createStandardColumnPart(const Reference< XPropertySet >& xColProp,const Reference< XConnection>& _xConnection,ISQLStatementHelper* _pHelper,const OUString& _sCreatePattern)
170 Reference<XDatabaseMetaData> xMetaData = _xConnection->getMetaData();
172 ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap();
174 bool bIsAutoIncrement = false;
175 xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_ISAUTOINCREMENT)) >>= bIsAutoIncrement;
177 const OUString sQuoteString = xMetaData->getIdentifierQuoteString();
178 OUStringBuffer aSql = ::dbtools::quoteName(sQuoteString,::comphelper::getString(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME))));
180 // check if the user enter a specific string to create autoincrement values
181 OUString sAutoIncrementValue;
182 Reference<XPropertySetInfo> xPropInfo = xColProp->getPropertySetInfo();
183 if ( xPropInfo.is() && xPropInfo->hasPropertyByName(rPropMap.getNameByIndex(PROPERTY_ID_AUTOINCREMENTCREATION)) )
184 xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_AUTOINCREMENTCREATION)) >>= sAutoIncrementValue;
186 aSql.appendAscii(" ");
188 aSql.append(createStandardTypePart(xColProp, _xConnection, _sCreatePattern));
190 if(::comphelper::getINT32(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_ISNULLABLE))) == ColumnValue::NO_NULLS)
191 aSql.append(" NOT NULL");
193 if ( bIsAutoIncrement && !sAutoIncrementValue.isEmpty())
195 aSql.appendAscii(" ");
196 aSql.append(sAutoIncrementValue);
199 if ( _pHelper )
200 _pHelper->addComment(xColProp,aSql);
202 return aSql.makeStringAndClear();
207 OUString createStandardCreateStatement(const Reference< XPropertySet >& descriptor,const Reference< XConnection>& _xConnection,ISQLStatementHelper* _pHelper,const OUString& _sCreatePattern)
209 OUStringBuffer aSql("CREATE TABLE ");
210 OUString sCatalog,sSchema,sTable,sComposedName;
212 Reference<XDatabaseMetaData> xMetaData = _xConnection->getMetaData();
213 ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap();
215 descriptor->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME)) >>= sCatalog;
216 descriptor->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_SCHEMANAME)) >>= sSchema;
217 descriptor->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME)) >>= sTable;
219 sComposedName = ::dbtools::composeTableName( xMetaData, sCatalog, sSchema, sTable, true, ::dbtools::eInTableDefinitions );
220 if ( sComposedName.isEmpty() )
221 ::dbtools::throwFunctionSequenceException(_xConnection);
223 aSql.append(sComposedName);
224 aSql.append(" (");
226 // columns
227 Reference<XColumnsSupplier> xColumnSup(descriptor,UNO_QUERY);
228 Reference<XIndexAccess> xColumns(xColumnSup->getColumns(),UNO_QUERY);
229 // check if there are columns
230 if(!xColumns.is() || !xColumns->getCount())
231 ::dbtools::throwFunctionSequenceException(_xConnection);
233 Reference< XPropertySet > xColProp;
235 sal_Int32 nCount = xColumns->getCount();
236 for(sal_Int32 i=0;i<nCount;++i)
238 if ( (xColumns->getByIndex(i) >>= xColProp) && xColProp.is() )
240 aSql.append(createStandardColumnPart(xColProp,_xConnection,_pHelper,_sCreatePattern));
241 aSql.appendAscii(",");
244 return aSql.makeStringAndClear();
246 namespace
248 OUString generateColumnNames(const Reference<XIndexAccess>& _xColumns,const Reference<XDatabaseMetaData>& _xMetaData)
250 ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap();
252 const OUString sQuote(_xMetaData->getIdentifierQuoteString());
253 OUString sSql( " (" );
254 Reference< XPropertySet > xColProp;
256 sal_Int32 nColCount = _xColumns->getCount();
257 for(sal_Int32 i=0;i<nColCount;++i)
259 if ( (_xColumns->getByIndex(i) >>= xColProp) && xColProp.is() )
260 sSql += ::dbtools::quoteName(sQuote,::comphelper::getString(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME))))
261 + ",";
264 if ( nColCount )
265 sSql = sSql.replaceAt(sSql.getLength()-1, 1, ")");
266 return sSql;
270 OUString createStandardKeyStatement(const Reference< XPropertySet >& descriptor,const Reference< XConnection>& _xConnection)
272 Reference<XDatabaseMetaData> xMetaData = _xConnection->getMetaData();
273 ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap();
275 OUStringBuffer aSql;
276 // keys
277 Reference<XKeysSupplier> xKeySup(descriptor,UNO_QUERY);
278 Reference<XIndexAccess> xKeys = xKeySup->getKeys();
279 if ( xKeys.is() )
281 Reference< XPropertySet > xColProp;
282 Reference<XIndexAccess> xColumns;
283 Reference<XColumnsSupplier> xColumnSup;
284 OUString sCatalog,sSchema,sTable,sComposedName;
285 bool bPKey = false;
286 for(sal_Int32 i=0;i<xKeys->getCount();++i)
288 if ( (xKeys->getByIndex(i) >>= xColProp) && xColProp.is() )
291 sal_Int32 nKeyType = ::comphelper::getINT32(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_TYPE)));
293 if ( nKeyType == KeyType::PRIMARY )
295 if(bPKey)
296 ::dbtools::throwFunctionSequenceException(_xConnection);
298 bPKey = true;
299 xColumnSup = Reference<XColumnsSupplier>(xColProp,UNO_QUERY);
300 xColumns = Reference<XIndexAccess>(xColumnSup->getColumns(),UNO_QUERY);
301 if(!xColumns.is() || !xColumns->getCount())
302 ::dbtools::throwFunctionSequenceException(_xConnection);
304 aSql.append(" PRIMARY KEY ");
305 aSql.append(generateColumnNames(xColumns,xMetaData));
307 else if(nKeyType == KeyType::UNIQUE)
309 xColumnSup = Reference<XColumnsSupplier>(xColProp,UNO_QUERY);
310 xColumns = Reference<XIndexAccess>(xColumnSup->getColumns(),UNO_QUERY);
311 if(!xColumns.is() || !xColumns->getCount())
312 ::dbtools::throwFunctionSequenceException(_xConnection);
314 aSql.append(" UNIQUE ");
315 aSql.append(generateColumnNames(xColumns,xMetaData));
317 else if(nKeyType == KeyType::FOREIGN)
319 sal_Int32 nDeleteRule = getINT32(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_DELETERULE)));
321 xColumnSup = Reference<XColumnsSupplier>(xColProp,UNO_QUERY);
322 xColumns = Reference<XIndexAccess>(xColumnSup->getColumns(),UNO_QUERY);
323 if(!xColumns.is() || !xColumns->getCount())
324 ::dbtools::throwFunctionSequenceException(_xConnection);
326 aSql.append(" FOREIGN KEY ");
327 OUString sRefTable = getString(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_REFERENCEDTABLE)));
328 ::dbtools::qualifiedNameComponents(xMetaData,
329 sRefTable,
330 sCatalog,
331 sSchema,
332 sTable,
333 ::dbtools::eInDataManipulation);
334 sComposedName = ::dbtools::composeTableName( xMetaData, sCatalog, sSchema, sTable, true, ::dbtools::eInTableDefinitions );
337 if ( sComposedName.isEmpty() )
338 ::dbtools::throwFunctionSequenceException(_xConnection);
340 aSql.append(generateColumnNames(xColumns,xMetaData));
342 switch(nDeleteRule)
344 case KeyRule::CASCADE:
345 aSql.append(" ON DELETE CASCADE ");
346 break;
347 case KeyRule::RESTRICT:
348 aSql.append(" ON DELETE RESTRICT ");
349 break;
350 case KeyRule::SET_NULL:
351 aSql.append(" ON DELETE SET NULL ");
352 break;
353 case KeyRule::SET_DEFAULT:
354 aSql.append(" ON DELETE SET DEFAULT ");
355 break;
356 default:
364 if ( !aSql.isEmpty() )
366 if ( aSql[aSql.getLength() - 1] == ',' )
367 aSql[aSql.getLength() - 1] = ')';
368 else
369 aSql.appendAscii(")");
372 return aSql.makeStringAndClear();
376 OUString createSqlCreateTableStatement( const Reference< XPropertySet >& descriptor,
377 const Reference< XConnection>& _xConnection,
378 ISQLStatementHelper* _pHelper,
379 const OUString& _sCreatePattern)
381 OUString aSql = ::dbtools::createStandardCreateStatement(descriptor,_xConnection,_pHelper,_sCreatePattern);
382 const OUString sKeyStmt = ::dbtools::createStandardKeyStatement(descriptor,_xConnection);
383 if ( !sKeyStmt.isEmpty() )
384 aSql += sKeyStmt;
385 else
387 if ( aSql.endsWith(",") )
388 aSql = aSql.replaceAt(aSql.getLength()-1, 1, ")");
389 else
390 aSql += ")";
392 return aSql;
394 namespace
396 Reference<XPropertySet> lcl_createSDBCXColumn(const Reference<XNameAccess>& _xPrimaryKeyColumns,
397 const Reference<XConnection>& _xConnection,
398 const Any& _aCatalog,
399 const OUString& _aSchema,
400 const OUString& _aTable,
401 const OUString& _rQueryName,
402 const OUString& _rName,
403 bool _bCase,
404 bool _bQueryForInfo,
405 bool _bIsAutoIncrement,
406 bool _bIsCurrency,
407 sal_Int32 _nDataType)
409 Reference<XPropertySet> xProp;
410 Reference<XDatabaseMetaData> xMetaData = _xConnection->getMetaData();
411 Reference< XResultSet > xResult = xMetaData->getColumns(_aCatalog, _aSchema, _aTable, _rQueryName);
412 OUString sCatalog;
413 _aCatalog >>= sCatalog;
415 if ( xResult.is() )
417 UStringMixEqual aMixCompare(_bCase);
418 Reference< XRow > xRow(xResult,UNO_QUERY);
419 while( xResult->next() )
421 if ( aMixCompare(xRow->getString(4),_rName) )
423 sal_Int32 nField5 = xRow->getInt(5);
424 OUString aField6 = xRow->getString(6);
425 sal_Int32 nField7 = xRow->getInt(7)
426 , nField9 = xRow->getInt(9)
427 , nField11= xRow->getInt(11);
428 OUString sField12 = xRow->getString(12),
429 sField13 = xRow->getString(13);
430 ::comphelper::disposeComponent(xRow);
432 bool bAutoIncrement = _bIsAutoIncrement
433 ,bIsCurrency = _bIsCurrency;
434 if ( _bQueryForInfo )
436 const OUString sQuote = xMetaData->getIdentifierQuoteString();
437 OUString sQuotedName = ::dbtools::quoteName(sQuote,_rName);
438 OUString sComposedName;
439 sComposedName = composeTableNameForSelect(_xConnection, getString( _aCatalog ), _aSchema, _aTable );
441 ColumnInformationMap aInfo(_bCase);
442 collectColumnInformation(_xConnection,sComposedName,sQuotedName,aInfo);
443 ColumnInformationMap::iterator aIter = aInfo.begin();
444 if ( aIter != aInfo.end() )
446 bAutoIncrement = aIter->second.first.first;
447 bIsCurrency = aIter->second.first.second;
448 if ( DataType::OTHER == nField5 )
449 nField5 = aIter->second.second;
452 else if ( DataType::OTHER == nField5 )
453 nField5 = _nDataType;
455 if ( nField11 != ColumnValue::NO_NULLS )
459 if ( _xPrimaryKeyColumns.is() )
461 if ( _xPrimaryKeyColumns->hasByName(_rName) )
462 nField11 = ColumnValue::NO_NULLS;
465 else
467 Reference< XResultSet > xPKeys = xMetaData->getPrimaryKeys( _aCatalog, _aSchema, _aTable );
468 Reference< XRow > xPKeyRow( xPKeys, UNO_QUERY_THROW );
469 while( xPKeys->next() ) // there can be only one primary key
471 OUString sKeyColumn = xPKeyRow->getString(4);
472 if ( aMixCompare(_rName,sKeyColumn) )
474 nField11 = ColumnValue::NO_NULLS;
475 break;
480 catch(SQLException&)
482 OSL_FAIL( "lcl_createSDBCXColumn: caught an exception!" );
486 connectivity::sdbcx::OColumn* pRet = new connectivity::sdbcx::OColumn(_rName,
487 aField6,
488 sField13,
489 sField12,
490 nField11,
491 nField7,
492 nField9,
493 nField5,
494 bAutoIncrement,
495 false,
496 bIsCurrency,
497 _bCase,
498 sCatalog,
499 _aSchema,
500 _aTable);
502 xProp = pRet;
503 break;
508 return xProp;
511 Reference< XModel> lcl_getXModel(const Reference< XInterface>& _xIface)
513 Reference< XInterface > xParent = _xIface;
514 Reference< XModel > xModel(xParent,UNO_QUERY);;
515 while( xParent.is() && !xModel.is() )
517 Reference<XChild> xChild(xParent,UNO_QUERY);
518 xParent.set(xChild.is() ? xChild->getParent() : Reference< XInterface >(),UNO_QUERY);
519 xModel.set(xParent,UNO_QUERY);
521 return xModel;
525 Reference<XPropertySet> createSDBCXColumn(const Reference<XPropertySet>& _xTable,
526 const Reference<XConnection>& _xConnection,
527 const OUString& _rName,
528 bool _bCase,
529 bool _bQueryForInfo,
530 bool _bIsAutoIncrement,
531 bool _bIsCurrency,
532 sal_Int32 _nDataType)
534 Reference<XPropertySet> xProp;
535 OSL_ENSURE(_xTable.is(),"Table is NULL!");
536 if ( !_xTable.is() )
537 return xProp;
539 ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap();
540 Reference<XDatabaseMetaData> xMetaData = _xConnection->getMetaData();
541 Any aCatalog;
542 aCatalog = _xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME));
543 OUString sCatalog;
544 aCatalog >>= sCatalog;
546 OUString aSchema, aTable;
547 _xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_SCHEMANAME)) >>= aSchema;
548 _xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME)) >>= aTable;
550 Reference<XNameAccess> xPrimaryKeyColumns = getPrimaryKeyColumns_throw(_xTable);
552 xProp = lcl_createSDBCXColumn(xPrimaryKeyColumns,_xConnection,aCatalog, aSchema, aTable, _rName,_rName,_bCase,_bQueryForInfo,_bIsAutoIncrement,_bIsCurrency,_nDataType);
553 if ( !xProp.is() )
555 xProp = lcl_createSDBCXColumn(xPrimaryKeyColumns,_xConnection,aCatalog, aSchema, aTable, OUString("%"),_rName,_bCase,_bQueryForInfo,_bIsAutoIncrement,_bIsCurrency,_nDataType);
556 if ( !xProp.is() )
557 xProp = new connectivity::sdbcx::OColumn(_rName,
558 OUString(),OUString(),OUString(),
559 ColumnValue::NULLABLE_UNKNOWN,
562 DataType::VARCHAR,
563 _bIsAutoIncrement,
564 false,
565 _bIsCurrency,
566 _bCase,
567 sCatalog,
568 aSchema,
569 aTable);
573 return xProp;
577 bool getBooleanDataSourceSetting( const Reference< XConnection >& _rxConnection, const sal_Char* _pAsciiSettingName )
579 bool bValue( false );
582 Reference< XPropertySet> xDataSourceProperties( findDataSource( _rxConnection ), UNO_QUERY );
583 OSL_ENSURE( xDataSourceProperties.is(), "::dbtools::getBooleanDataSourceSetting: somebody is using this with a non-SDB-level connection!" );
584 if ( xDataSourceProperties.is() )
586 Reference< XPropertySet > xSettings(
587 xDataSourceProperties->getPropertyValue("Settings"),
588 UNO_QUERY_THROW
590 OSL_VERIFY( xSettings->getPropertyValue( OUString::createFromAscii( _pAsciiSettingName ) ) >>= bValue );
593 catch( const Exception& )
595 DBG_UNHANDLED_EXCEPTION();
597 return bValue;
600 bool getDataSourceSetting( const Reference< XInterface >& _xChild, const OUString& _sAsciiSettingsName,
601 Any& /* [out] */ _rSettingsValue )
603 bool bIsPresent = false;
606 const Reference< XPropertySet> xDataSourceProperties( findDataSource( _xChild ), UNO_QUERY );
607 if ( !xDataSourceProperties.is() )
608 return false;
610 const Reference< XPropertySet > xSettings(
611 xDataSourceProperties->getPropertyValue("Settings"),
612 UNO_QUERY_THROW
615 _rSettingsValue = xSettings->getPropertyValue( _sAsciiSettingsName );
616 bIsPresent = true;
618 catch( const Exception& )
620 bIsPresent = false;
622 return bIsPresent;
625 bool getDataSourceSetting( const Reference< XInterface >& _rxDataSource, const sal_Char* _pAsciiSettingsName,
626 Any& /* [out] */ _rSettingsValue )
628 OUString sAsciiSettingsName = OUString::createFromAscii(_pAsciiSettingsName);
629 return getDataSourceSetting( _rxDataSource, sAsciiSettingsName,_rSettingsValue );
632 bool isDataSourcePropertyEnabled(const Reference<XInterface>& _xProp, const OUString& _sProperty, bool _bDefault)
634 bool bEnabled = _bDefault;
637 Reference< XPropertySet> xProp(findDataSource(_xProp),UNO_QUERY);
638 if ( xProp.is() )
640 Sequence< PropertyValue > aInfo;
641 xProp->getPropertyValue("Info") >>= aInfo;
642 const PropertyValue* pValue =::std::find_if(aInfo.getConstArray(),
643 aInfo.getConstArray() + aInfo.getLength(),
644 ::std::bind2nd(TPropertyValueEqualFunctor(),_sProperty));
645 if ( pValue && pValue != (aInfo.getConstArray() + aInfo.getLength()) )
646 pValue->Value >>= bEnabled;
649 catch(SQLException&)
651 DBG_UNHANDLED_EXCEPTION();
653 return bEnabled;
656 Reference< XTablesSupplier> getDataDefinitionByURLAndConnection(
657 const OUString& _rsUrl,
658 const Reference< XConnection>& _xConnection,
659 const Reference< XComponentContext >& _rxContext)
661 Reference< XTablesSupplier> xTablesSup;
664 Reference< XDriverManager2 > xManager = DriverManager::create( _rxContext );
665 Reference< XDataDefinitionSupplier > xSupp( xManager->getDriverByURL( _rsUrl ), UNO_QUERY );
667 if ( xSupp.is() )
669 xTablesSup = xSupp->getDataDefinitionByConnection( _xConnection );
670 OSL_ENSURE(xTablesSup.is(),"No table supplier!");
673 catch( const Exception& )
675 DBG_UNHANDLED_EXCEPTION();
677 return xTablesSup;
681 sal_Int32 getTablePrivileges(const Reference< XDatabaseMetaData>& _xMetaData,
682 const OUString& _sCatalog,
683 const OUString& _sSchema,
684 const OUString& _sTable)
686 OSL_ENSURE(_xMetaData.is(),"Invalid metadata!");
687 sal_Int32 nPrivileges = 0;
690 Any aVal;
691 if(!_sCatalog.isEmpty())
692 aVal <<= _sCatalog;
693 Reference< XResultSet > xPrivileges = _xMetaData->getTablePrivileges(aVal, _sSchema, _sTable);
694 Reference< XRow > xCurrentRow(xPrivileges, UNO_QUERY);
696 const OUString sUserWorkingFor = _xMetaData->getUserName();
697 static const char sSELECT[] = "SELECT";
698 static const char sINSERT[] = "INSERT";
699 static const char sUPDATE[] = "UPDATE";
700 static const char sDELETE[] = "DELETE";
701 static const char sREAD[] = "READ";
702 static const char sCREATE[] = "CREATE";
703 static const char sALTER[] = "ALTER";
704 static const char sREFERENCE[] = "REFERENCE";
705 static const char sDROP[] = "DROP";
707 if ( xCurrentRow.is() )
709 // after creation the set is positioned before the first record, per definition
710 OUString sPrivilege, sGrantee;
711 while ( xPrivileges->next() )
713 #ifdef DBG_UTIL
714 OUString sCat, sSchema, sName, sGrantor, sGrantable;
715 sCat = xCurrentRow->getString(1);
716 sSchema = xCurrentRow->getString(2);
717 sName = xCurrentRow->getString(3);
718 sGrantor = xCurrentRow->getString(4);
719 #endif
720 sGrantee = xCurrentRow->getString(5);
721 sPrivilege = xCurrentRow->getString(6);
722 #ifdef DBG_UTIL
723 sGrantable = xCurrentRow->getString(7);
724 #endif
726 if (!sUserWorkingFor.equalsIgnoreAsciiCase(sGrantee))
727 continue;
729 if (sPrivilege.equalsIgnoreAsciiCase(sSELECT))
730 nPrivileges |= Privilege::SELECT;
731 else if (sPrivilege.equalsIgnoreAsciiCase(sINSERT))
732 nPrivileges |= Privilege::INSERT;
733 else if (sPrivilege.equalsIgnoreAsciiCase(sUPDATE))
734 nPrivileges |= Privilege::UPDATE;
735 else if (sPrivilege.equalsIgnoreAsciiCase(sDELETE))
736 nPrivileges |= Privilege::DELETE;
737 else if (sPrivilege.equalsIgnoreAsciiCase(sREAD))
738 nPrivileges |= Privilege::READ;
739 else if (sPrivilege.equalsIgnoreAsciiCase(sCREATE))
740 nPrivileges |= Privilege::CREATE;
741 else if (sPrivilege.equalsIgnoreAsciiCase(sALTER))
742 nPrivileges |= Privilege::ALTER;
743 else if (sPrivilege.equalsIgnoreAsciiCase(sREFERENCE))
744 nPrivileges |= Privilege::REFERENCE;
745 else if (sPrivilege.equalsIgnoreAsciiCase(sDROP))
746 nPrivileges |= Privilege::DROP;
749 disposeComponent(xPrivileges);
751 // Some drivers put a table privilege as soon as any column has the privilege,
752 // some drivers only if all columns have the privilege.
753 // To unifiy the situation, collect column privileges here, too.
754 Reference< XResultSet > xColumnPrivileges = _xMetaData->getColumnPrivileges(aVal, _sSchema, _sTable, OUString("%"));
755 Reference< XRow > xColumnCurrentRow(xColumnPrivileges, UNO_QUERY);
756 if ( xColumnCurrentRow.is() )
758 // after creation the set is positioned before the first record, per definition
759 OUString sPrivilege, sGrantee;
760 while ( xColumnPrivileges->next() )
762 #ifdef DBG_UTIL
763 OUString sCat, sSchema, sTableName, sColumnName, sGrantor, sGrantable;
764 sCat = xColumnCurrentRow->getString(1);
765 sSchema = xColumnCurrentRow->getString(2);
766 sTableName = xColumnCurrentRow->getString(3);
767 sColumnName = xColumnCurrentRow->getString(4);
768 sGrantor = xColumnCurrentRow->getString(5);
769 #endif
770 sGrantee = xColumnCurrentRow->getString(6);
771 sPrivilege = xColumnCurrentRow->getString(7);
772 #ifdef DBG_UTIL
773 sGrantable = xColumnCurrentRow->getString(8);
774 #endif
776 if (!sUserWorkingFor.equalsIgnoreAsciiCase(sGrantee))
777 continue;
779 if (sPrivilege.equalsIgnoreAsciiCase(sSELECT))
780 nPrivileges |= Privilege::SELECT;
781 else if (sPrivilege.equalsIgnoreAsciiCase(sINSERT))
782 nPrivileges |= Privilege::INSERT;
783 else if (sPrivilege.equalsIgnoreAsciiCase(sUPDATE))
784 nPrivileges |= Privilege::UPDATE;
785 else if (sPrivilege.equalsIgnoreAsciiCase(sDELETE))
786 nPrivileges |= Privilege::DELETE;
787 else if (sPrivilege.equalsIgnoreAsciiCase(sREAD))
788 nPrivileges |= Privilege::READ;
789 else if (sPrivilege.equalsIgnoreAsciiCase(sCREATE))
790 nPrivileges |= Privilege::CREATE;
791 else if (sPrivilege.equalsIgnoreAsciiCase(sALTER))
792 nPrivileges |= Privilege::ALTER;
793 else if (sPrivilege.equalsIgnoreAsciiCase(sREFERENCE))
794 nPrivileges |= Privilege::REFERENCE;
795 else if (sPrivilege.equalsIgnoreAsciiCase(sDROP))
796 nPrivileges |= Privilege::DROP;
799 disposeComponent(xColumnPrivileges);
801 catch(const SQLException& e)
803 // some drivers don't support any privileges so we assume that we are allowed to do all we want :-)
804 if(e.SQLState == "IM001")
805 nPrivileges |= Privilege::DROP |
806 Privilege::REFERENCE |
807 Privilege::ALTER |
808 Privilege::CREATE |
809 Privilege::READ |
810 Privilege::DELETE |
811 Privilege::UPDATE |
812 Privilege::INSERT |
813 Privilege::SELECT;
814 else
815 OSL_FAIL("Could not collect the privileges !");
817 return nPrivileges;
820 // we need some more information about the column
821 void collectColumnInformation(const Reference< XConnection>& _xConnection,
822 const OUString& _sComposedName,
823 const OUString& _rName,
824 ColumnInformationMap& _rInfo)
826 OUString sSelect = "SELECT " + _rName +
827 " FROM " + _sComposedName +
828 " WHERE 0 = 1";
832 ::utl::SharedUNOComponent< XStatement > xStmt( _xConnection->createStatement() );
833 Reference< XPropertySet > xStatementProps( xStmt, UNO_QUERY_THROW );
834 xStatementProps->setPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_ESCAPEPROCESSING ), makeAny( false ) );
835 Reference< XResultSet > xResult( xStmt->executeQuery( sSelect ), UNO_QUERY_THROW );
836 Reference< XResultSetMetaDataSupplier > xSuppMeta( xResult, UNO_QUERY_THROW );
837 Reference< XResultSetMetaData > xMeta( xSuppMeta->getMetaData(), UNO_QUERY_THROW );
839 sal_Int32 nCount = xMeta->getColumnCount();
840 OSL_ENSURE( nCount != 0, "::dbtools::collectColumnInformation: result set has empty (column-less) meta data!" );
841 for (sal_Int32 i=1; i <= nCount ; ++i)
843 _rInfo.insert(ColumnInformationMap::value_type(xMeta->getColumnName(i),
844 ColumnInformation(TBoolPair(xMeta->isAutoIncrement(i),xMeta->isCurrency(i)),xMeta->getColumnType(i))));
847 catch( const Exception& )
849 DBG_UNHANDLED_EXCEPTION();
854 bool isEmbeddedInDatabase( const Reference< XInterface >& _rxComponent, Reference< XConnection >& _rxActualConnection )
856 bool bIsEmbedded = false;
859 Reference< XModel > xModel = lcl_getXModel( _rxComponent );
861 if ( xModel.is() )
863 Sequence< PropertyValue > aArgs = xModel->getArgs();
864 const PropertyValue* pIter = aArgs.getConstArray();
865 const PropertyValue* pEnd = pIter + aArgs.getLength();
866 for(;pIter != pEnd;++pIter)
868 if ( pIter->Name == "ComponentData" )
870 Sequence<PropertyValue> aDocumentContext;
871 pIter->Value >>= aDocumentContext;
872 const PropertyValue* pContextIter = aDocumentContext.getConstArray();
873 const PropertyValue* pContextEnd = pContextIter + aDocumentContext.getLength();
874 for(;pContextIter != pContextEnd;++pContextIter)
876 if ( pContextIter->Name == "ActiveConnection"
877 && ( pContextIter->Value >>= _rxActualConnection )
880 bIsEmbedded = true;
881 break;
884 break;
889 catch(Exception&)
891 // not interested in
893 return bIsEmbedded;
896 namespace
898 OUString lcl_getEncodingName( rtl_TextEncoding _eEncoding )
900 OUString sEncodingName;
902 OCharsetMap aCharsets;
903 OCharsetMap::CharsetIterator aEncodingPos = aCharsets.find( _eEncoding );
904 OSL_ENSURE( aEncodingPos != aCharsets.end(), "lcl_getEncodingName: *which* encoding?" );
905 if ( aEncodingPos != aCharsets.end() )
906 sEncodingName = (*aEncodingPos).getIanaName();
908 return sEncodingName;
913 sal_Int32 DBTypeConversion::convertUnicodeString( const OUString& _rSource, OString& _rDest, rtl_TextEncoding _eEncoding )
915 if ( !rtl_convertUStringToString( &_rDest.pData, _rSource.getStr(), _rSource.getLength(),
916 _eEncoding,
917 RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
918 RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACE |
919 RTL_UNICODETOTEXT_FLAGS_PRIVATE_MAPTO0 )
922 SharedResources aResources;
923 OUString sMessage = aResources.getResourceStringWithSubstitution( STR_CANNOT_CONVERT_STRING,
924 "$string$", _rSource,
925 "$charset$", lcl_getEncodingName( _eEncoding )
928 throw SQLException(
929 sMessage,
930 NULL,
931 OUString( "22018" ),
932 22018,
933 Any()
937 return _rDest.getLength();
941 sal_Int32 DBTypeConversion::convertUnicodeStringToLength( const OUString& _rSource, OString& _rDest,
942 sal_Int32 _nMaxLen, rtl_TextEncoding _eEncoding )
944 sal_Int32 nLen = convertUnicodeString( _rSource, _rDest, _eEncoding );
945 if ( nLen > _nMaxLen )
947 SharedResources aResources;
948 OUString sMessage = aResources.getResourceStringWithSubstitution( STR_STRING_LENGTH_EXCEEDED,
949 "$string$", _rSource,
950 "$maxlen$", OUString::number( _nMaxLen ),
951 "$charset$", lcl_getEncodingName( _eEncoding )
954 throw SQLException(
955 sMessage,
956 NULL,
957 OUString( "22001" ),
958 22001,
959 Any()
963 return nLen;
965 OUString lcl_getReportEngines()
967 return OUString("org.openoffice.Office.DataAccess/ReportEngines");
970 OUString lcl_getDefaultReportEngine()
972 return OUString("DefaultReportEngine");
975 OUString lcl_getReportEngineNames()
977 return OUString("ReportEngineNames");
980 OUString getDefaultReportEngineServiceName(const Reference< XComponentContext >& _rxORB)
982 ::utl::OConfigurationTreeRoot aReportEngines = ::utl::OConfigurationTreeRoot::createWithComponentContext(
983 _rxORB, lcl_getReportEngines(), -1, ::utl::OConfigurationTreeRoot::CM_READONLY);
985 if ( aReportEngines.isValid() )
987 OUString sDefaultReportEngineName;
988 aReportEngines.getNodeValue(lcl_getDefaultReportEngine()) >>= sDefaultReportEngineName;
989 if ( !sDefaultReportEngineName.isEmpty() )
991 ::utl::OConfigurationNode aReportEngineNames = aReportEngines.openNode(lcl_getReportEngineNames());
992 if ( aReportEngineNames.isValid() )
994 ::utl::OConfigurationNode aReportEngine = aReportEngineNames.openNode(sDefaultReportEngineName);
995 if ( aReportEngine.isValid() )
997 OUString sRet;
998 aReportEngine.getNodeValue("ServiceName") >>= sRet;
999 return sRet;
1003 else
1004 return OUString("org.libreoffice.report.pentaho.SOReportJobFactory");
1006 else
1007 return OUString("org.libreoffice.report.pentaho.SOReportJobFactory");
1008 return OUString();
1012 } // namespace dbtools
1015 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */