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"
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 <utility>
22#include <vcl/svapp.hxx>
24#include <tools/diagnose_ex.h>
25
26using namespace css;
27using namespace ::com::sun::star::beans;
28using namespace ::com::sun::star::sdbc;
29using namespace ::com::sun::star::uno;
30
31namespace sc
32{
34{
36 OUString maID;
37 const std::vector<std::shared_ptr<sc::DataTransformation>> maDataTransformations;
38 std::function<void()> maImportFinishedHdl;
39
40public:
41 SQLFetchThread(ScDocument& rDoc, const OUString& rID, std::function<void()> aImportFinishedHdl,
42 std::vector<std::shared_ptr<sc::DataTransformation>>&& rTransformations);
43
44 virtual void execute() override;
45};
46
48 ScDocument& rDoc, const OUString& rID, std::function<void()> aImportFinishedHdl,
49 std::vector<std::shared_ptr<sc::DataTransformation>>&& rTransformations)
50 : salhelper::Thread("SQL Fetch Thread")
51 , mrDocument(rDoc)
52 , maID(rID)
53 , maDataTransformations(std::move(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),
150 std::vector(mrDataSource.getDataTransformation()));
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
167const OUString& SQLDataProvider::GetURL() const { return mrDataSource.getURL(); }
168}
169
170/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
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:38
Abstract class for all data provider.
bool mbDeterministic
If true make the threaded import deterministic for the tests.
sc::ExternalDataSource & mrDataSource
const OUString & getID() const
const std::vector< std::shared_ptr< sc::DataTransformation > > & getDataTransformation() const
const OUString & getURL() const
ScDBDataManager * getDBManager()
SQLDataProvider(ScDocument *pDoc, sc::ExternalDataSource &rDataSource)
virtual const OUString & GetURL() const override
virtual ~SQLDataProvider() override
ScDocumentUniquePtr mpDoc
virtual void Import() override
rtl::Reference< SQLFetchThread > mxSQLFetchThread
SQLFetchThread(ScDocument &rDoc, const OUString &rID, std::function< void()> aImportFinishedHdl, std::vector< std::shared_ptr< sc::DataTransformation > > &&rTransformations)
std::function< void()> maImportFinishedHdl
ScDocument & mrDocument
virtual void execute() override
const std::vector< std::shared_ptr< sc::DataTransformation > > maDataTransformations
void WriteToDoc(ScDocument &rDoc)
#define TOOLS_WARN_EXCEPTION(area, stream)
@ SCDOCMODE_CLIP
Definition: document.hxx:256
sal_Int32 nIndex
Reference< XRow > xRow
Reference< XComponentContext > getProcessComponentContext()
CAUTION! The following defines must be in the same namespace as the respective type.
sal_Int16 SCTAB
Definition: types.hxx:22
sal_Int16 SCCOL
Definition: types.hxx:21
sal_Int32 SCROW
Definition: types.hxx:17