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/msgbox.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( 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 : {
80 0 : ::osl::MutexGuard aGuard(m_aMutex);
81 0 : stopAllComponentListening();
82 : }
83 :
84 0 : }
85 :
86 0 : void DirectSQLDialog::_disposing( const EventObject& _rSource )
87 : {
88 0 : SolarMutexGuard aSolarGuard;
89 0 : ::osl::MutexGuard aGuard(m_aMutex);
90 :
91 : OSL_ENSURE(Reference< XConnection >(_rSource.Source, UNO_QUERY).get() == m_xConnection.get(),
92 : "DirectSQLDialog::_disposing: where does this come from?");
93 : (void)_rSource;
94 :
95 : {
96 0 : OUString sMessage(ModuleRes(STR_DIRECTSQL_CONNECTIONLOST));
97 0 : ErrorBox aError(this, WB_OK, sMessage);
98 0 : aError.Execute();
99 : }
100 :
101 0 : PostUserEvent(LINK(this, DirectSQLDialog, OnClose));
102 0 : }
103 :
104 0 : sal_Int32 DirectSQLDialog::getHistorySize() const
105 : {
106 : CHECK_INVARIANTS("DirectSQLDialog::getHistorySize");
107 0 : return m_aStatementHistory.size();
108 : }
109 :
110 0 : void DirectSQLDialog::implEnsureHistoryLimit()
111 : {
112 : CHECK_INVARIANTS("DirectSQLDialog::implEnsureHistoryLimit");
113 :
114 0 : if (getHistorySize() <= m_nHistoryLimit)
115 : // nothing to do
116 0 : return;
117 :
118 0 : sal_Int32 nRemoveEntries = getHistorySize() - m_nHistoryLimit;
119 0 : while (nRemoveEntries--)
120 : {
121 0 : m_aStatementHistory.pop_front();
122 0 : m_aNormalizedHistory.pop_front();
123 0 : m_pSQLHistory->RemoveEntry((sal_uInt16)0);
124 : }
125 : }
126 :
127 0 : void DirectSQLDialog::implAddToStatementHistory(const OUString& _rStatement)
128 : {
129 : CHECK_INVARIANTS("DirectSQLDialog::implAddToStatementHistory");
130 :
131 : // add the statement to the history
132 0 : m_aStatementHistory.push_back(_rStatement);
133 :
134 : // normalize the statement, and remember the normalized form, too
135 0 : OUString sNormalized(_rStatement);
136 0 : sNormalized = sNormalized.replaceAll("\n", " ");
137 0 : m_aNormalizedHistory.push_back(sNormalized);
138 :
139 : // add the normalized version to the list box
140 0 : m_pSQLHistory->InsertEntry(sNormalized);
141 :
142 : // ensure that we don't exceed the history limit
143 0 : implEnsureHistoryLimit();
144 0 : }
145 :
146 : #ifdef DBG_UTIL
147 : const sal_Char* DirectSQLDialog::impl_CheckInvariants() const
148 : {
149 : if (m_aStatementHistory.size() != m_aNormalizedHistory.size())
150 : return "statement history is inconsistent!";
151 :
152 : if (!m_pSQLHistory)
153 : return "invalid listbox!";
154 :
155 : if (m_aStatementHistory.size() != static_cast<size_t>(m_pSQLHistory->GetEntryCount()))
156 : return "invalid listbox entry count!";
157 :
158 : if (!m_xConnection.is())
159 : return "have no connection!";
160 :
161 : return NULL;
162 : }
163 : #endif
164 :
165 0 : void DirectSQLDialog::implExecuteStatement(const OUString& _rStatement)
166 : {
167 : CHECK_INVARIANTS("DirectSQLDialog::implExecuteStatement");
168 :
169 0 : ::osl::MutexGuard aGuard(m_aMutex);
170 :
171 0 : OUString sStatus;
172 0 : ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet > xResultSet;
173 : try
174 : {
175 : // create a statement
176 0 : Reference< XStatement > xStatement = m_xConnection->createStatement();
177 : OSL_ENSURE(xStatement.is(), "DirectSQLDialog::implExecuteStatement: no statement returned by the connection!");
178 :
179 : // clear the output box
180 0 : m_pOutput->SetText(OUString());
181 0 : if (xStatement.is())
182 : {
183 0 : if (OUString(_rStatement).toAsciiUpperCase().startsWith("SELECT") && m_pShowOutput->IsChecked())
184 : {
185 : // execute it as a query
186 0 : xResultSet = xStatement->executeQuery(_rStatement);
187 : // get a handle for the rows
188 0 : ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow > xRow( xResultSet, ::com::sun::star::uno::UNO_QUERY );
189 : // work through each of the rows
190 0 : while (xResultSet->next())
191 : {
192 : // initialise the output line for each row
193 0 : OUString out("");
194 : // work along the columns until that are none left
195 : try
196 : {
197 0 : int i = 1;
198 : for (;;)
199 : {
200 : // be dumb, treat everything as a string
201 0 : out += xRow->getString(i) + ",";
202 0 : i++;
203 0 : }
204 : }
205 : // trap for when we fall off the end of the row
206 0 : catch (const SQLException&)
207 : {
208 : }
209 : // report the output
210 0 : addOutputText(OUString(out));
211 0 : }
212 : } else {
213 : // execute it
214 0 : xStatement->execute(_rStatement);
215 : }
216 : }
217 :
218 : // successful
219 0 : sStatus = ModuleRes(STR_COMMAND_EXECUTED_SUCCESSFULLY);
220 :
221 : // dispose the statement
222 0 : ::comphelper::disposeComponent(xStatement);
223 : }
224 0 : catch(const SQLException& e)
225 : {
226 0 : sStatus = e.Message;
227 : }
228 0 : catch( const Exception& )
229 : {
230 : DBG_UNHANDLED_EXCEPTION();
231 : }
232 :
233 : // add the status text
234 0 : addStatusText(sStatus);
235 0 : }
236 :
237 0 : void DirectSQLDialog::addStatusText(const OUString& _rMessage)
238 : {
239 0 : OUString sAppendMessage = OUString::number(m_nStatusCount++) + ": " + _rMessage + "\n\n";
240 :
241 0 : OUString sCompleteMessage = m_pStatus->GetText() + sAppendMessage;
242 0 : m_pStatus->SetText(sCompleteMessage);
243 :
244 0 : m_pStatus->SetSelection(Selection(sCompleteMessage.getLength(), sCompleteMessage.getLength()));
245 0 : }
246 :
247 0 : void DirectSQLDialog::addOutputText(const OUString& _rMessage)
248 : {
249 0 : OUString sAppendMessage = _rMessage;
250 0 : sAppendMessage += "\n";
251 :
252 0 : OUString sCompleteMessage = m_pOutput->GetText();
253 0 : sCompleteMessage += sAppendMessage;
254 0 : m_pOutput->SetText(sCompleteMessage);
255 0 : }
256 :
257 0 : void DirectSQLDialog::executeCurrent()
258 : {
259 : CHECK_INVARIANTS("DirectSQLDialog::executeCurrent");
260 :
261 0 : OUString sStatement = m_pSQL->GetText();
262 :
263 : // execute
264 0 : implExecuteStatement(sStatement);
265 :
266 : // add the statement to the history
267 0 : implAddToStatementHistory(sStatement);
268 :
269 0 : m_pSQL->SetSelection(Selection());
270 0 : m_pSQL->GrabFocus();
271 0 : }
272 :
273 0 : void DirectSQLDialog::switchToHistory(sal_Int32 _nHistoryPos, sal_Bool _bUpdateListBox)
274 : {
275 : CHECK_INVARIANTS("DirectSQLDialog::switchToHistory");
276 :
277 0 : if ((_nHistoryPos >= 0) && (_nHistoryPos < getHistorySize()))
278 : {
279 : // set the text in the statement editor
280 0 : OUString sStatement = m_aStatementHistory[_nHistoryPos];
281 0 : m_pSQL->SetText(sStatement);
282 0 : OnStatementModified(m_pSQL);
283 :
284 0 : if (_bUpdateListBox)
285 : {
286 : // selecte the normalized statement in the list box
287 0 : m_pSQLHistory->SelectEntryPos((sal_uInt16)_nHistoryPos);
288 : OSL_ENSURE(m_pSQLHistory->GetSelectEntry() == m_aNormalizedHistory[_nHistoryPos],
289 : "DirectSQLDialog::switchToHistory: inconsistent listbox entries!");
290 : }
291 :
292 0 : m_pSQL->GrabFocus();
293 0 : m_pSQL->SetSelection(Selection(sStatement.getLength(), sStatement.getLength()));
294 : }
295 : else
296 : OSL_FAIL("DirectSQLDialog::switchToHistory: invalid position!");
297 0 : }
298 :
299 0 : IMPL_LINK( DirectSQLDialog, OnStatementModified, void*, /*NOTINTERESTEDIN*/ )
300 : {
301 0 : m_pExecute->Enable(!m_pSQL->GetText().isEmpty());
302 0 : return 0L;
303 : }
304 :
305 0 : IMPL_LINK( DirectSQLDialog, OnClose, void*, /*NOTINTERESTEDIN*/ )
306 : {
307 0 : EndDialog( RET_OK );
308 0 : return 0L;
309 : }
310 :
311 0 : IMPL_LINK( DirectSQLDialog, OnExecute, void*, /*NOTINTERESTEDIN*/ )
312 : {
313 0 : executeCurrent();
314 0 : return 0L;
315 : }
316 :
317 0 : IMPL_LINK( DirectSQLDialog, OnListEntrySelected, void*, /*NOTINTERESTEDIN*/ )
318 : {
319 0 : if (!m_pSQLHistory->IsTravelSelect())
320 : {
321 0 : const sal_Int32 nSelected = m_pSQLHistory->GetSelectEntryPos();
322 0 : if (LISTBOX_ENTRY_NOTFOUND != nSelected)
323 0 : switchToHistory(nSelected, sal_False);
324 : }
325 0 : return 0L;
326 : }
327 :
328 : } // namespace dbaui
329 :
330 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|