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