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