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