19b5730f6SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 39b5730f6SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 49b5730f6SAndrew Rist * or more contributor license agreements. See the NOTICE file 59b5730f6SAndrew Rist * distributed with this work for additional information 69b5730f6SAndrew Rist * regarding copyright ownership. The ASF licenses this file 79b5730f6SAndrew Rist * to you under the Apache License, Version 2.0 (the 89b5730f6SAndrew Rist * "License"); you may not use this file except in compliance 99b5730f6SAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 119b5730f6SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 139b5730f6SAndrew Rist * Unless required by applicable law or agreed to in writing, 149b5730f6SAndrew Rist * software distributed under the License is distributed on an 159b5730f6SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 169b5730f6SAndrew Rist * KIND, either express or implied. See the License for the 179b5730f6SAndrew Rist * specific language governing permissions and limitations 189b5730f6SAndrew Rist * under the License. 19cdf0e10cSrcweir * 209b5730f6SAndrew Rist *************************************************************/ 219b5730f6SAndrew Rist 229b5730f6SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_connectivity.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir #include <stdio.h> 28cdf0e10cSrcweir #include <osl/diagnose.h> 29cdf0e10cSrcweir #include <osl/thread.h> 30cdf0e10cSrcweir #include <com/sun/star/sdbc/ResultSetConcurrency.hpp> 31cdf0e10cSrcweir #include <com/sun/star/sdbc/ResultSetType.hpp> 32cdf0e10cSrcweir #include <com/sun/star/sdbc/FetchDirection.hpp> 33cdf0e10cSrcweir #include <com/sun/star/lang/DisposedException.hpp> 34cdf0e10cSrcweir #include <cppuhelper/typeprovider.hxx> 35cdf0e10cSrcweir #include "propertyids.hxx" 36cdf0e10cSrcweir #include "NStatement.hxx" 37cdf0e10cSrcweir #include "NConnection.hxx" 38cdf0e10cSrcweir #include "NDatabaseMetaData.hxx" 39cdf0e10cSrcweir #include "NResultSet.hxx" 40cdf0e10cSrcweir #include "NDebug.hxx" 41cdf0e10cSrcweir #include "resource/evoab2_res.hrc" 42cdf0e10cSrcweir #include <resource/common_res.hrc> 43cdf0e10cSrcweir #include <connectivity/dbexception.hxx> 44cdf0e10cSrcweir #include <tools/diagnose_ex.h> 45cdf0e10cSrcweir 46cdf0e10cSrcweir namespace connectivity { namespace evoab { 47cdf0e10cSrcweir 48cdf0e10cSrcweir //------------------------------------------------------------------------------ 49cdf0e10cSrcweir using namespace com::sun::star::uno; 50cdf0e10cSrcweir using namespace com::sun::star::lang; 51cdf0e10cSrcweir using namespace com::sun::star::beans; 52cdf0e10cSrcweir using namespace com::sun::star::sdbc; 53cdf0e10cSrcweir using namespace com::sun::star::sdbcx; 54cdf0e10cSrcweir using namespace com::sun::star::container; 55cdf0e10cSrcweir using namespace com::sun::star::io; 56cdf0e10cSrcweir using namespace com::sun::star::util; 57cdf0e10cSrcweir //------------------------------------------------------------------------------ 58cdf0e10cSrcweir OCommonStatement::OCommonStatement(OEvoabConnection* _pConnection) 59cdf0e10cSrcweir : OCommonStatement_IBase(m_aMutex) 60cdf0e10cSrcweir , ::comphelper::OPropertyContainer(OCommonStatement_IBase::rBHelper) 61cdf0e10cSrcweir , OStatement_CBase( (::cppu::OWeakObject*)_pConnection, this ) 62cdf0e10cSrcweir , m_xResultSet(NULL) 63cdf0e10cSrcweir , m_pResultSet(NULL) 64cdf0e10cSrcweir , m_pConnection(_pConnection) 65cdf0e10cSrcweir , m_aParser(_pConnection->getDriver().getMSFactory()) 66cdf0e10cSrcweir , m_aSQLIterator( _pConnection, _pConnection->createCatalog()->getTables(), m_aParser, NULL ) 67cdf0e10cSrcweir , m_pParseTree(NULL) 68cdf0e10cSrcweir , m_nMaxFieldSize(0) 69cdf0e10cSrcweir , m_nMaxRows(0) 70cdf0e10cSrcweir , m_nQueryTimeOut(0) 71cdf0e10cSrcweir , m_nFetchSize(0) 72cdf0e10cSrcweir , m_nResultSetType(ResultSetType::FORWARD_ONLY) 73cdf0e10cSrcweir , m_nFetchDirection(FetchDirection::FORWARD) 74cdf0e10cSrcweir , m_nResultSetConcurrency(ResultSetConcurrency::UPDATABLE) 75cdf0e10cSrcweir , m_bEscapeProcessing(sal_True) 76cdf0e10cSrcweir , rBHelper(OCommonStatement_IBase::rBHelper) 77cdf0e10cSrcweir { 78cdf0e10cSrcweir m_pConnection->acquire(); 79cdf0e10cSrcweir 80cdf0e10cSrcweir #define REGISTER_PROP( id, member ) \ 81cdf0e10cSrcweir registerProperty( \ 82cdf0e10cSrcweir OMetaConnection::getPropMap().getNameByIndex( id ), \ 83cdf0e10cSrcweir id, \ 84cdf0e10cSrcweir 0, \ 85cdf0e10cSrcweir &member, \ 86cdf0e10cSrcweir ::getCppuType( &member ) \ 87cdf0e10cSrcweir ); 88cdf0e10cSrcweir 89cdf0e10cSrcweir REGISTER_PROP( PROPERTY_ID_CURSORNAME, m_aCursorName ); 90cdf0e10cSrcweir REGISTER_PROP( PROPERTY_ID_MAXFIELDSIZE, m_nMaxFieldSize ); 91cdf0e10cSrcweir REGISTER_PROP( PROPERTY_ID_MAXROWS, m_nMaxRows ); 92cdf0e10cSrcweir REGISTER_PROP( PROPERTY_ID_QUERYTIMEOUT, m_nQueryTimeOut ); 93cdf0e10cSrcweir REGISTER_PROP( PROPERTY_ID_FETCHSIZE, m_nFetchSize ); 94cdf0e10cSrcweir REGISTER_PROP( PROPERTY_ID_RESULTSETTYPE, m_nResultSetType ); 95cdf0e10cSrcweir REGISTER_PROP( PROPERTY_ID_FETCHDIRECTION, m_nFetchDirection ); 96cdf0e10cSrcweir REGISTER_PROP( PROPERTY_ID_ESCAPEPROCESSING, m_bEscapeProcessing ); 97cdf0e10cSrcweir REGISTER_PROP( PROPERTY_ID_RESULTSETCONCURRENCY, m_nResultSetConcurrency ); 98cdf0e10cSrcweir } 99cdf0e10cSrcweir // ----------------------------------------------------------------------------- 100cdf0e10cSrcweir OCommonStatement::~OCommonStatement() 101cdf0e10cSrcweir { 102cdf0e10cSrcweir } 103cdf0e10cSrcweir //------------------------------------------------------------------------------ 104cdf0e10cSrcweir void OCommonStatement::disposeResultSet() 105cdf0e10cSrcweir { 106cdf0e10cSrcweir // free the cursor if alive 107cdf0e10cSrcweir Reference< XComponent > xComp(m_xResultSet.get(), UNO_QUERY); 108cdf0e10cSrcweir if (xComp.is()) 109cdf0e10cSrcweir xComp->dispose(); 110cdf0e10cSrcweir m_xResultSet = Reference< XResultSet>(); 111cdf0e10cSrcweir } 112cdf0e10cSrcweir //------------------------------------------------------------------------------ 113cdf0e10cSrcweir void OCommonStatement::disposing() 114cdf0e10cSrcweir { 115cdf0e10cSrcweir ::osl::MutexGuard aGuard(m_aMutex); 116cdf0e10cSrcweir 117cdf0e10cSrcweir disposeResultSet(); 118cdf0e10cSrcweir 119cdf0e10cSrcweir if (m_pConnection) 120cdf0e10cSrcweir m_pConnection->release(); 121cdf0e10cSrcweir m_pConnection = NULL; 122cdf0e10cSrcweir 123cdf0e10cSrcweir dispose_ChildImpl(); 124cdf0e10cSrcweir OCommonStatement_IBase::disposing(); 125cdf0e10cSrcweir } 126cdf0e10cSrcweir //----------------------------------------------------------------------------- 127cdf0e10cSrcweir Any SAL_CALL OCommonStatement::queryInterface( const Type & rType ) throw(RuntimeException) 128cdf0e10cSrcweir { 129cdf0e10cSrcweir Any aRet = OCommonStatement_IBase::queryInterface(rType); 130cdf0e10cSrcweir if(!aRet.hasValue()) 131cdf0e10cSrcweir aRet = ::comphelper::OPropertyContainer::queryInterface(rType); 132cdf0e10cSrcweir return aRet; 133cdf0e10cSrcweir } 134cdf0e10cSrcweir // ------------------------------------------------------------------------- 135cdf0e10cSrcweir Sequence< Type > SAL_CALL OCommonStatement::getTypes( ) throw(RuntimeException) 136cdf0e10cSrcweir { 137cdf0e10cSrcweir ::cppu::OTypeCollection aTypes( ::getCppuType( (const Reference< XMultiPropertySet > *)0 ), 138cdf0e10cSrcweir ::getCppuType( (const Reference< XFastPropertySet > *)0 ), 139cdf0e10cSrcweir ::getCppuType( (const Reference< XPropertySet > *)0 )); 140cdf0e10cSrcweir 141cdf0e10cSrcweir return ::comphelper::concatSequences(aTypes.getTypes(),OCommonStatement_IBase::getTypes()); 142cdf0e10cSrcweir } 143cdf0e10cSrcweir // ------------------------------------------------------------------------- 144cdf0e10cSrcweir 145cdf0e10cSrcweir //void SAL_CALL OCommonStatement::cancel( ) throw(RuntimeException) 146cdf0e10cSrcweir //{ 147cdf0e10cSrcweir //::osl::MutexGuard aGuard( m_aMutex ); 148cdf0e10cSrcweir //checkDisposed(OCommonStatement_IBase::rBHelper.bDisposed); 149cdf0e10cSrcweir //// cancel the current sql statement 150cdf0e10cSrcweir //} 151cdf0e10cSrcweir 152cdf0e10cSrcweir // ------------------------------------------------------------------------- 153cdf0e10cSrcweir void SAL_CALL OCommonStatement::close( ) throw(SQLException, RuntimeException) 154cdf0e10cSrcweir { 155cdf0e10cSrcweir { 156cdf0e10cSrcweir ::osl::MutexGuard aGuard( m_aMutex ); 157cdf0e10cSrcweir checkDisposed(OCommonStatement_IBase::rBHelper.bDisposed); 158cdf0e10cSrcweir 159cdf0e10cSrcweir } 160cdf0e10cSrcweir dispose(); 161cdf0e10cSrcweir } 162cdf0e10cSrcweir // ------------------------------------------------------------------------- 163cdf0e10cSrcweir 164cdf0e10cSrcweir void OCommonStatement::reset() throw (SQLException) 165cdf0e10cSrcweir { 166cdf0e10cSrcweir ::osl::MutexGuard aGuard( m_aMutex ); 167cdf0e10cSrcweir checkDisposed(OCommonStatement_IBase::rBHelper.bDisposed); 168cdf0e10cSrcweir 169cdf0e10cSrcweir 170cdf0e10cSrcweir clearWarnings (); 171cdf0e10cSrcweir 172cdf0e10cSrcweir if (m_xResultSet.get().is()) 173cdf0e10cSrcweir clearMyResultSet(); 174cdf0e10cSrcweir } 175cdf0e10cSrcweir 176cdf0e10cSrcweir void OCommonStatement::clearMyResultSet () throw (SQLException) 177cdf0e10cSrcweir { 178cdf0e10cSrcweir ::osl::MutexGuard aGuard( m_aMutex ); 179cdf0e10cSrcweir checkDisposed(OCommonStatement_IBase::rBHelper.bDisposed); 180cdf0e10cSrcweir 181cdf0e10cSrcweir try 182cdf0e10cSrcweir { 183cdf0e10cSrcweir Reference<XCloseable> xCloseable; 184cdf0e10cSrcweir if ( ::comphelper::query_interface( m_xResultSet.get(), xCloseable ) ) 185cdf0e10cSrcweir xCloseable->close(); 186cdf0e10cSrcweir } 187cdf0e10cSrcweir catch( const DisposedException& ) { } 188cdf0e10cSrcweir 189cdf0e10cSrcweir m_xResultSet = Reference< XResultSet >(); 190cdf0e10cSrcweir } 191cdf0e10cSrcweir 192cdf0e10cSrcweir EBookQuery * 193cdf0e10cSrcweir OCommonStatement::createTrue() 194cdf0e10cSrcweir { // Not the world's most efficient unconditional true but ... 195cdf0e10cSrcweir return e_book_query_from_string("(exists \"full_name\")"); 196cdf0e10cSrcweir } 197cdf0e10cSrcweir 198cdf0e10cSrcweir EBookQuery * 199cdf0e10cSrcweir OCommonStatement::createTest( const ::rtl::OUString &aColumnName, 200cdf0e10cSrcweir EBookQueryTest eTest, 201cdf0e10cSrcweir const ::rtl::OUString &aMatch ) 202cdf0e10cSrcweir { 203cdf0e10cSrcweir ::rtl::OString sMatch = rtl::OUStringToOString( aMatch, RTL_TEXTENCODING_UTF8 ); 204cdf0e10cSrcweir ::rtl::OString sColumnName = rtl::OUStringToOString( aColumnName, RTL_TEXTENCODING_UTF8 ); 205cdf0e10cSrcweir 206cdf0e10cSrcweir return e_book_query_field_test( e_contact_field_id( sColumnName ), 207cdf0e10cSrcweir eTest, sMatch ); 208cdf0e10cSrcweir } 209cdf0e10cSrcweir 210cdf0e10cSrcweir // ------------------------------------------------------------------------- 211cdf0e10cSrcweir 212cdf0e10cSrcweir ::rtl::OUString OCommonStatement::impl_getColumnRefColumnName_throw( const OSQLParseNode& _rColumnRef ) 213cdf0e10cSrcweir { 214cdf0e10cSrcweir ENSURE_OR_THROW( SQL_ISRULE( &_rColumnRef, column_ref ), "internal error: only column_refs supported as LHS" ); 215cdf0e10cSrcweir 216cdf0e10cSrcweir ::rtl::OUString sColumnName; 217cdf0e10cSrcweir switch ( _rColumnRef.count() ) 218cdf0e10cSrcweir { 219cdf0e10cSrcweir case 3: // SQL_TOKEN_NAME '.' column_val 220cdf0e10cSrcweir { 221cdf0e10cSrcweir const OSQLParseNode* pPunct = _rColumnRef.getChild( 1 ); 222cdf0e10cSrcweir const OSQLParseNode* pColVal = _rColumnRef.getChild( 2 ); 223cdf0e10cSrcweir if ( SQL_ISPUNCTUATION( pPunct, "." ) 224cdf0e10cSrcweir && ( pColVal->count() == 1 ) 225cdf0e10cSrcweir ) 226cdf0e10cSrcweir { 227cdf0e10cSrcweir sColumnName = pColVal->getChild( 0 )->getTokenValue(); 228cdf0e10cSrcweir } 229cdf0e10cSrcweir } 230cdf0e10cSrcweir break; 231cdf0e10cSrcweir 232cdf0e10cSrcweir case 1: // column 233cdf0e10cSrcweir { 234cdf0e10cSrcweir sColumnName = _rColumnRef.getChild( 0 )->getTokenValue(); 235cdf0e10cSrcweir } 236cdf0e10cSrcweir break; 237cdf0e10cSrcweir } 238cdf0e10cSrcweir 239cdf0e10cSrcweir if ( !sColumnName.getLength() ) 240cdf0e10cSrcweir m_pConnection->throwGenericSQLException( STR_QUERY_TOO_COMPLEX, *this ); 241cdf0e10cSrcweir 242cdf0e10cSrcweir return sColumnName; 243cdf0e10cSrcweir } 244cdf0e10cSrcweir 245cdf0e10cSrcweir // ------------------------------------------------------------------------- 246cdf0e10cSrcweir void OCommonStatement::orderByAnalysis( const OSQLParseNode* _pOrderByClause, SortDescriptor& _out_rSort ) 247cdf0e10cSrcweir { 248cdf0e10cSrcweir ENSURE_OR_THROW( _pOrderByClause, "NULL node" ); 249cdf0e10cSrcweir ENSURE_OR_THROW( SQL_ISRULE( _pOrderByClause, opt_order_by_clause ), "wrong node type" ); 250cdf0e10cSrcweir 251cdf0e10cSrcweir _out_rSort.clear(); 252cdf0e10cSrcweir 253cdf0e10cSrcweir const OSQLParseNode* pOrderList = _pOrderByClause->getByRule( OSQLParseNode::ordering_spec_commalist ); 254cdf0e10cSrcweir ENSURE_OR_THROW( pOrderList, "unexpected parse tree structure" ); 255cdf0e10cSrcweir 256cdf0e10cSrcweir for ( sal_uInt32 i=0; i<pOrderList->count(); ++i ) 257cdf0e10cSrcweir { 258cdf0e10cSrcweir const OSQLParseNode* pOrderBy = pOrderList->getChild(i); 259cdf0e10cSrcweir if ( !pOrderBy || !SQL_ISRULE( pOrderBy, ordering_spec ) ) 260cdf0e10cSrcweir continue; 261cdf0e10cSrcweir const OSQLParseNode* pColumnRef = pOrderBy->count() == 2 ? pOrderBy->getChild(0) : NULL; 262cdf0e10cSrcweir const OSQLParseNode* pAscDesc = pOrderBy->count() == 2 ? pOrderBy->getChild(1) : NULL; 263cdf0e10cSrcweir ENSURE_OR_THROW( 264cdf0e10cSrcweir ( pColumnRef != NULL ) 265cdf0e10cSrcweir && ( pAscDesc != NULL ) 266cdf0e10cSrcweir && SQL_ISRULE( pAscDesc, opt_asc_desc ) 267cdf0e10cSrcweir && ( pAscDesc->count() < 2 ), 268cdf0e10cSrcweir "ordering_spec structure error" ); 269cdf0e10cSrcweir 270cdf0e10cSrcweir // column name -> column field 271cdf0e10cSrcweir if ( !SQL_ISRULE( pColumnRef, column_ref ) ) 272cdf0e10cSrcweir m_pConnection->throwGenericSQLException( STR_SORT_BY_COL_ONLY, *this ); 273cdf0e10cSrcweir const ::rtl::OUString sColumnName( impl_getColumnRefColumnName_throw( *pColumnRef ) ); 274cdf0e10cSrcweir guint nField = evoab::findEvoabField( sColumnName ); 275cdf0e10cSrcweir // ascending/descending? 276cdf0e10cSrcweir bool bAscending = true; 277cdf0e10cSrcweir if ( ( pAscDesc->count() == 1 ) 278cdf0e10cSrcweir && SQL_ISTOKEN( pAscDesc->getChild( 0 ), DESC ) 279cdf0e10cSrcweir ) 280cdf0e10cSrcweir bAscending = false; 281cdf0e10cSrcweir 282cdf0e10cSrcweir _out_rSort.push_back( FieldSort( nField, bAscending ) ); 283cdf0e10cSrcweir } 284cdf0e10cSrcweir } 285cdf0e10cSrcweir 286cdf0e10cSrcweir // ------------------------------------------------------------------------- 287cdf0e10cSrcweir EBookQuery *OCommonStatement::whereAnalysis( const OSQLParseNode* parseTree ) 288cdf0e10cSrcweir { 289cdf0e10cSrcweir EBookQuery *pResult = NULL; 290cdf0e10cSrcweir 291cdf0e10cSrcweir ENSURE_OR_THROW( parseTree, "invalid parse tree" ); 292cdf0e10cSrcweir 293cdf0e10cSrcweir // Nested brackets 294cdf0e10cSrcweir if( parseTree->count() == 3 && 295cdf0e10cSrcweir SQL_ISPUNCTUATION( parseTree->getChild( 0 ), "(" ) && 296cdf0e10cSrcweir SQL_ISPUNCTUATION( parseTree->getChild( 2 ), ")" ) ) 297cdf0e10cSrcweir { 298cdf0e10cSrcweir pResult = whereAnalysis( parseTree->getChild( 1 ) ); 299cdf0e10cSrcweir } 300cdf0e10cSrcweir 301cdf0e10cSrcweir // SQL AND, OR 302cdf0e10cSrcweir else if( ( SQL_ISRULE( parseTree, search_condition ) || 303cdf0e10cSrcweir SQL_ISRULE( parseTree, boolean_term ) ) && 304cdf0e10cSrcweir parseTree->count() == 3 ) 305cdf0e10cSrcweir { 306cdf0e10cSrcweir ENSURE_OR_THROW( SQL_ISTOKEN( parseTree->getChild( 1 ), OR ) 307cdf0e10cSrcweir || SQL_ISTOKEN( parseTree->getChild( 1 ), AND ), 308cdf0e10cSrcweir "unexpected search_condition structure" ); 309cdf0e10cSrcweir 310cdf0e10cSrcweir EBookQuery *pArgs[2]; 311cdf0e10cSrcweir pArgs[0] = whereAnalysis( parseTree->getChild( 0 ) ); 312cdf0e10cSrcweir pArgs[1] = whereAnalysis( parseTree->getChild( 2 ) ); 313cdf0e10cSrcweir 314cdf0e10cSrcweir if( SQL_ISTOKEN( parseTree->getChild( 1 ), OR ) ) 315cdf0e10cSrcweir pResult = e_book_query_or( 2, pArgs, TRUE ); 316cdf0e10cSrcweir else 317cdf0e10cSrcweir pResult = e_book_query_and( 2, pArgs, TRUE ); 318cdf0e10cSrcweir } 319cdf0e10cSrcweir // SQL =, != 320cdf0e10cSrcweir else if( SQL_ISRULE( parseTree, comparison_predicate ) ) 321cdf0e10cSrcweir { 322cdf0e10cSrcweir OSQLParseNode *pPrec = parseTree->getChild( 1 ); 323cdf0e10cSrcweir 324cdf0e10cSrcweir ENSURE_OR_THROW( parseTree->count() == 3, "unexpected comparison_predicate structure" ); 325cdf0e10cSrcweir 326cdf0e10cSrcweir OSQLParseNode* pLHS = parseTree->getChild( 0 ); 327cdf0e10cSrcweir OSQLParseNode* pRHS = parseTree->getChild( 2 ); 328cdf0e10cSrcweir 329cdf0e10cSrcweir if ( ( !( SQL_ISRULE( pLHS, column_ref ) ) // on the LHS, we accept a column or a constant int value 330cdf0e10cSrcweir && ( pLHS->getNodeType() != SQL_NODE_INTNUM ) 331cdf0e10cSrcweir ) 332cdf0e10cSrcweir || ( ( pRHS->getNodeType() != SQL_NODE_STRING ) // on the RHS, certain literals are acceptable 333cdf0e10cSrcweir && ( pRHS->getNodeType() != SQL_NODE_INTNUM ) 334cdf0e10cSrcweir && ( pRHS->getNodeType() != SQL_NODE_APPROXNUM ) 335cdf0e10cSrcweir && !( SQL_ISTOKEN( pRHS, TRUE ) ) 336cdf0e10cSrcweir && !( SQL_ISTOKEN( pRHS, FALSE ) ) 337cdf0e10cSrcweir ) 338cdf0e10cSrcweir || ( ( pLHS->getNodeType() == SQL_NODE_INTNUM ) // an int on LHS requires an int on RHS 339cdf0e10cSrcweir && ( pRHS->getNodeType() != SQL_NODE_INTNUM ) 340cdf0e10cSrcweir ) 341cdf0e10cSrcweir ) 342cdf0e10cSrcweir { 343cdf0e10cSrcweir m_pConnection->throwGenericSQLException( STR_QUERY_TOO_COMPLEX, *this ); 344cdf0e10cSrcweir } 345cdf0e10cSrcweir 346cdf0e10cSrcweir if ( ( pPrec->getNodeType() != SQL_NODE_EQUAL ) 347cdf0e10cSrcweir && ( pPrec->getNodeType() != SQL_NODE_NOTEQUAL ) 348cdf0e10cSrcweir ) 349cdf0e10cSrcweir { 350cdf0e10cSrcweir m_pConnection->throwGenericSQLException( STR_OPERATOR_TOO_COMPLEX, *this ); 351cdf0e10cSrcweir } 352cdf0e10cSrcweir 353cdf0e10cSrcweir // recognize the special "0 = 1" condition 354cdf0e10cSrcweir if ( ( pLHS->getNodeType() == SQL_NODE_INTNUM ) 355cdf0e10cSrcweir && ( pRHS->getNodeType() == SQL_NODE_INTNUM ) 356cdf0e10cSrcweir && ( pPrec->getNodeType() == SQL_NODE_EQUAL ) 357cdf0e10cSrcweir ) 358cdf0e10cSrcweir { 359cdf0e10cSrcweir const sal_Int32 nLHS = pLHS->getTokenValue().toInt64(); 360cdf0e10cSrcweir const sal_Int32 nRHS = pRHS->getTokenValue().toInt64(); 361cdf0e10cSrcweir return ( nLHS == nRHS ) ? createTrue() : NULL; 362cdf0e10cSrcweir } 363cdf0e10cSrcweir 364cdf0e10cSrcweir ::rtl::OUString aColumnName( impl_getColumnRefColumnName_throw( *pLHS ) ); 365cdf0e10cSrcweir 366cdf0e10cSrcweir ::rtl::OUString aMatchString; 367cdf0e10cSrcweir if ( pRHS->isToken() ) 368cdf0e10cSrcweir aMatchString = pRHS->getTokenValue(); 369cdf0e10cSrcweir else 370cdf0e10cSrcweir aMatchString = pRHS->getChild( 0 )->getTokenValue(); 371cdf0e10cSrcweir 372cdf0e10cSrcweir pResult = createTest( aColumnName, E_BOOK_QUERY_IS, aMatchString ); 373cdf0e10cSrcweir 374cdf0e10cSrcweir if ( pResult && ( pPrec->getNodeType() == SQL_NODE_NOTEQUAL ) ) 375cdf0e10cSrcweir pResult = e_book_query_not( pResult, TRUE ); 376cdf0e10cSrcweir } 377cdf0e10cSrcweir // SQL like 378cdf0e10cSrcweir else if( SQL_ISRULE( parseTree, like_predicate ) ) 379cdf0e10cSrcweir { 380cdf0e10cSrcweir ENSURE_OR_THROW( parseTree->count() == 2, "unexpected like_predicate structure" ); 381cdf0e10cSrcweir const OSQLParseNode* pPart2 = parseTree->getChild(1); 382cdf0e10cSrcweir 383cdf0e10cSrcweir if( ! SQL_ISRULE( parseTree->getChild( 0 ), column_ref) ) 384cdf0e10cSrcweir m_pConnection->throwGenericSQLException(STR_QUERY_INVALID_LIKE_COLUMN,*this); 385cdf0e10cSrcweir 386cdf0e10cSrcweir ::rtl::OUString aColumnName( impl_getColumnRefColumnName_throw( *parseTree->getChild( 0 ) ) ); 387cdf0e10cSrcweir 388cdf0e10cSrcweir OSQLParseNode *pAtom = pPart2->getChild( pPart2->count() - 2 ); // Match String 389cdf0e10cSrcweir bool bNotLike = pPart2->getChild(0)->isToken(); 390cdf0e10cSrcweir 391cdf0e10cSrcweir if( !( pAtom->getNodeType() == SQL_NODE_STRING || 392cdf0e10cSrcweir pAtom->getNodeType() == SQL_NODE_NAME || 393cdf0e10cSrcweir SQL_ISRULE( pAtom,parameter ) || 394cdf0e10cSrcweir ( pAtom->getChild( 0 ) && pAtom->getChild( 0 )->getNodeType() == SQL_NODE_NAME ) || 395cdf0e10cSrcweir ( pAtom->getChild( 0 ) && pAtom->getChild( 0 )->getNodeType() == SQL_NODE_STRING ) ) ) 396cdf0e10cSrcweir { 397cdf0e10cSrcweir OSL_TRACE( "analyseSQL : pAtom->count() = %d\n", pAtom->count() ); 398cdf0e10cSrcweir m_pConnection->throwGenericSQLException(STR_QUERY_INVALID_LIKE_STRING,*this); 399cdf0e10cSrcweir } 400cdf0e10cSrcweir 401cdf0e10cSrcweir const sal_Unicode WILDCARD = '%'; 402cdf0e10cSrcweir 403cdf0e10cSrcweir rtl::OUString aMatchString; 404cdf0e10cSrcweir aMatchString = pAtom->getTokenValue(); 405cdf0e10cSrcweir 406cdf0e10cSrcweir // Determine where '%' character is... 407cdf0e10cSrcweir if( aMatchString.equals( ::rtl::OUString::valueOf( WILDCARD ) ) ) 408cdf0e10cSrcweir { 409cdf0e10cSrcweir // String containing only a '%' and nothing else matches everything 410cdf0e10cSrcweir pResult = createTest( aColumnName, E_BOOK_QUERY_CONTAINS, 411cdf0e10cSrcweir rtl::OUString::createFromAscii( "" ) ); 412cdf0e10cSrcweir } 413cdf0e10cSrcweir else if( aMatchString.indexOf( WILDCARD ) == -1 ) 414cdf0e10cSrcweir { // Simple string , eg. "to match" "contains in evo" 415cdf0e10cSrcweir EVO_TRACE_STRING( "Plain contains '%s'", aMatchString ); 416cdf0e10cSrcweir pResult = createTest( aColumnName, E_BOOK_QUERY_CONTAINS, aMatchString ); 417cdf0e10cSrcweir if( pResult && bNotLike ) 418cdf0e10cSrcweir pResult = e_book_query_not( pResult, TRUE ); 419cdf0e10cSrcweir } 420cdf0e10cSrcweir else if( bNotLike ) 421cdf0e10cSrcweir { 422cdf0e10cSrcweir // We currently can't handle a 'NOT LIKE' when there are '%' 423cdf0e10cSrcweir m_pConnection->throwGenericSQLException(STR_QUERY_NOT_LIKE_TOO_COMPLEX,*this); 424cdf0e10cSrcweir } 425cdf0e10cSrcweir else if( (aMatchString.indexOf ( WILDCARD ) == aMatchString.lastIndexOf ( WILDCARD ) ) ) 426*07a3d7f1SPedro Giffuni { // One occurrence of '%' matches... 427cdf0e10cSrcweir if ( aMatchString.indexOf ( WILDCARD ) == 0 ) 428cdf0e10cSrcweir pResult = createTest( aColumnName, E_BOOK_QUERY_ENDS_WITH, aMatchString.copy( 1 ) ); 429cdf0e10cSrcweir else if ( aMatchString.indexOf ( WILDCARD ) == aMatchString.getLength() - 1 ) 430cdf0e10cSrcweir pResult = createTest( aColumnName, E_BOOK_QUERY_BEGINS_WITH, aMatchString.copy( 0, aMatchString.getLength() - 1 ) ); 431cdf0e10cSrcweir else 432cdf0e10cSrcweir m_pConnection->throwGenericSQLException(STR_QUERY_LIKE_WILDCARD,*this); 433cdf0e10cSrcweir 434cdf0e10cSrcweir if( pResult && bNotLike ) 435cdf0e10cSrcweir pResult = e_book_query_not( pResult, TRUE ); 436cdf0e10cSrcweir } 437cdf0e10cSrcweir else if( aMatchString.getLength() >= 3 && 438cdf0e10cSrcweir aMatchString.indexOf ( WILDCARD ) == 0 && 439cdf0e10cSrcweir aMatchString.indexOf ( WILDCARD, 1) == aMatchString.getLength() - 1 ) { 440cdf0e10cSrcweir // one '%' at the start and another at the end 441cdf0e10cSrcweir pResult = createTest( aColumnName, E_BOOK_QUERY_CONTAINS, aMatchString.copy (1, aMatchString.getLength() - 2) ); 442cdf0e10cSrcweir } 443cdf0e10cSrcweir else 444cdf0e10cSrcweir m_pConnection->throwGenericSQLException(STR_QUERY_LIKE_WILDCARD_MANY,*this); 445cdf0e10cSrcweir } 446cdf0e10cSrcweir 447cdf0e10cSrcweir return pResult; 448cdf0e10cSrcweir } 449cdf0e10cSrcweir 450cdf0e10cSrcweir rtl::OUString OCommonStatement::getTableName() 451cdf0e10cSrcweir { 452cdf0e10cSrcweir ::rtl::OUString aTableName; 453cdf0e10cSrcweir 454cdf0e10cSrcweir if( m_pParseTree && m_aSQLIterator.getStatementType() == SQL_STATEMENT_SELECT ) 455cdf0e10cSrcweir { 456cdf0e10cSrcweir Any aCatalog; 457cdf0e10cSrcweir ::rtl::OUString aSchema, aComposedName; 458cdf0e10cSrcweir const OSQLParseNode *pSelectStmnt = m_aSQLIterator.getParseTree(); 459cdf0e10cSrcweir const OSQLParseNode *pAllTableNames = pSelectStmnt->getChild( 3 )->getChild( 0 )->getChild( 1 ); 460cdf0e10cSrcweir 461cdf0e10cSrcweir if( m_aSQLIterator.isTableNode( pAllTableNames->getChild( 0 ) ) ) 462cdf0e10cSrcweir OSQLParseNode::getTableComponents( pAllTableNames->getChild( 0 ), 463cdf0e10cSrcweir aCatalog,aSchema, aTableName,NULL ); 464cdf0e10cSrcweir 465cdf0e10cSrcweir else if( SQL_ISRULE( pAllTableNames->getChild( 0 ), table_ref ) ) 466cdf0e10cSrcweir { 467cdf0e10cSrcweir OSQLParseNode *pNodeForTableName = pAllTableNames->getChild( 0 )->getChild( 0 ); 468cdf0e10cSrcweir if( m_aSQLIterator.isTableNode( pNodeForTableName ) ) 469cdf0e10cSrcweir { 470cdf0e10cSrcweir aTableName = OSQLParseNode::getTableRange(pAllTableNames->getChild( 0 )); 471cdf0e10cSrcweir if( !aTableName.getLength() ) 472cdf0e10cSrcweir OSQLParseNode::getTableComponents( pNodeForTableName, aCatalog, aSchema, aTableName,NULL); 473cdf0e10cSrcweir } 474cdf0e10cSrcweir else 475cdf0e10cSrcweir OSL_ENSURE( false, "odd table layout" ); 476cdf0e10cSrcweir } 477cdf0e10cSrcweir else 478cdf0e10cSrcweir OSL_ENSURE( false, "unusual table layout" ); 479cdf0e10cSrcweir } 480cdf0e10cSrcweir return aTableName; 481cdf0e10cSrcweir } 482cdf0e10cSrcweir 483cdf0e10cSrcweir void OCommonStatement::parseSql( const rtl::OUString& sql, QueryData& _out_rQueryData ) 484cdf0e10cSrcweir { 485cdf0e10cSrcweir EVO_TRACE_STRING( "parsing %s", sql ); 486cdf0e10cSrcweir 487cdf0e10cSrcweir _out_rQueryData.eFilterType = eFilterOther; 488cdf0e10cSrcweir 489cdf0e10cSrcweir ::rtl::OUString aErr; 490cdf0e10cSrcweir m_pParseTree = m_aParser.parseTree( aErr, sql ); 491cdf0e10cSrcweir m_aSQLIterator.setParseTree( m_pParseTree ); 492cdf0e10cSrcweir m_aSQLIterator.traverseAll(); 493cdf0e10cSrcweir 494cdf0e10cSrcweir _out_rQueryData.sTable = getTableName(); 495cdf0e10cSrcweir 496cdf0e10cSrcweir // to be sorted? 497cdf0e10cSrcweir const OSQLParseNode* pOrderByClause = m_aSQLIterator.getOrderTree(); 498cdf0e10cSrcweir if ( pOrderByClause ) 499cdf0e10cSrcweir { 500cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 0 501cdf0e10cSrcweir ::rtl::OUString sTreeDebug; 502cdf0e10cSrcweir pOrderByClause->showParseTree( sTreeDebug ); 503cdf0e10cSrcweir EVO_TRACE_STRING( "found order-by tree:\n%s", sTreeDebug ); 504cdf0e10cSrcweir #endif 505cdf0e10cSrcweir orderByAnalysis( pOrderByClause, _out_rQueryData.aSortOrder ); 506cdf0e10cSrcweir } 507cdf0e10cSrcweir 508cdf0e10cSrcweir const OSQLParseNode* pWhereClause = m_aSQLIterator.getWhereTree(); 509cdf0e10cSrcweir if ( pWhereClause && SQL_ISRULE( pWhereClause, where_clause ) ) 510cdf0e10cSrcweir { 511cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 0 512cdf0e10cSrcweir ::rtl::OUString sTreeDebug; 513cdf0e10cSrcweir pWhereClause->showParseTree( sTreeDebug ); 514cdf0e10cSrcweir EVO_TRACE_STRING( "found where tree:\n%s", sTreeDebug ); 515cdf0e10cSrcweir #endif 516cdf0e10cSrcweir EBookQuery* pQuery = whereAnalysis( pWhereClause->getChild( 1 ) ); 517cdf0e10cSrcweir if ( !pQuery ) 518cdf0e10cSrcweir { 519cdf0e10cSrcweir _out_rQueryData.eFilterType = eFilterAlwaysFalse; 520cdf0e10cSrcweir pQuery = createTrue(); 521cdf0e10cSrcweir } 522cdf0e10cSrcweir _out_rQueryData.setQuery( pQuery ); 523cdf0e10cSrcweir } 524cdf0e10cSrcweir else 525cdf0e10cSrcweir { 526cdf0e10cSrcweir _out_rQueryData.eFilterType = eFilterNone; 527cdf0e10cSrcweir _out_rQueryData.setQuery( createTrue() ); 528cdf0e10cSrcweir } 529cdf0e10cSrcweir } 530cdf0e10cSrcweir 531cdf0e10cSrcweir // ------------------------------------------------------------------------- 532cdf0e10cSrcweir 533cdf0e10cSrcweir Reference< XConnection > SAL_CALL OStatement::getConnection( ) throw(SQLException, RuntimeException) 534cdf0e10cSrcweir { 535cdf0e10cSrcweir ::osl::MutexGuard aGuard( m_aMutex ); 536cdf0e10cSrcweir checkDisposed(OCommonStatement_IBase::rBHelper.bDisposed); 537cdf0e10cSrcweir 538cdf0e10cSrcweir // just return our connection here 539cdf0e10cSrcweir return impl_getConnection(); 540cdf0e10cSrcweir } 541cdf0e10cSrcweir 542cdf0e10cSrcweir // ------------------------------------------------------------------------- 543cdf0e10cSrcweir Any SAL_CALL OCommonStatement::getWarnings( ) throw(SQLException, RuntimeException) 544cdf0e10cSrcweir { 545cdf0e10cSrcweir ::osl::MutexGuard aGuard( m_aMutex ); 546cdf0e10cSrcweir checkDisposed(OCommonStatement_IBase::rBHelper.bDisposed); 547cdf0e10cSrcweir 548cdf0e10cSrcweir 549cdf0e10cSrcweir return makeAny(SQLWarning()); 550cdf0e10cSrcweir } 551cdf0e10cSrcweir 552cdf0e10cSrcweir // ------------------------------------------------------------------------- 553cdf0e10cSrcweir void SAL_CALL OCommonStatement::clearWarnings( ) throw(SQLException, RuntimeException) 554cdf0e10cSrcweir { 555cdf0e10cSrcweir ::osl::MutexGuard aGuard( m_aMutex ); 556cdf0e10cSrcweir checkDisposed(OCommonStatement_IBase::rBHelper.bDisposed); 557cdf0e10cSrcweir 558cdf0e10cSrcweir } 559cdf0e10cSrcweir // ------------------------------------------------------------------------- 560cdf0e10cSrcweir ::cppu::IPropertyArrayHelper* OCommonStatement::createArrayHelper( ) const 561cdf0e10cSrcweir { 562cdf0e10cSrcweir Sequence< Property > aProps; 563cdf0e10cSrcweir describeProperties( aProps ); 564cdf0e10cSrcweir return new ::cppu::OPropertyArrayHelper( aProps ); 565cdf0e10cSrcweir } 566cdf0e10cSrcweir // ------------------------------------------------------------------------- 567cdf0e10cSrcweir ::cppu::IPropertyArrayHelper & OCommonStatement::getInfoHelper() 568cdf0e10cSrcweir { 569cdf0e10cSrcweir return *const_cast< OCommonStatement* >( this )->getArrayHelper(); 570cdf0e10cSrcweir } 571cdf0e10cSrcweir 572cdf0e10cSrcweir // ----------------------------------------------------------------------------- 573cdf0e10cSrcweir void SAL_CALL OCommonStatement::acquire() throw() 574cdf0e10cSrcweir { 575cdf0e10cSrcweir OCommonStatement_IBase::acquire(); 576cdf0e10cSrcweir } 577cdf0e10cSrcweir // ----------------------------------------------------------------------------- 578cdf0e10cSrcweir void SAL_CALL OCommonStatement::release() throw() 579cdf0e10cSrcweir { 580cdf0e10cSrcweir relase_ChildImpl(); 581cdf0e10cSrcweir } 582cdf0e10cSrcweir 583cdf0e10cSrcweir // ------------------------------------------------------------------------- 584cdf0e10cSrcweir QueryData OCommonStatement::impl_getEBookQuery_throw( const ::rtl::OUString& _rSql ) 585cdf0e10cSrcweir { 586cdf0e10cSrcweir QueryData aData; 587cdf0e10cSrcweir parseSql( _rSql, aData ); 588cdf0e10cSrcweir 589cdf0e10cSrcweir #ifdef DEBUG 590cdf0e10cSrcweir char *pSexpr = aData.getQuery() ? e_book_query_to_string( aData.getQuery() ) : g_strdup( "<map failed>" ); 591cdf0e10cSrcweir g_message( "Parsed SQL to sexpr '%s'\n", pSexpr ); 592cdf0e10cSrcweir g_free( pSexpr ); 593cdf0e10cSrcweir #endif 594cdf0e10cSrcweir 595cdf0e10cSrcweir if ( !aData.getQuery() ) 596cdf0e10cSrcweir m_pConnection->throwGenericSQLException( STR_QUERY_TOO_COMPLEX, *this ); 597cdf0e10cSrcweir 598cdf0e10cSrcweir // a postcondition of this method is that we properly determined the SELECT columns 599cdf0e10cSrcweir aData.xSelectColumns = m_aSQLIterator.getSelectColumns(); 600cdf0e10cSrcweir if ( !aData.xSelectColumns.isValid() ) 601cdf0e10cSrcweir m_pConnection->throwGenericSQLException( STR_QUERY_TOO_COMPLEX, *this ); 602cdf0e10cSrcweir 603cdf0e10cSrcweir return aData; 604cdf0e10cSrcweir } 605cdf0e10cSrcweir 606cdf0e10cSrcweir // ------------------------------------------------------------------------- 607cdf0e10cSrcweir Reference< XResultSet > OCommonStatement::impl_executeQuery_throw( const QueryData& _rQueryData ) 608cdf0e10cSrcweir { 609cdf0e10cSrcweir // create result set 610cdf0e10cSrcweir OEvoabResultSet* pResult = new OEvoabResultSet( this, m_pConnection ); 611cdf0e10cSrcweir Reference< XResultSet > xRS = pResult; 612cdf0e10cSrcweir pResult->construct( _rQueryData ); 613cdf0e10cSrcweir 614cdf0e10cSrcweir // done 615cdf0e10cSrcweir m_xResultSet = xRS; 616cdf0e10cSrcweir return xRS; 617cdf0e10cSrcweir } 618cdf0e10cSrcweir 619cdf0e10cSrcweir // ------------------------------------------------------------------------- 620cdf0e10cSrcweir Reference< XResultSet > OCommonStatement::impl_executeQuery_throw( const ::rtl::OUString& _rSql ) 621cdf0e10cSrcweir { 622cdf0e10cSrcweir EVO_TRACE_STRING( "OCommonStatement::impl_executeQuery_throw(%s)\n", _rSql ); 623cdf0e10cSrcweir 624cdf0e10cSrcweir #ifdef DEBUG 625cdf0e10cSrcweir g_message( "Parse SQL '%s'\n", 626cdf0e10cSrcweir (const sal_Char *)OUStringToOString( _rSql, RTL_TEXTENCODING_UTF8 ) ); 627cdf0e10cSrcweir #endif 628cdf0e10cSrcweir 629cdf0e10cSrcweir return impl_executeQuery_throw( impl_getEBookQuery_throw( _rSql ) ); 630cdf0e10cSrcweir } 631cdf0e10cSrcweir 632cdf0e10cSrcweir // ----------------------------------------------------------------------------- 633cdf0e10cSrcweir Reference< XPropertySetInfo > SAL_CALL OCommonStatement::getPropertySetInfo( ) throw(RuntimeException) 634cdf0e10cSrcweir { 635cdf0e10cSrcweir return ::cppu::OPropertySetHelper::createPropertySetInfo( getInfoHelper() ); 636cdf0e10cSrcweir } 637cdf0e10cSrcweir 638cdf0e10cSrcweir // ============================================================================= 639cdf0e10cSrcweir // = OStatement 640cdf0e10cSrcweir // ============================================================================= 641cdf0e10cSrcweir // ----------------------------------------------------------------------------- 642cdf0e10cSrcweir IMPLEMENT_SERVICE_INFO( OStatement, "com.sun.star.comp.sdbcx.evoab.OStatement", "com.sun.star.sdbc.Statement" ); 643cdf0e10cSrcweir 644cdf0e10cSrcweir // ----------------------------------------------------------------------------- 645cdf0e10cSrcweir IMPLEMENT_FORWARD_XINTERFACE2( OStatement, OCommonStatement, OStatement_IBase ) 646cdf0e10cSrcweir 647cdf0e10cSrcweir // ----------------------------------------------------------------------------- 648cdf0e10cSrcweir IMPLEMENT_FORWARD_XTYPEPROVIDER2( OStatement, OCommonStatement, OStatement_IBase ) 649cdf0e10cSrcweir 650cdf0e10cSrcweir // ------------------------------------------------------------------------- 651cdf0e10cSrcweir sal_Bool SAL_CALL OStatement::execute( const ::rtl::OUString& _sql ) throw(SQLException, RuntimeException) 652cdf0e10cSrcweir { 653cdf0e10cSrcweir ::osl::MutexGuard aGuard( m_aMutex ); 654cdf0e10cSrcweir checkDisposed(OCommonStatement_IBase::rBHelper.bDisposed); 655cdf0e10cSrcweir 656cdf0e10cSrcweir Reference< XResultSet > xRS = impl_executeQuery_throw( _sql ); 657cdf0e10cSrcweir return xRS.is(); 658cdf0e10cSrcweir } 659cdf0e10cSrcweir 660cdf0e10cSrcweir // ------------------------------------------------------------------------- 661cdf0e10cSrcweir Reference< XResultSet > SAL_CALL OStatement::executeQuery( const ::rtl::OUString& _sql ) throw(SQLException, RuntimeException) 662cdf0e10cSrcweir { 663cdf0e10cSrcweir ::osl::MutexGuard aGuard( m_aMutex ); 664cdf0e10cSrcweir checkDisposed(OCommonStatement_IBase::rBHelper.bDisposed); 665cdf0e10cSrcweir 666cdf0e10cSrcweir return impl_executeQuery_throw( _sql ); 667cdf0e10cSrcweir } 668cdf0e10cSrcweir 669cdf0e10cSrcweir // ----------------------------------------------------------------------------- 670cdf0e10cSrcweir sal_Int32 SAL_CALL OStatement::executeUpdate( const ::rtl::OUString& /*sql*/ ) throw(SQLException, RuntimeException) 671cdf0e10cSrcweir { 672cdf0e10cSrcweir ::osl::MutexGuard aGuard( m_aMutex ); 673cdf0e10cSrcweir checkDisposed(OCommonStatement_IBase::rBHelper.bDisposed); 674cdf0e10cSrcweir ::dbtools::throwFeatureNotImplementedException( "XStatement::executeUpdate", *this ); 675cdf0e10cSrcweir return 0; 676cdf0e10cSrcweir } 677cdf0e10cSrcweir 678cdf0e10cSrcweir } } // namespace ::connectivity::evoab 679