1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26
27
28
29 // INCLUDE --------------------------------------------------------------
30
31 #include <tools/debug.hxx>
32 #include <vcl/msgbox.hxx>
33 #include <svl/zforlist.hxx>
34 #include <comphelper/processfactory.hxx>
35 #include <comphelper/types.hxx>
36
37 #include <com/sun/star/sheet/DataImportMode.hpp>
38 #include <com/sun/star/beans/XPropertySet.hpp>
39 #include <com/sun/star/sdb/CommandType.hpp>
40 #include <com/sun/star/sdb/XCompletedExecution.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/XResultSetMetaDataSupplier.hpp>
45 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
46 #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
47
48 #include "dpsdbtab.hxx"
49 #include "collect.hxx"
50 #include "global.hxx"
51 #include "globstr.hrc"
52 #include "dpcachetable.hxx"
53 #include "dptabres.hxx"
54 #include "document.hxx"
55 #include "dpobject.hxx"
56
57 using namespace com::sun::star;
58
59 using ::std::vector;
60 using ::std::hash_map;
61 using ::std::hash_set;
62 using ::com::sun::star::uno::Sequence;
63 using ::com::sun::star::uno::Reference;
64 using ::com::sun::star::uno::Any;
65 using ::com::sun::star::uno::UNO_QUERY;
66
67 #define SC_SERVICE_ROWSET "com.sun.star.sdb.RowSet"
68 #define SC_SERVICE_INTHANDLER "com.sun.star.task.InteractionHandler"
69
70 //! move to a header file?
71 #define SC_DBPROP_DATASOURCENAME "DataSourceName"
72 #define SC_DBPROP_COMMAND "Command"
73 #define SC_DBPROP_COMMANDTYPE "CommandType"
74 // -----------------------------------------------------------------------
75 // Wang Xu Ming -- 2009-9-15
76 // DataPilot Migration - Cache&&Performance
GetExistDPObjectCache(ScDocument * pDoc) const77 ScDPTableDataCache* ScImportSourceDesc::GetExistDPObjectCache( ScDocument* pDoc ) const
78 {
79 ScDPTableDataCache* pCache = NULL;
80 ScDPCollection* pDPCollection= pDoc->GetDPCollection();
81 sal_uInt16 nCount = pDPCollection->GetCount();
82
83 for ( short i=nCount-1; i>=0 ; i--)
84 {
85 if ( const ScImportSourceDesc* pUsedDesc = (*pDPCollection)[i]->GetImportSourceDesc() )
86 if ( *this == *pUsedDesc )
87 {
88 long nID = (*pDPCollection)[i]->GetCacheId();
89 if ( nID >= 0 )
90 pCache= pDoc->GetDPObjectCache( nID );
91 if ( pCache )
92 return pCache;
93 }
94 }
95 return NULL;
96 }
97
CreateCache(ScDocument * pDoc,long nID) const98 ScDPTableDataCache* ScImportSourceDesc::CreateCache( ScDocument* pDoc , long nID ) const
99 {
100 if ( !pDoc )
101 return NULL;
102
103 sal_Int32 nSdbType = -1;
104
105 switch ( nType )
106 {
107 case sheet::DataImportMode_SQL: nSdbType = sdb::CommandType::COMMAND; break;
108 case sheet::DataImportMode_TABLE: nSdbType = sdb::CommandType::TABLE; break;
109 case sheet::DataImportMode_QUERY: nSdbType = sdb::CommandType::QUERY; break;
110 default:
111 return NULL;
112 }
113
114
115 ScDPTableDataCache* pCache = GetExistDPObjectCache( pDoc );
116
117 if ( pCache && ( nID < 0 || nID == pCache->GetId() ) )
118 return pCache;
119
120 if ( pCache == NULL )
121 pCache = new ScDPTableDataCache( pDoc );
122
123 uno::Reference<sdbc::XRowSet> xRowSet ;
124 try
125 {
126 xRowSet = uno::Reference<sdbc::XRowSet>(
127 comphelper::getProcessServiceFactory()->createInstance(
128 rtl::OUString::createFromAscii( SC_SERVICE_ROWSET ) ),
129 uno::UNO_QUERY);
130 uno::Reference<beans::XPropertySet> xRowProp( xRowSet, uno::UNO_QUERY );
131 DBG_ASSERT( xRowProp.is(), "can't get RowSet" );
132 if ( xRowProp.is() )
133 {
134 //
135 // set source parameters
136 //
137 uno::Any aAny;
138 aAny <<= rtl::OUString( aDBName );
139 xRowProp->setPropertyValue(
140 rtl::OUString::createFromAscii(SC_DBPROP_DATASOURCENAME), aAny );
141
142 aAny <<= rtl::OUString( aObject );
143 xRowProp->setPropertyValue(
144 rtl::OUString::createFromAscii(SC_DBPROP_COMMAND), aAny );
145
146 aAny <<= nSdbType;
147 xRowProp->setPropertyValue(
148 rtl::OUString::createFromAscii(SC_DBPROP_COMMANDTYPE), aAny );
149
150 uno::Reference<sdb::XCompletedExecution> xExecute( xRowSet, uno::UNO_QUERY );
151 if ( xExecute.is() )
152 {
153 uno::Reference<task::XInteractionHandler> xHandler(
154 comphelper::getProcessServiceFactory()->createInstance(
155 rtl::OUString::createFromAscii( SC_SERVICE_INTHANDLER ) ),
156 uno::UNO_QUERY);
157 xExecute->executeWithCompletion( xHandler );
158 }
159 else
160 xRowSet->execute();
161 SvNumberFormatter aFormat( pDoc->GetServiceManager(), ScGlobal::eLnge);
162 pCache->InitFromDataBase( xRowSet, *aFormat.GetNullDate() );
163 pCache->SetId( nID );
164 pDoc->AddDPObjectCache( pCache );
165 DBG_TRACE1("Create a cache id = %d \n", pCache->GetId() );
166 }
167 }
168 catch ( sdbc::SQLException& rError )
169 {
170 //! store error message
171 delete pCache;
172 pCache = NULL;
173 InfoBox aInfoBox( 0, String(rError.Message) );
174 aInfoBox.Execute();
175 }
176 catch ( uno::Exception& )
177 {
178 delete pCache;
179 pCache = NULL;
180 DBG_ERROR("Unexpected exception in database");
181 }
182
183
184 ::comphelper::disposeComponent( xRowSet );
185 return pCache;
186 }
187
GetCache(ScDocument * pDoc,long nID) const188 ScDPTableDataCache* ScImportSourceDesc::GetCache( ScDocument* pDoc, long nID ) const
189 {
190 ScDPTableDataCache* pCache = pDoc->GetDPObjectCache( nID );
191 if ( NULL == pCache && pDoc )
192 pCache = GetExistDPObjectCache( pDoc);
193 if ( NULL == pCache )
194 pCache = CreateCache( pDoc , nID );
195 return pCache;
196 }
197
GetCacheId(ScDocument * pDoc,long nID) const198 long ScImportSourceDesc:: GetCacheId( ScDocument* pDoc, long nID ) const
199 {
200 ScDPTableDataCache* pCache = GetCache( pDoc, nID);
201 if ( NULL == pCache )
202 return -1;
203 else
204 return pCache->GetId();
205 }
206
207 // -----------------------------------------------------------------------
208
ScDatabaseDPData(ScDocument * pDoc,const ScImportSourceDesc & rImport,long nCacheId)209 ScDatabaseDPData::ScDatabaseDPData(
210 ScDocument* pDoc,
211 const ScImportSourceDesc& rImport, long nCacheId /*=-1 */ ) :
212 ScDPTableData(pDoc, rImport.GetCacheId( pDoc, nCacheId) ),
213 aCacheTable( pDoc, GetCacheId() ) // base class ID is initialized with the GetCacheId call above
214 {
215
216 }
217
~ScDatabaseDPData()218 ScDatabaseDPData::~ScDatabaseDPData()
219 {
220 }
221
DisposeData()222 void ScDatabaseDPData::DisposeData()
223 {
224 //! use OpenDatabase here?
225 aCacheTable.clear();
226 }
227
GetColumnCount()228 long ScDatabaseDPData::GetColumnCount()
229 {
230 CreateCacheTable();
231 return GetCacheTable().getColSize();
232 }
233
234 // End Comments
235
getDimensionName(long nColumn)236 String ScDatabaseDPData::getDimensionName(long nColumn)
237 {
238 if (getIsDataLayoutDimension(nColumn))
239 {
240 //! different internal and display names?
241 //return "Data";
242 return ScGlobal::GetRscString(STR_PIVOT_DATA);
243 }
244
245 CreateCacheTable();
246 return aCacheTable.getFieldName((SCCOL)nColumn);
247 }
248
getIsDataLayoutDimension(long nColumn)249 sal_Bool ScDatabaseDPData::getIsDataLayoutDimension(long nColumn)
250 {
251 return ( nColumn == GetCacheTable().getColSize());
252 }
253
IsDateDimension(long)254 sal_Bool ScDatabaseDPData::IsDateDimension(long /* nDim */)
255 {
256 //! later...
257 return sal_False;
258 }
259
SetEmptyFlags(sal_Bool,sal_Bool)260 void ScDatabaseDPData::SetEmptyFlags( sal_Bool /* bIgnoreEmptyRows */, sal_Bool /* bRepeatIfEmpty */ )
261 {
262 // not used for database data
263 //! disable flags
264 }
265
CreateCacheTable()266 void ScDatabaseDPData::CreateCacheTable()
267 {
268 if (!aCacheTable.empty())
269 return;
270
271 aCacheTable.fillTable();
272 }
273
FilterCacheTable(const vector<ScDPCacheTable::Criterion> & rCriteria,const hash_set<sal_Int32> & rCatDims)274 void ScDatabaseDPData::FilterCacheTable(const vector<ScDPCacheTable::Criterion>& rCriteria, const hash_set<sal_Int32>& rCatDims)
275 {
276 CreateCacheTable();
277 aCacheTable.filterByPageDimension(
278 rCriteria, (IsRepeatIfEmpty() ? rCatDims : hash_set<sal_Int32>()));
279 }
280
GetDrillDownData(const vector<ScDPCacheTable::Criterion> & rCriteria,const hash_set<sal_Int32> & rCatDims,Sequence<Sequence<Any>> & rData)281 void ScDatabaseDPData::GetDrillDownData(const vector<ScDPCacheTable::Criterion>& rCriteria, const hash_set<sal_Int32>& rCatDims, Sequence< Sequence<Any> >& rData)
282 {
283 CreateCacheTable();
284 sal_Int32 nRowSize = aCacheTable.getRowSize();
285 if (!nRowSize)
286 return;
287
288 aCacheTable.filterTable(
289 rCriteria, rData, IsRepeatIfEmpty() ? rCatDims : hash_set<sal_Int32>());
290 }
291
CalcResults(CalcInfo & rInfo,bool bAutoShow)292 void ScDatabaseDPData::CalcResults(CalcInfo& rInfo, bool bAutoShow)
293 {
294 CreateCacheTable();
295 CalcResultsFromCacheTable( aCacheTable, rInfo, bAutoShow);
296 }
297
GetCacheTable() const298 const ScDPCacheTable& ScDatabaseDPData::GetCacheTable() const
299 {
300 return aCacheTable;
301 }
302
303 // -----------------------------------------------------------------------
304
305
306
307
308
309