xref: /AOO41X/main/connectivity/source/commontools/statementcomposer.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_connectivity.hxx"
30 #include <connectivity/statementcomposer.hxx>
31 
32 #include <connectivity/dbtools.hxx>
33 
34 /** === begin UNO includes === **/
35 #include <com/sun/star/sdb/CommandType.hpp>
36 #include <com/sun/star/lang/NullPointerException.hpp>
37 #include <com/sun/star/lang/XComponent.hpp>
38 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
39 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
40 /** === end UNO includes === **/
41 
42 #include <unotools/sharedunocomponent.hxx>
43 #include <tools/diagnose_ex.h>
44 #include <comphelper/property.hxx>
45 
46 //........................................................................
47 namespace dbtools
48 {
49 //........................................................................
50 
51 	/** === begin UNO using === **/
52     using ::com::sun::star::uno::Reference;
53     using ::com::sun::star::sdbc::XConnection;
54     using ::com::sun::star::sdb::XSingleSelectQueryComposer;
55     using ::com::sun::star::lang::NullPointerException;
56     using ::com::sun::star::uno::Exception;
57     using ::com::sun::star::lang::XComponent;
58     using ::com::sun::star::uno::UNO_QUERY_THROW;
59     using ::com::sun::star::sdb::XQueriesSupplier;
60     using ::com::sun::star::container::XNameAccess;
61     using ::com::sun::star::uno::UNO_QUERY;
62     using ::com::sun::star::beans::XPropertySet;
63     using ::com::sun::star::lang::XMultiServiceFactory;
64     using ::com::sun::star::sdbc::SQLException;
65 	/** === end UNO using === **/
66     namespace CommandType = ::com::sun::star::sdb::CommandType;
67 
68 	//====================================================================
69 	//= StatementComposer_Data
70 	//====================================================================
71     struct StatementComposer_Data
72     {
73         const Reference< XConnection >          xConnection;
74         Reference< XSingleSelectQueryComposer > xComposer;
75         ::rtl::OUString                         sCommand;
76         ::rtl::OUString                         sFilter;
77         ::rtl::OUString                         sOrder;
78         sal_Int32                               nCommandType;
79         sal_Bool                                bEscapeProcessing;
80         bool                                    bComposerDirty;
81         bool                                    bDisposeComposer;
82 
83         StatementComposer_Data( const Reference< XConnection >& _rxConnection )
84             :xConnection( _rxConnection )
85             ,sCommand()
86             ,sFilter()
87             ,sOrder()
88             ,nCommandType( CommandType::COMMAND )
89             ,bEscapeProcessing( sal_True )
90             ,bComposerDirty( true )
91             ,bDisposeComposer( true )
92         {
93             if ( !_rxConnection.is() )
94                 throw NullPointerException();
95         }
96     };
97 
98 	//--------------------------------------------------------------------
99     namespace
100     {
101         //----------------------------------------------------------------
102         void    lcl_resetComposer( StatementComposer_Data& _rData )
103         {
104             if ( _rData.bDisposeComposer && _rData.xComposer.is() )
105             {
106                 try
107                 {
108                     Reference< XComponent > xComposerComponent( _rData.xComposer, UNO_QUERY_THROW );
109                     xComposerComponent->dispose();
110                 }
111                 catch( const Exception& )
112                 {
113         	        DBG_UNHANDLED_EXCEPTION();
114                 }
115             }
116             _rData.xComposer.clear();
117         }
118 
119         //----------------------------------------------------------------
120         bool    lcl_ensureUpToDateComposer_nothrow( StatementComposer_Data& _rData )
121         {
122             if ( !_rData.bComposerDirty )
123                 return _rData.xComposer.is();
124             lcl_resetComposer( _rData );
125 
126             try
127             {
128                 ::rtl::OUString sStatement;
129                 switch ( _rData.nCommandType )
130 	            {
131 		            case CommandType::COMMAND:
132 			            if ( _rData.bEscapeProcessing )
133 				            sStatement = _rData.sCommand;
134 			            // (in case of no escape processing  we assume a not parseable statement)
135 			            break;
136 
137                     case CommandType::TABLE:
138 		            {
139 			            if ( !_rData.sCommand.getLength() )
140                             break;
141 
142 			            sStatement = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SELECT * FROM " ) );
143 
144 	                    ::rtl::OUString sCatalog, sSchema, sTable;
145 	                    qualifiedNameComponents( _rData.xConnection->getMetaData(), _rData.sCommand, sCatalog, sSchema, sTable, eInDataManipulation );
146 
147                         sStatement += composeTableNameForSelect( _rData.xConnection, sCatalog, sSchema, sTable );
148 		            }
149 		            break;
150 
151 		            case CommandType::QUERY:
152 		            {
153 			            // ask the connection for the query
154 			            Reference< XQueriesSupplier > xSupplyQueries( _rData.xConnection, UNO_QUERY_THROW );
155 			            Reference< XNameAccess >      xQueries( xSupplyQueries->getQueries(), UNO_QUERY_THROW );
156 
157 			            if ( !xQueries->hasByName( _rData.sCommand ) )
158 				            break;
159 
160 			            Reference< XPropertySet > xQuery( xQueries->getByName( _rData.sCommand ), UNO_QUERY_THROW );
161 
162                         //  a native query ?
163                         sal_Bool bQueryEscapeProcessing = sal_False;
164                         xQuery->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "EscapeProcessing" ) ) ) >>= bQueryEscapeProcessing;
165 			            if ( !bQueryEscapeProcessing )
166 				            break;
167 
168 			            // the command used by the query
169 			            xQuery->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Command" ) ) ) >>= sStatement;
170                         if ( !sStatement.getLength() )
171                             break;
172 
173 			            // use a composer to build a statement from the query filter/order props
174                         Reference< XMultiServiceFactory > xFactory( _rData.xConnection, UNO_QUERY_THROW );
175                         ::utl::SharedUNOComponent< XSingleSelectQueryComposer > xComposer;
176                         xComposer.set(
177                             xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.SingleSelectQueryComposer" ) ) ),
178                             UNO_QUERY_THROW
179                         );
180 
181                         // the "basic" statement
182 			            xComposer->setElementaryQuery( sStatement );
183 
184                         // the sort order
185                         const ::rtl::OUString sPropOrder( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Order" ) ) );
186                         if ( ::comphelper::hasProperty( sPropOrder, xQuery ) )
187                         {
188                             ::rtl::OUString sOrder;
189                             OSL_VERIFY( xQuery->getPropertyValue( sPropOrder ) >>= sOrder );
190 				            xComposer->setOrder( sOrder );
191                         }
192 
193                         // the filter
194 			            sal_Bool bApplyFilter = sal_True;
195 			            const ::rtl::OUString sPropApply = ::rtl::OUString::createFromAscii( "ApplyFilter" );
196                         if ( ::comphelper::hasProperty( sPropApply, xQuery ) )
197                         {
198                             OSL_VERIFY( xQuery->getPropertyValue( sPropApply ) >>= bApplyFilter );
199                         }
200 
201 			            if ( bApplyFilter )
202                         {
203                             ::rtl::OUString sFilter;
204                             OSL_VERIFY( xQuery->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Filter" ) ) ) >>= sFilter );
205                             xComposer->setFilter( sFilter );
206                         }
207 
208                         // the composed statement
209                         sStatement = xComposer->getQuery();
210 		            }
211 		            break;
212 
213                     default:
214 			            OSL_ENSURE(sal_False, "lcl_ensureUpToDateComposer_nothrow: no table, no query, no statement - what else ?!");
215 			            break;
216 	            }
217 
218 	            if ( sStatement.getLength() )
219 	            {
220 		            // create an composer
221                     Reference< XMultiServiceFactory > xFactory( _rData.xConnection, UNO_QUERY_THROW );
222                     Reference< XSingleSelectQueryComposer > xComposer( xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.SingleSelectQueryComposer" ) ) ),
223                         UNO_QUERY_THROW );
224 			        xComposer->setElementaryQuery( sStatement );
225 
226 			        // append sort/filter
227 				    xComposer->setOrder( _rData.sOrder );
228 					xComposer->setFilter( _rData.sFilter );
229 
230                     sStatement = xComposer->getQuery();
231 
232                     _rData.xComposer = xComposer;
233                     _rData.bComposerDirty = false;
234 		        }
235             }
236             catch( const SQLException& )
237             {
238                 // allowed to leave here
239             }
240             catch( const Exception& )
241             {
242             	DBG_UNHANDLED_EXCEPTION();
243             }
244 
245             return _rData.xComposer.is();
246         }
247     }
248 
249 	//====================================================================
250 	//= StatementComposer
251 	//====================================================================
252 	//--------------------------------------------------------------------
253     StatementComposer::StatementComposer( const Reference< XConnection >& _rxConnection,
254         const ::rtl::OUString&  _rCommand, const sal_Int32 _nCommandType, const sal_Bool _bEscapeProcessing )
255         :m_pData( new StatementComposer_Data( _rxConnection ) )
256     {
257         OSL_PRECOND( _rxConnection.is(), "StatementComposer::StatementComposer: illegal connection!" );
258         m_pData->sCommand = _rCommand;
259         m_pData->nCommandType = _nCommandType;
260         m_pData->bEscapeProcessing = _bEscapeProcessing;
261     }
262 
263 	//--------------------------------------------------------------------
264     StatementComposer::~StatementComposer()
265     {
266         lcl_resetComposer( *m_pData );
267     }
268 
269     //--------------------------------------------------------------------
270     void StatementComposer::setDisposeComposer( bool _bDoDispose )
271     {
272         m_pData->bDisposeComposer = _bDoDispose;
273     }
274 
275     //--------------------------------------------------------------------
276     bool StatementComposer::getDisposeComposer() const
277     {
278         return m_pData->bDisposeComposer;
279     }
280 
281     //--------------------------------------------------------------------
282     void StatementComposer::setFilter( const ::rtl::OUString& _rFilter )
283     {
284         m_pData->sFilter = _rFilter;
285         m_pData->bComposerDirty = true;
286     }
287 
288 	//--------------------------------------------------------------------
289     void StatementComposer::setOrder( const ::rtl::OUString& _rOrder )
290     {
291         m_pData->sOrder = _rOrder;
292         m_pData->bComposerDirty = true;
293     }
294 
295 	//--------------------------------------------------------------------
296     Reference< XSingleSelectQueryComposer > StatementComposer::getComposer()
297     {
298         lcl_ensureUpToDateComposer_nothrow( *m_pData );
299         return m_pData->xComposer;
300     }
301 
302 	//--------------------------------------------------------------------
303     ::rtl::OUString StatementComposer::getQuery()
304     {
305         if ( lcl_ensureUpToDateComposer_nothrow( *m_pData ) )
306         {
307             return m_pData->xComposer->getQuery();
308         }
309 
310         return ::rtl::OUString();
311     }
312 
313 //........................................................................
314 } // namespace dbtools
315 //........................................................................
316