LibreOffice Module sc (master)  1
sqldataprovider.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  */
9 
10 #include "sqldataprovider.hxx"
11 #include <datatransformation.hxx>
12 #include <salhelper/thread.hxx>
13 #include <com/sun/star/sdb/DatabaseContext.hpp>
14 #include <com/sun/star/sdb/XCompletedConnection.hpp>
15 #include <com/sun/star/task/InteractionHandler.hpp>
16 #include <com/sun/star/sdbc/XRow.hpp>
17 #include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
18 #include <com/sun/star/sdbc/XResultSetMetaData.hpp>
19 #include <dbdocutl.hxx>
20 #include <datamapper.hxx>
21 #include <vcl/svapp.hxx>
23 #include <osl/diagnose.h>
24 #include <tools/diagnose_ex.h>
25 
26 using namespace css;
27 using namespace ::com::sun::star::beans;
28 using namespace ::com::sun::star::sdbc;
29 using namespace ::com::sun::star::uno;
30 
31 namespace sc
32 {
34 {
36  OUString maID;
37  const std::vector<std::shared_ptr<sc::DataTransformation>> maDataTransformations;
38  std::function<void()> maImportFinishedHdl;
39 
40 public:
41  SQLFetchThread(ScDocument& rDoc, const OUString& rID, std::function<void()> aImportFinishedHdl,
42  const std::vector<std::shared_ptr<sc::DataTransformation>>& rTransformations);
43 
44  virtual void execute() override;
45 };
46 
47 SQLFetchThread::SQLFetchThread(
48  ScDocument& rDoc, const OUString& rID, std::function<void()> aImportFinishedHdl,
49  const std::vector<std::shared_ptr<sc::DataTransformation>>& rTransformations)
50  : salhelper::Thread("SQL Fetch Thread")
51  , mrDocument(rDoc)
52  , maID(rID)
53  , maDataTransformations(rTransformations)
54  , maImportFinishedHdl(aImportFinishedHdl)
55 {
56 }
57 
59 {
60  sal_Int32 nIndex = maID.indexOf("@");
61  if (nIndex == -1)
62  return;
63 
64  OUString aTable = maID.copy(0, nIndex);
65  OUString aDatabase = maID.copy(nIndex + 1);
66 
67  try
68  {
69  uno::Reference<sdb::XDatabaseContext> xContext
70  = sdb::DatabaseContext::create(comphelper::getProcessComponentContext());
71  uno::Any aSourceAny = xContext->getByName(aDatabase);
72 
73  uno::Reference<sdb::XCompletedConnection> xSource(aSourceAny, uno::UNO_QUERY);
74  if (!xSource.is())
75  return;
76 
77  uno::Reference<task::XInteractionHandler> xHandler(
78  task::InteractionHandler::createWithParent(comphelper::getProcessComponentContext(),
79  nullptr),
80  uno::UNO_QUERY_THROW);
81 
82  uno::Reference<sdbc::XConnection> xConnection = xSource->connectWithCompletion(xHandler);
83 
84  uno::Reference<sdbc::XStatement> xStatement = xConnection->createStatement();
85 
86  uno::Reference<sdbc::XResultSet> xResult
87  = xStatement->executeQuery("SELECT * FROM " + aTable);
88 
89  if (xResult.is())
90  {
91  Reference<sdbc::XResultSetMetaDataSupplier> xMetaDataSupplier(xResult, UNO_QUERY);
92 
93  Reference<sdbc::XResultSetMetaData> xMetaData = xMetaDataSupplier->getMetaData();
94 
95  Reference<XRow> xRow(xResult, UNO_QUERY);
96 
97  SCCOL nColCount = static_cast<SCCOL>(xMetaData->getColumnCount());
98 
99  while (xResult->next())
100  {
101  SCROW nRow = static_cast<SCROW>(xResult->getRow());
102 
103  for (SCCOL nCol = 0; nCol < nColCount; nCol++)
104  {
105  ScDatabaseDocUtil::PutData(mrDocument, nCol, nRow - 1, 0, xRow, nCol + 1,
106  xMetaData->getColumnType(nCol + 1), false);
107  }
108  }
109  }
110  }
111  catch (uno::Exception&)
112  {
113  TOOLS_WARN_EXCEPTION("sc", "exception in database");
114  }
115 
116  for (auto& itr : maDataTransformations)
117  {
118  itr->Transform(mrDocument);
119  }
120 
121  SolarMutexGuard aGuard;
123 }
124 
126  : DataProvider(rDataSource)
127  , mpDocument(pDoc)
128 {
129 }
130 
132 {
133  if (mxSQLFetchThread.is())
134  {
135  SolarMutexReleaser aReleaser;
136  mxSQLFetchThread->join();
137  }
138 }
139 
141 {
142  // already importing data
143  if (mpDoc)
144  return;
145 
146  mpDoc.reset(new ScDocument(SCDOCMODE_CLIP));
147  mpDoc->ResetClip(mpDocument, SCTAB(0));
149  std::bind(&SQLDataProvider::ImportFinished, this),
151  mxSQLFetchThread->launch();
152 
153  if (mbDeterministic)
154  {
155  SolarMutexReleaser aReleaser;
156  mxSQLFetchThread->join();
157  }
158 }
159 
161 {
163  mxSQLFetchThread.clear();
164  mpDoc.reset();
165 }
166 
167 const OUString& SQLDataProvider::GetURL() const { return mrDataSource.getURL(); }
168 }
169 
170 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_Int32 nIndex
const std::vector< std::shared_ptr< sc::DataTransformation > > maDataTransformations
sc::ExternalDataSource & mrDataSource
virtual void execute() override
rtl::Reference< SQLFetchThread > mxSQLFetchThread
Abstract class for all data provider.
virtual ~SQLDataProvider() override
ScDocument & mrDocument
bool mbDeterministic
If true make the threaded import deterministic for the tests.
virtual void Import() override
uno::Reference< sdbc::XRow > xRow
void WriteToDoc(ScDocument &rDoc)
ScDocumentUniquePtr mpDoc
#define TOOLS_WARN_EXCEPTION(area, stream)
std::function< void()> maImportFinishedHdl
sal_Int16 SCCOL
Definition: types.hxx:22
const OUString & getURL() const
ScDBDataManager * getDBManager()
sal_Int32 SCROW
Definition: types.hxx:18
virtual const OUString & GetURL() const override
Reference< XComponentContext > getProcessComponentContext()
SQLDataProvider(ScDocument *pDoc, sc::ExternalDataSource &rDataSource)
const std::vector< std::shared_ptr< sc::DataTransformation > > & getDataTransformation() const
const OUString & getID() const
static void PutData(ScDocument &rDoc, SCCOL nCol, SCROW nRow, SCTAB nTab, const css::uno::Reference< css::sdbc::XRow > &xRow, sal_Int32 nRowPos, tools::Long nType, bool bCurrency, StrData *pStrData=nullptr)
Definition: dbdocutl.cxx:37
sal_Int16 SCTAB
Definition: types.hxx:23