Line data Source code
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 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "directsql.hxx"
21 : #include "dbu_dlg.hrc"
22 : #include <vcl/layout.hxx>
23 : #include <comphelper/types.hxx>
24 : #include <vcl/svapp.hxx>
25 : #include <osl/mutex.hxx>
26 : #include <tools/diagnose_ex.h>
27 : #include <rtl/strbuf.hxx>
28 : #include <com/sun/star/sdbc/XRow.hpp>
29 :
30 : namespace dbaui
31 : {
32 :
33 : using namespace ::com::sun::star::uno;
34 : using namespace ::com::sun::star::sdbc;
35 : using namespace ::com::sun::star::lang;
36 :
37 : // DirectSQLDialog
38 0 : DirectSQLDialog::DirectSQLDialog( vcl::Window* _pParent, const Reference< XConnection >& _rxConn )
39 : :ModalDialog(_pParent, "DirectSQLDialog" , "dbaccess/ui/directsqldialog.ui")
40 : ,m_nHistoryLimit(20)
41 : ,m_nStatusCount(1)
42 0 : ,m_xConnection(_rxConn)
43 : {
44 0 : get(m_pSQL,"sql");
45 0 : Size aSize(m_pSQL->CalcBlockSize(60, 7));
46 0 : m_pSQL->set_width_request(aSize.Width());
47 0 : m_pSQL->set_height_request(aSize.Height());
48 0 : get(m_pExecute,"execute");
49 0 : get(m_pSQLHistory,"sqlhistory");
50 0 : get(m_pStatus,"status");
51 0 : aSize = m_pStatus->CalcBlockSize(60, 5);
52 0 : m_pStatus->set_height_request(aSize.Height());
53 0 : get(m_pShowOutput,"showoutput");
54 0 : get(m_pOutput,"output");
55 0 : aSize = m_pOutput->CalcBlockSize(60, 5);
56 0 : m_pOutput->set_height_request(aSize.Height());
57 0 : get(m_pClose,"close");
58 :
59 :
60 0 : m_pSQL->GrabFocus();
61 :
62 0 : m_pExecute->SetClickHdl(LINK(this, DirectSQLDialog, OnExecute));
63 0 : m_pClose->SetClickHdl(LINK(this, DirectSQLDialog, OnClose));
64 0 : m_pSQLHistory->SetSelectHdl(LINK(this, DirectSQLDialog, OnListEntrySelected));
65 0 : m_pSQLHistory->SetDropDownLineCount(10);
66 :
67 : // add a dispose listener to the connection
68 0 : Reference< XComponent > xConnComp(m_xConnection, UNO_QUERY);
69 : OSL_ENSURE(xConnComp.is(), "DirectSQLDialog::DirectSQLDialog: invalid connection!");
70 0 : if (xConnComp.is())
71 0 : startComponentListening(xConnComp);
72 :
73 0 : m_pSQL->SetModifyHdl(LINK(this, DirectSQLDialog, OnStatementModified));
74 0 : OnStatementModified(m_pSQL);
75 0 : }
76 :
77 0 : DirectSQLDialog::~DirectSQLDialog()
78 : {
79 0 : disposeOnce();
80 0 : }
81 :
82 0 : void DirectSQLDialog::dispose()
83 : {
84 : {
85 0 : ::osl::MutexGuard aGuard(m_aMutex);
86 0 : stopAllComponentListening();
87 : }
88 0 : m_pSQL.clear();
89 0 : m_pExecute.clear();
90 0 : m_pSQLHistory.clear();
91 0 : m_pStatus.clear();
92 0 : m_pShowOutput.clear();
93 0 : m_pOutput.clear();
94 0 : m_pClose.clear();
95 0 : ModalDialog::dispose();
96 0 : }
97 :
98 0 : void DirectSQLDialog::_disposing( const EventObject& _rSource )
99 : {
100 0 : SolarMutexGuard aSolarGuard;
101 0 : ::osl::MutexGuard aGuard(m_aMutex);
102 :
103 : OSL_ENSURE(Reference< XConnection >(_rSource.Source, UNO_QUERY).get() == m_xConnection.get(),
104 : "DirectSQLDialog::_disposing: where does this come from?");
105 : (void)_rSource;
106 :
107 : {
108 0 : OUString sMessage(ModuleRes(STR_DIRECTSQL_CONNECTIONLOST));
109 0 : ScopedVclPtrInstance< MessageDialog > aError(this, sMessage);
110 0 : aError->Execute();
111 : }
112 :
113 0 : PostUserEvent(LINK(this, DirectSQLDialog, OnClose), NULL, true);
114 0 : }
115 :
116 0 : sal_Int32 DirectSQLDialog::getHistorySize() const
117 : {
118 : CHECK_INVARIANTS("DirectSQLDialog::getHistorySize");
119 0 : return m_aStatementHistory.size();
120 : }
121 :
122 0 : void DirectSQLDialog::implEnsureHistoryLimit()
123 : {
124 : CHECK_INVARIANTS("DirectSQLDialog::implEnsureHistoryLimit");
125 :
126 0 : if (getHistorySize() <= m_nHistoryLimit)
127 : // nothing to do
128 0 : return;
129 :
130 0 : sal_Int32 nRemoveEntries = getHistorySize() - m_nHistoryLimit;
131 0 : while (nRemoveEntries--)
132 : {
133 0 : m_aStatementHistory.pop_front();
134 0 : m_aNormalizedHistory.pop_front();
135 0 : m_pSQLHistory->RemoveEntry((sal_uInt16)0);
136 : }
137 : }
138 :
139 0 : void DirectSQLDialog::implAddToStatementHistory(const OUString& _rStatement)
140 : {
141 : CHECK_INVARIANTS("DirectSQLDialog::implAddToStatementHistory");
142 :
143 : // add the statement to the history
144 0 : m_aStatementHistory.push_back(_rStatement);
145 :
146 : // normalize the statement, and remember the normalized form, too
147 0 : OUString sNormalized(_rStatement);
148 0 : sNormalized = sNormalized.replaceAll("\n", " ");
149 0 : m_aNormalizedHistory.push_back(sNormalized);
150 :
151 : // add the normalized version to the list box
152 0 : m_pSQLHistory->InsertEntry(sNormalized);
153 :
154 : // ensure that we don't exceed the history limit
155 0 : implEnsureHistoryLimit();
156 0 : }
157 :
158 : #ifdef DBG_UTIL
159 : const sal_Char* DirectSQLDialog::impl_CheckInvariants() const
160 : {
161 : if (m_aStatementHistory.size() != m_aNormalizedHistory.size())
162 : return "statement history is inconsistent!";
163 :
164 : if (!m_pSQLHistory)
165 : return "invalid listbox!";
166 :
167 : if (m_aStatementHistory.size() != static_cast<size_t>(m_pSQLHistory->GetEntryCount()))
168 : return "invalid listbox entry count!";
169 :
170 : if (!m_xConnection.is())
171 : return "have no connection!";
172 :
173 : return NULL;
174 : }
175 : #endif
176 :
177 0 : void DirectSQLDialog::implExecuteStatement(const OUString& _rStatement)
178 : {
179 : CHECK_INVARIANTS("DirectSQLDialog::implExecuteStatement");
180 :
181 0 : ::osl::MutexGuard aGuard(m_aMutex);
182 :
183 0 : OUString sStatus;
184 0 : ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet > xResultSet;
185 : try
186 : {
187 : // create a statement
188 0 : Reference< XStatement > xStatement = m_xConnection->createStatement();
189 : OSL_ENSURE(xStatement.is(), "DirectSQLDialog::implExecuteStatement: no statement returned by the connection!");
190 :
191 : // clear the output box
192 0 : m_pOutput->SetText(OUString());
193 0 : if (xStatement.is())
194 : {
195 0 : if (OUString(_rStatement).toAsciiUpperCase().startsWith("SELECT") && m_pShowOutput->IsChecked())
196 : {
197 : // execute it as a query
198 0 : xResultSet = xStatement->executeQuery(_rStatement);
199 : // get a handle for the rows
200 0 : ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow > xRow( xResultSet, ::com::sun::star::uno::UNO_QUERY );
201 : // work through each of the rows
202 0 : while (xResultSet->next())
203 : {
204 : // initialise the output line for each row
205 0 : OUString out("");
206 : // work along the columns until that are none left
207 : try
208 : {
209 0 : int i = 1;
210 : for (;;)
211 : {
212 : // be dumb, treat everything as a string
213 0 : out += xRow->getString(i) + ",";
214 0 : i++;
215 0 : }
216 : }
217 : // trap for when we fall off the end of the row
218 0 : catch (const SQLException&)
219 : {
220 : }
221 : // report the output
222 0 : addOutputText(OUString(out));
223 0 : }
224 : } else {
225 : // execute it
226 0 : xStatement->execute(_rStatement);
227 : }
228 : }
229 :
230 : // successful
231 0 : sStatus = ModuleRes(STR_COMMAND_EXECUTED_SUCCESSFULLY);
232 :
233 : // dispose the statement
234 0 : ::comphelper::disposeComponent(xStatement);
235 : }
236 0 : catch(const SQLException& e)
237 : {
238 0 : sStatus = e.Message;
239 : }
240 0 : catch( const Exception& )
241 : {
242 : DBG_UNHANDLED_EXCEPTION();
243 : }
244 :
245 : // add the status text
246 0 : addStatusText(sStatus);
247 0 : }
248 :
249 0 : void DirectSQLDialog::addStatusText(const OUString& _rMessage)
250 : {
251 0 : OUString sAppendMessage = OUString::number(m_nStatusCount++) + ": " + _rMessage + "\n\n";
252 :
253 0 : OUString sCompleteMessage = m_pStatus->GetText() + sAppendMessage;
254 0 : m_pStatus->SetText(sCompleteMessage);
255 :
256 0 : m_pStatus->SetSelection(Selection(sCompleteMessage.getLength(), sCompleteMessage.getLength()));
257 0 : }
258 :
259 0 : void DirectSQLDialog::addOutputText(const OUString& _rMessage)
260 : {
261 0 : OUString sAppendMessage = _rMessage;
262 0 : sAppendMessage += "\n";
263 :
264 0 : OUString sCompleteMessage = m_pOutput->GetText();
265 0 : sCompleteMessage += sAppendMessage;
266 0 : m_pOutput->SetText(sCompleteMessage);
267 0 : }
268 :
269 0 : void DirectSQLDialog::executeCurrent()
270 : {
271 : CHECK_INVARIANTS("DirectSQLDialog::executeCurrent");
272 :
273 0 : OUString sStatement = m_pSQL->GetText();
274 :
275 : // execute
276 0 : implExecuteStatement(sStatement);
277 :
278 : // add the statement to the history
279 0 : implAddToStatementHistory(sStatement);
280 :
281 0 : m_pSQL->SetSelection(Selection());
282 0 : m_pSQL->GrabFocus();
283 0 : }
284 :
285 0 : void DirectSQLDialog::switchToHistory(sal_Int32 _nHistoryPos, bool _bUpdateListBox)
286 : {
287 : CHECK_INVARIANTS("DirectSQLDialog::switchToHistory");
288 :
289 0 : if ((_nHistoryPos >= 0) && (_nHistoryPos < getHistorySize()))
290 : {
291 : // set the text in the statement editor
292 0 : OUString sStatement = m_aStatementHistory[_nHistoryPos];
293 0 : m_pSQL->SetText(sStatement);
294 0 : OnStatementModified(m_pSQL);
295 :
296 0 : if (_bUpdateListBox)
297 : {
298 : // selecte the normalized statement in the list box
299 0 : m_pSQLHistory->SelectEntryPos((sal_uInt16)_nHistoryPos);
300 : OSL_ENSURE(m_pSQLHistory->GetSelectEntry() == m_aNormalizedHistory[_nHistoryPos],
301 : "DirectSQLDialog::switchToHistory: inconsistent listbox entries!");
302 : }
303 :
304 0 : m_pSQL->GrabFocus();
305 0 : m_pSQL->SetSelection(Selection(sStatement.getLength(), sStatement.getLength()));
306 : }
307 : else
308 : OSL_FAIL("DirectSQLDialog::switchToHistory: invalid position!");
309 0 : }
310 :
311 0 : IMPL_LINK_NOARG( DirectSQLDialog, OnStatementModified )
312 : {
313 0 : m_pExecute->Enable(!m_pSQL->GetText().isEmpty());
314 0 : return 0L;
315 : }
316 :
317 0 : IMPL_LINK_NOARG( DirectSQLDialog, OnClose )
318 : {
319 0 : EndDialog( RET_OK );
320 0 : return 0L;
321 : }
322 :
323 0 : IMPL_LINK_NOARG( DirectSQLDialog, OnExecute )
324 : {
325 0 : executeCurrent();
326 0 : return 0L;
327 : }
328 :
329 0 : IMPL_LINK_NOARG( DirectSQLDialog, OnListEntrySelected )
330 : {
331 0 : if (!m_pSQLHistory->IsTravelSelect())
332 : {
333 0 : const sal_Int32 nSelected = m_pSQLHistory->GetSelectEntryPos();
334 0 : if (LISTBOX_ENTRY_NOTFOUND != nSelected)
335 0 : switchToHistory(nSelected, false);
336 : }
337 0 : return 0L;
338 : }
339 :
340 36 : } // namespace dbaui
341 :
342 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|