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 :
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 1168 : Reference< XModel> lcl_getXModel(const Reference< XInterface>& _xIface)
512 : {
513 1168 : Reference< XInterface > xParent = _xIface;
514 1168 : Reference< XModel > xModel(xParent,UNO_QUERY);;
515 3834 : while( xParent.is() && !xModel.is() )
516 : {
517 1498 : Reference<XChild> xChild(xParent,UNO_QUERY);
518 1498 : xParent.set(xChild.is() ? xChild->getParent() : Reference< XInterface >(),UNO_QUERY);
519 1498 : xModel.set(xParent,UNO_QUERY);
520 1498 : }
521 1168 : 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 1862 : bool getDataSourceSetting( const Reference< XInterface >& _xChild, const OUString& _sAsciiSettingsName,
601 : Any& /* [out] */ _rSettingsValue )
602 : {
603 1862 : bool bIsPresent = false;
604 : try
605 : {
606 1862 : const Reference< XPropertySet> xDataSourceProperties( findDataSource( _xChild ), UNO_QUERY );
607 1862 : if ( !xDataSourceProperties.is() )
608 0 : return false;
609 :
610 : const Reference< XPropertySet > xSettings(
611 1862 : xDataSourceProperties->getPropertyValue("Settings"),
612 : UNO_QUERY_THROW
613 3724 : );
614 :
615 1862 : _rSettingsValue = xSettings->getPropertyValue( _sAsciiSettingsName );
616 3724 : bIsPresent = true;
617 : }
618 0 : catch( const Exception& )
619 : {
620 0 : bIsPresent = false;
621 : }
622 1862 : return bIsPresent;
623 : }
624 :
625 1780 : bool getDataSourceSetting( const Reference< XInterface >& _rxDataSource, const sal_Char* _pAsciiSettingsName,
626 : Any& /* [out] */ _rSettingsValue )
627 : {
628 1780 : OUString sAsciiSettingsName = OUString::createFromAscii(_pAsciiSettingsName);
629 1780 : return getDataSourceSetting( _rxDataSource, sAsciiSettingsName,_rSettingsValue );
630 : }
631 :
632 116 : bool isDataSourcePropertyEnabled(const Reference<XInterface>& _xProp, const OUString& _sProperty, bool _bDefault)
633 : {
634 116 : bool bEnabled = _bDefault;
635 : try
636 : {
637 116 : Reference< XPropertySet> xProp(findDataSource(_xProp),UNO_QUERY);
638 116 : if ( xProp.is() )
639 : {
640 108 : Sequence< PropertyValue > aInfo;
641 108 : xProp->getPropertyValue("Info") >>= aInfo;
642 : const PropertyValue* pValue =::std::find_if(aInfo.getConstArray(),
643 108 : aInfo.getConstArray() + aInfo.getLength(),
644 216 : ::std::bind2nd(TPropertyValueEqualFunctor(),_sProperty));
645 108 : if ( pValue && pValue != (aInfo.getConstArray() + aInfo.getLength()) )
646 0 : pValue->Value >>= bEnabled;
647 116 : }
648 : }
649 0 : catch(SQLException&)
650 : {
651 : DBG_UNHANDLED_EXCEPTION();
652 : }
653 116 : return bEnabled;
654 : }
655 :
656 70 : Reference< XTablesSupplier> getDataDefinitionByURLAndConnection(
657 : const OUString& _rsUrl,
658 : const Reference< XConnection>& _xConnection,
659 : const Reference< XComponentContext >& _rxContext)
660 : {
661 70 : Reference< XTablesSupplier> xTablesSup;
662 : try
663 : {
664 70 : Reference< XDriverManager2 > xManager = DriverManager::create( _rxContext );
665 140 : Reference< XDataDefinitionSupplier > xSupp( xManager->getDriverByURL( _rsUrl ), UNO_QUERY );
666 :
667 70 : if ( xSupp.is() )
668 : {
669 70 : xTablesSup = xSupp->getDataDefinitionByConnection( _xConnection );
670 : OSL_ENSURE(xTablesSup.is(),"No table supplier!");
671 70 : }
672 : }
673 0 : catch( const Exception& )
674 : {
675 : DBG_UNHANDLED_EXCEPTION();
676 : }
677 70 : return xTablesSup;
678 : }
679 :
680 :
681 2 : 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 2 : sal_Int32 nPrivileges = 0;
688 : try
689 : {
690 2 : Any aVal;
691 2 : if(!_sCatalog.isEmpty())
692 0 : aVal <<= _sCatalog;
693 4 : Reference< XResultSet > xPrivileges = _xMetaData->getTablePrivileges(aVal, _sSchema, _sTable);
694 4 : Reference< XRow > xCurrentRow(xPrivileges, UNO_QUERY);
695 :
696 4 : const OUString sUserWorkingFor = _xMetaData->getUserName();
697 2 : static const OUString sSELECT( "SELECT" );
698 2 : static const OUString sINSERT( "INSERT" );
699 2 : static const OUString sUPDATE( "UPDATE" );
700 2 : static const OUString sDELETE( "DELETE" );
701 2 : static const OUString sREAD( "READ" );
702 2 : static const OUString sCREATE( "CREATE" );
703 2 : static const OUString sALTER( "ALTER" );
704 2 : static const OUString sREFERENCE( "REFERENCE" );
705 2 : static const OUString sDROP( "DROP" );
706 :
707 2 : if ( xCurrentRow.is() )
708 : {
709 : // after creation the set is positioned before the first record, per definition
710 4 : OUString sPrivilege, sGrantee;
711 22 : 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 18 : sGrantee = xCurrentRow->getString(5);
721 18 : sPrivilege = xCurrentRow->getString(6);
722 : #ifdef DBG_UTIL
723 : sGrantable = xCurrentRow->getString(7);
724 : #endif
725 :
726 18 : if (!sUserWorkingFor.equalsIgnoreAsciiCase(sGrantee))
727 0 : continue;
728 :
729 18 : if (sPrivilege.equalsIgnoreAsciiCase(sSELECT))
730 2 : nPrivileges |= Privilege::SELECT;
731 16 : else if (sPrivilege.equalsIgnoreAsciiCase(sINSERT))
732 2 : nPrivileges |= Privilege::INSERT;
733 14 : else if (sPrivilege.equalsIgnoreAsciiCase(sUPDATE))
734 2 : nPrivileges |= Privilege::UPDATE;
735 12 : else if (sPrivilege.equalsIgnoreAsciiCase(sDELETE))
736 2 : nPrivileges |= Privilege::DELETE;
737 10 : else if (sPrivilege.equalsIgnoreAsciiCase(sREAD))
738 2 : nPrivileges |= Privilege::READ;
739 8 : else if (sPrivilege.equalsIgnoreAsciiCase(sCREATE))
740 2 : nPrivileges |= Privilege::CREATE;
741 6 : else if (sPrivilege.equalsIgnoreAsciiCase(sALTER))
742 2 : nPrivileges |= Privilege::ALTER;
743 4 : else if (sPrivilege.equalsIgnoreAsciiCase(sREFERENCE))
744 2 : nPrivileges |= Privilege::REFERENCE;
745 2 : else if (sPrivilege.equalsIgnoreAsciiCase(sDROP))
746 2 : nPrivileges |= Privilege::DROP;
747 2 : }
748 : }
749 2 : 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 4 : Reference< XResultSet > xColumnPrivileges = _xMetaData->getColumnPrivileges(aVal, _sSchema, _sTable, OUString("%"));
755 4 : Reference< XRow > xColumnCurrentRow(xColumnPrivileges, UNO_QUERY);
756 2 : if ( xColumnCurrentRow.is() )
757 : {
758 : // after creation the set is positioned before the first record, per definition
759 4 : OUString sPrivilege, sGrantee;
760 4068 : 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 4064 : sGrantee = xColumnCurrentRow->getString(6);
771 4064 : sPrivilege = xColumnCurrentRow->getString(7);
772 : #ifdef DBG_UTIL
773 : sGrantable = xColumnCurrentRow->getString(8);
774 : #endif
775 :
776 4064 : if (!sUserWorkingFor.equalsIgnoreAsciiCase(sGrantee))
777 808 : continue;
778 :
779 3256 : if (sPrivilege.equalsIgnoreAsciiCase(sSELECT))
780 814 : nPrivileges |= Privilege::SELECT;
781 2442 : else if (sPrivilege.equalsIgnoreAsciiCase(sINSERT))
782 814 : nPrivileges |= Privilege::INSERT;
783 1628 : else if (sPrivilege.equalsIgnoreAsciiCase(sUPDATE))
784 814 : nPrivileges |= Privilege::UPDATE;
785 814 : else if (sPrivilege.equalsIgnoreAsciiCase(sDELETE))
786 814 : 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 2 : }
798 : }
799 4 : disposeComponent(xColumnPrivileges);
800 : }
801 0 : catch(const SQLException& e)
802 : {
803 0 : static OUString sNotSupportedState( "IM001" );
804 : // some drivers don't support any privileges so we assume that we are allowed to do all we want :-)
805 0 : if(e.SQLState == sNotSupportedState)
806 : nPrivileges |= Privilege::DROP |
807 : Privilege::REFERENCE |
808 : Privilege::ALTER |
809 : Privilege::CREATE |
810 : Privilege::READ |
811 : Privilege::DELETE |
812 : Privilege::UPDATE |
813 : Privilege::INSERT |
814 0 : Privilege::SELECT;
815 : else
816 : OSL_FAIL("Could not collect the privileges !");
817 : }
818 2 : return nPrivileges;
819 : }
820 :
821 : // we need some more information about the column
822 4 : void collectColumnInformation(const Reference< XConnection>& _xConnection,
823 : const OUString& _sComposedName,
824 : const OUString& _rName,
825 : ColumnInformationMap& _rInfo)
826 : {
827 8 : OUString sSelect = "SELECT " + _rName +
828 8 : " FROM " + _sComposedName +
829 4 : " WHERE 0 = 1";
830 :
831 : try
832 : {
833 4 : ::utl::SharedUNOComponent< XStatement > xStmt( _xConnection->createStatement() );
834 8 : Reference< XPropertySet > xStatementProps( xStmt, UNO_QUERY_THROW );
835 4 : xStatementProps->setPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_ESCAPEPROCESSING ), makeAny( false ) );
836 8 : Reference< XResultSet > xResult( xStmt->executeQuery( sSelect ), UNO_QUERY_THROW );
837 8 : Reference< XResultSetMetaDataSupplier > xSuppMeta( xResult, UNO_QUERY_THROW );
838 8 : Reference< XResultSetMetaData > xMeta( xSuppMeta->getMetaData(), UNO_QUERY_THROW );
839 :
840 4 : sal_Int32 nCount = xMeta->getColumnCount();
841 : OSL_ENSURE( nCount != 0, "::dbtools::collectColumnInformation: result set has empty (column-less) meta data!" );
842 22 : for (sal_Int32 i=1; i <= nCount ; ++i)
843 : {
844 18 : _rInfo.insert(ColumnInformationMap::value_type(xMeta->getColumnName(i),
845 36 : ColumnInformation(TBoolPair(xMeta->isAutoIncrement(i),xMeta->isCurrency(i)),xMeta->getColumnType(i))));
846 4 : }
847 : }
848 0 : catch( const Exception& )
849 : {
850 : DBG_UNHANDLED_EXCEPTION();
851 4 : }
852 4 : }
853 :
854 :
855 1168 : bool isEmbeddedInDatabase( const Reference< XInterface >& _rxComponent, Reference< XConnection >& _rxActualConnection )
856 : {
857 1168 : bool bIsEmbedded = false;
858 : try
859 : {
860 1168 : Reference< XModel > xModel = lcl_getXModel( _rxComponent );
861 :
862 1168 : if ( xModel.is() )
863 : {
864 1154 : Sequence< PropertyValue > aArgs = xModel->getArgs();
865 554 : const PropertyValue* pIter = aArgs.getConstArray();
866 554 : const PropertyValue* pEnd = pIter + aArgs.getLength();
867 6100 : for(;pIter != pEnd;++pIter)
868 : {
869 5546 : if ( pIter->Name == "ComponentData" )
870 : {
871 0 : Sequence<PropertyValue> aDocumentContext;
872 0 : pIter->Value >>= aDocumentContext;
873 0 : const PropertyValue* pContextIter = aDocumentContext.getConstArray();
874 0 : const PropertyValue* pContextEnd = pContextIter + aDocumentContext.getLength();
875 0 : for(;pContextIter != pContextEnd;++pContextIter)
876 : {
877 0 : if ( pContextIter->Name == "ActiveConnection"
878 0 : && ( pContextIter->Value >>= _rxActualConnection )
879 : )
880 : {
881 0 : bIsEmbedded = true;
882 0 : break;
883 : }
884 : }
885 0 : break;
886 : }
887 554 : }
888 1168 : }
889 : }
890 600 : catch(Exception&)
891 : {
892 : // not interested in
893 : }
894 1168 : return bIsEmbedded;
895 : }
896 :
897 : namespace
898 : {
899 0 : OUString lcl_getEncodingName( rtl_TextEncoding _eEncoding )
900 : {
901 0 : OUString sEncodingName;
902 :
903 0 : OCharsetMap aCharsets;
904 0 : OCharsetMap::CharsetIterator aEncodingPos = aCharsets.find( _eEncoding );
905 : OSL_ENSURE( aEncodingPos != aCharsets.end(), "lcl_getEncodingName: *which* encoding?" );
906 0 : if ( aEncodingPos != aCharsets.end() )
907 0 : sEncodingName = (*aEncodingPos).getIanaName();
908 :
909 0 : return sEncodingName;
910 : }
911 : }
912 :
913 :
914 10 : sal_Int32 DBTypeConversion::convertUnicodeString( const OUString& _rSource, OString& _rDest, rtl_TextEncoding _eEncoding )
915 : {
916 10 : if ( !rtl_convertUStringToString( &_rDest.pData, _rSource.getStr(), _rSource.getLength(),
917 : _eEncoding,
918 : RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
919 : RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACE |
920 10 : RTL_UNICODETOTEXT_FLAGS_PRIVATE_MAPTO0 )
921 : )
922 : {
923 0 : SharedResources aResources;
924 : OUString sMessage = aResources.getResourceStringWithSubstitution( STR_CANNOT_CONVERT_STRING,
925 : "$string$", _rSource,
926 : "$charset$", lcl_getEncodingName( _eEncoding )
927 0 : );
928 :
929 : throw SQLException(
930 : sMessage,
931 : NULL,
932 : OUString( "22018" ),
933 : 22018,
934 : Any()
935 0 : );
936 : }
937 :
938 10 : return _rDest.getLength();
939 : }
940 :
941 :
942 8 : sal_Int32 DBTypeConversion::convertUnicodeStringToLength( const OUString& _rSource, OString& _rDest,
943 : sal_Int32 _nMaxLen, rtl_TextEncoding _eEncoding )
944 : {
945 8 : sal_Int32 nLen = convertUnicodeString( _rSource, _rDest, _eEncoding );
946 8 : if ( nLen > _nMaxLen )
947 : {
948 0 : SharedResources aResources;
949 : OUString sMessage = aResources.getResourceStringWithSubstitution( STR_STRING_LENGTH_EXCEEDED,
950 : "$string$", _rSource,
951 : "$maxlen$", OUString::number( _nMaxLen ),
952 : "$charset$", lcl_getEncodingName( _eEncoding )
953 0 : );
954 :
955 : throw SQLException(
956 : sMessage,
957 : NULL,
958 : OUString( "22001" ),
959 : 22001,
960 : Any()
961 0 : );
962 : }
963 :
964 8 : return nLen;
965 : }
966 14 : OUString lcl_getReportEngines()
967 : {
968 14 : static OUString s_sNodeName("org.openoffice.Office.DataAccess/ReportEngines");
969 14 : return s_sNodeName;
970 : }
971 :
972 14 : OUString lcl_getDefaultReportEngine()
973 : {
974 14 : static OUString s_sNodeName("DefaultReportEngine");
975 14 : return s_sNodeName;
976 : }
977 :
978 14 : OUString lcl_getReportEngineNames()
979 : {
980 14 : static OUString s_sNodeName("ReportEngineNames");
981 14 : return s_sNodeName;
982 : }
983 :
984 14 : OUString getDefaultReportEngineServiceName(const Reference< XComponentContext >& _rxORB)
985 : {
986 : ::utl::OConfigurationTreeRoot aReportEngines = ::utl::OConfigurationTreeRoot::createWithComponentContext(
987 14 : _rxORB, lcl_getReportEngines(), -1, ::utl::OConfigurationTreeRoot::CM_READONLY);
988 :
989 14 : if ( aReportEngines.isValid() )
990 : {
991 14 : OUString sDefaultReportEngineName;
992 14 : aReportEngines.getNodeValue(lcl_getDefaultReportEngine()) >>= sDefaultReportEngineName;
993 14 : if ( !sDefaultReportEngineName.isEmpty() )
994 : {
995 14 : ::utl::OConfigurationNode aReportEngineNames = aReportEngines.openNode(lcl_getReportEngineNames());
996 14 : if ( aReportEngineNames.isValid() )
997 : {
998 14 : ::utl::OConfigurationNode aReportEngine = aReportEngineNames.openNode(sDefaultReportEngineName);
999 14 : if ( aReportEngine.isValid() )
1000 : {
1001 14 : OUString sRet;
1002 14 : aReportEngine.getNodeValue("ServiceName") >>= sRet;
1003 14 : return sRet;
1004 0 : }
1005 0 : }
1006 : }
1007 : else
1008 0 : return OUString("org.libreoffice.report.pentaho.SOReportJobFactory");
1009 : }
1010 : else
1011 0 : return OUString("org.libreoffice.report.pentaho.SOReportJobFactory");
1012 0 : return OUString();
1013 : }
1014 :
1015 :
1016 : } // namespace dbtools
1017 :
1018 :
1019 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|