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