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