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 "calc/CDatabaseMetaData.hxx"
21 : #include "calc/CConnection.hxx"
22 : #include <com/sun/star/sdbc/DataType.hpp>
23 : #include <com/sun/star/sdbc/ResultSetType.hpp>
24 : #include <com/sun/star/sdbc/ColumnValue.hpp>
25 : #include <com/sun/star/beans/XPropertySet.hpp>
26 : #include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
27 : #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
28 : #include <com/sun/star/sdbcx/XIndexesSupplier.hpp>
29 : #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
30 : #include <com/sun/star/sheet/XSpreadsheet.hpp>
31 : #include <com/sun/star/sheet/XCellRangesQuery.hpp>
32 : #include <com/sun/star/sheet/XCellRangeAddressable.hpp>
33 : #include <com/sun/star/sheet/XDatabaseRanges.hpp>
34 : #include <com/sun/star/sheet/XDatabaseRange.hpp>
35 : #include "FDatabaseMetaDataResultSet.hxx"
36 : #include <com/sun/star/lang/XUnoTunnel.hpp>
37 : #include <comphelper/types.hxx>
38 :
39 : using namespace connectivity::calc;
40 : using namespace connectivity::file;
41 : using namespace ::com::sun::star::uno;
42 : using namespace ::com::sun::star::beans;
43 : using namespace ::com::sun::star::sdbcx;
44 : using namespace ::com::sun::star::sdbc;
45 : using namespace ::com::sun::star::container;
46 : using namespace ::com::sun::star::table;
47 : using namespace ::com::sun::star::sheet;
48 :
49 :
50 :
51 4 : OCalcDatabaseMetaData::OCalcDatabaseMetaData(OConnection* _pCon) :ODatabaseMetaData(_pCon)
52 : {
53 4 : }
54 :
55 :
56 :
57 8 : OCalcDatabaseMetaData::~OCalcDatabaseMetaData()
58 : {
59 8 : }
60 :
61 :
62 0 : Reference< XResultSet > OCalcDatabaseMetaData::impl_getTypeInfo_throw( )
63 : {
64 0 : ::osl::MutexGuard aGuard( m_aMutex );
65 :
66 0 : ODatabaseMetaDataResultSet* pResult = new ODatabaseMetaDataResultSet(::connectivity::ODatabaseMetaDataResultSet::eTypeInfo);
67 0 : Reference< XResultSet > xRef = pResult;
68 :
69 0 : static ODatabaseMetaDataResultSet::ORows aRows;
70 0 : if(aRows.empty())
71 : {
72 0 : ODatabaseMetaDataResultSet::ORow aRow;
73 :
74 0 : aRows.reserve(6);
75 0 : aRow.reserve(18);
76 :
77 0 : aRow.push_back(ODatabaseMetaDataResultSet::getEmptyValue());
78 0 : aRow.push_back(new ORowSetValueDecorator(OUString("VARCHAR")));
79 0 : aRow.push_back(new ORowSetValueDecorator(DataType::VARCHAR));
80 0 : aRow.push_back(new ORowSetValueDecorator((sal_Int32)65535));
81 0 : aRow.push_back(ODatabaseMetaDataResultSet::getQuoteValue());
82 0 : aRow.push_back(ODatabaseMetaDataResultSet::getQuoteValue());
83 0 : aRow.push_back(ODatabaseMetaDataResultSet::getEmptyValue());
84 0 : aRow.push_back(ODatabaseMetaDataResultSet::get1Value()); // ORowSetValue((sal_Int32)ColumnValue::NULLABLE)
85 0 : aRow.push_back(ODatabaseMetaDataResultSet::get1Value());
86 0 : aRow.push_back(new ORowSetValueDecorator((sal_Int32)ColumnSearch::CHAR));
87 0 : aRow.push_back(ODatabaseMetaDataResultSet::get1Value());
88 0 : aRow.push_back(ODatabaseMetaDataResultSet::get0Value());
89 0 : aRow.push_back(ODatabaseMetaDataResultSet::get0Value());
90 0 : aRow.push_back(ODatabaseMetaDataResultSet::getEmptyValue());
91 0 : aRow.push_back(ODatabaseMetaDataResultSet::get0Value());
92 0 : aRow.push_back(ODatabaseMetaDataResultSet::get0Value());
93 0 : aRow.push_back(ODatabaseMetaDataResultSet::getEmptyValue());
94 0 : aRow.push_back(ODatabaseMetaDataResultSet::getEmptyValue());
95 0 : aRow.push_back(new ORowSetValueDecorator((sal_Int32)10));
96 :
97 :
98 0 : aRows.push_back(aRow);
99 :
100 0 : aRow[1] = new ORowSetValueDecorator(OUString("DECIMAL"));
101 0 : aRow[2] = new ORowSetValueDecorator(DataType::DECIMAL);
102 0 : aRow[3] = ODatabaseMetaDataResultSet::get0Value();
103 0 : aRow[9] = ODatabaseMetaDataResultSet::getBasicValue();
104 0 : aRow[15] = ODatabaseMetaDataResultSet::get0Value();
105 0 : aRows.push_back(aRow);
106 :
107 0 : aRow[1] = new ORowSetValueDecorator(OUString("BOOL"));
108 0 : aRow[2] = new ORowSetValueDecorator(DataType::BIT);
109 0 : aRow[3] = new ORowSetValueDecorator((sal_Int32)20);
110 0 : aRow[9] = ODatabaseMetaDataResultSet::getBasicValue();
111 0 : aRow[15] = new ORowSetValueDecorator((sal_Int32)15);
112 0 : aRows.push_back(aRow);
113 :
114 0 : aRow[1] = new ORowSetValueDecorator(OUString("DATE"));
115 0 : aRow[2] = new ORowSetValueDecorator(DataType::DATE);
116 0 : aRow[3] = ODatabaseMetaDataResultSet::get0Value();
117 0 : aRow[9] = ODatabaseMetaDataResultSet::getBasicValue();
118 0 : aRow[15] = ODatabaseMetaDataResultSet::get0Value();
119 0 : aRows.push_back(aRow);
120 :
121 0 : aRow[1] = new ORowSetValueDecorator(OUString("TIME"));
122 0 : aRow[2] = new ORowSetValueDecorator(DataType::TIME);
123 0 : aRow[3] = ODatabaseMetaDataResultSet::get0Value();
124 0 : aRow[9] = ODatabaseMetaDataResultSet::getBasicValue();
125 0 : aRow[15] = ODatabaseMetaDataResultSet::get0Value();
126 0 : aRows.push_back(aRow);
127 :
128 0 : aRow[1] = new ORowSetValueDecorator(OUString("TIMESTAMP"));
129 0 : aRow[2] = new ORowSetValueDecorator(DataType::TIMESTAMP);
130 0 : aRow[3] = ODatabaseMetaDataResultSet::get0Value();
131 0 : aRow[9] = ODatabaseMetaDataResultSet::getBasicValue();
132 0 : aRow[15] = ODatabaseMetaDataResultSet::get0Value();
133 0 : aRows.push_back(aRow);
134 : }
135 :
136 0 : pResult->setRows(aRows);
137 0 : return xRef;
138 : }
139 :
140 :
141 :
142 0 : Reference< XResultSet > SAL_CALL OCalcDatabaseMetaData::getColumns(
143 : const Any& /*catalog*/, const OUString& /*schemaPattern*/, const OUString& tableNamePattern,
144 : const OUString& columnNamePattern ) throw(SQLException, RuntimeException, std::exception)
145 : {
146 0 : ::osl::MutexGuard aGuard( m_aMutex );
147 :
148 :
149 0 : Reference< XTablesSupplier > xTables = m_pConnection->createCatalog();
150 0 : if(!xTables.is())
151 0 : throw SQLException();
152 :
153 0 : Reference< XNameAccess> xNames = xTables->getTables();
154 0 : if(!xNames.is())
155 0 : throw SQLException();
156 :
157 0 : ODatabaseMetaDataResultSet::ORows aRows;
158 0 : ODatabaseMetaDataResultSet::ORow aRow(19);
159 :
160 0 : aRow[10] = new ORowSetValueDecorator((sal_Int32)10);
161 :
162 0 : Sequence< OUString> aTabNames(xNames->getElementNames());
163 0 : const OUString* pTabIter = aTabNames.getConstArray();
164 0 : const OUString* pTabEnd = pTabIter + aTabNames.getLength();
165 0 : for(;pTabIter != pTabEnd;++pTabIter)
166 : {
167 0 : if(match(tableNamePattern,*pTabIter,'\0'))
168 : {
169 0 : const Reference< XColumnsSupplier> xTable(xNames->getByName(*pTabIter),UNO_QUERY_THROW);
170 : OSL_ENSURE(xTable.is(),"Table not found! Normally a exception had to be thrown here!");
171 0 : aRow[3] = new ORowSetValueDecorator(*pTabIter);
172 :
173 0 : const Reference< XNameAccess> xColumns = xTable->getColumns();
174 0 : if(!xColumns.is())
175 0 : throw SQLException();
176 :
177 0 : const Sequence< OUString> aColNames(xColumns->getElementNames());
178 :
179 0 : const OUString* pColumnIter = aColNames.getConstArray();
180 0 : const OUString* pEnd = pColumnIter + aColNames.getLength();
181 0 : Reference< XPropertySet> xColumn;
182 0 : for(sal_Int32 i=1;pColumnIter != pEnd;++pColumnIter,++i)
183 : {
184 0 : if(match(columnNamePattern,*pColumnIter,'\0'))
185 : {
186 0 : aRow[4] = new ORowSetValueDecorator( *pColumnIter);
187 :
188 0 : xColumns->getByName(*pColumnIter) >>= xColumn;
189 : OSL_ENSURE(xColumn.is(),"Columns contains a column who isn't a fastpropertyset!");
190 0 : aRow[5] = new ORowSetValueDecorator(::comphelper::getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE))));
191 0 : aRow[6] = new ORowSetValueDecorator(::comphelper::getString(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPENAME))));
192 0 : aRow[7] = new ORowSetValueDecorator(::comphelper::getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION))));
193 : // aRow[8] = xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPENAME));
194 0 : aRow[9] = new ORowSetValueDecorator(::comphelper::getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE))));
195 0 : aRow[11] = new ORowSetValueDecorator(::comphelper::getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISNULLABLE))));
196 : // aRow[12] = xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPENAME));
197 0 : aRow[13] = new ORowSetValueDecorator(::comphelper::getString(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE))));
198 : // aRow[14] = xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPENAME));
199 : // aRow[15] = xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPENAME));
200 0 : switch(sal_Int32(aRow[5]->getValue()))
201 : {
202 : case DataType::CHAR:
203 : case DataType::VARCHAR:
204 0 : aRow[16] = new ORowSetValueDecorator((sal_Int32)254);
205 0 : break;
206 : case DataType::LONGVARCHAR:
207 0 : aRow[16] = new ORowSetValueDecorator((sal_Int32)65535);
208 0 : break;
209 : default:
210 0 : aRow[16] = new ORowSetValueDecorator((sal_Int32)0);
211 : }
212 0 : aRow[17] = new ORowSetValueDecorator(i);
213 0 : switch(sal_Int32(aRow[11]->getValue()))
214 : {
215 : case ColumnValue::NO_NULLS:
216 0 : aRow[18] = new ORowSetValueDecorator(OUString("NO"));
217 0 : break;
218 : case ColumnValue::NULLABLE:
219 0 : aRow[18] = new ORowSetValueDecorator(OUString("YES"));
220 0 : break;
221 : default:
222 0 : aRow[18] = new ORowSetValueDecorator(OUString());
223 : }
224 0 : aRows.push_back(aRow);
225 : }
226 0 : }
227 : }
228 : }
229 :
230 0 : ODatabaseMetaDataResultSet* pResult = new ODatabaseMetaDataResultSet(::connectivity::ODatabaseMetaDataResultSet::eColumns);
231 0 : Reference< XResultSet > xRef = pResult;
232 0 : pResult->setRows(aRows);
233 :
234 0 : return xRef;
235 : }
236 :
237 :
238 :
239 4 : OUString SAL_CALL OCalcDatabaseMetaData::getURL( ) throw(SQLException, RuntimeException, std::exception)
240 : {
241 4 : ::osl::MutexGuard aGuard( m_aMutex );
242 :
243 4 : return OUString("sdbc:calc:") + m_pConnection->getURL();
244 : }
245 :
246 :
247 :
248 0 : sal_Int32 SAL_CALL OCalcDatabaseMetaData::getMaxBinaryLiteralLength( ) throw(SQLException, RuntimeException, std::exception)
249 : {
250 0 : return SAL_MAX_INT32;
251 : }
252 :
253 :
254 :
255 0 : sal_Int32 SAL_CALL OCalcDatabaseMetaData::getMaxCharLiteralLength( ) throw(SQLException, RuntimeException, std::exception)
256 : {
257 0 : return SAL_MAX_INT32;
258 : }
259 :
260 0 : sal_Int32 SAL_CALL OCalcDatabaseMetaData::getMaxColumnNameLength( ) throw(SQLException, RuntimeException, std::exception)
261 : {
262 0 : return SAL_MAX_INT32;
263 : }
264 :
265 0 : sal_Int32 SAL_CALL OCalcDatabaseMetaData::getMaxColumnsInIndex( ) throw(SQLException, RuntimeException, std::exception)
266 : {
267 0 : return 1;
268 : }
269 :
270 0 : sal_Int32 SAL_CALL OCalcDatabaseMetaData::getMaxColumnsInTable( ) throw(SQLException, RuntimeException, std::exception)
271 : {
272 0 : return 256;
273 : }
274 :
275 :
276 :
277 4 : static bool lcl_IsEmptyOrHidden( const Reference<XSpreadsheets>& xSheets, const OUString& rName )
278 : {
279 4 : Any aAny = xSheets->getByName( rName );
280 8 : Reference<XSpreadsheet> xSheet;
281 4 : if ( aAny >>= xSheet )
282 : {
283 : // test if sheet is hidden
284 :
285 4 : Reference<XPropertySet> xProp( xSheet, UNO_QUERY );
286 4 : if (xProp.is())
287 : {
288 : bool bVisible;
289 4 : Any aVisAny = xProp->getPropertyValue("IsVisible");
290 4 : if ( aVisAny >>= bVisible )
291 4 : if (!bVisible)
292 0 : return true; // hidden
293 : }
294 :
295 : // use the same data area as in OCalcTable to test for empty table
296 :
297 8 : Reference<XSheetCellCursor> xCursor = xSheet->createCursor();
298 8 : Reference<XCellRangeAddressable> xRange( xCursor, UNO_QUERY );
299 4 : if ( xRange.is() )
300 : {
301 4 : xCursor->collapseToSize( 1, 1 ); // single (first) cell
302 4 : xCursor->collapseToCurrentRegion(); // contiguous data area
303 :
304 4 : CellRangeAddress aRangeAddr = xRange->getRangeAddress();
305 4 : if ( aRangeAddr.StartColumn == aRangeAddr.EndColumn &&
306 0 : aRangeAddr.StartRow == aRangeAddr.EndRow )
307 : {
308 : // single cell -> check content
309 0 : Reference<XCell> xCell = xCursor->getCellByPosition( 0, 0 );
310 0 : if ( xCell.is() && xCell->getType() == CellContentType_EMPTY )
311 0 : return true;
312 : }
313 4 : }
314 : }
315 :
316 8 : return false;
317 : }
318 :
319 0 : static bool lcl_IsUnnamed( const Reference<XDatabaseRanges>& xRanges, const OUString& rName )
320 : {
321 0 : bool bUnnamed = false;
322 :
323 0 : Any aAny = xRanges->getByName( rName );
324 0 : Reference<XDatabaseRange> xRange;
325 0 : if ( aAny >>= xRange )
326 : {
327 0 : Reference<XPropertySet> xRangeProp( xRange, UNO_QUERY );
328 0 : if ( xRangeProp.is() )
329 : {
330 : try
331 : {
332 0 : Any aUserAny = xRangeProp->getPropertyValue("IsUserDefined");
333 : bool bUserDefined;
334 0 : if ( aUserAny >>= bUserDefined )
335 0 : bUnnamed = !bUserDefined;
336 : }
337 0 : catch ( UnknownPropertyException& )
338 : {
339 : // optional property
340 : }
341 0 : }
342 : }
343 :
344 0 : return bUnnamed;
345 : }
346 :
347 :
348 :
349 4 : Reference< XResultSet > SAL_CALL OCalcDatabaseMetaData::getTables(
350 : const Any& /*catalog*/, const OUString& /*schemaPattern*/,
351 : const OUString& tableNamePattern, const Sequence< OUString >& types )
352 : throw(SQLException, RuntimeException, std::exception)
353 : {
354 4 : ::osl::MutexGuard aGuard( m_aMutex );
355 :
356 4 : ODatabaseMetaDataResultSet* pResult = new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eTables);
357 4 : Reference< XResultSet > xRef = pResult;
358 :
359 : // check if ORowSetValue type is given
360 : // when no types are given then we have to return all tables e.g. TABLE
361 :
362 8 : OUString aTable("TABLE");
363 :
364 4 : bool bTableFound = true;
365 4 : sal_Int32 nLength = types.getLength();
366 4 : if(nLength)
367 : {
368 0 : bTableFound = false;
369 :
370 0 : const OUString* pIter = types.getConstArray();
371 0 : const OUString* pEnd = pIter + nLength;
372 0 : for(;pIter != pEnd;++pIter)
373 : {
374 0 : if(*pIter == aTable)
375 : {
376 0 : bTableFound = true;
377 0 : break;
378 : }
379 : }
380 : }
381 4 : if(!bTableFound)
382 0 : return xRef;
383 :
384 : // get the sheet names from the document
385 :
386 8 : OCalcConnection::ODocHolder aDocHodler(static_cast<OCalcConnection*>(m_pConnection));
387 8 : Reference<XSpreadsheetDocument> xDoc = aDocHodler.getDoc();
388 4 : if ( !xDoc.is() )
389 0 : throw SQLException();
390 8 : Reference<XSpreadsheets> xSheets = xDoc->getSheets();
391 4 : if ( !xSheets.is() )
392 0 : throw SQLException();
393 8 : Sequence< OUString > aSheetNames = xSheets->getElementNames();
394 :
395 8 : ODatabaseMetaDataResultSet::ORows aRows;
396 4 : sal_Int32 nSheetCount = aSheetNames.getLength();
397 8 : for (sal_Int32 nSheet=0; nSheet<nSheetCount; nSheet++)
398 : {
399 4 : OUString aName = aSheetNames[nSheet];
400 4 : if ( !lcl_IsEmptyOrHidden( xSheets, aName ) && match(tableNamePattern,aName,'\0') )
401 : {
402 4 : ODatabaseMetaDataResultSet::ORow aRow(3);
403 4 : aRow.reserve(6);
404 4 : aRow.push_back(new ORowSetValueDecorator(aName));
405 4 : aRow.push_back(new ORowSetValueDecorator(aTable));
406 4 : aRow.push_back(ODatabaseMetaDataResultSet::getEmptyValue());
407 4 : aRows.push_back(aRow);
408 : }
409 4 : }
410 :
411 : // also use database ranges
412 :
413 8 : Reference<XPropertySet> xDocProp( xDoc, UNO_QUERY );
414 4 : if ( xDocProp.is() )
415 : {
416 4 : Any aRangesAny = xDocProp->getPropertyValue("DatabaseRanges");
417 8 : Reference<XDatabaseRanges> xRanges;
418 4 : if ( aRangesAny >>= xRanges )
419 : {
420 4 : Sequence< OUString > aDBNames = xRanges->getElementNames();
421 4 : sal_Int32 nDBCount = aDBNames.getLength();
422 4 : for (sal_Int32 nRange=0; nRange<nDBCount; nRange++)
423 : {
424 0 : OUString aName = aDBNames[nRange];
425 0 : if ( !lcl_IsUnnamed( xRanges, aName ) && match(tableNamePattern,aName,'\0') )
426 : {
427 0 : ODatabaseMetaDataResultSet::ORow aRow(3);
428 0 : aRow.reserve(6);
429 0 : aRow.push_back(new ORowSetValueDecorator(aName));
430 0 : aRow.push_back(new ORowSetValueDecorator(aTable));
431 0 : aRow.push_back(ODatabaseMetaDataResultSet::getEmptyValue());
432 0 : aRows.push_back(aRow);
433 : }
434 4 : }
435 4 : }
436 : }
437 :
438 4 : pResult->setRows(aRows);
439 :
440 8 : return xRef;
441 : }
442 :
443 :
444 :
445 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|