1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "calc/CTable.hxx"
21 #include <com/sun/star/sdbc/ColumnValue.hpp>
22 #include <com/sun/star/sdbc/DataType.hpp>
23 #include <com/sun/star/sdbc/XRow.hpp>
24 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
25 #include <com/sun/star/sheet/XSpreadsheet.hpp>
26 #include <com/sun/star/sheet/XCellRangeAddressable.hpp>
27 #include <com/sun/star/sheet/XCellRangesQuery.hpp>
28 #include <com/sun/star/sheet/XDatabaseRanges.hpp>
29 #include <com/sun/star/sheet/XDatabaseRange.hpp>
30 #include <com/sun/star/sheet/XCellRangeReferrer.hpp>
31 #include <com/sun/star/sheet/XUsedAreaCursor.hpp>
32 #include <com/sun/star/sheet/CellFlags.hpp>
33 #include <com/sun/star/sheet/FormulaResult.hpp>
34 #include <com/sun/star/util/NumberFormat.hpp>
35 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
36 #include <com/sun/star/text/XText.hpp>
37 #include <svl/converter.hxx>
38 #include "calc/CConnection.hxx"
39 #include "calc/CColumns.hxx"
40 #include "connectivity/sdbcx/VColumn.hxx"
41 #include <rtl/ustrbuf.hxx>
42 #include <osl/thread.h>
43 #include <comphelper/sequence.hxx>
44 #include <svl/zforlist.hxx>
45 #include <rtl/math.hxx>
46 #include <comphelper/extract.hxx>
47 #include <connectivity/dbexception.hxx>
48 #include <connectivity/dbconversion.hxx>
49 #include <comphelper/types.hxx>
51 using namespace connectivity
;
52 using namespace connectivity::calc
;
53 using namespace connectivity::file
;
54 using namespace ::cppu
;
55 using namespace ::dbtools
;
56 using namespace ::com::sun::star::uno
;
57 using namespace ::com::sun::star::beans
;
58 using namespace ::com::sun::star::sdbcx
;
59 using namespace ::com::sun::star::sdbc
;
60 using namespace ::com::sun::star::container
;
61 using namespace ::com::sun::star::lang
;
62 using namespace ::com::sun::star::sheet
;
63 using namespace ::com::sun::star::table
;
64 using namespace ::com::sun::star::text
;
65 using namespace ::com::sun::star::util
;
68 static void lcl_UpdateArea( const Reference
<XCellRange
>& xUsedRange
, sal_Int32
& rEndCol
, sal_Int32
& rEndRow
)
70 // update rEndCol, rEndRow if any non-empty cell in xUsedRange is right/below
72 const Reference
<XCellRangesQuery
> xUsedQuery( xUsedRange
, UNO_QUERY
);
73 if ( xUsedQuery
.is() )
75 const sal_Int16 nContentFlags
=
76 CellFlags::STRING
| CellFlags::VALUE
| CellFlags::DATETIME
| CellFlags::FORMULA
| CellFlags::ANNOTATION
;
78 const Reference
<XSheetCellRanges
> xUsedRanges
= xUsedQuery
->queryContentCells( nContentFlags
);
79 const Sequence
<CellRangeAddress
> aAddresses
= xUsedRanges
->getRangeAddresses();
81 const sal_Int32 nCount
= aAddresses
.getLength();
82 const CellRangeAddress
* pData
= aAddresses
.getConstArray();
83 for ( sal_Int32 i
=0; i
<nCount
; i
++ )
85 rEndCol
= pData
[i
].EndColumn
> rEndCol
? pData
[i
].EndColumn
: rEndCol
;
86 rEndRow
= pData
[i
].EndRow
> rEndRow
? pData
[i
].EndRow
: rEndRow
;
91 static void lcl_GetDataArea( const Reference
<XSpreadsheet
>& xSheet
, sal_Int32
& rColumnCount
, sal_Int32
& rRowCount
)
93 Reference
<XSheetCellCursor
> xCursor
= xSheet
->createCursor();
94 Reference
<XCellRangeAddressable
> xRange( xCursor
, UNO_QUERY
);
97 rColumnCount
= rRowCount
= 0;
101 // first find the contiguous cell area starting at A1
103 xCursor
->collapseToSize( 1, 1 ); // single (first) cell
104 xCursor
->collapseToCurrentRegion(); // contiguous data area
106 CellRangeAddress aRegionAddr
= xRange
->getRangeAddress();
107 sal_Int32 nEndCol
= aRegionAddr
.EndColumn
;
108 sal_Int32 nEndRow
= aRegionAddr
.EndRow
;
110 Reference
<XUsedAreaCursor
> xUsed( xCursor
, UNO_QUERY
);
113 // The used area from XUsedAreaCursor includes visible attributes.
114 // If the used area is larger than the contiguous cell area, find non-empty
115 // cells in that area.
117 xUsed
->gotoEndOfUsedArea( sal_False
);
118 CellRangeAddress aUsedAddr
= xRange
->getRangeAddress();
120 if ( aUsedAddr
.EndColumn
> aRegionAddr
.EndColumn
)
122 Reference
<XCellRange
> xUsedRange
= xSheet
->getCellRangeByPosition(
123 aRegionAddr
.EndColumn
+ 1, 0, aUsedAddr
.EndColumn
, aUsedAddr
.EndRow
);
124 lcl_UpdateArea( xUsedRange
, nEndCol
, nEndRow
);
127 if ( aUsedAddr
.EndRow
> aRegionAddr
.EndRow
)
129 // only up to the last column of aRegionAddr, the other columns are handled above
130 Reference
<XCellRange
> xUsedRange
= xSheet
->getCellRangeByPosition(
131 0, aRegionAddr
.EndRow
+ 1, aRegionAddr
.EndColumn
, aUsedAddr
.EndRow
);
132 lcl_UpdateArea( xUsedRange
, nEndCol
, nEndRow
);
136 rColumnCount
= nEndCol
+ 1; // number of columns
137 rRowCount
= nEndRow
; // first row (headers) is not counted
140 static CellContentType
lcl_GetContentOrResultType( const Reference
<XCell
>& xCell
)
142 CellContentType eCellType
= xCell
->getType();
143 if ( eCellType
== CellContentType_FORMULA
)
145 static const OUString
s_sFormulaResultType("FormulaResultType");
146 Reference
<XPropertySet
> xProp( xCell
, UNO_QUERY
);
149 xProp
->getPropertyValue( s_sFormulaResultType
) >>= eCellType
; // type of formula result
151 catch (UnknownPropertyException
&)
153 eCellType
= CellContentType_VALUE
; // if FormulaResultType property not available
159 static Reference
<XCell
> lcl_GetUsedCell( const Reference
<XSpreadsheet
>& xSheet
, sal_Int32 nDocColumn
, sal_Int32 nDocRow
)
161 Reference
<XCell
> xCell
= xSheet
->getCellByPosition( nDocColumn
, nDocRow
);
162 if ( xCell
.is() && xCell
->getType() == CellContentType_EMPTY
)
164 // get first non-empty cell
166 Reference
<XCellRangeAddressable
> xAddr( xSheet
, UNO_QUERY
);
169 CellRangeAddress aTotalRange
= xAddr
->getRangeAddress();
170 sal_Int32 nLastRow
= aTotalRange
.EndRow
;
171 Reference
<XCellRangesQuery
> xQuery( xSheet
->getCellRangeByPosition( nDocColumn
, nDocRow
, nDocColumn
, nLastRow
), UNO_QUERY
);
174 // queryIntersection to get a ranges object
175 Reference
<XSheetCellRanges
> xRanges
= xQuery
->queryIntersection( aTotalRange
);
178 Reference
<XEnumerationAccess
> xCells
= xRanges
->getCells();
181 Reference
<XEnumeration
> xEnum
= xCells
->createEnumeration();
182 if ( xEnum
.is() && xEnum
->hasMoreElements() )
184 // get first non-empty cell from enumeration
185 xCell
.set(xEnum
->nextElement(),UNO_QUERY
);
187 // otherwise, keep empty cell
196 static bool lcl_HasTextInColumn( const Reference
<XSpreadsheet
>& xSheet
, sal_Int32 nDocColumn
, sal_Int32 nDocRow
)
198 // look for any text cell or text result in the column
200 Reference
<XCellRangeAddressable
> xAddr( xSheet
, UNO_QUERY
);
203 CellRangeAddress aTotalRange
= xAddr
->getRangeAddress();
204 sal_Int32 nLastRow
= aTotalRange
.EndRow
;
205 Reference
<XCellRangesQuery
> xQuery( xSheet
->getCellRangeByPosition( nDocColumn
, nDocRow
, nDocColumn
, nLastRow
), UNO_QUERY
);
208 // are there text cells in the column?
209 Reference
<XSheetCellRanges
> xTextContent
= xQuery
->queryContentCells( CellFlags::STRING
);
210 if ( xTextContent
.is() && xTextContent
->hasElements() )
213 // are there formulas with text results in the column?
214 Reference
<XSheetCellRanges
> xTextFormula
= xQuery
->queryFormulaCells( FormulaResult::STRING
);
215 if ( xTextFormula
.is() && xTextFormula
->hasElements() )
223 static void lcl_GetColumnInfo( const Reference
<XSpreadsheet
>& xSheet
, const Reference
<XNumberFormats
>& xFormats
,
224 sal_Int32 nDocColumn
, sal_Int32 nStartRow
, bool bHasHeaders
,
225 OUString
& rName
, sal_Int32
& rDataType
, bool& rCurrency
)
227 //! avoid duplicate field names
229 // get column name from first row, if range contains headers
233 Reference
<XText
> xHeaderText( xSheet
->getCellByPosition( nDocColumn
, nStartRow
), UNO_QUERY
);
234 if ( xHeaderText
.is() )
235 rName
= xHeaderText
->getString();
238 // get column type from first data row
240 sal_Int32 nDataRow
= nStartRow
;
243 Reference
<XCell
> xDataCell
= lcl_GetUsedCell( xSheet
, nDocColumn
, nDataRow
);
245 Reference
<XPropertySet
> xProp( xDataCell
, UNO_QUERY
);
248 rCurrency
= false; // set to true for currency below
250 const CellContentType eCellType
= lcl_GetContentOrResultType( xDataCell
);
251 // #i35178# use "text" type if there is any text cell in the column
252 if ( eCellType
== CellContentType_TEXT
|| lcl_HasTextInColumn( xSheet
, nDocColumn
, nDataRow
) )
253 rDataType
= DataType::VARCHAR
;
254 else if ( eCellType
== CellContentType_VALUE
)
256 // get number format to distinguish between different types
258 sal_Int16 nNumType
= NumberFormat::NUMBER
;
261 static OUString
s_NumberFormat("NumberFormat");
264 if ( xProp
->getPropertyValue( s_NumberFormat
) >>= nKey
)
266 const Reference
<XPropertySet
> xFormat
= xFormats
->getByKey( nKey
);
269 xFormat
->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE
) ) >>= nNumType
;
277 if ( nNumType
& NumberFormat::TEXT
)
278 rDataType
= DataType::VARCHAR
;
279 else if ( nNumType
& NumberFormat::NUMBER
)
280 rDataType
= DataType::DECIMAL
;
281 else if ( nNumType
& NumberFormat::CURRENCY
)
284 rDataType
= DataType::DECIMAL
;
286 else if ( ( nNumType
& NumberFormat::DATETIME
) == NumberFormat::DATETIME
)
288 // NumberFormat::DATETIME is DATE | TIME
289 rDataType
= DataType::TIMESTAMP
;
291 else if ( nNumType
& NumberFormat::DATE
)
292 rDataType
= DataType::DATE
;
293 else if ( nNumType
& NumberFormat::TIME
)
294 rDataType
= DataType::TIME
;
295 else if ( nNumType
& NumberFormat::LOGICAL
)
296 rDataType
= DataType::BIT
;
298 rDataType
= DataType::DECIMAL
;
302 // whole column empty
303 rDataType
= DataType::VARCHAR
;
310 static void lcl_SetValue( ORowSetValue
& rValue
, const Reference
<XSpreadsheet
>& xSheet
,
311 sal_Int32 nStartCol
, sal_Int32 nStartRow
, bool bHasHeaders
,
312 const ::Date
& rNullDate
,
313 sal_Int32 nDBRow
, sal_Int32 nDBColumn
, sal_Int32 nType
)
315 sal_Int32 nDocColumn
= nStartCol
+ nDBColumn
- 1; // database counts from 1
316 sal_Int32 nDocRow
= nStartRow
+ nDBRow
- 1;
320 const Reference
<XCell
> xCell
= xSheet
->getCellByPosition( nDocColumn
, nDocRow
);
323 CellContentType eCellType
= lcl_GetContentOrResultType( xCell
);
326 case DataType::VARCHAR
:
327 if ( eCellType
== CellContentType_EMPTY
)
331 // #i25840# still let Calc convert numbers to text
332 const Reference
<XText
> xText( xCell
, UNO_QUERY
);
334 rValue
= xText
->getString();
337 case DataType::DECIMAL
:
338 if ( eCellType
== CellContentType_VALUE
)
339 rValue
= xCell
->getValue(); // double
344 if ( eCellType
== CellContentType_VALUE
)
345 rValue
= xCell
->getValue() != 0.0;
350 if ( eCellType
== CellContentType_VALUE
)
352 ::Date
aDate( rNullDate
);
353 aDate
+= (long)::rtl::math::approxFloor( xCell
->getValue() );
354 ::com::sun::star::util::Date
aDateStruct( aDate
.GetDay(), aDate
.GetMonth(), aDate
.GetYear() );
355 rValue
= aDateStruct
;
361 if ( eCellType
== CellContentType_VALUE
)
363 double fCellVal
= xCell
->getValue();
364 double fTime
= fCellVal
- rtl::math::approxFloor( fCellVal
);
365 sal_Int64 nIntTime
= static_cast<sal_Int64
>(rtl::math::round( fTime
* static_cast<double>(::Time::nanoSecPerDay
) ));
366 if ( nIntTime
== ::Time::nanoSecPerDay
)
367 nIntTime
= 0; // 23:59:59.9999999995 and above is 00:00:00.00
368 ::com::sun::star::util::Time aTime
;
369 aTime
.NanoSeconds
= (sal_uInt32
)( nIntTime
% ::Time::nanoSecPerSec
);
370 nIntTime
/= ::Time::nanoSecPerSec
;
371 aTime
.Seconds
= (sal_uInt16
)( nIntTime
% 60 );
373 aTime
.Minutes
= (sal_uInt16
)( nIntTime
% 60 );
375 OSL_ENSURE( nIntTime
< 24, "error in time calculation" );
376 aTime
.Hours
= (sal_uInt16
) nIntTime
;
382 case DataType::TIMESTAMP
:
383 if ( eCellType
== CellContentType_VALUE
)
385 double fCellVal
= xCell
->getValue();
386 double fDays
= ::rtl::math::approxFloor( fCellVal
);
387 double fTime
= fCellVal
- fDays
;
388 long nIntDays
= (long)fDays
;
389 sal_Int64 nIntTime
= ::rtl::math::round( fTime
* static_cast<double>(::Time::nanoSecPerDay
) );
390 if ( nIntTime
== ::Time::nanoSecPerDay
)
392 nIntTime
= 0; // 23:59:59.9999999995 and above is 00:00:00.00
393 ++nIntDays
; // (next day)
396 ::com::sun::star::util::DateTime aDateTime
;
398 aDateTime
.NanoSeconds
= (sal_uInt16
)( nIntTime
% ::Time::nanoSecPerSec
);
399 nIntTime
/= ::Time::nanoSecPerSec
;
400 aDateTime
.Seconds
= (sal_uInt16
)( nIntTime
% 60 );
402 aDateTime
.Minutes
= (sal_uInt16
)( nIntTime
% 60 );
404 OSL_ENSURE( nIntTime
< 24, "error in time calculation" );
405 aDateTime
.Hours
= (sal_uInt16
) nIntTime
;
407 ::Date
aDate( rNullDate
);
409 aDateTime
.Day
= aDate
.GetDay();
410 aDateTime
.Month
= aDate
.GetMonth();
411 aDateTime
.Year
= aDate
.GetYear();
421 // rValue.setTypeKind(nType);
426 static OUString
lcl_GetColumnStr( sal_Int32 nColumn
)
429 return OUString( (sal_Unicode
) ( 'A' + nColumn
) );
432 OUStringBuffer
aBuffer(2);
433 aBuffer
.setLength( 2 );
434 aBuffer
[0] = (sal_Unicode
) ( 'A' + ( nColumn
/ 26 ) - 1 );
435 aBuffer
[1] = (sal_Unicode
) ( 'A' + ( nColumn
% 26 ) );
436 return aBuffer
.makeStringAndClear();
440 void OCalcTable::fillColumns()
442 if ( !m_xSheet
.is() )
443 throw SQLException();
446 ::comphelper::UStringMixEqual
aCase(m_pConnection
->getMetaData()->supportsMixedCaseQuotedIdentifiers());
447 const bool bStoresMixedCaseQuotedIdentifiers
= getConnection()->getMetaData()->supportsMixedCaseQuotedIdentifiers();
449 for (sal_Int32 i
= 0; i
< m_nDataCols
; i
++)
451 OUString aColumnName
;
452 sal_Int32 eType
= DataType::OTHER
;
453 bool bCurrency
= false;
455 lcl_GetColumnInfo( m_xSheet
, m_xFormats
, m_nStartCol
+ i
, m_nStartRow
, m_bHasHeaders
,
456 aColumnName
, eType
, bCurrency
);
458 if ( aColumnName
.isEmpty() )
459 aColumnName
= lcl_GetColumnStr( i
);
461 sal_Int32 nPrecision
= 0; //! ...
462 sal_Int32 nDecimals
= 0; //! ...
466 case DataType::VARCHAR
:
468 static const OUString
s_sType("VARCHAR");
472 case DataType::DECIMAL
:
473 aTypeName
= "DECIMAL";
484 case DataType::TIMESTAMP
:
485 aTypeName
= "TIMESTAMP";
488 SAL_WARN( "connectivity.drivers","missing type name");
492 // check if the column name already exists
493 OUString aAlias
= aColumnName
;
494 OSQLColumns::Vector::const_iterator aFind
= connectivity::find(m_aColumns
->get().begin(),m_aColumns
->get().end(),aAlias
,aCase
);
495 sal_Int32 nExprCnt
= 0;
496 while(aFind
!= m_aColumns
->get().end())
498 (aAlias
= aColumnName
) += OUString::number(++nExprCnt
);
499 aFind
= connectivity::find(m_aColumns
->get().begin(),m_aColumns
->get().end(),aAlias
,aCase
);
502 sdbcx::OColumn
* pColumn
= new sdbcx::OColumn( aAlias
, aTypeName
, OUString(),OUString(),
503 ColumnValue::NULLABLE
, nPrecision
, nDecimals
,
504 eType
, false, false, bCurrency
,
505 bStoresMixedCaseQuotedIdentifiers
,
506 m_CatalogName
, getSchema(), getName());
507 Reference
< XPropertySet
> xCol
= pColumn
;
508 m_aColumns
->get().push_back(xCol
);
509 m_aTypes
.push_back(eType
);
510 m_aPrecisions
.push_back(nPrecision
);
511 m_aScales
.push_back(nDecimals
);
516 OCalcTable::OCalcTable(sdbcx::OCollection
* _pTables
,OCalcConnection
* _pConnection
,
517 const OUString
& _Name
,
518 const OUString
& _Type
,
519 const OUString
& _Description
,
520 const OUString
& _SchemaName
,
521 const OUString
& _CatalogName
522 ) : OCalcTable_BASE(_pTables
,_pConnection
,_Name
,
527 ,m_pConnection(_pConnection
)
532 ,m_bHasHeaders(false)
533 ,m_aNullDate(::Date::EMPTY
)
537 void OCalcTable::construct()
540 Reference
< XSpreadsheetDocument
> xDoc
= m_pConnection
->acquireDoc();
543 Reference
<XSpreadsheets
> xSheets
= xDoc
->getSheets();
544 if ( xSheets
.is() && xSheets
->hasByName( m_Name
) )
546 m_xSheet
.set(xSheets
->getByName( m_Name
),UNO_QUERY
);
549 lcl_GetDataArea( m_xSheet
, m_nDataCols
, m_nDataRows
);
550 m_bHasHeaders
= true;
551 // whole sheet is always assumed to include a header row
554 else // no sheet -> try database range
556 Reference
<XPropertySet
> xDocProp( xDoc
, UNO_QUERY
);
559 Reference
<XDatabaseRanges
> xRanges(xDocProp
->getPropertyValue("DatabaseRanges"),UNO_QUERY
);
561 if ( xRanges
.is() && xRanges
->hasByName( m_Name
) )
563 Reference
<XDatabaseRange
> xDBRange(xRanges
->getByName( m_Name
),UNO_QUERY
);
564 Reference
<XCellRangeReferrer
> xRefer( xDBRange
, UNO_QUERY
);
567 // Header flag is always stored with database range
568 // Get flag from FilterDescriptor
570 bool bRangeHeader
= true;
571 Reference
<XPropertySet
> xFiltProp( xDBRange
->getFilterDescriptor(), UNO_QUERY
);
572 if ( xFiltProp
.is() )
573 xFiltProp
->getPropertyValue("ContainsHeader") >>= bRangeHeader
;
575 Reference
<XSheetCellRange
> xSheetRange( xRefer
->getReferredCells(), UNO_QUERY
);
576 Reference
<XCellRangeAddressable
> xAddr( xSheetRange
, UNO_QUERY
);
577 if ( xSheetRange
.is() && xAddr
.is() )
579 m_xSheet
= xSheetRange
->getSpreadsheet();
580 CellRangeAddress aRangeAddr
= xAddr
->getRangeAddress();
581 m_nStartCol
= aRangeAddr
.StartColumn
;
582 m_nStartRow
= aRangeAddr
.StartRow
;
583 m_nDataCols
= aRangeAddr
.EndColumn
- m_nStartCol
+ 1;
584 // m_nDataRows is excluding header row
585 m_nDataRows
= aRangeAddr
.EndRow
- m_nStartRow
;
588 // m_nDataRows counts the whole range
592 m_bHasHeaders
= bRangeHeader
;
599 Reference
<XNumberFormatsSupplier
> xSupp( xDoc
, UNO_QUERY
);
601 m_xFormats
= xSupp
->getNumberFormats();
603 Reference
<XPropertySet
> xProp( xDoc
, UNO_QUERY
);
606 ::com::sun::star::util::Date aDateStruct
;
607 if ( xProp
->getPropertyValue("NullDate") >>= aDateStruct
)
608 m_aNullDate
= ::Date( aDateStruct
.Day
, aDateStruct
.Month
, aDateStruct
.Year
);
612 //! default if no null date available?
619 void OCalcTable::refreshColumns()
621 ::osl::MutexGuard
aGuard( m_aMutex
);
623 TStringVector aVector
;
625 OSQLColumns::Vector::const_iterator aEnd
= m_aColumns
->get().end();
626 for(OSQLColumns::Vector::const_iterator aIter
= m_aColumns
->get().begin();aIter
!= aEnd
;++aIter
)
627 aVector
.push_back(Reference
< XNamed
>(*aIter
,UNO_QUERY
)->getName());
630 m_pColumns
->reFill(aVector
);
632 m_pColumns
= new OCalcColumns(this,m_aMutex
,aVector
);
635 void OCalcTable::refreshIndexes()
637 // Calc table has no index
641 void SAL_CALL
OCalcTable::disposing(void)
643 OFileTable::disposing();
644 ::osl::MutexGuard
aGuard(m_aMutex
);
647 m_pConnection
->releaseDoc();
648 m_pConnection
= NULL
;
652 Sequence
< Type
> SAL_CALL
OCalcTable::getTypes( ) throw(RuntimeException
, std::exception
)
654 Sequence
< Type
> aTypes
= OTable_TYPEDEF::getTypes();
655 ::std::vector
<Type
> aOwnTypes
;
656 aOwnTypes
.reserve(aTypes
.getLength());
658 const Type
* pBegin
= aTypes
.getConstArray();
659 const Type
* pEnd
= pBegin
+ aTypes
.getLength();
660 for(;pBegin
!= pEnd
;++pBegin
)
662 if(!( *pBegin
== ::getCppuType((const Reference
<XKeysSupplier
>*)0) ||
663 *pBegin
== ::getCppuType((const Reference
<XIndexesSupplier
>*)0) ||
664 *pBegin
== ::getCppuType((const Reference
<XRename
>*)0) ||
665 *pBegin
== ::getCppuType((const Reference
<XAlterTable
>*)0) ||
666 *pBegin
== ::getCppuType((const Reference
<XDataDescriptorFactory
>*)0)))
667 aOwnTypes
.push_back(*pBegin
);
669 aOwnTypes
.push_back(::getCppuType( (const Reference
< ::com::sun::star::lang::XUnoTunnel
> *)0 ));
671 const Type
* pAttrs
= aOwnTypes
.empty() ? 0 : &aOwnTypes
[0];
672 return Sequence
< Type
>(pAttrs
, aOwnTypes
.size());
676 Any SAL_CALL
OCalcTable::queryInterface( const Type
& rType
) throw(RuntimeException
, std::exception
)
678 if( rType
== ::getCppuType((const Reference
<XKeysSupplier
>*)0) ||
679 rType
== ::getCppuType((const Reference
<XIndexesSupplier
>*)0) ||
680 rType
== ::getCppuType((const Reference
<XRename
>*)0) ||
681 rType
== ::getCppuType((const Reference
<XAlterTable
>*)0) ||
682 rType
== ::getCppuType((const Reference
<XDataDescriptorFactory
>*)0))
685 const Any aRet
= ::cppu::queryInterface(rType
,static_cast< ::com::sun::star::lang::XUnoTunnel
*> (this));
686 return aRet
.hasValue() ? aRet
: OTable_TYPEDEF::queryInterface(rType
);
690 Sequence
< sal_Int8
> OCalcTable::getUnoTunnelImplementationId()
692 static ::cppu::OImplementationId
* pId
= 0;
695 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
698 static ::cppu::OImplementationId aId
;
702 return pId
->getImplementationId();
705 // com::sun::star::lang::XUnoTunnel
707 sal_Int64
OCalcTable::getSomething( const Sequence
< sal_Int8
> & rId
) throw (RuntimeException
, std::exception
)
709 return (rId
.getLength() == 16 && 0 == memcmp(getUnoTunnelImplementationId().getConstArray(), rId
.getConstArray(), 16 ) )
710 ? reinterpret_cast< sal_Int64
>( this )
711 : OCalcTable_BASE::getSomething(rId
);
714 sal_Int32
OCalcTable::getCurrentLastPos() const
719 bool OCalcTable::seekRow(IResultSetHelper::Movement eCursorPosition
, sal_Int32 nOffset
, sal_Int32
& nCurPos
)
721 // prepare positioning:
723 sal_uInt32 nNumberOfRecords
= m_nDataRows
;
724 sal_uInt32 nTempPos
= m_nFilePos
;
725 m_nFilePos
= nCurPos
;
727 switch(eCursorPosition
)
729 case IResultSetHelper::NEXT
:
732 case IResultSetHelper::PRIOR
:
736 case IResultSetHelper::FIRST
:
739 case IResultSetHelper::LAST
:
740 m_nFilePos
= nNumberOfRecords
;
742 case IResultSetHelper::RELATIVE
:
743 m_nFilePos
= (((sal_Int32
)m_nFilePos
) + nOffset
< 0) ? 0L
744 : (sal_uInt32
)(((sal_Int32
)m_nFilePos
) + nOffset
);
746 case IResultSetHelper::ABSOLUTE
:
747 case IResultSetHelper::BOOKMARK
:
748 m_nFilePos
= (sal_uInt32
)nOffset
;
752 if (m_nFilePos
> (sal_Int32
)nNumberOfRecords
)
753 m_nFilePos
= (sal_Int32
)nNumberOfRecords
+ 1;
755 if (m_nFilePos
== 0 || m_nFilePos
== (sal_Int32
)nNumberOfRecords
+ 1)
759 //! read buffer / setup row object etc?
764 switch(eCursorPosition
)
766 case IResultSetHelper::PRIOR
:
767 case IResultSetHelper::FIRST
:
770 case IResultSetHelper::LAST
:
771 case IResultSetHelper::NEXT
:
772 case IResultSetHelper::ABSOLUTE
:
773 case IResultSetHelper::RELATIVE
:
775 m_nFilePos
= nNumberOfRecords
+ 1;
776 else if (nOffset
< 0)
779 case IResultSetHelper::BOOKMARK
:
780 m_nFilePos
= nTempPos
; // previous position
782 // aStatus.Set(SDB_STAT_NO_DATA_FOUND);
786 nCurPos
= m_nFilePos
;
790 bool OCalcTable::fetchRow( OValueRefRow
& _rRow
, const OSQLColumns
& _rCols
,
791 bool _bUseTableDefs
, bool bRetrieveData
)
795 bool bIsCurRecordDeleted
= false;
796 _rRow
->setDeleted(bIsCurRecordDeleted
);
797 *(_rRow
->get())[0] = m_nFilePos
;
804 OSQLColumns::Vector::const_iterator aIter
= _rCols
.get().begin();
805 OSQLColumns::Vector::const_iterator aEnd
= _rCols
.get().end();
806 const OValueRefVector::Vector::size_type nCount
= _rRow
->get().size();
807 for (OValueRefVector::Vector::size_type i
= 1; aIter
!= aEnd
&& i
< nCount
;
810 if ( (_rRow
->get())[i
]->isBound() )
813 if ( _bUseTableDefs
)
814 nType
= m_aTypes
[i
-1];
816 (*aIter
)->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE
)) >>= nType
;
819 lcl_SetValue( (_rRow
->get())[i
]->get(), m_xSheet
, m_nStartCol
, m_nStartRow
, m_bHasHeaders
,
820 m_aNullDate
, m_nFilePos
, i
, nType
);
826 void OCalcTable::FileClose()
828 ::osl::MutexGuard
aGuard(m_aMutex
);
830 OCalcTable_BASE::FileClose();
834 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */