1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: CDatabaseMetaData.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_connectivity.hxx"
35 #include "calc/CDatabaseMetaData.hxx"
36 #include "calc/CConnection.hxx"
37 #include <com/sun/star/sdbc/DataType.hpp>
38 #include <com/sun/star/sdbc/ResultSetType.hpp>
39 #include <com/sun/star/sdbc/ColumnValue.hpp>
40 #include <com/sun/star/beans/XPropertySet.hpp>
41 #include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
42 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
43 #include <com/sun/star/sdbcx/XIndexesSupplier.hpp>
44 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
45 #include <com/sun/star/sheet/XSpreadsheet.hpp>
46 #include <com/sun/star/sheet/XCellRangesQuery.hpp>
47 #include <com/sun/star/sheet/XCellRangeAddressable.hpp>
48 #include <com/sun/star/sheet/XDatabaseRanges.hpp>
49 #include <com/sun/star/sheet/XDatabaseRange.hpp>
50 #include <tools/urlobj.hxx>
51 #include "FDatabaseMetaDataResultSet.hxx"
52 #include <com/sun/star/lang/XUnoTunnel.hpp>
53 #include <comphelper/types.hxx>
54 #include <rtl/logfile.hxx>
56 using namespace connectivity::calc
;
57 using namespace connectivity::file
;
58 using namespace ::com::sun::star::uno
;
59 using namespace ::com::sun::star::beans
;
60 using namespace ::com::sun::star::sdbcx
;
61 using namespace ::com::sun::star::sdbc
;
62 using namespace ::com::sun::star::container
;
63 using namespace ::com::sun::star::table
;
64 using namespace ::com::sun::star::sheet
;
66 // -------------------------------------------------------------------------
68 OCalcDatabaseMetaData::OCalcDatabaseMetaData(OConnection
* _pCon
) :ODatabaseMetaData(_pCon
)
70 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "calc", "Ocke.Janssen@sun.com", "OCalcDatabaseMetaData::OCalcDatabaseMetaData" );
73 // -------------------------------------------------------------------------
75 OCalcDatabaseMetaData::~OCalcDatabaseMetaData()
79 // -------------------------------------------------------------------------
80 Reference
< XResultSet
> OCalcDatabaseMetaData::impl_getTypeInfo_throw( )
82 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "calc", "Ocke.Janssen@sun.com", "OCalcDatabaseMetaData::impl_getTypeInfo_throw" );
83 ::osl::MutexGuard
aGuard( m_aMutex
);
85 ODatabaseMetaDataResultSet
* pResult
= new ODatabaseMetaDataResultSet(::connectivity::ODatabaseMetaDataResultSet::eTypeInfo
);
86 Reference
< XResultSet
> xRef
= pResult
;
88 static ODatabaseMetaDataResultSet::ORows aRows
;
91 ODatabaseMetaDataResultSet::ORow aRow
;
96 aRow
.push_back(ODatabaseMetaDataResultSet::getEmptyValue());
97 aRow
.push_back(new ORowSetValueDecorator(::rtl::OUString::createFromAscii("VARCHAR")));
98 aRow
.push_back(new ORowSetValueDecorator(DataType::VARCHAR
));
99 aRow
.push_back(new ORowSetValueDecorator((sal_Int32
)65535));
100 aRow
.push_back(ODatabaseMetaDataResultSet::getQuoteValue());
101 aRow
.push_back(ODatabaseMetaDataResultSet::getQuoteValue());
102 aRow
.push_back(ODatabaseMetaDataResultSet::getEmptyValue());
103 aRow
.push_back(ODatabaseMetaDataResultSet::get1Value()); // ORowSetValue((sal_Int32)ColumnValue::NULLABLE)
104 aRow
.push_back(ODatabaseMetaDataResultSet::get1Value());
105 aRow
.push_back(new ORowSetValueDecorator((sal_Int32
)ColumnSearch::CHAR
));
106 aRow
.push_back(ODatabaseMetaDataResultSet::get1Value());
107 aRow
.push_back(ODatabaseMetaDataResultSet::get0Value());
108 aRow
.push_back(ODatabaseMetaDataResultSet::get0Value());
109 aRow
.push_back(ODatabaseMetaDataResultSet::getEmptyValue());
110 aRow
.push_back(ODatabaseMetaDataResultSet::get0Value());
111 aRow
.push_back(ODatabaseMetaDataResultSet::get0Value());
112 aRow
.push_back(ODatabaseMetaDataResultSet::getEmptyValue());
113 aRow
.push_back(ODatabaseMetaDataResultSet::getEmptyValue());
114 aRow
.push_back(new ORowSetValueDecorator((sal_Int32
)10));
117 aRows
.push_back(aRow
);
119 aRow
[1] = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("DECIMAL"));
120 aRow
[2] = new ORowSetValueDecorator(DataType::DECIMAL
);
121 aRow
[3] = ODatabaseMetaDataResultSet::get0Value();
122 aRow
[9] = ODatabaseMetaDataResultSet::getBasicValue();
123 aRow
[15] = ODatabaseMetaDataResultSet::get0Value();
124 aRows
.push_back(aRow
);
126 aRow
[1] = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("BOOL"));
127 aRow
[2] = new ORowSetValueDecorator(DataType::BIT
);
128 aRow
[3] = new ORowSetValueDecorator((sal_Int32
)20);
129 aRow
[9] = ODatabaseMetaDataResultSet::getBasicValue();
130 aRow
[15] = new ORowSetValueDecorator((sal_Int32
)15);
131 aRows
.push_back(aRow
);
133 aRow
[1] = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("DATE"));
134 aRow
[2] = new ORowSetValueDecorator(DataType::DATE
);
135 aRow
[3] = ODatabaseMetaDataResultSet::get0Value();
136 aRow
[9] = ODatabaseMetaDataResultSet::getBasicValue();
137 aRow
[15] = ODatabaseMetaDataResultSet::get0Value();
138 aRows
.push_back(aRow
);
140 aRow
[1] = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("TIME"));
141 aRow
[2] = new ORowSetValueDecorator(DataType::TIME
);
142 aRow
[3] = ODatabaseMetaDataResultSet::get0Value();
143 aRow
[9] = ODatabaseMetaDataResultSet::getBasicValue();
144 aRow
[15] = ODatabaseMetaDataResultSet::get0Value();
145 aRows
.push_back(aRow
);
147 aRow
[1] = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("TIMESTAMP"));
148 aRow
[2] = new ORowSetValueDecorator(DataType::TIMESTAMP
);
149 aRow
[3] = ODatabaseMetaDataResultSet::get0Value();
150 aRow
[9] = ODatabaseMetaDataResultSet::getBasicValue();
151 aRow
[15] = ODatabaseMetaDataResultSet::get0Value();
152 aRows
.push_back(aRow
);
155 pResult
->setRows(aRows
);
159 // -------------------------------------------------------------------------
161 Reference
< XResultSet
> SAL_CALL
OCalcDatabaseMetaData::getColumns(
162 const Any
& /*catalog*/, const ::rtl::OUString
& /*schemaPattern*/, const ::rtl::OUString
& tableNamePattern
,
163 const ::rtl::OUString
& columnNamePattern
) throw(SQLException
, RuntimeException
)
165 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "calc", "Ocke.Janssen@sun.com", "OCalcDatabaseMetaData::getColumns" );
166 ::osl::MutexGuard
aGuard( m_aMutex
);
169 Reference
< XTablesSupplier
> xTables
= m_pConnection
->createCatalog();
171 throw SQLException();
173 Reference
< XNameAccess
> xNames
= xTables
->getTables();
175 throw SQLException();
177 ODatabaseMetaDataResultSet::ORows aRows
;
178 ODatabaseMetaDataResultSet::ORow
aRow(19);
180 aRow
[10] = new ORowSetValueDecorator((sal_Int32
)10);
182 Sequence
< ::rtl::OUString
> aTabNames(xNames
->getElementNames());
183 const ::rtl::OUString
* pTabIter
= aTabNames
.getConstArray();
184 const ::rtl::OUString
* pTabEnd
= pTabIter
+ aTabNames
.getLength();
185 for(;pTabIter
!= pTabEnd
;++pTabIter
)
187 if(match(tableNamePattern
,*pTabIter
,'\0'))
189 const Reference
< XColumnsSupplier
> xTable(xNames
->getByName(*pTabIter
),UNO_QUERY_THROW
);
190 OSL_ENSURE(xTable
.is(),"Table not found! Normallya exception had to be thrown here!");
191 aRow
[3] = new ORowSetValueDecorator(*pTabIter
);
193 const Reference
< XNameAccess
> xColumns
= xTable
->getColumns();
195 throw SQLException();
197 const Sequence
< ::rtl::OUString
> aColNames(xColumns
->getElementNames());
199 const ::rtl::OUString
* pColumnIter
= aColNames
.getConstArray();
200 const ::rtl::OUString
* pEnd
= pColumnIter
+ aColNames
.getLength();
201 Reference
< XPropertySet
> xColumn
;
202 for(sal_Int32 i
=1;pColumnIter
!= pEnd
;++pColumnIter
,++i
)
204 if(match(columnNamePattern
,*pColumnIter
,'\0'))
206 aRow
[4] = new ORowSetValueDecorator( *pColumnIter
);
208 xColumns
->getByName(*pColumnIter
) >>= xColumn
;
209 OSL_ENSURE(xColumn
.is(),"Columns contains a column who isn't a fastpropertyset!");
210 aRow
[5] = new ORowSetValueDecorator(::comphelper::getINT32(xColumn
->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE
))));
211 aRow
[6] = new ORowSetValueDecorator(::comphelper::getString(xColumn
->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPENAME
))));
212 aRow
[7] = new ORowSetValueDecorator(::comphelper::getINT32(xColumn
->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION
))));
213 // aRow[8] = xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPENAME));
214 aRow
[9] = new ORowSetValueDecorator(::comphelper::getINT32(xColumn
->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE
))));
215 aRow
[11] = new ORowSetValueDecorator(::comphelper::getINT32(xColumn
->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISNULLABLE
))));
216 // aRow[12] = xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPENAME));
217 aRow
[13] = new ORowSetValueDecorator(::comphelper::getString(xColumn
->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE
))));
218 // aRow[14] = xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPENAME));
219 // aRow[15] = xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPENAME));
220 switch(sal_Int32(aRow
[5]->getValue()))
223 case DataType::VARCHAR
:
224 aRow
[16] = new ORowSetValueDecorator((sal_Int32
)254);
226 case DataType::LONGVARCHAR
:
227 aRow
[16] = new ORowSetValueDecorator((sal_Int32
)65535);
230 aRow
[16] = new ORowSetValueDecorator((sal_Int32
)0);
232 aRow
[17] = new ORowSetValueDecorator(i
);
233 switch(sal_Int32(aRow
[11]->getValue()))
235 case ColumnValue::NO_NULLS
:
236 aRow
[18] = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("NO"));
238 case ColumnValue::NULLABLE
:
239 aRow
[18] = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("YES"));
242 aRow
[18] = new ORowSetValueDecorator(::rtl::OUString());
244 aRows
.push_back(aRow
);
250 ODatabaseMetaDataResultSet
* pResult
= new ODatabaseMetaDataResultSet(::connectivity::ODatabaseMetaDataResultSet::eColumns
);
251 Reference
< XResultSet
> xRef
= pResult
;
252 pResult
->setRows(aRows
);
257 // -------------------------------------------------------------------------
259 ::rtl::OUString SAL_CALL
OCalcDatabaseMetaData::getURL( ) throw(SQLException
, RuntimeException
)
261 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "calc", "Ocke.Janssen@sun.com", "OCalcDatabaseMetaData::getURL" );
262 ::osl::MutexGuard
aGuard( m_aMutex
);
264 return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("sdbc:calc:")) + m_pConnection
->getURL();
267 // -------------------------------------------------------------------------
269 sal_Int32 SAL_CALL
OCalcDatabaseMetaData::getMaxBinaryLiteralLength( ) throw(SQLException
, RuntimeException
)
271 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "calc", "Ocke.Janssen@sun.com", "OCalcDatabaseMetaData::getMaxBinaryLiteralLength" );
272 return STRING_MAXLEN
;
275 // -------------------------------------------------------------------------
277 sal_Int32 SAL_CALL
OCalcDatabaseMetaData::getMaxCharLiteralLength( ) throw(SQLException
, RuntimeException
)
279 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "calc", "Ocke.Janssen@sun.com", "OCalcDatabaseMetaData::getMaxCharLiteralLength" );
280 return STRING_MAXLEN
;
282 // -------------------------------------------------------------------------
283 sal_Int32 SAL_CALL
OCalcDatabaseMetaData::getMaxColumnNameLength( ) throw(SQLException
, RuntimeException
)
285 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "calc", "Ocke.Janssen@sun.com", "OCalcDatabaseMetaData::getMaxColumnNameLength" );
286 return STRING_MAXLEN
;
288 // -------------------------------------------------------------------------
289 sal_Int32 SAL_CALL
OCalcDatabaseMetaData::getMaxColumnsInIndex( ) throw(SQLException
, RuntimeException
)
291 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "calc", "Ocke.Janssen@sun.com", "OCalcDatabaseMetaData::getMaxColumnsInIndex" );
294 // -------------------------------------------------------------------------
295 sal_Int32 SAL_CALL
OCalcDatabaseMetaData::getMaxColumnsInTable( ) throw(SQLException
, RuntimeException
)
297 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "calc", "Ocke.Janssen@sun.com", "OCalcDatabaseMetaData::getMaxColumnsInTable" );
301 // -------------------------------------------------------------------------
303 sal_Bool
lcl_IsEmptyOrHidden( const Reference
<XSpreadsheets
>& xSheets
, const ::rtl::OUString
& rName
)
305 Any aAny
= xSheets
->getByName( rName
);
306 Reference
<XSpreadsheet
> xSheet
;
307 if ( aAny
>>= xSheet
)
309 // test if sheet is hidden
311 Reference
<XPropertySet
> xProp( xSheet
, UNO_QUERY
);
314 sal_Bool bVisible
= sal_Bool();
315 Any aVisAny
= xProp
->getPropertyValue( ::rtl::OUString::createFromAscii("IsVisible") );
316 if ( aVisAny
>>= bVisible
)
318 return sal_True
; // hidden
322 // test if whole sheet is empty
324 Reference
<XCellRangeAddressable
> xAddr( xSheet
, UNO_QUERY
);
325 Reference
<XCellRangesQuery
> xQuery( xSheet
, UNO_QUERY
);
326 if ( xAddr
.is() && xQuery
.is() )
328 CellRangeAddress aTotalRange
= xAddr
->getRangeAddress();
329 // queryIntersection to get a ranges object
330 Reference
<XSheetCellRanges
> xRanges
= xQuery
->queryIntersection( aTotalRange
);
333 Reference
<XEnumerationAccess
> xCells
= xRanges
->getCells();
336 if ( !xCells
->hasElements() )
337 return sal_True
; // empty
343 // use the same data area as in OCalcTable to test for empty table
345 Reference
<XSheetCellCursor
> xCursor
= xSheet
->createCursor();
346 Reference
<XCellRangeAddressable
> xRange( xCursor
, UNO_QUERY
);
349 xCursor
->collapseToSize( 1, 1 ); // single (first) cell
350 xCursor
->collapseToCurrentRegion(); // contiguous data area
352 CellRangeAddress aRangeAddr
= xRange
->getRangeAddress();
353 if ( aRangeAddr
.StartColumn
== aRangeAddr
.EndColumn
&&
354 aRangeAddr
.StartRow
== aRangeAddr
.EndRow
)
356 // single cell -> check content
357 Reference
<XCell
> xCell
= xCursor
->getCellByPosition( 0, 0 );
358 if ( xCell
.is() && xCell
->getType() == CellContentType_EMPTY
)
367 sal_Bool
lcl_IsUnnamed( const Reference
<XDatabaseRanges
>& xRanges
, const ::rtl::OUString
& rName
)
369 sal_Bool bUnnamed
= sal_False
;
371 Any aAny
= xRanges
->getByName( rName
);
372 Reference
<XDatabaseRange
> xRange
;
373 if ( aAny
>>= xRange
)
375 Reference
<XPropertySet
> xRangeProp( xRange
, UNO_QUERY
);
376 if ( xRangeProp
.is() )
380 Any aUserAny
= xRangeProp
->getPropertyValue( ::rtl::OUString::createFromAscii("IsUserDefined") );
381 sal_Bool bUserDefined
= sal_Bool();
382 if ( aUserAny
>>= bUserDefined
)
383 bUnnamed
= !bUserDefined
;
385 catch ( UnknownPropertyException
& )
395 // -------------------------------------------------------------------------
397 Reference
< XResultSet
> SAL_CALL
OCalcDatabaseMetaData::getTables(
398 const Any
& /*catalog*/, const ::rtl::OUString
& /*schemaPattern*/,
399 const ::rtl::OUString
& tableNamePattern
, const Sequence
< ::rtl::OUString
>& types
)
400 throw(SQLException
, RuntimeException
)
402 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "calc", "Ocke.Janssen@sun.com", "OCalcDatabaseMetaData::getTables" );
403 ::osl::MutexGuard
aGuard( m_aMutex
);
405 ODatabaseMetaDataResultSet
* pResult
= new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eTables
);
406 Reference
< XResultSet
> xRef
= pResult
;
408 // check if ORowSetValue type is given
409 // when no types are given then we have to return all tables e.g. TABLE
411 ::rtl::OUString
aTable(::rtl::OUString::createFromAscii("TABLE"));
413 sal_Bool bTableFound
= sal_True
;
414 sal_Int32 nLength
= types
.getLength();
417 bTableFound
= sal_False
;
419 const ::rtl::OUString
* pIter
= types
.getConstArray();
420 const ::rtl::OUString
* pEnd
= pIter
+ nLength
;
421 for(;pIter
!= pEnd
;++pIter
)
425 bTableFound
= sal_True
;
433 // get the sheet names from the document
435 OCalcConnection::ODocHolder
aDocHodler(((OCalcConnection
*)m_pConnection
));
436 Reference
<XSpreadsheetDocument
> xDoc
= aDocHodler
.getDoc();
438 throw SQLException();
439 Reference
<XSpreadsheets
> xSheets
= xDoc
->getSheets();
441 throw SQLException();
442 Sequence
< ::rtl::OUString
> aSheetNames
= xSheets
->getElementNames();
444 ODatabaseMetaDataResultSet::ORows aRows
;
445 sal_Int32 nSheetCount
= aSheetNames
.getLength();
446 for (sal_Int32 nSheet
=0; nSheet
<nSheetCount
; nSheet
++)
448 ::rtl::OUString aName
= aSheetNames
[nSheet
];
449 if ( !lcl_IsEmptyOrHidden( xSheets
, aName
) && match(tableNamePattern
,aName
,'\0') )
451 ODatabaseMetaDataResultSet::ORow
aRow(3);
453 aRow
.push_back(new ORowSetValueDecorator(aName
));
454 aRow
.push_back(new ORowSetValueDecorator(aTable
));
455 aRow
.push_back(ODatabaseMetaDataResultSet::getEmptyValue());
456 aRows
.push_back(aRow
);
460 // also use database ranges
462 Reference
<XPropertySet
> xDocProp( xDoc
, UNO_QUERY
);
465 Any aRangesAny
= xDocProp
->getPropertyValue( ::rtl::OUString::createFromAscii("DatabaseRanges") );
466 Reference
<XDatabaseRanges
> xRanges
;
467 if ( aRangesAny
>>= xRanges
)
469 Sequence
< ::rtl::OUString
> aDBNames
= xRanges
->getElementNames();
470 sal_Int32 nDBCount
= aDBNames
.getLength();
471 for (sal_Int32 nRange
=0; nRange
<nDBCount
; nRange
++)
473 ::rtl::OUString aName
= aDBNames
[nRange
];
474 if ( !lcl_IsUnnamed( xRanges
, aName
) && match(tableNamePattern
,aName
,'\0') )
476 ODatabaseMetaDataResultSet::ORow
aRow(3);
478 aRow
.push_back(new ORowSetValueDecorator(aName
));
479 aRow
.push_back(new ORowSetValueDecorator(aTable
));
480 aRow
.push_back(ODatabaseMetaDataResultSet::getEmptyValue());
481 aRows
.push_back(aRow
);
487 pResult
->setRows(aRows
);
491 // -----------------------------------------------------------------------------