1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_connectivity.hxx" 30 #include "connectivity/dbtools.hxx" 31 #include "connectivity/dbconversion.hxx" 32 #include "connectivity/dbcharset.hxx" 33 #include "connectivity/SQLStatementHelper.hxx" 34 #include <unotools/confignode.hxx> 35 #include "resource/sharedresources.hxx" 36 #include "resource/common_res.hrc" 37 #include <com/sun/star/sdbc/XConnection.hpp> 38 #include <com/sun/star/sdbc/ColumnValue.hpp> 39 #include <com/sun/star/sdbc/DataType.hpp> 40 #include <com/sun/star/sdbc/XRow.hpp> 41 #include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> 42 #include <com/sun/star/sdbcx/XKeysSupplier.hpp> 43 #include <com/sun/star/sdbc/XDriverAccess.hpp> 44 #include <com/sun/star/sdbcx/XDataDefinitionSupplier.hpp> 45 #include <com/sun/star/sdbcx/Privilege.hpp> 46 #include <com/sun/star/container/XIndexAccess.hpp> 47 #include <com/sun/star/container/XEnumerationAccess.hpp> 48 #include <com/sun/star/sdbc/KeyRule.hpp> 49 #include <com/sun/star/sdbcx/KeyType.hpp> 50 #include "TConnection.hxx" 51 #include "connectivity/sdbcx/VColumn.hxx" 52 #include <com/sun/star/frame/XModel.hpp> 53 #include <com/sun/star/container/XChild.hpp> 54 55 #include <tools/diagnose_ex.h> 56 #include <unotools/sharedunocomponent.hxx> 57 #include <comphelper/configurationhelper.hxx> 58 59 //......................................................................... 60 namespace dbtools 61 { 62 //......................................................................... 63 using namespace ::com::sun::star::uno; 64 using namespace ::com::sun::star::beans; 65 using namespace ::com::sun::star::sdbc; 66 using namespace ::com::sun::star::sdbcx; 67 using namespace ::com::sun::star::lang; 68 using namespace ::com::sun::star::container; 69 using namespace ::com::sun::star::frame; 70 using namespace connectivity; 71 using namespace comphelper; 72 73 ::rtl::OUString createStandardColumnPart(const Reference< XPropertySet >& xColProp,const Reference< XConnection>& _xConnection,ISQLStatementHelper* _pHelper,const ::rtl::OUString& _sCreatePattern) 74 { 75 76 Reference<XDatabaseMetaData> xMetaData = _xConnection->getMetaData(); 77 78 ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap(); 79 80 ::rtl::OUString sTypeName; 81 sal_Int32 nDataType = 0; 82 sal_Int32 nPrecision = 0; 83 sal_Int32 nScale = 0; 84 85 const ::rtl::OUString sQuoteString = xMetaData->getIdentifierQuoteString(); 86 ::rtl::OUStringBuffer aSql = ::dbtools::quoteName(sQuoteString,::comphelper::getString(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME)))); 87 88 aSql.appendAscii(" "); 89 90 nDataType = nPrecision = nScale = 0; 91 sal_Bool bIsAutoIncrement = sal_False; 92 xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_TYPENAME)) >>= sTypeName; 93 xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_TYPE)) >>= nDataType; 94 xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_PRECISION)) >>= nPrecision; 95 xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_SCALE)) >>= nScale; 96 xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_ISAUTOINCREMENT)) >>= bIsAutoIncrement; 97 98 // check if the user enter a specific string to create autoincrement values 99 ::rtl::OUString sAutoIncrementValue; 100 Reference<XPropertySetInfo> xPropInfo = xColProp->getPropertySetInfo(); 101 if ( xPropInfo.is() && xPropInfo->hasPropertyByName(rPropMap.getNameByIndex(PROPERTY_ID_AUTOINCREMENTCREATION)) ) 102 xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_AUTOINCREMENTCREATION)) >>= sAutoIncrementValue; 103 // look if we have to use precisions 104 sal_Bool bUseLiteral = sal_False; 105 ::rtl::OUString sPreFix,sPostFix,sCreateParams; 106 { 107 Reference<XResultSet> xRes = xMetaData->getTypeInfo(); 108 if(xRes.is()) 109 { 110 Reference<XRow> xRow(xRes,UNO_QUERY); 111 while(xRes->next()) 112 { 113 ::rtl::OUString sTypeName2Cmp = xRow->getString(1); 114 sal_Int32 nType = xRow->getShort(2); 115 sPreFix = xRow->getString (4); 116 sPostFix = xRow->getString (5); 117 sCreateParams = xRow->getString(6); 118 // first identical type will be used if typename is empty 119 if ( !sTypeName.getLength() && nType == nDataType ) 120 sTypeName = sTypeName2Cmp; 121 122 if( sTypeName.equalsIgnoreAsciiCase(sTypeName2Cmp) && nType == nDataType && sCreateParams.getLength() && !xRow->wasNull()) 123 { 124 bUseLiteral = sal_True; 125 break; 126 } 127 } 128 } 129 } 130 131 sal_Int32 nIndex = 0; 132 if ( sAutoIncrementValue.getLength() && (nIndex = sTypeName.indexOf(sAutoIncrementValue)) != -1 ) 133 { 134 sTypeName = sTypeName.replaceAt(nIndex,sTypeName.getLength() - nIndex,::rtl::OUString()); 135 } 136 137 if ( (nPrecision > 0 || nScale > 0) && bUseLiteral ) 138 { 139 sal_Int32 nParenPos = sTypeName.indexOf('('); 140 if ( nParenPos == -1 ) 141 { 142 aSql.append(sTypeName); 143 aSql.appendAscii("("); 144 } 145 else 146 { 147 aSql.append(sTypeName.copy(0,++nParenPos)); 148 } 149 150 if ( nPrecision > 0 && nDataType != DataType::TIMESTAMP ) 151 { 152 aSql.append(nPrecision); 153 if ( (nScale > 0) || (_sCreatePattern.getLength() && sCreateParams.indexOf(_sCreatePattern) != -1) ) 154 aSql.appendAscii(","); 155 } 156 if ( (nScale > 0) || (_sCreatePattern.getLength() && sCreateParams.indexOf(_sCreatePattern) != -1 ) || nDataType == DataType::TIMESTAMP ) 157 aSql.append(nScale); 158 159 if ( nParenPos == -1 ) 160 aSql.appendAscii(")"); 161 else 162 { 163 nParenPos = sTypeName.indexOf(')',nParenPos); 164 aSql.append(sTypeName.copy(nParenPos)); 165 } 166 } 167 else 168 aSql.append(sTypeName); // simply add the type name 169 170 ::rtl::OUString aDefault = ::comphelper::getString(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_DEFAULTVALUE))); 171 if ( aDefault.getLength() ) 172 { 173 aSql.append(::rtl::OUString::createFromAscii(" DEFAULT ")); 174 aSql.append(sPreFix); 175 aSql.append(aDefault); 176 aSql.append(sPostFix); 177 } // if ( aDefault.getLength() ) 178 179 if(::comphelper::getINT32(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_ISNULLABLE))) == ColumnValue::NO_NULLS) 180 aSql.append(::rtl::OUString::createFromAscii(" NOT NULL")); 181 182 if ( bIsAutoIncrement && sAutoIncrementValue.getLength()) 183 { 184 aSql.appendAscii(" "); 185 aSql.append(sAutoIncrementValue); 186 } 187 188 if ( _pHelper ) 189 _pHelper->addComment(xColProp,aSql); 190 191 return aSql.makeStringAndClear(); 192 } 193 // ----------------------------------------------------------------------------- 194 195 ::rtl::OUString createStandardCreateStatement(const Reference< XPropertySet >& descriptor,const Reference< XConnection>& _xConnection,ISQLStatementHelper* _pHelper,const ::rtl::OUString& _sCreatePattern) 196 { 197 ::rtl::OUStringBuffer aSql = ::rtl::OUString::createFromAscii("CREATE TABLE "); 198 ::rtl::OUString sCatalog,sSchema,sTable,sComposedName; 199 200 Reference<XDatabaseMetaData> xMetaData = _xConnection->getMetaData(); 201 ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap(); 202 203 descriptor->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME)) >>= sCatalog; 204 descriptor->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_SCHEMANAME)) >>= sSchema; 205 descriptor->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME)) >>= sTable; 206 207 sComposedName = ::dbtools::composeTableName( xMetaData, sCatalog, sSchema, sTable, sal_True, ::dbtools::eInTableDefinitions ); 208 if ( !sComposedName.getLength() ) 209 ::dbtools::throwFunctionSequenceException(_xConnection); 210 211 aSql.append(sComposedName); 212 aSql.append(::rtl::OUString::createFromAscii(" (")); 213 214 // columns 215 Reference<XColumnsSupplier> xColumnSup(descriptor,UNO_QUERY); 216 Reference<XIndexAccess> xColumns(xColumnSup->getColumns(),UNO_QUERY); 217 // check if there are columns 218 if(!xColumns.is() || !xColumns->getCount()) 219 ::dbtools::throwFunctionSequenceException(_xConnection); 220 221 Reference< XPropertySet > xColProp; 222 223 sal_Int32 nCount = xColumns->getCount(); 224 for(sal_Int32 i=0;i<nCount;++i) 225 { 226 if ( (xColumns->getByIndex(i) >>= xColProp) && xColProp.is() ) 227 { 228 aSql.append(createStandardColumnPart(xColProp,_xConnection,_pHelper,_sCreatePattern)); 229 aSql.appendAscii(","); 230 } 231 } 232 return aSql.makeStringAndClear(); 233 } 234 namespace 235 { 236 ::rtl::OUString generateColumnNames(const Reference<XIndexAccess>& _xColumns,const Reference<XDatabaseMetaData>& _xMetaData) 237 { 238 ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap(); 239 static const ::rtl::OUString sComma(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(","))); 240 241 const ::rtl::OUString sQuote(_xMetaData->getIdentifierQuoteString()); 242 ::rtl::OUString sSql = ::rtl::OUString::createFromAscii(" ("); 243 Reference< XPropertySet > xColProp; 244 245 sal_Int32 nColCount = _xColumns->getCount(); 246 for(sal_Int32 i=0;i<nColCount;++i) 247 { 248 if ( (_xColumns->getByIndex(i) >>= xColProp) && xColProp.is() ) 249 sSql += ::dbtools::quoteName(sQuote,::comphelper::getString(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME)))) 250 + sComma; 251 } 252 253 if ( nColCount ) 254 sSql = sSql.replaceAt(sSql.getLength()-1,1,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(")"))); 255 return sSql; 256 } 257 } 258 // ----------------------------------------------------------------------------- 259 ::rtl::OUString createStandardKeyStatement(const Reference< XPropertySet >& descriptor,const Reference< XConnection>& _xConnection) 260 { 261 Reference<XDatabaseMetaData> xMetaData = _xConnection->getMetaData(); 262 ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap(); 263 264 ::rtl::OUStringBuffer aSql; 265 // keys 266 Reference<XKeysSupplier> xKeySup(descriptor,UNO_QUERY); 267 Reference<XIndexAccess> xKeys = xKeySup->getKeys(); 268 if ( xKeys.is() ) 269 { 270 Reference< XPropertySet > xColProp; 271 Reference<XIndexAccess> xColumns; 272 Reference<XColumnsSupplier> xColumnSup; 273 ::rtl::OUString sCatalog,sSchema,sTable,sComposedName; 274 sal_Bool bPKey = sal_False; 275 for(sal_Int32 i=0;i<xKeys->getCount();++i) 276 { 277 if ( (xKeys->getByIndex(i) >>= xColProp) && xColProp.is() ) 278 { 279 280 sal_Int32 nKeyType = ::comphelper::getINT32(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_TYPE))); 281 282 if ( nKeyType == KeyType::PRIMARY ) 283 { 284 if(bPKey) 285 ::dbtools::throwFunctionSequenceException(_xConnection); 286 287 bPKey = sal_True; 288 xColumnSup = Reference<XColumnsSupplier>(xColProp,UNO_QUERY); 289 xColumns = Reference<XIndexAccess>(xColumnSup->getColumns(),UNO_QUERY); 290 if(!xColumns.is() || !xColumns->getCount()) 291 ::dbtools::throwFunctionSequenceException(_xConnection); 292 293 const ::rtl::OUString sQuote = xMetaData->getIdentifierQuoteString(); 294 aSql.append(::rtl::OUString::createFromAscii(" PRIMARY KEY ")); 295 aSql.append(generateColumnNames(xColumns,xMetaData)); 296 } 297 else if(nKeyType == KeyType::UNIQUE) 298 { 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); 303 304 const ::rtl::OUString sQuote = xMetaData->getIdentifierQuoteString(); 305 aSql.append(::rtl::OUString::createFromAscii(" UNIQUE ")); 306 aSql.append(generateColumnNames(xColumns,xMetaData)); 307 } 308 else if(nKeyType == KeyType::FOREIGN) 309 { 310 sal_Int32 nDeleteRule = getINT32(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_DELETERULE))); 311 312 xColumnSup = Reference<XColumnsSupplier>(xColProp,UNO_QUERY); 313 xColumns = Reference<XIndexAccess>(xColumnSup->getColumns(),UNO_QUERY); 314 if(!xColumns.is() || !xColumns->getCount()) 315 ::dbtools::throwFunctionSequenceException(_xConnection); 316 317 aSql.append(::rtl::OUString::createFromAscii(" FOREIGN KEY ")); 318 ::rtl::OUString sRefTable = getString(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_REFERENCEDTABLE))); 319 ::dbtools::qualifiedNameComponents(xMetaData, 320 sRefTable, 321 sCatalog, 322 sSchema, 323 sTable, 324 ::dbtools::eInDataManipulation); 325 sComposedName = ::dbtools::composeTableName( xMetaData, sCatalog, sSchema, sTable, sal_True, ::dbtools::eInTableDefinitions ); 326 327 328 if ( !sComposedName.getLength() ) 329 ::dbtools::throwFunctionSequenceException(_xConnection); 330 331 aSql.append(generateColumnNames(xColumns,xMetaData)); 332 333 switch(nDeleteRule) 334 { 335 case KeyRule::CASCADE: 336 aSql.append(::rtl::OUString::createFromAscii(" ON DELETE CASCADE ")); 337 break; 338 case KeyRule::RESTRICT: 339 aSql.append(::rtl::OUString::createFromAscii(" ON DELETE RESTRICT ")); 340 break; 341 case KeyRule::SET_NULL: 342 aSql.append(::rtl::OUString::createFromAscii(" ON DELETE SET NULL ")); 343 break; 344 case KeyRule::SET_DEFAULT: 345 aSql.append(::rtl::OUString::createFromAscii(" ON DELETE SET DEFAULT ")); 346 break; 347 default: 348 ; 349 } 350 } 351 } 352 } 353 } 354 355 if ( aSql.getLength() ) 356 { 357 if ( aSql.charAt(aSql.getLength()-1) == ',' ) 358 aSql.setCharAt(aSql.getLength()-1,')'); 359 else 360 aSql.appendAscii(")"); 361 } 362 363 return aSql.makeStringAndClear(); 364 365 } 366 // ----------------------------------------------------------------------------- 367 ::rtl::OUString createSqlCreateTableStatement( const Reference< XPropertySet >& descriptor, 368 const Reference< XConnection>& _xConnection, 369 ISQLStatementHelper* _pHelper, 370 const ::rtl::OUString& _sCreatePattern) 371 { 372 ::rtl::OUString aSql = ::dbtools::createStandardCreateStatement(descriptor,_xConnection,_pHelper,_sCreatePattern); 373 const ::rtl::OUString sKeyStmt = ::dbtools::createStandardKeyStatement(descriptor,_xConnection); 374 if ( sKeyStmt.getLength() ) 375 aSql += sKeyStmt; 376 else 377 { 378 if ( aSql.lastIndexOf(',') == (aSql.getLength()-1) ) 379 aSql = aSql.replaceAt(aSql.getLength()-1,1,::rtl::OUString::createFromAscii(")")); 380 else 381 aSql += ::rtl::OUString::createFromAscii(")"); 382 } 383 return aSql; 384 } 385 namespace 386 { 387 Reference<XPropertySet> lcl_createSDBCXColumn(const Reference<XNameAccess>& _xPrimaryKeyColumns, 388 const Reference<XConnection>& _xConnection, 389 const Any& _aCatalog, 390 const ::rtl::OUString& _aSchema, 391 const ::rtl::OUString& _aTable, 392 const ::rtl::OUString& _rQueryName, 393 const ::rtl::OUString& _rName, 394 sal_Bool _bCase, 395 sal_Bool _bQueryForInfo, 396 sal_Bool _bIsAutoIncrement, 397 sal_Bool _bIsCurrency, 398 sal_Int32 _nDataType) 399 { 400 Reference<XPropertySet> xProp; 401 Reference<XDatabaseMetaData> xMetaData = _xConnection->getMetaData(); 402 Reference< XResultSet > xResult = xMetaData->getColumns(_aCatalog, _aSchema, _aTable, _rQueryName); 403 404 if ( xResult.is() ) 405 { 406 UStringMixEqual aMixCompare(_bCase); 407 Reference< XRow > xRow(xResult,UNO_QUERY); 408 while( xResult->next() ) 409 { 410 if ( aMixCompare(xRow->getString(4),_rName) ) 411 { 412 sal_Int32 nField5 = xRow->getInt(5); 413 ::rtl::OUString aField6 = xRow->getString(6); 414 sal_Int32 nField7 = xRow->getInt(7) 415 , nField9 = xRow->getInt(9) 416 , nField11= xRow->getInt(11); 417 ::rtl::OUString sField12 = xRow->getString(12), 418 sField13 = xRow->getString(13); 419 ::comphelper::disposeComponent(xRow); 420 421 sal_Bool bAutoIncrement = _bIsAutoIncrement 422 ,bIsCurrency = _bIsCurrency; 423 if ( _bQueryForInfo ) 424 { 425 const ::rtl::OUString sQuote = xMetaData->getIdentifierQuoteString(); 426 ::rtl::OUString sQuotedName = ::dbtools::quoteName(sQuote,_rName); 427 ::rtl::OUString sComposedName; 428 sComposedName = composeTableNameForSelect(_xConnection, getString( _aCatalog ), _aSchema, _aTable ); 429 430 ColumnInformationMap aInfo(_bCase); 431 collectColumnInformation(_xConnection,sComposedName,sQuotedName,aInfo); 432 ColumnInformationMap::iterator aIter = aInfo.begin(); 433 if ( aIter != aInfo.end() ) 434 { 435 bAutoIncrement = aIter->second.first.first; 436 bIsCurrency = aIter->second.first.second; 437 if ( DataType::OTHER == nField5 ) 438 nField5 = aIter->second.second; 439 } 440 } 441 else if ( DataType::OTHER == nField5 ) 442 nField5 = _nDataType; 443 444 if ( nField11 != ColumnValue::NO_NULLS ) 445 { 446 try 447 { 448 if ( _xPrimaryKeyColumns.is() ) 449 { 450 if ( _xPrimaryKeyColumns->hasByName(_rName) ) 451 nField11 = ColumnValue::NO_NULLS; 452 453 } 454 else 455 { 456 Reference< XResultSet > xPKeys = xMetaData->getPrimaryKeys( _aCatalog, _aSchema, _aTable ); 457 Reference< XRow > xPKeyRow( xPKeys, UNO_QUERY_THROW ); 458 while( xPKeys->next() ) // there can be only one primary key 459 { 460 ::rtl::OUString sKeyColumn = xPKeyRow->getString(4); 461 if ( aMixCompare(_rName,sKeyColumn) ) 462 { 463 nField11 = ColumnValue::NO_NULLS; 464 break; 465 } 466 } 467 } 468 } 469 catch(SQLException&) 470 { 471 OSL_ENSURE( false, "lcl_createSDBCXColumn: caught an exception!" ); 472 } 473 } 474 475 connectivity::sdbcx::OColumn* pRet = new connectivity::sdbcx::OColumn(_rName, 476 aField6, 477 sField13, 478 sField12, 479 nField11, 480 nField7, 481 nField9, 482 nField5, 483 bAutoIncrement, 484 sal_False, 485 bIsCurrency, 486 _bCase); 487 488 xProp = pRet; 489 break; 490 } 491 } 492 } 493 494 return xProp; 495 } 496 //------------------------------------------------------------------ 497 Reference< XModel> lcl_getXModel(const Reference< XInterface>& _xIface) 498 { 499 Reference< XInterface > xParent = _xIface; 500 Reference< XModel > xModel(xParent,UNO_QUERY);; 501 while( xParent.is() && !xModel.is() ) 502 { 503 Reference<XChild> xChild(xParent,UNO_QUERY); 504 xParent.set(xChild.is() ? xChild->getParent() : Reference< XInterface >(),UNO_QUERY); 505 xModel.set(xParent,UNO_QUERY); 506 } 507 return xModel; 508 } 509 } 510 // ----------------------------------------------------------------------------- 511 Reference<XPropertySet> createSDBCXColumn(const Reference<XPropertySet>& _xTable, 512 const Reference<XConnection>& _xConnection, 513 const ::rtl::OUString& _rName, 514 sal_Bool _bCase, 515 sal_Bool _bQueryForInfo, 516 sal_Bool _bIsAutoIncrement, 517 sal_Bool _bIsCurrency, 518 sal_Int32 _nDataType) 519 { 520 Reference<XPropertySet> xProp; 521 OSL_ENSURE(_xTable.is(),"Table is NULL!"); 522 if ( !_xTable.is() ) 523 return xProp; 524 525 ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap(); 526 Reference<XDatabaseMetaData> xMetaData = _xConnection->getMetaData(); 527 Any aCatalog; 528 aCatalog = _xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME)); 529 530 ::rtl::OUString aSchema, aTable; 531 _xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_SCHEMANAME)) >>= aSchema; 532 _xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME)) >>= aTable; 533 534 Reference<XNameAccess> xPrimaryKeyColumns = getPrimaryKeyColumns_throw(_xTable); 535 536 xProp = lcl_createSDBCXColumn(xPrimaryKeyColumns,_xConnection,aCatalog, aSchema, aTable, _rName,_rName,_bCase,_bQueryForInfo,_bIsAutoIncrement,_bIsCurrency,_nDataType); 537 if ( !xProp.is() ) 538 { 539 xProp = lcl_createSDBCXColumn(xPrimaryKeyColumns,_xConnection,aCatalog, aSchema, aTable, ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("%")),_rName,_bCase,_bQueryForInfo,_bIsAutoIncrement,_bIsCurrency,_nDataType); 540 if ( !xProp.is() ) 541 xProp = new connectivity::sdbcx::OColumn(_rName, 542 ::rtl::OUString(),::rtl::OUString(),::rtl::OUString(), 543 ColumnValue::NULLABLE_UNKNOWN, 544 0, 545 0, 546 DataType::VARCHAR, 547 _bIsAutoIncrement, 548 sal_False, 549 _bIsCurrency, 550 _bCase); 551 552 } 553 554 return xProp; 555 } 556 557 // ----------------------------------------------------------------------------- 558 bool getBooleanDataSourceSetting( const Reference< XConnection >& _rxConnection, const sal_Char* _pAsciiSettingName ) 559 { 560 bool bValue( false ); 561 try 562 { 563 Reference< XPropertySet> xDataSourceProperties( findDataSource( _rxConnection ), UNO_QUERY ); 564 OSL_ENSURE( xDataSourceProperties.is(), "::dbtools::getBooleanDataSourceSetting: somebody is using this with a non-SDB-level connection!" ); 565 if ( xDataSourceProperties.is() ) 566 { 567 Reference< XPropertySet > xSettings( 568 xDataSourceProperties->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Settings") ) ), 569 UNO_QUERY_THROW 570 ); 571 OSL_VERIFY( xSettings->getPropertyValue( ::rtl::OUString::createFromAscii( _pAsciiSettingName ) ) >>= bValue ); 572 } 573 } 574 catch( const Exception& ) 575 { 576 DBG_UNHANDLED_EXCEPTION(); 577 } 578 return bValue; 579 } 580 // ------------------------------------------------------------------------- 581 bool getDataSourceSetting( const Reference< XInterface >& _xChild, const ::rtl::OUString& _sAsciiSettingsName, 582 Any& /* [out] */ _rSettingsValue ) 583 { 584 bool bIsPresent = false; 585 try 586 { 587 const Reference< XPropertySet> xDataSourceProperties( findDataSource( _xChild ), UNO_QUERY ); 588 if ( !xDataSourceProperties.is() ) 589 return false; 590 591 const Reference< XPropertySet > xSettings( 592 xDataSourceProperties->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Settings") ) ), 593 UNO_QUERY_THROW 594 ); 595 596 _rSettingsValue = xSettings->getPropertyValue( _sAsciiSettingsName ); 597 bIsPresent = true; 598 } 599 catch( const Exception& ) 600 { 601 bIsPresent = false; 602 } 603 return bIsPresent; 604 } 605 // ------------------------------------------------------------------------- 606 bool getDataSourceSetting( const Reference< XInterface >& _rxDataSource, const sal_Char* _pAsciiSettingsName, 607 Any& /* [out] */ _rSettingsValue ) 608 { 609 ::rtl::OUString sAsciiSettingsName = ::rtl::OUString::createFromAscii(_pAsciiSettingsName); 610 return getDataSourceSetting( _rxDataSource, sAsciiSettingsName,_rSettingsValue ); 611 } 612 // ----------------------------------------------------------------------------- 613 sal_Bool isDataSourcePropertyEnabled(const Reference<XInterface>& _xProp,const ::rtl::OUString& _sProperty,sal_Bool _bDefault) 614 { 615 sal_Bool bEnabled = _bDefault; 616 try 617 { 618 Reference< XPropertySet> xProp(findDataSource(_xProp),UNO_QUERY); 619 if ( xProp.is() ) 620 { 621 Sequence< PropertyValue > aInfo; 622 xProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Info"))) >>= aInfo; 623 const PropertyValue* pValue =::std::find_if(aInfo.getConstArray(), 624 aInfo.getConstArray() + aInfo.getLength(), 625 ::std::bind2nd(TPropertyValueEqualFunctor(),_sProperty)); 626 if ( pValue && pValue != (aInfo.getConstArray() + aInfo.getLength()) ) 627 pValue->Value >>= bEnabled; 628 } 629 } 630 catch(SQLException&) 631 { 632 DBG_UNHANDLED_EXCEPTION(); 633 } 634 return bEnabled; 635 } 636 // ----------------------------------------------------------------------------- 637 Reference< XTablesSupplier> getDataDefinitionByURLAndConnection( 638 const ::rtl::OUString& _rsUrl, 639 const Reference< XConnection>& _xConnection, 640 const Reference< XMultiServiceFactory>& _rxFactory) 641 { 642 Reference< XTablesSupplier> xTablesSup; 643 try 644 { 645 Reference< XDriverAccess> xManager( 646 _rxFactory->createInstance( ::rtl::OUString::createFromAscii("com.sun.star.sdbc.DriverManager") ), 647 UNO_QUERY_THROW ); 648 Reference< XDataDefinitionSupplier > xSupp( xManager->getDriverByURL( _rsUrl ), UNO_QUERY ); 649 650 if ( xSupp.is() ) 651 { 652 xTablesSup = xSupp->getDataDefinitionByConnection( _xConnection ); 653 OSL_ENSURE(xTablesSup.is(),"No table supplier!"); 654 } 655 } 656 catch( const Exception& ) 657 { 658 DBG_UNHANDLED_EXCEPTION(); 659 } 660 return xTablesSup; 661 } 662 663 // ----------------------------------------------------------------------------- 664 sal_Int32 getTablePrivileges(const Reference< XDatabaseMetaData>& _xMetaData, 665 const ::rtl::OUString& _sCatalog, 666 const ::rtl::OUString& _sSchema, 667 const ::rtl::OUString& _sTable) 668 { 669 OSL_ENSURE(_xMetaData.is(),"Invalid metadata!"); 670 sal_Int32 nPrivileges = 0; 671 try 672 { 673 Any aVal; 674 if(_sCatalog.getLength()) 675 aVal <<= _sCatalog; 676 Reference< XResultSet > xPrivileges = _xMetaData->getTablePrivileges(aVal, _sSchema, _sTable); 677 Reference< XRow > xCurrentRow(xPrivileges, UNO_QUERY); 678 679 if ( xCurrentRow.is() ) 680 { 681 ::rtl::OUString sUserWorkingFor = _xMetaData->getUserName(); 682 static const ::rtl::OUString sSELECT = ::rtl::OUString::createFromAscii("SELECT"); 683 static const ::rtl::OUString sINSERT = ::rtl::OUString::createFromAscii("INSERT"); 684 static const ::rtl::OUString sUPDATE = ::rtl::OUString::createFromAscii("UPDATE"); 685 static const ::rtl::OUString sDELETE = ::rtl::OUString::createFromAscii("DELETE"); 686 static const ::rtl::OUString sREAD = ::rtl::OUString::createFromAscii("READ"); 687 static const ::rtl::OUString sCREATE = ::rtl::OUString::createFromAscii("CREATE"); 688 static const ::rtl::OUString sALTER = ::rtl::OUString::createFromAscii("ALTER"); 689 static const ::rtl::OUString sREFERENCE = ::rtl::OUString::createFromAscii("REFERENCE"); 690 static const ::rtl::OUString sDROP = ::rtl::OUString::createFromAscii("DROP"); 691 // after creation the set is positioned before the first record, per definitionem 692 #ifdef DBG_UTIL 693 Reference< XResultSetMetaDataSupplier > xSup(xPrivileges,UNO_QUERY); 694 if ( xSup.is() ) 695 { 696 Reference< XResultSetMetaData > xRsMetaData = xSup->getMetaData(); 697 if ( xRsMetaData.is() ) 698 { 699 sal_Int32 nCount = xRsMetaData->getColumnCount(); 700 for (sal_Int32 i=1; i<=nCount; ++i) 701 { 702 ::rtl::OUString sColumnName = xRsMetaData->getColumnName(i); 703 } 704 } 705 } 706 #endif 707 708 ::rtl::OUString sPrivilege, sGrantee; 709 while ( xPrivileges->next() ) 710 { 711 #ifdef DBG_UTIL 712 ::rtl::OUString sCat, sSchema, sName, sGrantor, sGrantable; 713 sCat = xCurrentRow->getString(1); 714 sSchema = xCurrentRow->getString(2); 715 sName = xCurrentRow->getString(3); 716 sGrantor = xCurrentRow->getString(4); 717 #endif 718 sGrantee = xCurrentRow->getString(5); 719 sPrivilege = xCurrentRow->getString(6); 720 #ifdef DBG_UTIL 721 sGrantable = xCurrentRow->getString(7); 722 #endif 723 724 if (!sUserWorkingFor.equalsIgnoreAsciiCase(sGrantee)) 725 continue; 726 727 if (sPrivilege.equalsIgnoreAsciiCase(sSELECT)) 728 nPrivileges |= Privilege::SELECT; 729 else if (sPrivilege.equalsIgnoreAsciiCase(sINSERT)) 730 nPrivileges |= Privilege::INSERT; 731 else if (sPrivilege.equalsIgnoreAsciiCase(sUPDATE)) 732 nPrivileges |= Privilege::UPDATE; 733 else if (sPrivilege.equalsIgnoreAsciiCase(sDELETE)) 734 nPrivileges |= Privilege::DELETE; 735 else if (sPrivilege.equalsIgnoreAsciiCase(sREAD)) 736 nPrivileges |= Privilege::READ; 737 else if (sPrivilege.equalsIgnoreAsciiCase(sCREATE)) 738 nPrivileges |= Privilege::CREATE; 739 else if (sPrivilege.equalsIgnoreAsciiCase(sALTER)) 740 nPrivileges |= Privilege::ALTER; 741 else if (sPrivilege.equalsIgnoreAsciiCase(sREFERENCE)) 742 nPrivileges |= Privilege::REFERENCE; 743 else if (sPrivilege.equalsIgnoreAsciiCase(sDROP)) 744 nPrivileges |= Privilege::DROP; 745 } 746 } 747 disposeComponent(xPrivileges); 748 } 749 catch(const SQLException& e) 750 { 751 static ::rtl::OUString sNotSupportedState = ::rtl::OUString::createFromAscii("IM001"); 752 // some drivers don't support any privileges so we assume that we are allowed to do all we want :-) 753 if(e.SQLState == sNotSupportedState) 754 nPrivileges |= Privilege::DROP | 755 Privilege::REFERENCE | 756 Privilege::ALTER | 757 Privilege::CREATE | 758 Privilege::READ | 759 Privilege::DELETE | 760 Privilege::UPDATE | 761 Privilege::INSERT | 762 Privilege::SELECT; 763 else 764 OSL_ENSURE(0,"Could not collect the privileges !"); 765 } 766 return nPrivileges; 767 } 768 // ----------------------------------------------------------------------------- 769 // we need some more information about the column 770 void collectColumnInformation(const Reference< XConnection>& _xConnection, 771 const ::rtl::OUString& _sComposedName, 772 const ::rtl::OUString& _rName, 773 ColumnInformationMap& _rInfo) 774 { 775 static ::rtl::OUString STR_WHERE = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" WHERE ")); 776 777 ::rtl::OUString sSelect = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SELECT ")); 778 sSelect += _rName; 779 sSelect += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" FROM ")); 780 sSelect += _sComposedName; 781 sSelect += STR_WHERE; 782 sSelect += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("0 = 1")); 783 784 try 785 { 786 ::utl::SharedUNOComponent< XStatement > xStmt( _xConnection->createStatement() ); 787 Reference< XPropertySet > xStatementProps( xStmt, UNO_QUERY_THROW ); 788 xStatementProps->setPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_ESCAPEPROCESSING ), makeAny( (sal_Bool)sal_False ) ); 789 Reference< XResultSet > xResult( xStmt->executeQuery( sSelect ), UNO_QUERY_THROW ); 790 Reference< XResultSetMetaDataSupplier > xSuppMeta( xResult, UNO_QUERY_THROW ); 791 Reference< XResultSetMetaData > xMeta( xSuppMeta->getMetaData(), UNO_QUERY_THROW ); 792 793 sal_Int32 nCount = xMeta->getColumnCount(); 794 OSL_ENSURE( nCount != 0, "::dbtools::collectColumnInformation: result set has empty (column-less) meta data!" ); 795 for (sal_Int32 i=1; i <= nCount ; ++i) 796 { 797 _rInfo.insert(ColumnInformationMap::value_type(xMeta->getColumnName(i), 798 ColumnInformation(TBoolPair(xMeta->isAutoIncrement(i),xMeta->isCurrency(i)),xMeta->getColumnType(i)))); 799 } 800 } 801 catch( const Exception& ) 802 { 803 DBG_UNHANDLED_EXCEPTION(); 804 } 805 } 806 807 // ----------------------------------------------------------------------------- 808 bool isEmbeddedInDatabase( const Reference< XInterface >& _rxComponent, Reference< XConnection >& _rxActualConnection ) 809 { 810 bool bIsEmbedded = false; 811 try 812 { 813 Reference< XModel > xModel = lcl_getXModel( _rxComponent ); 814 815 if ( xModel.is() ) 816 { 817 Sequence< PropertyValue > aArgs = xModel->getArgs(); 818 const PropertyValue* pIter = aArgs.getConstArray(); 819 const PropertyValue* pEnd = pIter + aArgs.getLength(); 820 for(;pIter != pEnd;++pIter) 821 { 822 if ( pIter->Name.equalsAscii("ComponentData") ) 823 { 824 Sequence<PropertyValue> aDocumentContext; 825 pIter->Value >>= aDocumentContext; 826 const PropertyValue* pContextIter = aDocumentContext.getConstArray(); 827 const PropertyValue* pContextEnd = pContextIter + aDocumentContext.getLength(); 828 for(;pContextIter != pContextEnd;++pContextIter) 829 { 830 if ( pContextIter->Name.equalsAscii( "ActiveConnection" ) 831 && ( pContextIter->Value >>= _rxActualConnection ) 832 ) 833 { 834 bIsEmbedded = true; 835 break; 836 } 837 } 838 break; 839 } 840 } 841 } 842 } 843 catch(Exception&) 844 { 845 // not intereseted in 846 } 847 return bIsEmbedded; 848 } 849 // ----------------------------------------------------------------------------- 850 namespace 851 { 852 ::rtl::OUString lcl_getEncodingName( rtl_TextEncoding _eEncoding ) 853 { 854 ::rtl::OUString sEncodingName; 855 856 OCharsetMap aCharsets; 857 OCharsetMap::CharsetIterator aEncodingPos = aCharsets.find( _eEncoding ); 858 OSL_ENSURE( aEncodingPos != aCharsets.end(), "lcl_getEncodingName: *which* encoding?" ); 859 if ( aEncodingPos != aCharsets.end() ) 860 sEncodingName = (*aEncodingPos).getIanaName(); 861 862 return sEncodingName; 863 } 864 } 865 866 // ----------------------------------------------------------------------------- 867 sal_Int32 DBTypeConversion::convertUnicodeString( const ::rtl::OUString& _rSource, ::rtl::OString& _rDest, rtl_TextEncoding _eEncoding ) SAL_THROW((com::sun::star::sdbc::SQLException)) 868 { 869 if ( !rtl_convertUStringToString( &_rDest.pData, _rSource.getStr(), _rSource.getLength(), 870 _eEncoding, 871 RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR | 872 RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACE | 873 RTL_UNICODETOTEXT_FLAGS_PRIVATE_MAPTO0 | 874 RTL_UNICODETOTEXT_FLAGS_NOCOMPOSITE ) 875 ) 876 { 877 SharedResources aResources; 878 ::rtl::OUString sMessage = aResources.getResourceStringWithSubstitution( STR_CANNOT_CONVERT_STRING, 879 "$string$", _rSource, 880 "$charset$", lcl_getEncodingName( _eEncoding ) 881 ); 882 883 throw SQLException( 884 sMessage, 885 NULL, 886 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "22018" ) ), 887 22018, 888 Any() 889 ); 890 } 891 892 return _rDest.getLength(); 893 } 894 895 // ----------------------------------------------------------------------------- 896 sal_Int32 DBTypeConversion::convertUnicodeStringToLength( const ::rtl::OUString& _rSource, ::rtl::OString& _rDest, 897 sal_Int32 _nMaxLen, rtl_TextEncoding _eEncoding ) SAL_THROW((SQLException)) 898 { 899 sal_Int32 nLen = convertUnicodeString( _rSource, _rDest, _eEncoding ); 900 if ( nLen > _nMaxLen ) 901 { 902 SharedResources aResources; 903 ::rtl::OUString sMessage = aResources.getResourceStringWithSubstitution( STR_STRING_LENGTH_EXCEEDED, 904 "$string$", _rSource, 905 "$maxlen$", ::rtl::OUString::valueOf( _nMaxLen ), 906 "$charset$", lcl_getEncodingName( _eEncoding ) 907 ); 908 909 throw SQLException( 910 sMessage, 911 NULL, 912 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "22001" ) ), 913 22001, 914 Any() 915 ); 916 } 917 918 return nLen; 919 } 920 ::rtl::OUString lcl_getReportEngines() 921 { 922 static ::rtl::OUString s_sNodeName(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.DataAccess/ReportEngines")); 923 return s_sNodeName; 924 } 925 // ----------------------------------------------------------------------------- 926 ::rtl::OUString lcl_getDefaultReportEngine() 927 { 928 static ::rtl::OUString s_sNodeName(RTL_CONSTASCII_USTRINGPARAM("DefaultReportEngine")); 929 return s_sNodeName; 930 } 931 // ----------------------------------------------------------------------------- 932 ::rtl::OUString lcl_getReportEngineNames() 933 { 934 static ::rtl::OUString s_sNodeName(RTL_CONSTASCII_USTRINGPARAM("ReportEngineNames")); 935 return s_sNodeName; 936 } 937 // ----------------------------------------------------------------------------- 938 ::rtl::OUString getDefaultReportEngineServiceName(const Reference< XMultiServiceFactory >& _rxORB) 939 { 940 ::utl::OConfigurationTreeRoot aReportEngines = ::utl::OConfigurationTreeRoot::createWithServiceFactory( 941 _rxORB, lcl_getReportEngines(), -1, ::utl::OConfigurationTreeRoot::CM_READONLY); 942 943 if ( aReportEngines.isValid() ) 944 { 945 ::rtl::OUString sDefaultReportEngineName; 946 aReportEngines.getNodeValue(lcl_getDefaultReportEngine()) >>= sDefaultReportEngineName; 947 if ( sDefaultReportEngineName.getLength() ) 948 { 949 ::utl::OConfigurationNode aReportEngineNames = aReportEngines.openNode(lcl_getReportEngineNames()); 950 if ( aReportEngineNames.isValid() ) 951 { 952 ::utl::OConfigurationNode aReportEngine = aReportEngineNames.openNode(sDefaultReportEngineName); 953 if ( aReportEngine.isValid() ) 954 { 955 ::rtl::OUString sRet; 956 const static ::rtl::OUString s_sService(RTL_CONSTASCII_USTRINGPARAM("ServiceName")); 957 aReportEngine.getNodeValue(s_sService) >>= sRet; 958 return sRet; 959 } 960 } 961 } 962 else 963 return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.report.pentaho.SOReportJobFactory")); 964 } 965 else 966 return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.report.pentaho.SOReportJobFactory")); 967 return ::rtl::OUString(); 968 } 969 // ----------------------------------------------------------------------------- 970 //......................................................................... 971 } // namespace dbtools 972 //......................................................................... 973 974