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 <connectivity/statementcomposer.hxx>
21 :
22 : #include <connectivity/dbtools.hxx>
23 :
24 : #include <com/sun/star/sdb/CommandType.hpp>
25 : #include <com/sun/star/lang/NullPointerException.hpp>
26 : #include <com/sun/star/lang/XComponent.hpp>
27 : #include <com/sun/star/sdb/XQueriesSupplier.hpp>
28 : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
29 :
30 : #include <unotools/sharedunocomponent.hxx>
31 : #include <tools/diagnose_ex.h>
32 : #include <comphelper/property.hxx>
33 :
34 :
35 : namespace dbtools
36 : {
37 :
38 :
39 : using ::com::sun::star::uno::Reference;
40 : using ::com::sun::star::sdbc::XConnection;
41 : using ::com::sun::star::sdb::XSingleSelectQueryComposer;
42 : using ::com::sun::star::lang::NullPointerException;
43 : using ::com::sun::star::uno::Exception;
44 : using ::com::sun::star::lang::XComponent;
45 : using ::com::sun::star::uno::UNO_QUERY_THROW;
46 : using ::com::sun::star::sdb::XQueriesSupplier;
47 : using ::com::sun::star::container::XNameAccess;
48 : using ::com::sun::star::uno::UNO_QUERY;
49 : using ::com::sun::star::beans::XPropertySet;
50 : using ::com::sun::star::lang::XMultiServiceFactory;
51 : using ::com::sun::star::sdbc::SQLException;
52 :
53 : namespace CommandType = ::com::sun::star::sdb::CommandType;
54 :
55 :
56 : //= StatementComposer_Data
57 :
58 34 : struct StatementComposer_Data
59 : {
60 : const Reference< XConnection > xConnection;
61 : Reference< XSingleSelectQueryComposer > xComposer;
62 : OUString sCommand;
63 : OUString sFilter;
64 : OUString sOrder;
65 : sal_Int32 nCommandType;
66 : bool bEscapeProcessing;
67 : bool bComposerDirty;
68 : bool bDisposeComposer;
69 :
70 34 : StatementComposer_Data( const Reference< XConnection >& _rxConnection )
71 : :xConnection( _rxConnection )
72 : ,sCommand()
73 : ,sFilter()
74 : ,sOrder()
75 : ,nCommandType( CommandType::COMMAND )
76 : ,bEscapeProcessing( true )
77 : ,bComposerDirty( true )
78 34 : ,bDisposeComposer( true )
79 : {
80 34 : if ( !_rxConnection.is() )
81 0 : throw NullPointerException();
82 34 : }
83 : };
84 :
85 :
86 : namespace
87 : {
88 :
89 68 : void lcl_resetComposer( StatementComposer_Data& _rData )
90 : {
91 68 : if ( _rData.bDisposeComposer && _rData.xComposer.is() )
92 : {
93 : try
94 : {
95 0 : Reference< XComponent > xComposerComponent( _rData.xComposer, UNO_QUERY_THROW );
96 0 : xComposerComponent->dispose();
97 : }
98 0 : catch( const Exception& )
99 : {
100 : DBG_UNHANDLED_EXCEPTION();
101 : }
102 : }
103 68 : _rData.xComposer.clear();
104 68 : }
105 :
106 :
107 68 : bool lcl_ensureUpToDateComposer_nothrow( StatementComposer_Data& _rData )
108 : {
109 68 : if ( !_rData.bComposerDirty )
110 34 : return _rData.xComposer.is();
111 34 : lcl_resetComposer( _rData );
112 :
113 : try
114 : {
115 34 : OUString sStatement;
116 34 : switch ( _rData.nCommandType )
117 : {
118 : case CommandType::COMMAND:
119 8 : if ( _rData.bEscapeProcessing )
120 8 : sStatement = _rData.sCommand;
121 : // (in case of no escape processing we assume a not parseable statement)
122 8 : break;
123 :
124 : case CommandType::TABLE:
125 : {
126 26 : if ( _rData.sCommand.isEmpty() )
127 0 : break;
128 :
129 26 : sStatement = "SELECT * FROM ";
130 :
131 52 : OUString sCatalog, sSchema, sTable;
132 26 : qualifiedNameComponents( _rData.xConnection->getMetaData(), _rData.sCommand, sCatalog, sSchema, sTable, eInDataManipulation );
133 :
134 52 : sStatement += composeTableNameForSelect( _rData.xConnection, sCatalog, sSchema, sTable );
135 : }
136 26 : break;
137 :
138 : case CommandType::QUERY:
139 : {
140 : // ask the connection for the query
141 0 : Reference< XQueriesSupplier > xSupplyQueries( _rData.xConnection, UNO_QUERY_THROW );
142 0 : Reference< XNameAccess > xQueries( xSupplyQueries->getQueries(), UNO_QUERY_THROW );
143 :
144 0 : if ( !xQueries->hasByName( _rData.sCommand ) )
145 0 : break;
146 :
147 0 : Reference< XPropertySet > xQuery( xQueries->getByName( _rData.sCommand ), UNO_QUERY_THROW );
148 :
149 : // a native query ?
150 0 : bool bQueryEscapeProcessing = false;
151 0 : xQuery->getPropertyValue("EscapeProcessing") >>= bQueryEscapeProcessing;
152 0 : if ( !bQueryEscapeProcessing )
153 0 : break;
154 :
155 : // the command used by the query
156 0 : xQuery->getPropertyValue("Command") >>= sStatement;
157 0 : if ( sStatement.isEmpty() )
158 0 : break;
159 :
160 : // use a composer to build a statement from the query filter/order props
161 0 : Reference< XMultiServiceFactory > xFactory( _rData.xConnection, UNO_QUERY_THROW );
162 0 : ::utl::SharedUNOComponent< XSingleSelectQueryComposer > xComposer;
163 : xComposer.set(
164 0 : xFactory->createInstance("com.sun.star.sdb.SingleSelectQueryComposer"),
165 : UNO_QUERY_THROW
166 0 : );
167 :
168 : // the "basic" statement
169 0 : xComposer->setElementaryQuery( sStatement );
170 :
171 : // the sort order
172 0 : const OUString sPropOrder( "Order" );
173 0 : if ( ::comphelper::hasProperty( sPropOrder, xQuery ) )
174 : {
175 0 : OUString sOrder;
176 0 : OSL_VERIFY( xQuery->getPropertyValue( sPropOrder ) >>= sOrder );
177 0 : xComposer->setOrder( sOrder );
178 : }
179 :
180 : // the filter
181 0 : bool bApplyFilter = true;
182 0 : const OUString sPropApply( "ApplyFilter" );
183 0 : if ( ::comphelper::hasProperty( sPropApply, xQuery ) )
184 : {
185 0 : OSL_VERIFY( xQuery->getPropertyValue( sPropApply ) >>= bApplyFilter );
186 : }
187 :
188 0 : if ( bApplyFilter )
189 : {
190 0 : OUString sFilter;
191 0 : OSL_VERIFY( xQuery->getPropertyValue("Filter") >>= sFilter );
192 0 : xComposer->setFilter( sFilter );
193 : }
194 :
195 : // the composed statement
196 0 : sStatement = xComposer->getQuery();
197 : }
198 0 : break;
199 :
200 : default:
201 : OSL_FAIL("lcl_ensureUpToDateComposer_nothrow: no table, no query, no statement - what else ?!");
202 0 : break;
203 : }
204 :
205 34 : if ( !sStatement.isEmpty() )
206 : {
207 : // create an composer
208 34 : Reference< XMultiServiceFactory > xFactory( _rData.xConnection, UNO_QUERY_THROW );
209 34 : Reference< XSingleSelectQueryComposer > xComposer( xFactory->createInstance("com.sun.star.sdb.SingleSelectQueryComposer"),
210 68 : UNO_QUERY_THROW );
211 34 : xComposer->setElementaryQuery( sStatement );
212 :
213 : // append sort/filter
214 34 : xComposer->setOrder( _rData.sOrder );
215 34 : xComposer->setFilter( _rData.sFilter );
216 :
217 34 : sStatement = xComposer->getQuery();
218 :
219 34 : _rData.xComposer = xComposer;
220 68 : _rData.bComposerDirty = false;
221 34 : }
222 : }
223 0 : catch( const SQLException& )
224 : {
225 : // allowed to leave here
226 : }
227 0 : catch( const Exception& )
228 : {
229 : DBG_UNHANDLED_EXCEPTION();
230 : }
231 :
232 34 : return _rData.xComposer.is();
233 : }
234 : }
235 :
236 :
237 : //= StatementComposer
238 :
239 :
240 34 : StatementComposer::StatementComposer( const Reference< XConnection >& _rxConnection,
241 : const OUString& _rCommand, const sal_Int32 _nCommandType, const bool _bEscapeProcessing )
242 34 : :m_pData( new StatementComposer_Data( _rxConnection ) )
243 : {
244 : OSL_PRECOND( _rxConnection.is(), "StatementComposer::StatementComposer: illegal connection!" );
245 34 : m_pData->sCommand = _rCommand;
246 34 : m_pData->nCommandType = _nCommandType;
247 34 : m_pData->bEscapeProcessing = _bEscapeProcessing;
248 34 : }
249 :
250 :
251 68 : StatementComposer::~StatementComposer()
252 : {
253 34 : lcl_resetComposer( *m_pData );
254 34 : }
255 :
256 :
257 34 : void StatementComposer::setDisposeComposer( bool _bDoDispose )
258 : {
259 34 : m_pData->bDisposeComposer = _bDoDispose;
260 34 : }
261 :
262 :
263 22 : void StatementComposer::setFilter( const OUString& _rFilter )
264 : {
265 22 : m_pData->sFilter = _rFilter;
266 22 : m_pData->bComposerDirty = true;
267 22 : }
268 :
269 :
270 34 : void StatementComposer::setOrder( const OUString& _rOrder )
271 : {
272 34 : m_pData->sOrder = _rOrder;
273 34 : m_pData->bComposerDirty = true;
274 34 : }
275 :
276 :
277 34 : Reference< XSingleSelectQueryComposer > StatementComposer::getComposer()
278 : {
279 34 : lcl_ensureUpToDateComposer_nothrow( *m_pData );
280 34 : return m_pData->xComposer;
281 : }
282 :
283 :
284 34 : OUString StatementComposer::getQuery()
285 : {
286 34 : if ( lcl_ensureUpToDateComposer_nothrow( *m_pData ) )
287 : {
288 34 : return m_pData->xComposer->getQuery();
289 : }
290 :
291 0 : return OUString();
292 : }
293 :
294 :
295 : } // namespace dbtools
296 :
297 :
298 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|