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