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