1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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>
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!");
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!");
167 { // instantiate the default SDB interaction handler
168 Reference
< XInteractionHandler
> xHandler
= InteractionHandler::createWithParent(_rxContext
, nullptr);
169 _rOUTConnection
= xConnectionCompletion
->connectWithCompletion(xHandler
);
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");
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
;
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();
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() )
233 if ( aSQLError
.isValid() )
237 *_pErrorInfo
= aSQLError
;
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();
257 Reference
<XOfficeDatabaseDocument
> xOfficeDoc(_xObject
,UNO_QUERY
);
258 if ( xOfficeDoc
.is() )
259 xRet
= xOfficeDoc
->getDataSource();
265 TOTypeInfoSP
getTypeInfoFromType(const OTypeInfoMap
& _rTypeInfo
,
267 const OUString
& _sTypeName
,
268 const OUString
& _sCreateParams
,
269 sal_Int32 _nPrecision
,
271 bool _bAutoIncrement
,
272 bool& _brForceToType
)
274 TOTypeInfoSP pTypeInfo
;
275 _brForceToType
= false;
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
285 OUString sDBTypeName
= aIter
->second
->aTypeName
; (void)sDBTypeName
;
289 || (aIter
->second
->aTypeName
.equalsIgnoreAsciiCase(_sTypeName
))
293 !aIter
->second
->aCreateParams
.getLength()
294 && _sCreateParams
.isEmpty()
297 (aIter
->second
->nPrecision
>= _nPrecision
)
298 && (aIter
->second
->nMaximumScale
>= _nScale
)
299 && ( (_bAutoIncrement
&& aIter
->second
->bAutoIncrement
) || !_bAutoIncrement
)
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).");
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
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
)
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
)
357 if ( aIter
== aPair
.second
)
359 // try it without the auto increment flag
360 pTypeInfo
= getTypeInfoFromType(_rTypeInfo
,
370 pTypeInfo
= aIter
->second
;
374 pTypeInfo
= aPair
.first
->second
;
375 _brForceToType
= true;
379 pTypeInfo
= aIter
->second
;
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
;
395 OSL_ENSURE(pTypeInfo
, "getTypeInfoFromType: no type info found for this type!");
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())
406 Reference
< XResultSet
> xRs
= _rxConnection
->getMetaData ()->getTypeInfo ();
407 Reference
< XRow
> xRow(xRs
,UNO_QUERY
);
408 // Information for a single SQL type
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
419 TOTypeInfoSP pInfo
= std::make_shared
<OTypeInfo
>();
421 if ( aTypes
.empty() )
423 sal_Int32 nCount
= xResultSetMetaData
->getColumnCount();
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
;
439 aValue
.fill(nPos
,aTypes
[nPos
],aNullable
[nPos
],xRow
);
440 pInfo
->nType
= aValue
;
442 aValue
.fill(nPos
,aTypes
[nPos
],aNullable
[nPos
],xRow
);
443 pInfo
->nPrecision
= aValue
;
445 aValue
.fill(nPos
,aTypes
[nPos
],aNullable
[nPos
],xRow
); // LiteralPrefix
447 aValue
.fill(nPos
,aTypes
[nPos
],aNullable
[nPos
],xRow
); //LiteralSuffix
449 aValue
.fill(nPos
,aTypes
[nPos
],aNullable
[nPos
],xRow
);
450 pInfo
->aCreateParams
= aValue
;
452 aValue
.fill(nPos
,aTypes
[nPos
],aNullable
[nPos
],xRow
);
453 pInfo
->bNullable
= static_cast<sal_Int32
>(aValue
) == ColumnValue::NULLABLE
;
455 aValue
.fill(nPos
,aTypes
[nPos
],aNullable
[nPos
],xRow
);
458 aValue
.fill(nPos
,aTypes
[nPos
],aNullable
[nPos
],xRow
);
459 pInfo
->nSearchType
= aValue
;
461 aValue
.fill(nPos
,aTypes
[nPos
],aNullable
[nPos
],xRow
);
464 aValue
.fill(nPos
,aTypes
[nPos
],aNullable
[nPos
],xRow
);
465 pInfo
->bCurrency
= static_cast<bool>(aValue
);
467 aValue
.fill(nPos
,aTypes
[nPos
],aNullable
[nPos
],xRow
);
468 pInfo
->bAutoIncrement
= static_cast<bool>(aValue
);
470 aValue
.fill(nPos
,aTypes
[nPos
],aNullable
[nPos
],xRow
);
471 pInfo
->aLocalTypeName
= aValue
;
473 aValue
.fill(nPos
,aTypes
[nPos
],aNullable
[nPos
],xRow
);
474 pInfo
->nMinimumScale
= aValue
;
476 aValue
.fill(nPos
,aTypes
[nPos
],aNullable
[nPos
],xRow
);
477 pInfo
->nMaximumScale
= aValue
;
479 // 16 and 17 are unused
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;
498 aName
= _rsTypeNames
.getToken(TYPE_CHAR
, ';');
500 case DataType::VARCHAR
:
501 aName
= _rsTypeNames
.getToken(TYPE_TEXT
, ';');
503 case DataType::DECIMAL
:
504 aName
= _rsTypeNames
.getToken(TYPE_DECIMAL
, ';');
506 case DataType::NUMERIC
:
507 aName
= _rsTypeNames
.getToken(TYPE_NUMERIC
, ';');
509 case DataType::BIGINT
:
510 aName
= _rsTypeNames
.getToken(TYPE_BIGINT
, ';');
512 case DataType::FLOAT
:
513 aName
= _rsTypeNames
.getToken(TYPE_FLOAT
, ';');
515 case DataType::DOUBLE
:
516 aName
= _rsTypeNames
.getToken(TYPE_DOUBLE
, ';');
518 case DataType::LONGVARCHAR
:
519 aName
= _rsTypeNames
.getToken(TYPE_MEMO
, ';');
521 case DataType::LONGVARBINARY
:
522 aName
= _rsTypeNames
.getToken(TYPE_IMAGE
, ';');
525 aName
= _rsTypeNames
.getToken(TYPE_DATE
, ';');
528 aName
= _rsTypeNames
.getToken(TYPE_TIME
, ';');
530 case DataType::TIMESTAMP
:
531 aName
= _rsTypeNames
.getToken(TYPE_DATETIME
, ';');
534 if ( !pInfo
->aCreateParams
.isEmpty() )
536 aName
= _rsTypeNames
.getToken(TYPE_BIT
, ';');
540 case DataType::BOOLEAN
:
541 aName
= _rsTypeNames
.getToken(TYPE_BOOL
, ';');
543 case DataType::TINYINT
:
544 aName
= _rsTypeNames
.getToken(TYPE_TINYINT
, ';');
546 case DataType::SMALLINT
:
547 aName
= _rsTypeNames
.getToken(TYPE_SMALLINT
, ';');
549 case DataType::INTEGER
:
550 aName
= _rsTypeNames
.getToken(TYPE_INTEGER
, ';');
553 aName
= _rsTypeNames
.getToken(TYPE_REAL
, ';');
555 case DataType::BINARY
:
556 aName
= _rsTypeNames
.getToken(TYPE_BINARY
, ';');
558 case DataType::VARBINARY
:
559 aName
= _rsTypeNames
.getToken(TYPE_VARBINARY
, ';');
561 case DataType::SQLNULL
:
562 aName
= _rsTypeNames
.getToken(TYPE_SQLNULL
, ';');
564 case DataType::OBJECT
:
565 aName
= _rsTypeNames
.getToken(TYPE_OBJECT
, ';');
567 case DataType::DISTINCT
:
568 aName
= _rsTypeNames
.getToken(TYPE_DISTINCT
, ';');
570 case DataType::STRUCT
:
571 aName
= _rsTypeNames
.getToken(TYPE_STRUCT
, ';');
573 case DataType::ARRAY
:
574 aName
= _rsTypeNames
.getToken(TYPE_ARRAY
, ';');
577 aName
= _rsTypeNames
.getToken(TYPE_BLOB
, ';');
580 aName
= _rsTypeNames
.getToken(TYPE_CLOB
, ';');
583 aName
= _rsTypeNames
.getToken(TYPE_REF
, ';');
585 case DataType::OTHER
:
586 aName
= _rsTypeNames
.getToken(TYPE_OTHER
, ';');
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();
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);
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
&)
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
);
679 { // try if this one is a URL
682 bRet
= xDataBaseContext
->getByName(_sDataSourceName
).hasValue();
684 catch(const Exception
&)
691 sal_Int32
mapTextAllign(const SvxCellHorJustify
& _eAlignment
)
693 sal_Int32 nAlignment
= css::awt::TextAlign::LEFT
;
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;
701 SAL_WARN("dbaccess.ui", "Invalid TextAlign!");
706 SvxCellHorJustify
mapTextJustify(sal_Int32 _nAlignment
)
708 SvxCellHorJustify eJustify
= SvxCellHorJustify::Left
;
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;
715 SAL_WARN("dbaccess.ui", "Invalid TextAlign!");
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()))
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;
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
))));
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
,
766 static SfxItemInfo aItemInfos
[] =
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
));
797 pFormatDescriptor
->Put(SvxHorJustifyItem(_eJustify
, SBA_ATTR_ALIGN_HOR_JUSTIFY
));
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
))
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
));
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())
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();
838 const SfxUInt32Item
* pFormat
= pSet
->GetItem
<SfxUInt32Item
>(SBA_DEF_FMTVALUE
);
839 _nFormatKey
= static_cast<sal_Int32
>(pFormat
->GetValue());
844 const SfxItemSet
* pResult
= aDlg
.GetOutputItemSet();
847 const SfxPoolItem
* pItem
= pResult
->GetItem( SID_ATTR_NUMBERFORMAT_INFO
);
848 const SvxNumberInfoItem
* pInfoItem
= static_cast<const SvxNumberInfoItem
*>(pItem
);
851 for (sal_uInt32 key
: pInfoItem
->GetDelFormats())
852 _pFormatter
->DeleteEntry(key
);
857 pFormatDescriptor
.reset();
858 SfxItemPool::Free(pPool
);
859 for (SfxPoolItem
* pDefault
: pDefaults
)
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!");
872 bool appendToFilter(const Reference
<XConnection
>& _xConnection
,
873 const OUString
& _sName
,
874 const Reference
< XComponentContext
>& _rxContext
,
875 weld::Window
* pParent
)
878 Reference
< XChild
> xChild(_xConnection
,UNO_QUERY
);
881 Reference
< XPropertySet
> xProp(xChild
->getParent(),UNO_QUERY
);
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;
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
);
912 aFilter
.realloc(aFilter
.getLength()+1);
913 aFilter
.getArray()[aFilter
.getLength()-1] = _sName
;
914 xProp
->setPropertyValue(PROPERTY_TABLEFILTER
,makeAny(aFilter
));
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;
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
)
948 sal_Int32 nValue
= aColumnSizeDlg
.GetValue();
951 nValue
= _pBox
->GetDefaultColumnWidth( _pBox
->GetColumnTitle( _nColId
) );
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() )
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
);
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
);
1035 void setEvalDateFormatForFormatter(Reference
< css::util::XNumberFormatter
> const & _rxFormatter
)
1037 OSL_ENSURE( _rxFormatter
.is(),"setEvalDateFormatForFormatter: Formatter is NULL!");
1038 if ( !_rxFormatter
.is() )
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
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!");
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
;
1090 case DataType::TINYINT
:
1091 if( (pTypeInfo
= queryTypeInfoByType(DataType::SMALLINT
,_rTypeInfo
) ) )
1094 case DataType::SMALLINT
:
1095 if( (pTypeInfo
= queryTypeInfoByType(DataType::INTEGER
,_rTypeInfo
) ) )
1098 case DataType::INTEGER
:
1099 if( (pTypeInfo
= queryTypeInfoByType(DataType::FLOAT
,_rTypeInfo
) ) )
1102 case DataType::FLOAT
:
1103 if( (pTypeInfo
= queryTypeInfoByType(DataType::REAL
,_rTypeInfo
) ) )
1106 case DataType::DATE
:
1107 case DataType::TIME
:
1108 if( DataType::DATE
== _nDataType
|| DataType::TIME
== _nDataType
)
1110 if( (pTypeInfo
= queryTypeInfoByType(DataType::TIMESTAMP
,_rTypeInfo
) ) )
1114 case DataType::TIMESTAMP
:
1115 case DataType::REAL
:
1116 case DataType::BIGINT
:
1117 if ( (pTypeInfo
= queryTypeInfoByType(DataType::DOUBLE
,_rTypeInfo
) ) )
1120 case DataType::DOUBLE
:
1121 if ( (pTypeInfo
= queryTypeInfoByType(DataType::NUMERIC
,_rTypeInfo
) ) )
1124 case DataType::NUMERIC
:
1125 pTypeInfo
= queryTypeInfoByType(DataType::DECIMAL
,_rTypeInfo
);
1127 case DataType::DECIMAL
:
1128 if ( (pTypeInfo
= queryTypeInfoByType(DataType::NUMERIC
,_rTypeInfo
) ) )
1130 if ( (pTypeInfo
= queryTypeInfoByType(DataType::DOUBLE
,_rTypeInfo
) ) )
1133 case DataType::VARCHAR
:
1134 if ( (pTypeInfo
= queryTypeInfoByType(DataType::LONGVARCHAR
,_rTypeInfo
) ) )
1137 case DataType::LONGVARCHAR
:
1138 if ( (pTypeInfo
= queryTypeInfoByType(DataType::CLOB
,_rTypeInfo
) ) )
1147 pTypeInfo
= ::dbaui::getTypeInfoFromType(_rTypeInfo
,DataType::VARCHAR
,OUString(),"x",50,0,false,bForce
);
1149 OSL_ENSURE(pTypeInfo
,"Wrong DataType supplied!");
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
);
1161 aAsk
.add_button(DBA_RES(STR_BUTTON_TEXT_ALL
), RET_ALL
, HID_CONFIRM_DROP_BUTTON_ALL
);
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
;
1192 xViews
= xSup
->getViews();
1193 Reference
<XDataDescriptorFactory
> xFact(xViews
,UNO_QUERY
);
1194 OSL_ENSURE(xFact
.is(),"No XDataDescriptorFactory available!");
1198 Reference
<XPropertySet
> xView
= xFact
->createDataDescriptor();
1202 OUString sCatalog
,sSchema
,sTable
;
1203 ::dbtools::qualifiedNameComponents(_rxConnection
->getMetaData(),
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
);
1218 xAppend
->appendByDescriptor(xView
);
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
;
1227 xTables
= xTabSup
->getTables();
1228 if ( xTables
.is() && xTables
->hasByName( _rName
) )
1229 xTables
->getByName( _rName
) >>= xView
;
1235 Reference
<XPropertySet
> createView( const OUString
& _rName
, const Reference
< XConnection
>& _rxConnection
1236 ,const Reference
<XPropertySet
>& _rxSourceObject
)
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
);
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
,
1261 const Reference
<XContent
>& _xContent
,
1264 OSL_ENSURE( _xNames
.is(), "insertHierachyElement: illegal name container!" );
1265 if ( !_xNames
.is() )
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() )
1282 Reference
<XPropertySet
> xProp(_xContent
,UNO_QUERY
);
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
;
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
,
1306 SADFlags::AdditionalDescription
| SADFlags::TitlePasteAs
);
1307 if ( RET_OK
!= aAskForName
.run() )
1308 // cancelled by the user
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
)},
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");
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");
1374 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */