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