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 <sal/config.h>
21 
22 #include <string_view>
23 
24 #include <ado/ADatabaseMetaData.hxx>
25 #include <ado/ADatabaseMetaDataResultSetMetaData.hxx>
26 #include <ado/Awrapado.hxx>
27 #include <ado/AGroup.hxx>
28 #include <ado/adoimp.hxx>
29 #include <ado/AIndex.hxx>
30 #include <ado/AKey.hxx>
31 #include <ado/ATable.hxx>
32 #include <com/sun/star/sdbc/DataType.hpp>
33 #include <com/sun/star/sdbc/ProcedureResult.hpp>
34 #include <com/sun/star/sdbc/ColumnValue.hpp>
35 #ifdef DELETE
36 #undef DELETE
37 #endif
38 #include <com/sun/star/sdbcx/Privilege.hpp>
39 #include <com/sun/star/sdbcx/PrivilegeObject.hpp>
40 #include <com/sun/star/sdbc/KeyRule.hpp>
41 #include <com/sun/star/sdbcx/KeyType.hpp>
42 
43 using namespace connectivity::ado;
44 using namespace ::com::sun::star::sdbc;
45 using namespace ::com::sun::star::sdbcx;
46 using namespace ::com::sun::star::uno;
47 
48 
fillLiterals()49 void ODatabaseMetaData::fillLiterals()
50 {
51     ADORecordset *pRecordset = nullptr;
52     OLEVariant  vtEmpty;
53     vtEmpty.setNoArg();
54     m_pADOConnection->OpenSchema(adSchemaDBInfoLiterals,vtEmpty,vtEmpty,&pRecordset);
55 
56     ADOS::ThrowException(*m_pADOConnection,*this);
57 
58     OSL_ENSURE(pRecordset,"fillLiterals: no resultset!");
59     if ( pRecordset )
60     {
61         WpADORecordset aRecordset(pRecordset);
62 
63         aRecordset.MoveFirst();
64         OLEVariant  aValue;
65         LiteralInfo aInfo;
66         while(!aRecordset.IsAtEOF())
67         {
68             WpOLEAppendCollection<ADOFields, ADOField, WpADOField>  aFields(aRecordset.GetFields());
69             WpADOField aField(aFields.GetItem(1));
70             aInfo.pwszLiteralValue = aField.get_Value().getString();
71             aField = aFields.GetItem(5);
72             aInfo.fSupported = aField.get_Value().getBool();
73             aField = aFields.GetItem(6);
74             aInfo.cchMaxLen = aField.get_Value().getUInt32();
75 
76             aField = aFields.GetItem(4);
77             sal_uInt32 nId = aField.get_Value().getUInt32();
78             m_aLiteralInfo[nId] = aInfo;
79 
80             aRecordset.MoveNext();
81         }
82         aRecordset.Close();
83     }
84 }
85 
getMaxSize(sal_uInt32 _nId)86 sal_Int32 ODatabaseMetaData::getMaxSize(sal_uInt32 _nId)
87 {
88     if(m_aLiteralInfo.empty())
89         fillLiterals();
90 
91     sal_Int32 nSize = 0;
92     std::map<sal_uInt32,LiteralInfo>::const_iterator aIter = m_aLiteralInfo.find(_nId);
93     if(aIter != m_aLiteralInfo.end() && (*aIter).second.fSupported)
94         nSize = (static_cast<sal_Int32>((*aIter).second.cchMaxLen) == -1) ? 0 : (*aIter).second.cchMaxLen;
95     return nSize;
96 }
97 
isCapable(sal_uInt32 _nId)98 bool ODatabaseMetaData::isCapable(sal_uInt32 _nId)
99 {
100     if(m_aLiteralInfo.empty())
101         fillLiterals();
102     bool bSupported = false;
103     std::map<sal_uInt32,LiteralInfo>::const_iterator aIter = m_aLiteralInfo.find(_nId);
104     if(aIter != m_aLiteralInfo.end())
105         bSupported = (*aIter).second.fSupported;
106     return bSupported;
107 }
108 
109 
getLiteral(sal_uInt32 _nId)110 OUString ODatabaseMetaData::getLiteral(sal_uInt32 _nId)
111 {
112     if(m_aLiteralInfo.empty())
113         fillLiterals();
114     OUString sStr;
115     std::map<sal_uInt32,LiteralInfo>::const_iterator aIter = m_aLiteralInfo.find(_nId);
116     if(aIter != m_aLiteralInfo.end() && (*aIter).second.fSupported)
117         sStr = (*aIter).second.pwszLiteralValue;
118     return sStr;
119 }
120 
121 
setColumnPrivilegesMap()122 void ODatabaseMetaDataResultSetMetaData::setColumnPrivilegesMap()
123 {
124     m_mColumns[8] = OColumn(OUString(),"IS_GRANTABLE",
125         ColumnValue::NULLABLE,
126         3,3,0,
127         DataType::VARCHAR);
128 }
129 
setColumnsMap()130 void ODatabaseMetaDataResultSetMetaData::setColumnsMap()
131 {
132     m_mColumns[6] = OColumn(OUString(),"TYPE_NAME",
133         ColumnValue::NO_NULLS,
134         0,0,0,
135         DataType::VARCHAR);
136     m_mColumns[11] = OColumn(OUString(),"NULLABLE",
137         ColumnValue::NO_NULLS,
138         1,1,0,
139         DataType::INTEGER);
140     m_mColumns[12] = OColumn(OUString(),"REMARKS",
141         ColumnValue::NULLABLE,
142         0,0,0,
143         DataType::VARCHAR);
144     m_mColumns[13] = OColumn(OUString(),"COLUMN_DEF",
145         ColumnValue::NULLABLE,
146         0,0,0,
147         DataType::VARCHAR);
148     m_mColumns[14] = OColumn(OUString(),"SQL_DATA_TYPE",
149         ColumnValue::NO_NULLS,
150         1,1,0,
151         DataType::INTEGER);
152     m_mColumns[15] = OColumn(OUString(),"SQL_DATETIME_SUB",
153         ColumnValue::NO_NULLS,
154         1,1,0,
155         DataType::INTEGER);
156     m_mColumns[16] = OColumn(OUString(),"CHAR_OCTET_LENGTH",
157         ColumnValue::NO_NULLS,
158         1,1,0,
159         DataType::INTEGER);
160 }
161 
setTablesMap()162 void ODatabaseMetaDataResultSetMetaData::setTablesMap()
163 {
164     m_mColumns[5] = OColumn(OUString(),"REMARKS",
165         ColumnValue::NULLABLE,
166         0,0,0,
167         DataType::VARCHAR);
168 }
169 
setProcedureColumnsMap()170 void ODatabaseMetaDataResultSetMetaData::setProcedureColumnsMap()
171 {
172     m_mColumns[12] = OColumn(OUString(),"NULLABLE",
173         ColumnValue::NO_NULLS,
174         1,1,0,
175         DataType::INTEGER);
176 }
177 
setPrimaryKeysMap()178 void ODatabaseMetaDataResultSetMetaData::setPrimaryKeysMap()
179 {
180     m_mColumns[5] = OColumn(OUString(),"KEY_SEQ",
181         ColumnValue::NO_NULLS,
182         1,1,0,
183         DataType::INTEGER);
184     m_mColumns[6] = OColumn(OUString(),"PK_NAME",
185         ColumnValue::NULLABLE,
186         0,0,0,
187         DataType::VARCHAR);
188 }
189 
setIndexInfoMap()190 void ODatabaseMetaDataResultSetMetaData::setIndexInfoMap()
191 {
192     m_mColumns[4] = OColumn(OUString(),"NON_UNIQUE",
193         ColumnValue::NO_NULLS,
194         1,1,0,
195         DataType::BIT);
196     m_mColumns[5] = OColumn(OUString(),"INDEX_QUALIFIER",
197         ColumnValue::NULLABLE,
198         0,0,0,
199         DataType::VARCHAR);
200     m_mColumns[10] = OColumn(OUString(),"ASC_OR_DESC",
201         ColumnValue::NULLABLE,
202         0,0,0,
203         DataType::VARCHAR);
204 }
205 
setTablePrivilegesMap()206 void ODatabaseMetaDataResultSetMetaData::setTablePrivilegesMap()
207 {
208     m_mColumns[6] = OColumn(OUString(),"PRIVILEGE",
209         ColumnValue::NULLABLE,
210         0,0,0,
211         DataType::VARCHAR);
212     m_mColumns[7] = OColumn(OUString(),"IS_GRANTABLE",
213         ColumnValue::NULLABLE,
214         0,0,0,
215         DataType::VARCHAR);
216 }
217 
setCrossReferenceMap()218 void ODatabaseMetaDataResultSetMetaData::setCrossReferenceMap()
219 {
220     m_mColumns[9] = OColumn(OUString(),"KEY_SEQ",
221         ColumnValue::NO_NULLS,
222         1,1,0,
223         DataType::INTEGER);
224 }
225 
setTypeInfoMap()226 void ODatabaseMetaDataResultSetMetaData::setTypeInfoMap()
227 {
228     m_mColumns[3] = OColumn(OUString(),"PRECISION",
229         ColumnValue::NO_NULLS,
230         1,1,0,
231         DataType::INTEGER);
232     m_mColumns[7] = OColumn(OUString(),"NULLABLE",
233         ColumnValue::NO_NULLS,
234         1,1,0,
235         DataType::INTEGER);
236     m_mColumns[12] = OColumn(OUString(),"AUTO_INCREMENT",
237         ColumnValue::NO_NULLS,
238         1,1,0,
239         DataType::BIT);
240     m_mColumns[16] = OColumn(OUString(),"SQL_DATA_TYPE",
241         ColumnValue::NO_NULLS,
242         1,1,0,
243         DataType::INTEGER);
244     m_mColumns[17] = OColumn(OUString(),"SQL_DATETIME_SUB",
245         ColumnValue::NO_NULLS,
246         1,1,0,
247         DataType::INTEGER);
248     m_mColumns[18] = OColumn(OUString(),"NUM_PREC_RADIX",
249         ColumnValue::NO_NULLS,
250         1,1,0,
251         DataType::INTEGER);
252 }
253 
setProceduresMap()254 void ODatabaseMetaDataResultSetMetaData::setProceduresMap()
255 {
256     m_mColumns[7] = OColumn(OUString(),"REMARKS",
257         ColumnValue::NULLABLE,
258         0,0,0,
259         DataType::VARCHAR);
260 }
261 
isSearchable(sal_Int32 column)262 sal_Bool SAL_CALL ODatabaseMetaDataResultSetMetaData::isSearchable( sal_Int32 column )
263 {
264     if(!m_mColumns.empty() && (m_mColumnsIter = m_mColumns.find(column)) != m_mColumns.end())
265         return (*m_mColumnsIter).second.isSearchable();
266     return true;
267 }
268 
isAutoIncrement(sal_Int32 column)269 sal_Bool SAL_CALL ODatabaseMetaDataResultSetMetaData::isAutoIncrement( sal_Int32 column )
270 {
271     if(!m_mColumns.empty() && (m_mColumnsIter = m_mColumns.find(column)) != m_mColumns.end())
272         return (*m_mColumnsIter).second.isAutoIncrement();
273     return false;
274 }
275 
getColumnServiceName(sal_Int32)276 OUString SAL_CALL ODatabaseMetaDataResultSetMetaData::getColumnServiceName( sal_Int32 /*column*/ )
277 {
278     return OUString();
279 }
280 
getTableName(sal_Int32 column)281 OUString SAL_CALL ODatabaseMetaDataResultSetMetaData::getTableName( sal_Int32 column )
282 {
283     if(!m_mColumns.empty() && (m_mColumnsIter = m_mColumns.find(column)) != m_mColumns.end())
284         return (*m_mColumnsIter).second.getTableName();
285     return OUString();
286 }
287 
getCatalogName(sal_Int32)288 OUString SAL_CALL ODatabaseMetaDataResultSetMetaData::getCatalogName( sal_Int32 /*column*/ )
289 {
290     return OUString();
291 }
292 
getColumnTypeName(sal_Int32)293 OUString SAL_CALL ODatabaseMetaDataResultSetMetaData::getColumnTypeName( sal_Int32 /*column*/ )
294 {
295     return OUString();
296 }
297 
298 
isCaseSensitive(sal_Int32 column)299 sal_Bool SAL_CALL ODatabaseMetaDataResultSetMetaData::isCaseSensitive( sal_Int32 column )
300 {
301     if(!m_mColumns.empty() && (m_mColumnsIter = m_mColumns.find(column)) != m_mColumns.end())
302         return (*m_mColumnsIter).second.isCaseSensitive();
303     return true;
304 }
305 
306 
getSchemaName(sal_Int32)307 OUString SAL_CALL ODatabaseMetaDataResultSetMetaData::getSchemaName( sal_Int32 /*column*/ )
308 {
309     return OUString();
310 }
311 
312 
MapObjectType(sal_Int32 ObjType)313 ObjectTypeEnum OAdoGroup::MapObjectType(sal_Int32 ObjType)
314 {
315     ObjectTypeEnum eNumType= adPermObjTable;
316     switch(ObjType)
317     {
318         case PrivilegeObject::TABLE:
319             break;
320         case PrivilegeObject::VIEW:
321             eNumType = adPermObjView;
322             break;
323         case PrivilegeObject::COLUMN:
324             eNumType = adPermObjColumn;
325             break;
326     }
327     return eNumType;
328 }
329 
MapRight(RightsEnum _eNum)330 sal_Int32 OAdoGroup::MapRight(RightsEnum _eNum)
331 {
332     sal_Int32 nRight = 0;
333     if(_eNum & adRightRead)
334                 nRight |= Privilege::SELECT;
335     if(_eNum & adRightInsert)
336                 nRight |= Privilege::INSERT;
337     if(_eNum & adRightUpdate)
338                 nRight |= Privilege::UPDATE;
339     if(_eNum & adRightDelete)
340                 nRight |= Privilege::DELETE;
341     if(_eNum & adRightReadDesign)
342                 nRight |= Privilege::READ;
343     if(_eNum & adRightCreate)
344                 nRight |= Privilege::CREATE;
345     if(_eNum & adRightWriteDesign)
346                 nRight |= Privilege::ALTER;
347     if(_eNum & adRightReference)
348                 nRight |= Privilege::REFERENCE;
349     if(_eNum & adRightDrop)
350                 nRight |= Privilege::DROP;
351 
352     return nRight;
353 }
354 
Map2Right(sal_Int32 _eNum)355 RightsEnum OAdoGroup::Map2Right(sal_Int32 _eNum)
356 {
357     sal_Int32 nRight = adRightNone;
358     if(_eNum & Privilege::SELECT)
359         nRight |= adRightRead;
360 
361     if(_eNum & Privilege::INSERT)
362         nRight |= adRightInsert;
363 
364     if(_eNum & Privilege::UPDATE)
365         nRight |= adRightUpdate;
366 
367     if(_eNum & Privilege::DELETE)
368         nRight |= adRightDelete;
369 
370     if(_eNum & Privilege::READ)
371         nRight |= adRightReadDesign;
372 
373     if(_eNum & Privilege::CREATE)
374         nRight |= adRightCreate;
375 
376     if(_eNum & Privilege::ALTER)
377         nRight |= adRightWriteDesign;
378 
379     if(_eNum & Privilege::REFERENCE)
380         nRight |= adRightReference;
381 
382     if(_eNum & Privilege::DROP)
383         nRight |= adRightDrop;
384 
385     return static_cast<RightsEnum>(nRight);
386 }
387 
Create()388 void WpADOIndex::Create()
389 {
390     _ADOIndex* pIndex = nullptr;
391     HRESULT hr = CoCreateInstance(ADOS::CLSID_ADOINDEX_25,
392                           nullptr,
393                           CLSCTX_INPROC_SERVER,
394                           ADOS::IID_ADOINDEX_25,
395                           reinterpret_cast<void**>(&pIndex) );
396 
397 
398     if( !FAILED( hr ) )
399     {
400         operator=( pIndex );
401         pIndex->Release();
402     }
403 }
404 
fillPropertyValues()405 void OAdoIndex::fillPropertyValues()
406 {
407     if(m_aIndex.IsValid())
408     {
409         m_Name              = m_aIndex.get_Name();
410         m_IsUnique          = m_aIndex.get_Unique();
411         m_IsPrimaryKeyIndex = m_aIndex.get_PrimaryKey();
412         m_IsClustered       = m_aIndex.get_Clustered();
413     }
414 }
415 
Create()416 void WpADOKey::Create()
417 {
418     _ADOKey* pKey = nullptr;
419     HRESULT hr = CoCreateInstance(ADOS::CLSID_ADOKEY_25,
420                           nullptr,
421                           CLSCTX_INPROC_SERVER,
422                           ADOS::IID_ADOKEY_25,
423                           reinterpret_cast<void**>(&pKey) );
424 
425 
426     if( !FAILED( hr ) )
427     {
428         operator=( pKey );
429         pKey->Release();
430     }
431 }
432 
fillPropertyValues()433 void OAdoKey::fillPropertyValues()
434 {
435     if(m_aKey.IsValid())
436     {
437         m_aProps->m_Type            = MapKeyRule(m_aKey.get_Type());
438         m_Name                      = m_aKey.get_Name();
439         m_aProps->m_ReferencedTable = m_aKey.get_RelatedTable();
440         m_aProps->m_UpdateRule      = MapRule(m_aKey.get_UpdateRule());
441         m_aProps->m_DeleteRule      = MapRule(m_aKey.get_DeleteRule());
442     }
443 }
444 
MapRule(const RuleEnum & _eNum)445 sal_Int32 OAdoKey::MapRule(const RuleEnum& _eNum)
446 {
447     sal_Int32 eNum = KeyRule::NO_ACTION;
448     switch(_eNum)
449     {
450         case adRICascade:
451             eNum = KeyRule::CASCADE;
452             break;
453         case adRISetNull:
454             eNum = KeyRule::SET_NULL;
455             break;
456         case adRINone:
457             eNum = KeyRule::NO_ACTION;
458             break;
459         case adRISetDefault:
460             eNum = KeyRule::SET_DEFAULT;
461             break;
462     }
463     return eNum;
464 }
465 
Map2Rule(sal_Int32 _eNum)466 RuleEnum OAdoKey::Map2Rule(sal_Int32 _eNum)
467 {
468     RuleEnum eNum = adRINone;
469     switch(_eNum)
470     {
471         case KeyRule::CASCADE:
472             eNum = adRICascade;
473             break;
474         case KeyRule::SET_NULL:
475             eNum = adRISetNull;
476             break;
477         case KeyRule::NO_ACTION:
478             eNum = adRINone;
479             break;
480         case KeyRule::SET_DEFAULT:
481             eNum = adRISetDefault;
482             break;
483     }
484     return eNum;
485 }
486 
MapKeyRule(const KeyTypeEnum & _eNum)487 sal_Int32 OAdoKey::MapKeyRule(const KeyTypeEnum& _eNum)
488 {
489     sal_Int32 nKeyType = KeyType::PRIMARY;
490     switch(_eNum)
491     {
492         case adKeyPrimary:
493             nKeyType = KeyType::PRIMARY;
494             break;
495         case adKeyForeign:
496             nKeyType = KeyType::FOREIGN;
497             break;
498         case adKeyUnique:
499             nKeyType = KeyType::UNIQUE;
500             break;
501     }
502     return nKeyType;
503 }
504 
Map2KeyRule(sal_Int32 _eNum)505 KeyTypeEnum OAdoKey::Map2KeyRule(sal_Int32 _eNum)
506 {
507     KeyTypeEnum eNum( adKeyPrimary );
508     switch(_eNum)
509     {
510         case KeyType::PRIMARY:
511             eNum = adKeyPrimary;
512             break;
513         case KeyType::FOREIGN:
514             eNum = adKeyForeign;
515             break;
516         case KeyType::UNIQUE:
517             eNum = adKeyUnique;
518             break;
519         default:
520             OSL_FAIL( "OAdoKey::Map2KeyRule: invalid key type!" );
521     }
522     return eNum;
523 }
524 
Create()525 void WpADOTable::Create()
526 {
527     _ADOTable* pTable = nullptr;
528     HRESULT hr = CoCreateInstance(ADOS::CLSID_ADOTABLE_25,
529                           nullptr,
530                           CLSCTX_INPROC_SERVER,
531                           ADOS::IID_ADOTABLE_25,
532                           reinterpret_cast<void**>(&pTable) );
533 
534 
535     if( !FAILED( hr ) )
536     {
537         operator=( pTable );
538         pTable->Release();
539     }
540 }
541 
GetObjectOwner(std::u16string_view _rName,ObjectTypeEnum _eNum)542 OUString WpADOCatalog::GetObjectOwner(std::u16string_view _rName, ObjectTypeEnum _eNum)
543 {
544     OLEVariant _rVar;
545     _rVar.setNoArg();
546     OLEString aBSTR;
547     OLEString sStr1(_rName);
548     pInterface->GetObjectOwner(sStr1.asBSTR(),_eNum,_rVar,aBSTR.getAddress());
549     return aBSTR.asOUString();
550 }
551 
fillPropertyValues()552 void OAdoTable::fillPropertyValues()
553 {
554     if(m_aTable.IsValid())
555     {
556         m_Name  = m_aTable.get_Name();
557         m_Type  = m_aTable.get_Type();
558         {
559             WpADOCatalog aCat(m_aTable.get_ParentCatalog());
560             if(aCat.IsValid())
561                 m_CatalogName = aCat.GetObjectOwner(m_aTable.get_Name(),adPermObjTable);
562         }
563         {
564             WpADOProperties aProps = m_aTable.get_Properties();
565             if(aProps.IsValid())
566                 m_Description
567                     = OTools::getValue(aProps, std::u16string_view(u"Description")).getString();
568         }
569     }
570 }
571 
Create()572 void WpADOUser::Create()
573 {
574     _ADOUser* pUser = nullptr;
575     HRESULT hr = CoCreateInstance(ADOS::CLSID_ADOUSER_25,
576                           nullptr,
577                           CLSCTX_INPROC_SERVER,
578                           ADOS::IID_ADOUSER_25,
579                           reinterpret_cast<void**>(&pUser) );
580 
581 
582     if( !FAILED( hr ) )
583     {
584         operator=( pUser );
585         pUser->Release();
586     }
587 }
588 
589 
590 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
591