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