1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 11 * Licensed to the Apache Software Foundation (ASF) under one or more 12 * contributor license agreements. See the NOTICE file distributed 13 * with this work for additional information regarding copyright 14 * ownership. The ASF licenses this file to you under the Apache 15 * License, Version 2.0 (the "License"); you may not use this file 16 * except in compliance with the License. You may obtain a copy of 17 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 18 */ 19 20 #include <UITools.hxx> 21 #include <sfx2/docfilt.hxx> 22 #include <callbacks.hxx> 23 #include <core_resource.hxx> 24 #include <stringconstants.hxx> 25 #include <dlgsave.hxx> 26 #include <dbtreelistbox.hxx> 27 #include <defaultobjectnamecheck.hxx> 28 #include <comphelper/extract.hxx> 29 #include <com/sun/star/sdb/DatabaseContext.hpp> 30 #include <com/sun/star/sdb/XSingleSelectQueryAnalyzer.hpp> 31 #include <com/sun/star/sdb/XCompletedConnection.hpp> 32 #include <com/sun/star/sdbc/XDataSource.hpp> 33 #include <com/sun/star/sdb/SQLContext.hpp> 34 #include <com/sun/star/sdbcx/XKeysSupplier.hpp> 35 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp> 36 #include <com/sun/star/sdbcx/XViewsSupplier.hpp> 37 #include <com/sun/star/sdbcx/XTablesSupplier.hpp> 38 #include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp> 39 #include <com/sun/star/sdbcx/XAppend.hpp> 40 #include <com/sun/star/sdbc/XRow.hpp> 41 #include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> 42 #include <com/sun/star/sdbc/XResultSetMetaData.hpp> 43 #include <com/sun/star/sdbc/ColumnValue.hpp> 44 #include <com/sun/star/task/InteractionHandler.hpp> 45 #include <com/sun/star/ucb/XContent.hpp> 46 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> 47 #include <com/sun/star/beans/PropertyValue.hpp> 48 #include <com/sun/star/container/XIndexAccess.hpp> 49 #include <com/sun/star/container/XNameContainer.hpp> 50 #include <com/sun/star/ucb/InteractiveIOException.hpp> 51 #include <com/sun/star/sdb/XDocumentDataSource.hpp> 52 #include <com/sun/star/ucb/IOErrorCode.hpp> 53 #include <toolkit/helper/vclunohelper.hxx> 54 #include <toolkit/awt/vclxwindow.hxx> 55 #include <vcl/stdtext.hxx> 56 #include <vcl/settings.hxx> 57 #include <vcl/svapp.hxx> 58 #include <com/sun/star/beans/XPropertySetInfo.hpp> 59 #include <com/sun/star/beans/XPropertySet.hpp> 60 #include <com/sun/star/container/XNameAccess.hpp> 61 #include <com/sun/star/container/XContainer.hpp> 62 #include <com/sun/star/container/XHierarchicalNameContainer.hpp> 63 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 64 #include <com/sun/star/awt/TextAlign.hpp> 65 #include <com/sun/star/awt/FontDescriptor.hpp> 66 #include <com/sun/star/awt/FontWeight.hpp> 67 #include <com/sun/star/awt/FontRelief.hpp> 68 #include <com/sun/star/awt/FontWidth.hpp> 69 #include <com/sun/star/awt/XWindow.hpp> 70 #include <TypeInfo.hxx> 71 #include <FieldDescriptions.hxx> 72 #include <comphelper/stl_types.hxx> 73 #include <comphelper/types.hxx> 74 #include <comphelper/propertysequence.hxx> 75 76 #include <svx/svxids.hrc> 77 78 #include <sal/log.hxx> 79 #include <svl/itempool.hxx> 80 #include <helpids.h> 81 #include <svl/itemset.hxx> 82 #include <sbagrid.hrc> 83 #include <svl/rngitem.hxx> 84 #include <svl/intitem.hxx> 85 #include <svx/algitem.hxx> 86 #include <svx/numinf.hxx> 87 #include <svl/zforlist.hxx> 88 #include <dlgattr.hxx> 89 #include <com/sun/star/container/XChild.hpp> 90 #include <com/sun/star/util/NumberFormatter.hpp> 91 #include <com/sun/star/util/XNumberFormatsSupplier.hpp> 92 #include <com/sun/star/util/XNumberFormatter.hpp> 93 #include <strings.hrc> 94 #include <sqlmessage.hxx> 95 #include <com/sun/star/util/NumberFormat.hpp> 96 #include <com/sun/star/util/URL.hpp> 97 #include <vcl/toolbox.hxx> 98 #include <dlgsize.hxx> 99 #include <svtools/editbrowsebox.hxx> 100 #include <unotools/configmgr.hxx> 101 #include <svtools/helpopt.hxx> 102 #include <ucbhelper/content.hxx> 103 #include <tools/urlobj.hxx> 104 #include <tools/diagnose_ex.h> 105 #include <svl/numuno.hxx> 106 #include <unotools/pathoptions.hxx> 107 #include <svl/filenotation.hxx> 108 #include <connectivity/FValue.hxx> 109 110 #include <editeng/justifyitem.hxx> 111 #include <memory> 112 113 namespace dbaui 114 { 115 using namespace ::dbtools; 116 using namespace ::comphelper; 117 using namespace ::com::sun::star; 118 using namespace ::com::sun::star::uno; 119 using namespace ::com::sun::star::task; 120 using namespace ::com::sun::star::sdbcx; 121 using namespace ::com::sun::star::sdbc; 122 using namespace ::com::sun::star::sdb; 123 using namespace ::com::sun::star::util; 124 using namespace ::com::sun::star::ucb; 125 using namespace ::com::sun::star::beans; 126 using namespace ::com::sun::star::container; 127 using namespace ::com::sun::star::lang; 128 using namespace ::com::sun::star::ui::dialogs; 129 using namespace ::svt; 130 using ::com::sun::star::ucb::InteractiveIOException; 131 using ::com::sun::star::ucb::IOErrorCode_NO_FILE; 132 using ::com::sun::star::ucb::IOErrorCode_NOT_EXISTING; 133 134 SQLExceptionInfo createConnection( const OUString& _rsDataSourceName, 135 const Reference< css::container::XNameAccess >& _xDatabaseContext, 136 const Reference< css::uno::XComponentContext >& _rxContext, 137 Reference< css::lang::XEventListener> const & _rEvtLst, 138 Reference< css::sdbc::XConnection>& _rOUTConnection ) 139 { 140 Reference<XPropertySet> xProp; 141 try 142 { 143 xProp.set(_xDatabaseContext->getByName(_rsDataSourceName),UNO_QUERY); 144 } 145 catch(const Exception&) 146 { 147 } 148 149 return createConnection(xProp,_rxContext,_rEvtLst,_rOUTConnection); 150 } 151 152 SQLExceptionInfo createConnection( const Reference< css::beans::XPropertySet>& _xDataSource, 153 const Reference< css::uno::XComponentContext >& _rxContext, 154 Reference< css::lang::XEventListener> const & _rEvtLst, 155 Reference< css::sdbc::XConnection>& _rOUTConnection ) 156 { 157 SQLExceptionInfo aInfo; 158 if ( !_xDataSource.is() ) 159 { 160 SAL_WARN("dbaccess.ui", "createConnection: could not retrieve the data source!"); 161 return aInfo; 162 } 163 164 OUString sPwd, sUser; 165 bool bPwdReq = false; 166 try 167 { 168 _xDataSource->getPropertyValue(PROPERTY_PASSWORD) >>= sPwd; 169 bPwdReq = ::cppu::any2bool(_xDataSource->getPropertyValue(PROPERTY_ISPASSWORDREQUIRED)); 170 _xDataSource->getPropertyValue(PROPERTY_USER) >>= sUser; 171 } 172 catch(const Exception&) 173 { 174 SAL_WARN("dbaccess.ui", "createConnection: error while retrieving data source properties!"); 175 } 176 177 try 178 { 179 if(bPwdReq && sPwd.isEmpty()) 180 { // password required, but empty -> connect using an interaction handler 181 Reference<XCompletedConnection> xConnectionCompletion(_xDataSource, UNO_QUERY); 182 if (!xConnectionCompletion.is()) 183 { 184 SAL_WARN("dbaccess.ui", "createConnection: missing an interface ... need an error message here!"); 185 } 186 else 187 { // instantiate the default SDB interaction handler 188 Reference< XInteractionHandler > xHandler = InteractionHandler::createWithParent(_rxContext, nullptr); 189 _rOUTConnection = xConnectionCompletion->connectWithCompletion(xHandler); 190 } 191 } 192 else 193 { 194 Reference<XDataSource> xDataSource(_xDataSource,UNO_QUERY); 195 _rOUTConnection = xDataSource->getConnection(sUser, sPwd); 196 } 197 // be notified when connection is in disposing 198 Reference< XComponent > xComponent(_rOUTConnection, UNO_QUERY); 199 if (xComponent.is() && _rEvtLst.is()) 200 xComponent->addEventListener(_rEvtLst); 201 } 202 catch(const SQLContext& e) { aInfo = SQLExceptionInfo(e); } 203 catch(const SQLWarning& e) { aInfo = SQLExceptionInfo(e); } 204 catch(const SQLException& e) { aInfo = SQLExceptionInfo(e); } 205 catch(const Exception&) { 206 TOOLS_WARN_EXCEPTION("dbaccess.ui", "SbaTableQueryBrowser::OnExpandEntry: could not connect - unknown exception"); 207 } 208 209 return aInfo; 210 } 211 212 Reference< XDataSource > getDataSourceByName( const OUString& _rDataSourceName, 213 weld::Window* _pErrorMessageParent, const Reference< XComponentContext >& _rxContext, ::dbtools::SQLExceptionInfo* _pErrorInfo ) 214 { 215 Reference< XDatabaseContext > xDatabaseContext = DatabaseContext::create(_rxContext); 216 217 Reference< XDataSource > xDatasource; 218 Any aError; 219 SQLExceptionInfo aSQLError; 220 try 221 { 222 xDatabaseContext->getByName( _rDataSourceName ) >>= xDatasource; 223 } 224 catch(const WrappedTargetException& e) 225 { 226 InteractiveIOException aIOException; 227 if ( ( e.TargetException >>= aIOException ) 228 && ( ( aIOException.Code == IOErrorCode_NO_FILE ) 229 || ( aIOException.Code == IOErrorCode_NOT_EXISTING ) 230 ) 231 ) 232 { 233 OUString sErrorMessage( DBA_RES( STR_FILE_DOES_NOT_EXIST ) ); 234 OFileNotation aTransformer( e.Message ); 235 sErrorMessage = sErrorMessage.replaceFirst( "$file$", aTransformer.get( OFileNotation::N_SYSTEM ) ); 236 aSQLError = SQLExceptionInfo( sErrorMessage ).get(); 237 } 238 else 239 { 240 aSQLError = SQLExceptionInfo( e.TargetException ); 241 if ( !aSQLError.isValid() ) 242 aError = e.TargetException; 243 } 244 } 245 catch( const Exception& ) 246 { 247 DBG_UNHANDLED_EXCEPTION("dbaccess"); 248 } 249 250 if ( xDatasource.is() ) 251 return xDatasource; 252 253 if ( aSQLError.isValid() ) 254 { 255 if ( _pErrorInfo ) 256 { 257 *_pErrorInfo = aSQLError; 258 } 259 else 260 { 261 showError( aSQLError, _pErrorMessageParent ? _pErrorMessageParent->GetXWindow() : nullptr, _rxContext ); 262 } 263 } 264 265 return Reference<XDataSource>(); 266 } 267 268 Reference< XInterface > getDataSourceOrModel(const Reference< XInterface >& _xObject) 269 { 270 Reference< XInterface > xRet; 271 Reference<XDocumentDataSource> xDocumentDataSource(_xObject,UNO_QUERY); 272 if ( xDocumentDataSource.is() ) 273 xRet = xDocumentDataSource->getDatabaseDocument(); 274 275 if ( !xRet.is() ) 276 { 277 Reference<XOfficeDatabaseDocument> xOfficeDoc(_xObject,UNO_QUERY); 278 if ( xOfficeDoc.is() ) 279 xRet = xOfficeDoc->getDataSource(); 280 } 281 282 return xRet; 283 } 284 285 TOTypeInfoSP getTypeInfoFromType(const OTypeInfoMap& _rTypeInfo, 286 sal_Int32 _nType, 287 const OUString& _sTypeName, 288 const OUString& _sCreateParams, 289 sal_Int32 _nPrecision, 290 sal_Int32 _nScale, 291 bool _bAutoIncrement, 292 bool& _brForceToType) 293 { 294 TOTypeInfoSP pTypeInfo; 295 _brForceToType = false; 296 // search for type 297 std::pair<OTypeInfoMap::const_iterator, OTypeInfoMap::const_iterator> aPair = _rTypeInfo.equal_range(_nType); 298 OTypeInfoMap::const_iterator aIter = aPair.first; 299 if(aIter != _rTypeInfo.end()) // compare with end is correct here 300 { 301 for(;aIter != aPair.second;++aIter) 302 { 303 // search the best matching type 304 #ifdef DBG_UTIL 305 OUString sDBTypeName = aIter->second->aTypeName; (void)sDBTypeName; 306 #endif 307 if ( ( 308 _sTypeName.isEmpty() 309 || (aIter->second->aTypeName.equalsIgnoreAsciiCase(_sTypeName)) 310 ) 311 && ( 312 ( 313 !aIter->second->aCreateParams.getLength() 314 && _sCreateParams.isEmpty() 315 ) 316 || ( 317 (aIter->second->nPrecision >= _nPrecision) 318 && (aIter->second->nMaximumScale >= _nScale) 319 && ( (_bAutoIncrement && aIter->second->bAutoIncrement) || !_bAutoIncrement ) 320 ) 321 ) 322 ) 323 break; 324 } 325 326 if (aIter == aPair.second) 327 { 328 for(aIter = aPair.first; aIter != aPair.second; ++aIter) 329 { 330 sal_Int32 nPrec = aIter->second->nPrecision; 331 sal_Int32 nScale = aIter->second->nMaximumScale; 332 // search the best matching type (now comparing the local names) 333 if ( (aIter->second->aLocalTypeName.equalsIgnoreAsciiCase(_sTypeName)) 334 && (nPrec >= _nPrecision) 335 && (nScale >= _nScale) 336 && ( (_bAutoIncrement && aIter->second->bAutoIncrement) || !_bAutoIncrement ) 337 ) 338 { 339 SAL_WARN("dbaccess.ui", "getTypeInfoFromType: assuming column type " << 340 aIter->second->aTypeName << "\" (expected type name " << 341 _sTypeName << " matches the type's local name)."); 342 break; 343 } 344 } 345 } 346 347 if (aIter == aPair.second) 348 { // no match for the names, no match for the local names 349 // -> drop the precision and the scale restriction, accept any type with the property 350 // type id (nType) 351 352 for(aIter = aPair.first; aIter != aPair.second; ++aIter) 353 { 354 // search the best matching type (now comparing the local names) 355 sal_Int32 nPrec = aIter->second->nPrecision; 356 sal_Int32 nScale = aIter->second->nMaximumScale; 357 if ( (nPrec >= _nPrecision) 358 && (nScale >= _nScale) 359 && ( (_bAutoIncrement && aIter->second->bAutoIncrement) || !_bAutoIncrement ) 360 ) 361 break; 362 } 363 } 364 if (aIter == aPair.second) 365 { 366 if ( _bAutoIncrement ) 367 { 368 for(aIter = aPair.first; aIter != aPair.second; ++aIter) 369 { 370 // search the best matching type (now comparing the local names) 371 sal_Int32 nScale = aIter->second->nMaximumScale; 372 if ( (nScale >= _nScale) 373 && (aIter->second->bAutoIncrement == _bAutoIncrement) 374 ) 375 break; 376 } 377 if ( aIter == aPair.second ) 378 { 379 // try it without the auto increment flag 380 pTypeInfo = getTypeInfoFromType(_rTypeInfo, 381 _nType, 382 _sTypeName, 383 _sCreateParams, 384 _nPrecision, 385 _nScale, 386 false, 387 _brForceToType); 388 } 389 else 390 pTypeInfo = aIter->second; 391 } 392 else 393 { 394 pTypeInfo = aPair.first->second; 395 _brForceToType = true; 396 } 397 } 398 else 399 pTypeInfo = aIter->second; 400 } 401 else 402 { 403 ::comphelper::UStringMixEqual aCase(false); 404 // search for typeinfo where the typename is equal _sTypeName 405 for (auto const& elem : _rTypeInfo) 406 { 407 if ( aCase( elem.second->getDBName() , _sTypeName ) ) 408 { 409 pTypeInfo = elem.second; 410 break; 411 } 412 } 413 } 414 415 OSL_ENSURE(pTypeInfo, "getTypeInfoFromType: no type info found for this type!"); 416 return pTypeInfo; 417 } 418 419 void fillTypeInfo( const Reference< css::sdbc::XConnection>& _rxConnection, 420 const OUString& _rsTypeNames, 421 OTypeInfoMap& _rTypeInfoMap, 422 std::vector<OTypeInfoMap::iterator>& _rTypeInfoIters) 423 { 424 if(!_rxConnection.is()) 425 return; 426 Reference< XResultSet> xRs = _rxConnection->getMetaData ()->getTypeInfo (); 427 Reference< XRow> xRow(xRs,UNO_QUERY); 428 // Information for a single SQL type 429 if(xRs.is()) 430 { 431 Reference<XResultSetMetaData> xResultSetMetaData = Reference<XResultSetMetaDataSupplier>(xRs,UNO_QUERY_THROW)->getMetaData(); 432 ::connectivity::ORowSetValue aValue; 433 std::vector<sal_Int32> aTypes; 434 std::vector<bool> aNullable; 435 // Loop on the result set until we reach end of file 436 while (xRs->next()) 437 { 438 TOTypeInfoSP pInfo = std::make_shared<OTypeInfo>(); 439 sal_Int32 nPos = 1; 440 if ( aTypes.empty() ) 441 { 442 sal_Int32 nCount = xResultSetMetaData->getColumnCount(); 443 if ( nCount < 1 ) 444 nCount = 18; 445 aTypes.reserve(nCount+1); 446 aTypes.push_back(-1); 447 aNullable.push_back(false); 448 for (sal_Int32 j = 1; j <= nCount ; ++j) 449 { 450 aTypes.push_back(xResultSetMetaData->getColumnType(j)); 451 aNullable.push_back(xResultSetMetaData->isNullable(j) != ColumnValue::NO_NULLS); 452 } 453 } 454 455 aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow); 456 pInfo->aTypeName = aValue; 457 ++nPos; 458 aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow); 459 pInfo->nType = aValue; 460 ++nPos; 461 aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow); 462 pInfo->nPrecision = aValue; 463 ++nPos; 464 aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow); // LiteralPrefix 465 ++nPos; 466 aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow); //LiteralSuffix 467 ++nPos; 468 aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow); 469 pInfo->aCreateParams = aValue; 470 ++nPos; 471 aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow); 472 pInfo->bNullable = static_cast<sal_Int32>(aValue) == ColumnValue::NULLABLE; 473 ++nPos; 474 aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow); 475 // bCaseSensitive 476 ++nPos; 477 aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow); 478 pInfo->nSearchType = aValue; 479 ++nPos; 480 aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow); 481 // bUnsigned 482 ++nPos; 483 aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow); 484 pInfo->bCurrency = static_cast<bool>(aValue); 485 ++nPos; 486 aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow); 487 pInfo->bAutoIncrement = static_cast<bool>(aValue); 488 ++nPos; 489 aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow); 490 pInfo->aLocalTypeName = aValue; 491 ++nPos; 492 aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow); 493 pInfo->nMinimumScale = aValue; 494 ++nPos; 495 aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow); 496 pInfo->nMaximumScale = aValue; 497 assert(nPos == 15); 498 // 16 and 17 are unused 499 nPos = 18; 500 aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow); 501 pInfo->nNumPrecRadix = aValue; 502 503 // check if values are less than zero like it happens in a oracle jdbc driver 504 if( pInfo->nPrecision < 0) 505 pInfo->nPrecision = 0; 506 if( pInfo->nMinimumScale < 0) 507 pInfo->nMinimumScale = 0; 508 if( pInfo->nMaximumScale < 0) 509 pInfo->nMaximumScale = 0; 510 if( pInfo->nNumPrecRadix <= 1) 511 pInfo->nNumPrecRadix = 10; 512 513 OUString aName; 514 switch(pInfo->nType) 515 { 516 case DataType::CHAR: 517 aName = _rsTypeNames.getToken(TYPE_CHAR, ';'); 518 break; 519 case DataType::VARCHAR: 520 aName = _rsTypeNames.getToken(TYPE_TEXT, ';'); 521 break; 522 case DataType::DECIMAL: 523 aName = _rsTypeNames.getToken(TYPE_DECIMAL, ';'); 524 break; 525 case DataType::NUMERIC: 526 aName = _rsTypeNames.getToken(TYPE_NUMERIC, ';'); 527 break; 528 case DataType::BIGINT: 529 aName = _rsTypeNames.getToken(TYPE_BIGINT, ';'); 530 break; 531 case DataType::FLOAT: 532 aName = _rsTypeNames.getToken(TYPE_FLOAT, ';'); 533 break; 534 case DataType::DOUBLE: 535 aName = _rsTypeNames.getToken(TYPE_DOUBLE, ';'); 536 break; 537 case DataType::LONGVARCHAR: 538 aName = _rsTypeNames.getToken(TYPE_MEMO, ';'); 539 break; 540 case DataType::LONGVARBINARY: 541 aName = _rsTypeNames.getToken(TYPE_IMAGE, ';'); 542 break; 543 case DataType::DATE: 544 aName = _rsTypeNames.getToken(TYPE_DATE, ';'); 545 break; 546 case DataType::TIME: 547 aName = _rsTypeNames.getToken(TYPE_TIME, ';'); 548 break; 549 case DataType::TIMESTAMP: 550 aName = _rsTypeNames.getToken(TYPE_DATETIME, ';'); 551 break; 552 case DataType::BIT: 553 if ( !pInfo->aCreateParams.isEmpty() ) 554 { 555 aName = _rsTypeNames.getToken(TYPE_BIT, ';'); 556 break; 557 } 558 [[fallthrough]]; 559 case DataType::BOOLEAN: 560 aName = _rsTypeNames.getToken(TYPE_BOOL, ';'); 561 break; 562 case DataType::TINYINT: 563 aName = _rsTypeNames.getToken(TYPE_TINYINT, ';'); 564 break; 565 case DataType::SMALLINT: 566 aName = _rsTypeNames.getToken(TYPE_SMALLINT, ';'); 567 break; 568 case DataType::INTEGER: 569 aName = _rsTypeNames.getToken(TYPE_INTEGER, ';'); 570 break; 571 case DataType::REAL: 572 aName = _rsTypeNames.getToken(TYPE_REAL, ';'); 573 break; 574 case DataType::BINARY: 575 aName = _rsTypeNames.getToken(TYPE_BINARY, ';'); 576 break; 577 case DataType::VARBINARY: 578 aName = _rsTypeNames.getToken(TYPE_VARBINARY, ';'); 579 break; 580 case DataType::SQLNULL: 581 aName = _rsTypeNames.getToken(TYPE_SQLNULL, ';'); 582 break; 583 case DataType::OBJECT: 584 aName = _rsTypeNames.getToken(TYPE_OBJECT, ';'); 585 break; 586 case DataType::DISTINCT: 587 aName = _rsTypeNames.getToken(TYPE_DISTINCT, ';'); 588 break; 589 case DataType::STRUCT: 590 aName = _rsTypeNames.getToken(TYPE_STRUCT, ';'); 591 break; 592 case DataType::ARRAY: 593 aName = _rsTypeNames.getToken(TYPE_ARRAY, ';'); 594 break; 595 case DataType::BLOB: 596 aName = _rsTypeNames.getToken(TYPE_BLOB, ';'); 597 break; 598 case DataType::CLOB: 599 aName = _rsTypeNames.getToken(TYPE_CLOB, ';'); 600 break; 601 case DataType::REF: 602 aName = _rsTypeNames.getToken(TYPE_REF, ';'); 603 break; 604 case DataType::OTHER: 605 aName = _rsTypeNames.getToken(TYPE_OTHER, ';'); 606 break; 607 } 608 if ( !aName.isEmpty() ) 609 { 610 pInfo->aUIName = aName; 611 pInfo->aUIName += " [ "; 612 } 613 pInfo->aUIName += pInfo->aTypeName; 614 if ( !aName.isEmpty() ) 615 pInfo->aUIName += " ]"; 616 // Now that we have the type info, save it in the multimap 617 _rTypeInfoMap.emplace(pInfo->nType,pInfo); 618 } 619 // for a faster index access 620 _rTypeInfoIters.reserve(_rTypeInfoMap.size()); 621 622 OTypeInfoMap::iterator aIter = _rTypeInfoMap.begin(); 623 OTypeInfoMap::const_iterator aEnd = _rTypeInfoMap.end(); 624 for(;aIter != aEnd;++aIter) 625 _rTypeInfoIters.push_back(aIter); 626 627 // Close the result set/statement. 628 629 ::comphelper::disposeComponent(xRs); 630 } 631 } 632 633 void setColumnProperties(const Reference<XPropertySet>& _rxColumn,const OFieldDescription* _pFieldDesc) 634 { 635 _rxColumn->setPropertyValue(PROPERTY_NAME,makeAny(_pFieldDesc->GetName())); 636 _rxColumn->setPropertyValue(PROPERTY_TYPENAME,makeAny(_pFieldDesc->getTypeInfo()->aTypeName)); 637 _rxColumn->setPropertyValue(PROPERTY_TYPE,makeAny(_pFieldDesc->GetType())); 638 _rxColumn->setPropertyValue(PROPERTY_PRECISION,makeAny(_pFieldDesc->GetPrecision())); 639 _rxColumn->setPropertyValue(PROPERTY_SCALE,makeAny(_pFieldDesc->GetScale())); 640 _rxColumn->setPropertyValue(PROPERTY_ISNULLABLE, makeAny(_pFieldDesc->GetIsNullable())); 641 _rxColumn->setPropertyValue(PROPERTY_ISAUTOINCREMENT, css::uno::makeAny(_pFieldDesc->IsAutoIncrement())); 642 _rxColumn->setPropertyValue(PROPERTY_DESCRIPTION,makeAny(_pFieldDesc->GetDescription())); 643 if ( _rxColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_ISCURRENCY) && _pFieldDesc->IsCurrency() ) 644 _rxColumn->setPropertyValue(PROPERTY_ISCURRENCY, css::uno::makeAny(_pFieldDesc->IsCurrency())); 645 // set autoincrement value when available 646 // and only set when the entry is not empty, that lets the value in the column untouched 647 if ( _pFieldDesc->IsAutoIncrement() && !_pFieldDesc->GetAutoIncrementValue().isEmpty() && _rxColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_AUTOINCREMENTCREATION) ) 648 _rxColumn->setPropertyValue(PROPERTY_AUTOINCREMENTCREATION,makeAny(_pFieldDesc->GetAutoIncrementValue())); 649 } 650 651 OUString createDefaultName(const Reference< XDatabaseMetaData>& _xMetaData,const Reference<XNameAccess>& _xTables,const OUString& _sName) 652 { 653 OSL_ENSURE(_xMetaData.is(),"No MetaData!"); 654 OUString sDefaultName = _sName; 655 try 656 { 657 OUString sCatalog,sSchema,sCompsedName; 658 if(_xMetaData->supportsCatalogsInTableDefinitions()) 659 { 660 try 661 { 662 Reference< XConnection> xCon = _xMetaData->getConnection(); 663 if ( xCon.is() ) 664 sCatalog = xCon->getCatalog(); 665 if ( sCatalog.isEmpty() ) 666 { 667 Reference<XResultSet> xRes = _xMetaData->getCatalogs(); 668 Reference<XRow> xRow(xRes,UNO_QUERY); 669 while(xRes.is() && xRes->next()) 670 { 671 sCatalog = xRow->getString(1); 672 if(!xRow->wasNull()) 673 break; 674 } 675 } 676 } 677 catch(const SQLException&) 678 { 679 } 680 } 681 if(_xMetaData->supportsSchemasInTableDefinitions()) 682 { 683 sSchema = _xMetaData->getUserName(); 684 } 685 sCompsedName = ::dbtools::composeTableName( _xMetaData, sCatalog, sSchema, _sName, false, ::dbtools::EComposeRule::InDataManipulation ); 686 sDefaultName = ::dbtools::createUniqueName(_xTables,sCompsedName); 687 } 688 catch(const SQLException&) 689 { 690 } 691 return sDefaultName; 692 } 693 694 bool checkDataSourceAvailable(const OUString& _sDataSourceName,const Reference< css::uno::XComponentContext >& _xContext) 695 { 696 Reference< XDatabaseContext > xDataBaseContext = DatabaseContext::create(_xContext); 697 bool bRet = xDataBaseContext->hasByName(_sDataSourceName); 698 if ( !bRet ) 699 { // try if this one is a URL 700 try 701 { 702 bRet = xDataBaseContext->getByName(_sDataSourceName).hasValue(); 703 } 704 catch(const Exception&) 705 { 706 } 707 } 708 return bRet; 709 } 710 711 sal_Int32 mapTextAllign(const SvxCellHorJustify& _eAlignment) 712 { 713 sal_Int32 nAlignment = css::awt::TextAlign::LEFT; 714 switch (_eAlignment) 715 { 716 case SvxCellHorJustify::Standard: 717 case SvxCellHorJustify::Left: nAlignment = css::awt::TextAlign::LEFT; break; 718 case SvxCellHorJustify::Center: nAlignment = css::awt::TextAlign::CENTER; break; 719 case SvxCellHorJustify::Right: nAlignment = css::awt::TextAlign::RIGHT; break; 720 default: 721 SAL_WARN("dbaccess.ui", "Invalid TextAlign!"); 722 } 723 return nAlignment; 724 } 725 726 SvxCellHorJustify mapTextJustify(sal_Int32 _nAlignment) 727 { 728 SvxCellHorJustify eJustify = SvxCellHorJustify::Left; 729 switch (_nAlignment) 730 { 731 case css::awt::TextAlign::LEFT : eJustify = SvxCellHorJustify::Left; break; 732 case css::awt::TextAlign::CENTER : eJustify = SvxCellHorJustify::Center; break; 733 case css::awt::TextAlign::RIGHT : eJustify = SvxCellHorJustify::Right; break; 734 default: 735 SAL_WARN("dbaccess.ui", "Invalid TextAlign!"); 736 } 737 return eJustify; 738 } 739 740 void callColumnFormatDialog(const Reference<XPropertySet>& xAffectedCol, 741 const Reference<XPropertySet>& xField, 742 SvNumberFormatter* _pFormatter, 743 const vcl::Window* _pParent) 744 { 745 if (xAffectedCol.is() && xField.is()) 746 { 747 try 748 { 749 Reference< XPropertySetInfo > xInfo = xAffectedCol->getPropertySetInfo(); 750 bool bHasFormat = xInfo->hasPropertyByName(PROPERTY_FORMATKEY); 751 sal_Int32 nDataType = ::comphelper::getINT32(xField->getPropertyValue(PROPERTY_TYPE)); 752 753 SvxCellHorJustify eJustify(SvxCellHorJustify::Standard); 754 Any aAlignment = xAffectedCol->getPropertyValue(PROPERTY_ALIGN); 755 if (aAlignment.hasValue()) 756 eJustify = dbaui::mapTextJustify(::comphelper::getINT16(aAlignment)); 757 sal_Int32 nFormatKey = 0; 758 if ( bHasFormat ) 759 nFormatKey = ::comphelper::getINT32(xAffectedCol->getPropertyValue(PROPERTY_FORMATKEY)); 760 761 if(callColumnFormatDialog(_pParent,_pFormatter,nDataType,nFormatKey,eJustify,bHasFormat)) 762 { 763 xAffectedCol->setPropertyValue(PROPERTY_ALIGN, makeAny(static_cast<sal_Int16>(dbaui::mapTextAllign(eJustify)))); 764 if (bHasFormat) 765 xAffectedCol->setPropertyValue(PROPERTY_FORMATKEY, makeAny(nFormatKey)); 766 767 } 768 } 769 catch( const Exception& ) 770 { 771 DBG_UNHANDLED_EXCEPTION("dbaccess"); 772 } 773 } 774 } 775 776 bool callColumnFormatDialog(const vcl::Window* _pParent, 777 SvNumberFormatter* _pFormatter, 778 sal_Int32 _nDataType, 779 sal_Int32& _nFormatKey, 780 SvxCellHorJustify& _eJustify, 781 bool _bHasFormat) 782 { 783 bool bRet = false; 784 785 // UNO->ItemSet 786 static SfxItemInfo aItemInfos[] = 787 { 788 { 0, false }, 789 { SID_ATTR_NUMBERFORMAT_VALUE, true }, 790 { SID_ATTR_ALIGN_HOR_JUSTIFY, true }, 791 { SID_ATTR_NUMBERFORMAT_ONE_AREA, true }, 792 { SID_ATTR_NUMBERFORMAT_INFO, true } 793 }; 794 static const sal_uInt16 aAttrMap[] = 795 { 796 SBA_DEF_RANGEFORMAT, SBA_ATTR_ALIGN_HOR_JUSTIFY, 797 SID_ATTR_NUMBERFORMAT_ONE_AREA, SID_ATTR_NUMBERFORMAT_ONE_AREA, 798 SID_ATTR_NUMBERFORMAT_INFO, SID_ATTR_NUMBERFORMAT_INFO, 799 0 800 }; 801 802 std::vector<SfxPoolItem*> pDefaults 803 { 804 new SfxRangeItem(SBA_DEF_RANGEFORMAT, SBA_DEF_FMTVALUE, SBA_ATTR_ALIGN_HOR_JUSTIFY), 805 new SfxUInt32Item(SBA_DEF_FMTVALUE), 806 new SvxHorJustifyItem(SvxCellHorJustify::Standard, SBA_ATTR_ALIGN_HOR_JUSTIFY), 807 new SfxBoolItem(SID_ATTR_NUMBERFORMAT_ONE_AREA, false), 808 new SvxNumberInfoItem(SID_ATTR_NUMBERFORMAT_INFO) 809 }; 810 811 SfxItemPool* pPool = new SfxItemPool("GridBrowserProperties", SBA_DEF_RANGEFORMAT, SBA_ATTR_ALIGN_HOR_JUSTIFY, aItemInfos, &pDefaults); 812 pPool->SetDefaultMetric( MapUnit::MapTwip ); // ripped, don't understand why 813 pPool->FreezeIdRanges(); // the same 814 815 std::unique_ptr<SfxItemSet> pFormatDescriptor(new SfxItemSet(*pPool, aAttrMap)); 816 // fill it 817 pFormatDescriptor->Put(SvxHorJustifyItem(_eJustify, SBA_ATTR_ALIGN_HOR_JUSTIFY)); 818 bool bText = false; 819 if (_bHasFormat) 820 { 821 // if the col is bound to a text field we have to disallow all non-text formats 822 if ((DataType::CHAR == _nDataType) || (DataType::VARCHAR == _nDataType) || (DataType::LONGVARCHAR == _nDataType) || (DataType::CLOB == _nDataType)) 823 { 824 bText = true; 825 pFormatDescriptor->Put(SfxBoolItem(SID_ATTR_NUMBERFORMAT_ONE_AREA, true)); 826 if (!_pFormatter->IsTextFormat(_nFormatKey)) 827 // text fields can only have text formats 828 _nFormatKey = _pFormatter->GetStandardFormat(SvNumFormatType::TEXT,_pParent->GetSettings().GetLanguageTag().getLanguageType()); 829 } 830 831 pFormatDescriptor->Put(SfxUInt32Item(SBA_DEF_FMTVALUE, _nFormatKey)); 832 } 833 834 if (!bText) 835 { 836 SvxNumberInfoItem aFormatter(_pFormatter, 1234.56789, SID_ATTR_NUMBERFORMAT_INFO); 837 pFormatDescriptor->Put(aFormatter); 838 } 839 840 { // want the dialog to be destroyed before our set 841 SbaSbAttrDlg aDlg(_pParent->GetFrameWeld(), pFormatDescriptor.get(), _pFormatter, _bHasFormat); 842 if (RET_OK == aDlg.run()) 843 { 844 // ItemSet->UNO 845 // UNO-properties 846 const SfxItemSet* pSet = aDlg.GetExampleSet(); 847 // (of course we could put the modified items directly into the column, but then the UNO-model 848 // won't reflect these changes, and why do we have a model, then ?) 849 850 // horizontal justify 851 const SvxHorJustifyItem* pHorJustify = pSet->GetItem<SvxHorJustifyItem>(SBA_ATTR_ALIGN_HOR_JUSTIFY); 852 853 _eJustify = pHorJustify->GetValue(); 854 855 // format key 856 if (_bHasFormat) 857 { 858 const SfxUInt32Item* pFormat = pSet->GetItem<SfxUInt32Item>(SBA_DEF_FMTVALUE); 859 _nFormatKey = static_cast<sal_Int32>(pFormat->GetValue()); 860 } 861 bRet = true; 862 } 863 // deleted formats 864 const SfxItemSet* pResult = aDlg.GetOutputItemSet(); 865 if (pResult) 866 { 867 const SfxPoolItem* pItem = pResult->GetItem( SID_ATTR_NUMBERFORMAT_INFO ); 868 const SvxNumberInfoItem* pInfoItem = static_cast<const SvxNumberInfoItem*>(pItem); 869 if (pInfoItem) 870 { 871 for (sal_uInt32 key : pInfoItem->GetDelFormats()) 872 _pFormatter->DeleteEntry(key); 873 } 874 } 875 } 876 877 pFormatDescriptor.reset(); 878 SfxItemPool::Free(pPool); 879 for (SfxPoolItem* pDefault : pDefaults) 880 delete pDefault; 881 882 return bRet; 883 } 884 885 std::shared_ptr<const SfxFilter> getStandardDatabaseFilter() 886 { 887 std::shared_ptr<const SfxFilter> pFilter = SfxFilter::GetFilterByName("StarOffice XML (Base)"); 888 OSL_ENSURE(pFilter,"Filter: StarOffice XML (Base) could not be found!"); 889 return pFilter; 890 } 891 892 bool appendToFilter(const Reference<XConnection>& _xConnection, 893 const OUString& _sName, 894 const Reference< XComponentContext >& _rxContext, 895 weld::Window* pParent) 896 { 897 bool bRet = false; 898 Reference< XChild> xChild(_xConnection,UNO_QUERY); 899 if(xChild.is()) 900 { 901 Reference< XPropertySet> xProp(xChild->getParent(),UNO_QUERY); 902 if(xProp.is()) 903 { 904 Sequence< OUString > aFilter; 905 xProp->getPropertyValue(PROPERTY_TABLEFILTER) >>= aFilter; 906 // first check if we have something like SCHEMA.% 907 bool bHasToInsert = true; 908 for (const OUString& rItem : std::as_const(aFilter)) 909 { 910 if(rItem.indexOf('%') != -1) 911 { 912 sal_Int32 nLen; 913 if((nLen = rItem.lastIndexOf('.')) != -1 && !rItem.compareTo(_sName,nLen)) 914 bHasToInsert = false; 915 else if(rItem.getLength() == 1) 916 bHasToInsert = false; 917 } 918 } 919 920 bRet = true; 921 if(bHasToInsert) 922 { 923 if(! ::dbaui::checkDataSourceAvailable(::comphelper::getString(xProp->getPropertyValue(PROPERTY_NAME)),_rxContext)) 924 { 925 OUString aMessage(DBA_RES(STR_TABLEDESIGN_DATASOURCE_DELETED)); 926 OSQLWarningBox aWarning(pParent, aMessage); 927 aWarning.run(); 928 bRet = false; 929 } 930 else 931 { 932 aFilter.realloc(aFilter.getLength()+1); 933 aFilter.getArray()[aFilter.getLength()-1] = _sName; 934 xProp->setPropertyValue(PROPERTY_TABLEFILTER,makeAny(aFilter)); 935 } 936 } 937 } 938 } 939 return bRet; 940 } 941 942 void notifySystemWindow(vcl::Window const * _pWindow, vcl::Window* _pToRegister, const ::comphelper::mem_fun1_t<TaskPaneList,vcl::Window*>& _rMemFunc) 943 { 944 OSL_ENSURE(_pWindow,"Window can not be null!"); 945 SystemWindow* pSystemWindow = _pWindow ? _pWindow->GetSystemWindow() : nullptr; 946 if ( pSystemWindow ) 947 { 948 _rMemFunc( pSystemWindow->GetTaskPaneList(), _pToRegister ); 949 } 950 } 951 952 void adjustBrowseBoxColumnWidth( ::svt::EditBrowseBox* _pBox, sal_uInt16 _nColId ) 953 { 954 sal_Int32 nColSize = -1; 955 sal_uInt32 nDefaultWidth = _pBox->GetDefaultColumnWidth( _pBox->GetColumnTitle( _nColId ) ); 956 if ( nDefaultWidth != _pBox->GetColumnWidth( _nColId ) ) 957 { 958 Size aSizeMM = _pBox->PixelToLogic( Size( _pBox->GetColumnWidth( _nColId ), 0 ), MapMode( MapUnit::MapMM ) ); 959 nColSize = aSizeMM.Width() * 10; 960 } 961 962 Size aDefaultMM = _pBox->PixelToLogic( Size( nDefaultWidth, 0 ), MapMode( MapUnit::MapMM ) ); 963 964 DlgSize aColumnSizeDlg(_pBox->GetFrameWeld(), nColSize, false, aDefaultMM.Width() * 10); 965 if (aColumnSizeDlg.run() == RET_OK) 966 { 967 sal_Int32 nValue = aColumnSizeDlg.GetValue(); 968 if ( -1 == nValue ) 969 { // default width 970 nValue = _pBox->GetDefaultColumnWidth( _pBox->GetColumnTitle( _nColId ) ); 971 } 972 else 973 { 974 Size aSizeMM( nValue / 10, 0 ); 975 nValue = _pBox->LogicToPixel( aSizeMM, MapMode( MapUnit::MapMM ) ).Width(); 976 } 977 _pBox->SetColumnWidth( _nColId, nValue ); 978 } 979 } 980 981 // check if SQL92 name checking is enabled 982 bool isSQL92CheckEnabled(const Reference<XConnection>& _xConnection) 983 { 984 return ::dbtools::getBooleanDataSourceSetting( _xConnection, PROPERTY_ENABLESQL92CHECK ); 985 } 986 987 bool isAppendTableAliasEnabled(const Reference<XConnection>& _xConnection) 988 { 989 return ::dbtools::getBooleanDataSourceSetting( _xConnection, INFO_APPEND_TABLE_ALIAS ); 990 } 991 992 bool generateAsBeforeTableAlias(const Reference<XConnection>& _xConnection) 993 { 994 return ::dbtools::getBooleanDataSourceSetting( _xConnection, INFO_AS_BEFORE_CORRELATION_NAME ); 995 } 996 997 void fillAutoIncrementValue(const Reference<XPropertySet>& _xDatasource, 998 bool& _rAutoIncrementValueEnabled, 999 OUString& _rsAutoIncrementValue) 1000 { 1001 if ( _xDatasource.is() ) 1002 { 1003 OSL_ENSURE(_xDatasource->getPropertySetInfo()->hasPropertyByName(PROPERTY_INFO),"NO datasource supplied!"); 1004 Sequence<PropertyValue> aInfo; 1005 _xDatasource->getPropertyValue(PROPERTY_INFO) >>= aInfo; 1006 1007 // search the right propertyvalue 1008 const PropertyValue* pValue =std::find_if(aInfo.begin(), aInfo.end(), 1009 [](const PropertyValue& lhs) 1010 {return lhs.Name == PROPERTY_AUTOINCREMENTCREATION;} ); 1011 1012 if ( pValue != aInfo.end() ) 1013 pValue->Value >>= _rsAutoIncrementValue; 1014 pValue =std::find_if(aInfo.begin(), aInfo.end(), 1015 [](const PropertyValue& lhs) 1016 {return lhs.Name == "IsAutoRetrievingEnabled";} ); 1017 1018 if ( pValue != aInfo.end() ) 1019 pValue->Value >>= _rAutoIncrementValueEnabled; 1020 } 1021 } 1022 1023 void fillAutoIncrementValue(const Reference<XConnection>& _xConnection, 1024 bool& _rAutoIncrementValueEnabled, 1025 OUString& _rsAutoIncrementValue) 1026 { 1027 Reference< XChild> xChild(_xConnection,UNO_QUERY); 1028 if(xChild.is()) 1029 { 1030 Reference< XPropertySet> xProp(xChild->getParent(),UNO_QUERY); 1031 fillAutoIncrementValue(xProp,_rAutoIncrementValueEnabled,_rsAutoIncrementValue); 1032 } 1033 } 1034 1035 OUString getStrippedDatabaseName(const Reference<XPropertySet>& _xDataSource,OUString& _rsDatabaseName) 1036 { 1037 if ( _rsDatabaseName.isEmpty() && _xDataSource.is() ) 1038 { 1039 try 1040 { 1041 _xDataSource->getPropertyValue(PROPERTY_NAME) >>= _rsDatabaseName; 1042 } 1043 catch(const Exception& ) 1044 { 1045 DBG_UNHANDLED_EXCEPTION("dbaccess"); 1046 } 1047 } 1048 OUString sName = _rsDatabaseName; 1049 INetURLObject aURL(sName); 1050 if ( aURL.GetProtocol() != INetProtocol::NotValid ) 1051 sName = aURL.getBase(INetURLObject::LAST_SEGMENT,true,INetURLObject::DecodeMechanism::Unambiguous); 1052 return sName; 1053 } 1054 1055 void setEvalDateFormatForFormatter(Reference< css::util::XNumberFormatter > const & _rxFormatter) 1056 { 1057 OSL_ENSURE( _rxFormatter.is(),"setEvalDateFormatForFormatter: Formatter is NULL!"); 1058 if ( _rxFormatter.is() ) 1059 { 1060 Reference< css::util::XNumberFormatsSupplier > xSupplier = _rxFormatter->getNumberFormatsSupplier(); 1061 1062 auto pSupplierImpl = comphelper::getUnoTunnelImplementation<SvNumberFormatsSupplierObj>(xSupplier); 1063 OSL_ENSURE(pSupplierImpl,"No Supplier!"); 1064 1065 if ( pSupplierImpl ) 1066 { 1067 SvNumberFormatter* pFormatter = pSupplierImpl->GetNumberFormatter(); 1068 pFormatter->SetEvalDateFormat(NF_EVALDATEFORMAT_FORMAT); 1069 } 1070 } 1071 } 1072 1073 TOTypeInfoSP queryPrimaryKeyType(const OTypeInfoMap& _rTypeInfo) 1074 { 1075 TOTypeInfoSP pTypeInfo; 1076 // first we search for a type which supports autoIncrement 1077 for (auto const& elem : _rTypeInfo) 1078 { 1079 // OJ: we don't want to set an autoincrement column to be key 1080 // because we don't have the possibility to know how to create 1081 // such auto increment column later on 1082 // so until we know how to do it, we create a column without autoincrement 1083 // therefore we have searched 1084 if ( elem.second->nType == DataType::INTEGER ) 1085 { 1086 pTypeInfo = elem.second; // alternative 1087 break; 1088 } 1089 else if ( !pTypeInfo.get() && elem.second->nType == DataType::DOUBLE ) 1090 pTypeInfo = elem.second; // alternative 1091 else if ( !pTypeInfo.get() && elem.second->nType == DataType::REAL ) 1092 pTypeInfo = elem.second; // alternative 1093 } 1094 if ( !pTypeInfo.get() ) // just a fallback 1095 pTypeInfo = queryTypeInfoByType(DataType::VARCHAR,_rTypeInfo); 1096 1097 OSL_ENSURE(pTypeInfo.get(),"checkColumns: can't find a type which is usable as a key!"); 1098 return pTypeInfo; 1099 } 1100 1101 TOTypeInfoSP queryTypeInfoByType(sal_Int32 _nDataType,const OTypeInfoMap& _rTypeInfo) 1102 { 1103 OTypeInfoMap::const_iterator aIter = _rTypeInfo.find(_nDataType); 1104 if(aIter != _rTypeInfo.end()) 1105 return aIter->second; 1106 // fall back if the type is unknown 1107 TOTypeInfoSP pTypeInfo; 1108 switch(_nDataType) 1109 { 1110 case DataType::TINYINT: 1111 if( (pTypeInfo = queryTypeInfoByType(DataType::SMALLINT,_rTypeInfo) ) ) 1112 break; 1113 [[fallthrough]]; 1114 case DataType::SMALLINT: 1115 if( (pTypeInfo = queryTypeInfoByType(DataType::INTEGER,_rTypeInfo) ) ) 1116 break; 1117 [[fallthrough]]; 1118 case DataType::INTEGER: 1119 if( (pTypeInfo = queryTypeInfoByType(DataType::FLOAT,_rTypeInfo) ) ) 1120 break; 1121 [[fallthrough]]; 1122 case DataType::FLOAT: 1123 if( (pTypeInfo = queryTypeInfoByType(DataType::REAL,_rTypeInfo) ) ) 1124 break; 1125 [[fallthrough]]; 1126 case DataType::DATE: 1127 case DataType::TIME: 1128 if( DataType::DATE == _nDataType || DataType::TIME == _nDataType ) 1129 { 1130 if( (pTypeInfo = queryTypeInfoByType(DataType::TIMESTAMP,_rTypeInfo) ) ) 1131 break; 1132 } 1133 [[fallthrough]]; 1134 case DataType::TIMESTAMP: 1135 case DataType::REAL: 1136 case DataType::BIGINT: 1137 if ( (pTypeInfo = queryTypeInfoByType(DataType::DOUBLE,_rTypeInfo) ) ) 1138 break; 1139 [[fallthrough]]; 1140 case DataType::DOUBLE: 1141 if ( (pTypeInfo = queryTypeInfoByType(DataType::NUMERIC,_rTypeInfo) ) ) 1142 break; 1143 [[fallthrough]]; 1144 case DataType::NUMERIC: 1145 pTypeInfo = queryTypeInfoByType(DataType::DECIMAL,_rTypeInfo); 1146 break; 1147 case DataType::DECIMAL: 1148 if ( (pTypeInfo = queryTypeInfoByType(DataType::NUMERIC,_rTypeInfo) ) ) 1149 break; 1150 if ( (pTypeInfo = queryTypeInfoByType(DataType::DOUBLE,_rTypeInfo) ) ) 1151 break; 1152 break; 1153 case DataType::VARCHAR: 1154 if ( (pTypeInfo = queryTypeInfoByType(DataType::LONGVARCHAR,_rTypeInfo) ) ) 1155 break; 1156 break; 1157 case DataType::LONGVARCHAR: 1158 if ( (pTypeInfo = queryTypeInfoByType(DataType::CLOB,_rTypeInfo) ) ) 1159 break; 1160 break; 1161 default: 1162 ; 1163 } 1164 if ( !pTypeInfo ) 1165 { 1166 bool bForce = true; 1167 pTypeInfo = ::dbaui::getTypeInfoFromType(_rTypeInfo,DataType::VARCHAR,OUString(),"x",50,0,false,bForce); 1168 } 1169 OSL_ENSURE(pTypeInfo,"Wrong DataType supplied!"); 1170 return pTypeInfo; 1171 } 1172 1173 sal_Int32 askForUserAction(weld::Window* pParent, const char* pTitle, const char* pText, bool _bAll, const OUString& _sName) 1174 { 1175 SolarMutexGuard aGuard; 1176 OUString aMsg = DBA_RES(pText); 1177 aMsg = aMsg.replaceFirst("%1", _sName); 1178 OSQLMessageBox aAsk(pParent, DBA_RES(pTitle), aMsg, MessBoxStyle::YesNo | MessBoxStyle::DefaultYes, MessageType::Query); 1179 if ( _bAll ) 1180 { 1181 aAsk.add_button(DBA_RES(STR_BUTTON_TEXT_ALL), RET_ALL, HID_CONFIRM_DROP_BUTTON_ALL); 1182 } 1183 return aAsk.run(); 1184 } 1185 1186 namespace 1187 { 1188 OUString lcl_createSDBCLevelStatement( const OUString& _rStatement, const Reference< XConnection >& _rxConnection ) 1189 { 1190 OUString sSDBCLevelStatement( _rStatement ); 1191 try 1192 { 1193 Reference< XMultiServiceFactory > xAnalyzerFactory( _rxConnection, UNO_QUERY_THROW ); 1194 Reference< XSingleSelectQueryAnalyzer > xAnalyzer( xAnalyzerFactory->createInstance( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER ), UNO_QUERY_THROW ); 1195 xAnalyzer->setQuery( _rStatement ); 1196 sSDBCLevelStatement = xAnalyzer->getQueryWithSubstitution(); 1197 } 1198 catch( const Exception& ) 1199 { 1200 DBG_UNHANDLED_EXCEPTION("dbaccess"); 1201 } 1202 return sSDBCLevelStatement; 1203 } 1204 } 1205 1206 Reference< XPropertySet > createView( const OUString& _rName, const Reference< XConnection >& _rxConnection, 1207 const OUString& _rCommand ) 1208 { 1209 Reference<XViewsSupplier> xSup(_rxConnection,UNO_QUERY); 1210 Reference< XNameAccess > xViews; 1211 if(xSup.is()) 1212 xViews = xSup->getViews(); 1213 Reference<XDataDescriptorFactory> xFact(xViews,UNO_QUERY); 1214 OSL_ENSURE(xFact.is(),"No XDataDescriptorFactory available!"); 1215 if(!xFact.is()) 1216 return nullptr; 1217 1218 Reference<XPropertySet> xView = xFact->createDataDescriptor(); 1219 if ( !xView.is() ) 1220 return nullptr; 1221 1222 OUString sCatalog,sSchema,sTable; 1223 ::dbtools::qualifiedNameComponents(_rxConnection->getMetaData(), 1224 _rName, 1225 sCatalog, 1226 sSchema, 1227 sTable, 1228 ::dbtools::EComposeRule::InDataManipulation); 1229 1230 xView->setPropertyValue(PROPERTY_CATALOGNAME,makeAny(sCatalog)); 1231 xView->setPropertyValue(PROPERTY_SCHEMANAME,makeAny(sSchema)); 1232 xView->setPropertyValue(PROPERTY_NAME,makeAny(sTable)); 1233 1234 xView->setPropertyValue( PROPERTY_COMMAND, makeAny( _rCommand ) ); 1235 1236 Reference<XAppend> xAppend(xViews,UNO_QUERY); 1237 if(xAppend.is()) 1238 xAppend->appendByDescriptor(xView); 1239 1240 xView = nullptr; 1241 // we need to reget the view because after appending it, it is no longer valid 1242 // but this time it isn't a view object it is a table object with type "VIEW" 1243 Reference<XTablesSupplier> xTabSup(_rxConnection,UNO_QUERY); 1244 Reference< XNameAccess > xTables; 1245 if ( xTabSup.is() ) 1246 { 1247 xTables = xTabSup->getTables(); 1248 if ( xTables.is() && xTables->hasByName( _rName ) ) 1249 xTables->getByName( _rName ) >>= xView; 1250 } 1251 1252 return xView; 1253 } 1254 1255 Reference<XPropertySet> createView( const OUString& _rName, const Reference< XConnection >& _rxConnection 1256 ,const Reference<XPropertySet>& _rxSourceObject) 1257 { 1258 OUString sCommand; 1259 Reference< XPropertySetInfo > xPSI( _rxSourceObject->getPropertySetInfo(), UNO_SET_THROW ); 1260 if ( xPSI->hasPropertyByName( PROPERTY_COMMAND ) ) 1261 { 1262 _rxSourceObject->getPropertyValue( PROPERTY_COMMAND ) >>= sCommand; 1263 1264 bool bEscapeProcessing( false ); 1265 OSL_VERIFY( _rxSourceObject->getPropertyValue( PROPERTY_ESCAPE_PROCESSING ) >>= bEscapeProcessing ); 1266 if ( bEscapeProcessing ) 1267 sCommand = lcl_createSDBCLevelStatement( sCommand, _rxConnection ); 1268 } 1269 else 1270 { 1271 sCommand = "SELECT * FROM " + composeTableNameForSelect( _rxConnection, _rxSourceObject ); 1272 } 1273 return createView( _rName, _rxConnection, sCommand ); 1274 } 1275 1276 bool insertHierachyElement(weld::Window* pParent, const Reference< XComponentContext >& _rxContext, 1277 const Reference<XHierarchicalNameContainer>& _xNames, 1278 const OUString& _sParentFolder, 1279 bool _bForm, 1280 bool _bCollection, 1281 const Reference<XContent>& _xContent, 1282 bool _bMove) 1283 { 1284 OSL_ENSURE( _xNames.is(), "insertHierachyElement: illegal name container!" ); 1285 if ( !_xNames.is() ) 1286 return false; 1287 1288 Reference<XNameAccess> xNameAccess( _xNames, UNO_QUERY ); 1289 if ( _xNames->hasByHierarchicalName(_sParentFolder) ) 1290 { 1291 Reference<XChild> xChild(_xNames->getByHierarchicalName(_sParentFolder),UNO_QUERY); 1292 xNameAccess.set(xChild,UNO_QUERY); 1293 if ( !xNameAccess.is() && xChild.is() ) 1294 xNameAccess.set(xChild->getParent(),UNO_QUERY); 1295 } 1296 1297 OSL_ENSURE( xNameAccess.is(), "insertHierachyElement: could not find the proper name container!" ); 1298 if ( !xNameAccess.is() ) 1299 return false; 1300 1301 OUString sNewName; 1302 Reference<XPropertySet> xProp(_xContent,UNO_QUERY); 1303 if ( xProp.is() ) 1304 xProp->getPropertyValue(PROPERTY_NAME) >>= sNewName; 1305 1306 if ( !_bMove || sNewName.isEmpty() ) 1307 { 1308 OUString sTargetName,sLabel; 1309 if ( sNewName.isEmpty() || xNameAccess->hasByName(sNewName) ) 1310 { 1311 if ( !sNewName.isEmpty() ) 1312 sTargetName = sNewName; 1313 else 1314 sTargetName = DBA_RES( _bCollection ? STR_NEW_FOLDER : ((_bForm) ? RID_STR_FORM : RID_STR_REPORT)); 1315 sLabel = DBA_RES( _bCollection ? STR_FOLDER_LABEL : ((_bForm) ? STR_FRM_LABEL : STR_RPT_LABEL)); 1316 sTargetName = ::dbtools::createUniqueName(xNameAccess,sTargetName); 1317 1318 // here we have everything needed to create a new query object ... 1319 HierarchicalNameCheck aNameChecker( _xNames.get(), _sParentFolder ); 1320 // ... ehm, except a new name 1321 OSaveAsDlg aAskForName(pParent, 1322 _rxContext, 1323 sTargetName, 1324 sLabel, 1325 aNameChecker, 1326 SADFlags::AdditionalDescription | SADFlags::TitlePasteAs); 1327 if ( RET_OK != aAskForName.run() ) 1328 // cancelled by the user 1329 return false; 1330 1331 sNewName = aAskForName.getName(); 1332 } 1333 } 1334 else if ( xNameAccess->hasByName(sNewName) ) 1335 { 1336 OUString sError(DBA_RES(STR_NAME_ALREADY_EXISTS)); 1337 sError = sError.replaceFirst("#",sNewName); 1338 throw SQLException(sError,nullptr,"S1000",0,Any()); 1339 } 1340 1341 try 1342 { 1343 Reference<XMultiServiceFactory> xORB( xNameAccess, UNO_QUERY_THROW ); 1344 uno::Sequence<uno::Any> aArguments(comphelper::InitAnyPropertySequence( 1345 { 1346 {"Name", uno::Any(sNewName)}, // set as folder 1347 {"Parent", uno::Any(xNameAccess)}, 1348 {PROPERTY_EMBEDDEDOBJECT, uno::Any(_xContent)}, 1349 })); 1350 OUString sServiceName(_bCollection ? (_bForm ? OUString(SERVICE_NAME_FORM_COLLECTION) : OUString(SERVICE_NAME_REPORT_COLLECTION)) : OUString(SERVICE_SDB_DOCUMENTDEFINITION)); 1351 1352 Reference<XContent > xNew( xORB->createInstanceWithArguments( sServiceName, aArguments ), UNO_QUERY_THROW ); 1353 Reference< XNameContainer > xNameContainer( xNameAccess, UNO_QUERY_THROW ); 1354 xNameContainer->insertByName( sNewName, makeAny( xNew ) ); 1355 } 1356 catch( const IllegalArgumentException& e ) 1357 { 1358 ::dbtools::throwGenericSQLException( e.Message, e.Context ); 1359 } 1360 catch( const Exception& ) 1361 { 1362 DBG_UNHANDLED_EXCEPTION("dbaccess"); 1363 return false; 1364 } 1365 1366 return true; 1367 } 1368 1369 Reference< XNumberFormatter > getNumberFormatter(const Reference< XConnection >& _rxConnection, const Reference< css::uno::XComponentContext >& _rxContext ) 1370 { 1371 // create a formatter working with the connections format supplier 1372 Reference< XNumberFormatter > xFormatter; 1373 1374 try 1375 { 1376 Reference< css::util::XNumberFormatsSupplier > xSupplier(::dbtools::getNumberFormats(_rxConnection, true, _rxContext)); 1377 1378 if ( xSupplier.is() ) 1379 { 1380 // create a new formatter 1381 xFormatter.set(util::NumberFormatter::create( _rxContext ), UNO_QUERY_THROW); 1382 xFormatter->attachNumberFormatsSupplier(xSupplier); 1383 } 1384 } 1385 catch(const Exception&) 1386 { 1387 DBG_UNHANDLED_EXCEPTION("dbaccess"); 1388 } 1389 return xFormatter; 1390 } 1391 1392 } // dbaui 1393 1394 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 1395
