Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include "dpcachetable.hxx"
30 : : #include "document.hxx"
31 : : #include "address.hxx"
32 : : #include "cell.hxx"
33 : : #include "dptabdat.hxx"
34 : : #include "dptabsrc.hxx"
35 : : #include "dpobject.hxx"
36 : : #include "queryparam.hxx"
37 : : #include "queryentry.hxx"
38 : : #include "dpitemdata.hxx"
39 : :
40 : : #include <com/sun/star/i18n/LocaleDataItem.hpp>
41 : : #include <com/sun/star/sdbc/DataType.hpp>
42 : : #include <com/sun/star/sdbc/XRow.hpp>
43 : : #include <com/sun/star/sdbc/XRowSet.hpp>
44 : : #include <com/sun/star/sdbc/XResultSetMetaData.hpp>
45 : : #include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
46 : : #include <com/sun/star/util/Date.hpp>
47 : : #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
48 : : #include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
49 : :
50 : : #include <memory>
51 : :
52 : : using namespace ::com::sun::star;
53 : :
54 : : using ::rtl::OUString;
55 : : using ::std::vector;
56 : : using ::std::pair;
57 : : using ::std::auto_ptr;
58 : : using ::com::sun::star::i18n::LocaleDataItem;
59 : : using ::com::sun::star::uno::Exception;
60 : : using ::com::sun::star::uno::Reference;
61 : : using ::com::sun::star::uno::Sequence;
62 : : using ::com::sun::star::uno::Any;
63 : : using ::com::sun::star::uno::UNO_QUERY;
64 : : using ::com::sun::star::uno::UNO_QUERY_THROW;
65 : : using ::com::sun::star::sheet::DataPilotFieldFilter;
66 : :
67 : 1618 : bool ScDPCacheTable::RowFlag::isActive() const
68 : : {
69 [ + + ][ + + ]: 1618 : return mbShowByFilter && mbShowByPage;
70 : : }
71 : :
72 : 1024 : ScDPCacheTable::RowFlag::RowFlag() :
73 : : mbShowByFilter(true),
74 : 1024 : mbShowByPage(true)
75 : : {
76 : 1024 : }
77 : :
78 : 566 : ScDPCacheTable::SingleFilter::SingleFilter(const ScDPItemData& rItem) :
79 [ + - ]: 566 : maItem(rItem) {}
80 : :
81 : 1128 : bool ScDPCacheTable::SingleFilter::match(const ScDPItemData& rCellData) const
82 : : {
83 : 1128 : return maItem == rCellData;
84 : : }
85 : :
86 : 0 : const ScDPItemData& ScDPCacheTable::SingleFilter::getMatchValue() const
87 : : {
88 : 0 : return maItem;
89 : : }
90 : :
91 [ + - ]: 670 : ScDPCacheTable::GroupFilter::GroupFilter()
92 : : {
93 : 670 : }
94 : :
95 : 0 : bool ScDPCacheTable::GroupFilter::match(const ScDPItemData& rCellData) const
96 : : {
97 : 0 : vector<ScDPItemData>::const_iterator it = maItems.begin(), itEnd = maItems.end();
98 [ # # ][ # # ]: 0 : for (; it != itEnd; ++it)
[ # # ]
99 : : {
100 [ # # ][ # # ]: 0 : bool bMatch = *it == rCellData;
101 [ # # ]: 0 : if (bMatch)
102 : 0 : return true;
103 : : }
104 : 0 : return false;
105 : : }
106 : :
107 : 3321 : void ScDPCacheTable::GroupFilter::addMatchItem(const ScDPItemData& rItem)
108 : : {
109 : 3321 : maItems.push_back(rItem);
110 : 3321 : }
111 : :
112 : 670 : size_t ScDPCacheTable::GroupFilter::getMatchItemCount() const
113 : : {
114 : 670 : return maItems.size();
115 : : }
116 : :
117 : : // ----------------------------------------------------------------------------
118 : :
119 : 1236 : ScDPCacheTable::Criterion::Criterion() :
120 : : mnFieldIndex(-1),
121 : 1236 : mpFilter(static_cast<FilterBase*>(NULL))
122 : : {
123 : 1236 : }
124 : :
125 : : // ----------------------------------------------------------------------------
126 : :
127 : 117 : ScDPCacheTable::ScDPCacheTable(const ScDPCache* pCache) :
128 [ + - ]: 117 : mpCache(pCache)
129 : : {
130 : 117 : }
131 : :
132 : 117 : ScDPCacheTable::~ScDPCacheTable()
133 : : {
134 : 117 : }
135 : :
136 : 976 : sal_Int32 ScDPCacheTable::getRowSize() const
137 : : {
138 [ + - ]: 976 : return mpCache ? getCache()->GetRowCount() : 0;
139 : : }
140 : :
141 : 127388 : sal_Int32 ScDPCacheTable::getColSize() const
142 : : {
143 [ + - ]: 127388 : return mpCache ? getCache()->GetColumnCount() : 0;
144 : : }
145 : :
146 : 512 : void ScDPCacheTable::fillTable(
147 : : const ScQueryParam& rQuery, bool bIgnoreEmptyRows, bool bRepeatIfEmpty)
148 : : {
149 : 512 : const SCROW nRowCount = getRowSize();
150 : 512 : const SCCOL nColCount = (SCCOL) getColSize();
151 [ - + ][ + + ]: 512 : if ( nRowCount <= 0 || nColCount <= 0)
152 : 512 : return;
153 : :
154 : 171 : maRowFlags.clear();
155 : 171 : maRowFlags.reserve(nRowCount);
156 : :
157 : : // Initialize field entries container.
158 : 171 : maFieldEntries.clear();
159 : 171 : maFieldEntries.reserve(nColCount);
160 : :
161 : : // Data rows
162 [ + + ]: 857 : for (SCCOL nCol = 0; nCol < nColCount; ++nCol)
163 : : {
164 [ + - ]: 686 : maFieldEntries.push_back( vector<SCROW>() );
165 : 686 : SCROW nMemCount = getCache()->GetDimMemberCount( nCol );
166 [ + - ]: 686 : if ( nMemCount )
167 : : {
168 [ + - ]: 686 : std::vector<SCROW> aAdded( nMemCount, -1 );
169 : :
170 [ + + ]: 4511 : for (SCROW nRow = 0; nRow < nRowCount; ++nRow )
171 : : {
172 [ + - ][ + - ]: 3825 : SCROW nIndex = getCache()->GetItemDataId( nCol, nRow, bRepeatIfEmpty );
173 [ + - ]: 3825 : SCROW nOrder = getOrder( nCol, nIndex );
174 : :
175 [ + + ]: 3825 : if ( nCol == 0 )
176 : : {
177 [ + - ][ + - ]: 1024 : maRowFlags.push_back(RowFlag());
178 [ + - ]: 1024 : maRowFlags.back().mbShowByFilter = false;
179 : : }
180 : :
181 [ + - ][ + - ]: 3825 : if (!getCache()->ValidQuery(nRow, rQuery))
[ + + ]
182 : 220 : continue;
183 : :
184 [ + + ][ + - ]: 3605 : if ( bIgnoreEmptyRows && getCache()->IsRowEmpty( nRow ) )
[ + - ][ + + ]
[ + + ]
185 : 24 : continue;
186 : :
187 [ + + ]: 3581 : if ( nCol == 0 )
188 [ + - ]: 968 : maRowFlags.back().mbShowByFilter = true;
189 : :
190 [ + - ]: 3581 : aAdded[nOrder] = nIndex;
191 : : }
192 [ + + ]: 4094 : for ( SCROW nRow = 0; nRow < nMemCount; nRow++ )
193 : : {
194 [ + - ][ + + ]: 3408 : if ( aAdded[nRow] != -1 )
195 [ + - ][ + - ]: 3251 : maFieldEntries.back().push_back( aAdded[nRow] );
[ + - ]
196 : 686 : }
197 : : }
198 : : }
199 : : }
200 : :
201 : 0 : void ScDPCacheTable::fillTable()
202 : : {
203 : 0 : const SCROW nRowCount = getRowSize();
204 : 0 : const SCCOL nColCount = (SCCOL) getColSize();
205 [ # # ][ # # ]: 0 : if ( nRowCount <= 0 || nColCount <= 0)
206 : 0 : return;
207 : :
208 : 0 : maRowFlags.clear();
209 : 0 : maRowFlags.reserve(nRowCount);
210 : :
211 : :
212 : : // Initialize field entries container.
213 : 0 : maFieldEntries.clear();
214 : 0 : maFieldEntries.reserve(nColCount);
215 : :
216 : : // Data rows
217 [ # # ]: 0 : for (SCCOL nCol = 0; nCol < nColCount; ++nCol)
218 : : {
219 [ # # ]: 0 : maFieldEntries.push_back( vector<SCROW>() );
220 : 0 : SCROW nMemCount = getCache()->GetDimMemberCount( nCol );
221 [ # # ]: 0 : if ( nMemCount )
222 : : {
223 [ # # ]: 0 : std::vector< SCROW > pAdded( nMemCount, -1 );
224 : :
225 [ # # ]: 0 : for (SCROW nRow = 0; nRow < nRowCount; ++nRow )
226 : : {
227 [ # # ][ # # ]: 0 : SCROW nIndex = getCache()->GetItemDataId( nCol, nRow, false );
228 [ # # ]: 0 : SCROW nOrder = getOrder( nCol, nIndex );
229 : :
230 [ # # ]: 0 : if ( nCol == 0 )
231 : : {
232 [ # # ][ # # ]: 0 : maRowFlags.push_back(RowFlag());
233 [ # # ]: 0 : maRowFlags.back().mbShowByFilter = true;
234 : : }
235 : :
236 [ # # ]: 0 : pAdded[nOrder] = nIndex;
237 : : }
238 [ # # ]: 0 : for ( SCROW nRow = 0; nRow < nMemCount; nRow++ )
239 : : {
240 [ # # ][ # # ]: 0 : if ( pAdded[nRow] != -1 )
241 [ # # ][ # # ]: 0 : maFieldEntries.back().push_back( pAdded[nRow] );
[ # # ]
242 : 0 : }
243 : : }
244 : : }
245 : : }
246 : :
247 : 828 : bool ScDPCacheTable::isRowActive(sal_Int32 nRow) const
248 : : {
249 [ + - ][ - + ]: 828 : if (nRow < 0 || static_cast<size_t>(nRow) >= maRowFlags.size())
[ - + ]
250 : : // row index out of bound
251 : 0 : return false;
252 : :
253 : 828 : return maRowFlags[nRow].isActive();
254 : : }
255 : :
256 : 6 : void ScDPCacheTable::filterByPageDimension(const vector<Criterion>& rCriteria, const boost::unordered_set<sal_Int32>& rRepeatIfEmptyDims)
257 : : {
258 : 6 : sal_Int32 nRowSize = getRowSize();
259 [ - + ]: 6 : if (nRowSize != static_cast<sal_Int32>(maRowFlags.size()))
260 : : {
261 : : // sizes of the two tables differ!
262 : 6 : return;
263 : : }
264 : :
265 [ + + ]: 54 : for (sal_Int32 nRow = 0; nRow < nRowSize; ++nRow)
266 : 48 : maRowFlags[nRow].mbShowByPage = isRowQualified(nRow, rCriteria, rRepeatIfEmptyDims);
267 : : }
268 : :
269 : 2288 : const ScDPItemData* ScDPCacheTable::getCell(SCCOL nCol, SCROW nRow, bool bRepeatIfEmpty) const
270 : : {
271 [ - + ]: 2288 : if (!mpCache)
272 : 0 : return NULL;
273 : :
274 : 2288 : SCROW nId= getCache()->GetItemDataId(nCol, nRow, bRepeatIfEmpty);
275 : 2288 : return getCache()->GetItemDataById( nCol, nId );
276 : : }
277 : :
278 : 810 : void ScDPCacheTable::getValue( ScDPValueData& rVal, SCCOL nCol, SCROW nRow, bool bRepeatIfEmpty) const
279 : : {
280 : 810 : const ScDPItemData* pData = getCell( nCol, nRow, bRepeatIfEmpty );
281 : :
282 [ + - ]: 810 : if (pData)
283 : : {
284 [ + + ]: 810 : rVal.fValue = pData->IsValue() ? pData->GetValue() : 0.0;
285 : 810 : rVal.nType = pData->GetCellType();
286 : : }
287 : : else
288 : 0 : rVal.Set(0.0, SC_VALTYPE_EMPTY);
289 : 810 : }
290 : :
291 : 36829 : rtl::OUString ScDPCacheTable::getFieldName(SCCOL nIndex) const
292 : : {
293 [ - + ]: 36829 : if (!mpCache)
294 : 0 : return rtl::OUString();
295 : :
296 : 36829 : return getCache()->GetDimensionName( nIndex );
297 : : }
298 : :
299 : 1450 : const ::std::vector<SCROW>& ScDPCacheTable::getFieldEntries( sal_Int32 nColumn ) const
300 : : {
301 [ + - ][ - + ]: 1450 : if (nColumn < 0 || static_cast<size_t>(nColumn) >= maFieldEntries.size())
[ - + ]
302 : : {
303 : : // index out of bound. Hopefully this code will never be reached.
304 [ # # ][ # # ]: 0 : static const ::std::vector<SCROW> emptyEntries;
[ # # ][ # # ]
305 : 0 : return emptyEntries;
306 : : }
307 : 1450 : return maFieldEntries[nColumn];
308 : : }
309 : :
310 : 158 : void ScDPCacheTable::filterTable(const vector<Criterion>& rCriteria, Sequence< Sequence<Any> >& rTabData,
311 : : const boost::unordered_set<sal_Int32>& rRepeatIfEmptyDims)
312 : : {
313 [ + - ]: 158 : sal_Int32 nRowSize = getRowSize();
314 [ + - ]: 158 : sal_Int32 nColSize = getColSize();
315 : :
316 [ + - ]: 158 : if (!nRowSize)
317 : : // no data to filter.
318 : 158 : return;
319 : :
320 : : // Row first, then column.
321 [ + - ]: 158 : vector< Sequence<Any> > tableData;
322 [ + - ]: 158 : tableData.reserve(nRowSize+1);
323 : :
324 : : // Header first.
325 [ + - ]: 158 : Sequence<Any> headerRow(nColSize);
326 [ + + ]: 948 : for (SCCOL nCol = 0; nCol < nColSize; ++nCol)
327 : : {
328 : 790 : OUString str;
329 [ + - ]: 790 : str = getFieldName( nCol);
330 : 790 : Any any;
331 [ + - ]: 790 : any <<= str;
332 [ + - ]: 790 : headerRow[nCol] = any;
333 : 790 : }
334 [ + - ]: 158 : tableData.push_back(headerRow);
335 : :
336 : :
337 [ + + ]: 948 : for (sal_Int32 nRow = 0; nRow < nRowSize; ++nRow)
338 : : {
339 [ + - ][ + - ]: 790 : if (!maRowFlags[nRow].isActive())
[ - + ]
340 : : // This row is filtered out.
341 : 0 : continue;
342 : :
343 [ + - ][ + + ]: 790 : if (!isRowQualified(nRow, rCriteria, rRepeatIfEmptyDims))
344 : 720 : continue;
345 : :
346 : : // Insert this row into table.
347 : :
348 [ + - ]: 70 : Sequence<Any> row(nColSize);
349 [ + + ]: 420 : for (SCCOL nCol = 0; nCol < nColSize; ++nCol)
350 : : {
351 : 350 : Any any;
352 [ + - ]: 350 : bool bRepeatIfEmpty = rRepeatIfEmptyDims.count(nCol) > 0;
353 [ + - ]: 350 : const ScDPItemData* pData= getCell(nCol, nRow, bRepeatIfEmpty);
354 [ + - ][ + - ]: 350 : if ( pData->IsValue() )
355 [ + - ][ + - ]: 350 : any <<= pData->GetValue();
356 : : else
357 : : {
358 [ # # ]: 0 : OUString string (pData->GetString() );
359 [ # # ]: 0 : any <<= string;
360 : : }
361 [ + - ]: 350 : row[nCol] = any;
362 : 350 : }
363 [ + - ]: 70 : tableData.push_back(row);
364 [ + - ]: 790 : }
365 : :
366 : : // convert vector to Seqeunce
367 : 158 : sal_Int32 nTabSize = static_cast<sal_Int32>(tableData.size());
368 [ + - ]: 158 : rTabData.realloc(nTabSize);
369 [ + + ]: 386 : for (sal_Int32 i = 0; i < nTabSize; ++i)
370 [ + - ][ + - ]: 386 : rTabData[i] = tableData[i];
[ + - ]
371 : : }
372 : :
373 : 6953 : SCROW ScDPCacheTable::getOrder(long nDim, SCROW nIndex) const
374 : : {
375 : 6953 : return mpCache->GetOrder(nDim, nIndex);
376 : : }
377 : :
378 : 185 : void ScDPCacheTable::clear()
379 : : {
380 : 185 : maFieldEntries.clear();
381 : 185 : maRowFlags.clear();
382 : 185 : }
383 : :
384 : 129326 : bool ScDPCacheTable::empty() const
385 : : {
386 : 129326 : return maFieldEntries.empty();
387 : : }
388 : :
389 : 512 : bool ScDPCacheTable::hasCache() const
390 : : {
391 : 512 : return mpCache != NULL;
392 : : }
393 : :
394 : 838 : bool ScDPCacheTable::isRowQualified(sal_Int32 nRow, const vector<Criterion>& rCriteria,
395 : : const boost::unordered_set<sal_Int32>& rRepeatIfEmptyDims) const
396 : : {
397 [ + - ]: 838 : sal_Int32 nColSize = getColSize();
398 : 838 : vector<Criterion>::const_iterator itrEnd = rCriteria.end();
399 [ + - ][ + - ]: 1222 : for (vector<Criterion>::const_iterator itr = rCriteria.begin(); itr != itrEnd; ++itr)
[ + + ]
400 : : {
401 [ + - ][ - + ]: 1128 : if (itr->mnFieldIndex >= nColSize)
402 : : // specified field is outside the source data columns. Don't
403 : : // use this criterion.
404 : 0 : continue;
405 : :
406 : : // Check if the 'repeat if empty' flag is set for this field.
407 [ + - ][ + - ]: 1128 : bool bRepeatIfEmpty = rRepeatIfEmptyDims.count(itr->mnFieldIndex) > 0;
408 [ + - ][ + - ]: 1128 : const ScDPItemData* pCellData = getCell(static_cast<SCCOL>(itr->mnFieldIndex), nRow, bRepeatIfEmpty);
409 [ + - ][ + - ]: 1128 : if (!itr->mpFilter->match(*pCellData))
[ + + ]
410 : 744 : return false;
411 : : }
412 : 838 : return true;
413 : : }
414 : :
415 : 197738 : const ScDPCache* ScDPCacheTable::getCache() const
416 : : {
417 : 197738 : return mpCache;
418 [ + - ][ + - ]: 153 : }
419 : :
420 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|