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 "file/fanalyzer.hxx" 31 #include "connectivity/sqlparse.hxx" 32 #include <osl/diagnose.h> 33 #include <tools/debug.hxx> 34 #include <comphelper/extract.hxx> 35 #include "connectivity/sqlnode.hxx" 36 #include "connectivity/dbexception.hxx" 37 #include "file/FConnection.hxx" 38 #include "resource/file_res.hrc" 39 40 using namespace ::connectivity; 41 using namespace ::connectivity::file; 42 using namespace ::com::sun::star::uno; 43 using namespace ::com::sun::star::beans; 44 using namespace ::com::sun::star::sdbc; 45 using namespace ::com::sun::star::container; 46 47 DBG_NAME( file_OSQLAnalyzer ) 48 //------------------------------------------------------------------ 49 OSQLAnalyzer::OSQLAnalyzer(OConnection* _pConnection) 50 :m_pConnection(_pConnection) 51 ,m_bHasSelectionCode(sal_False) 52 ,m_bSelectionFirstTime(sal_True) 53 { 54 DBG_CTOR( file_OSQLAnalyzer, NULL ); 55 m_aCompiler = new OPredicateCompiler(this); 56 m_aInterpreter = new OPredicateInterpreter(m_aCompiler); 57 } 58 59 // ----------------------------------------------------------------------------- 60 OSQLAnalyzer::~OSQLAnalyzer() 61 { 62 DBG_DTOR( file_OSQLAnalyzer, NULL ); 63 } 64 65 // ----------------------------------------------------------------------------- 66 void OSQLAnalyzer::setIndexes(const Reference< XNameAccess>& _xIndexes) 67 { 68 m_aCompiler->m_xIndexes = _xIndexes; 69 } 70 //------------------------------------------------------------------ 71 void OSQLAnalyzer::start(OSQLParseNode* pSQLParseNode) 72 { 73 if (SQL_ISRULE(pSQLParseNode,select_statement)) 74 { 75 DBG_ASSERT(pSQLParseNode->count() >= 4,"OFILECursor: Fehler im Parse Tree"); 76 77 // check that we don't use anything other than count(*) as function 78 OSQLParseNode* pSelection = pSQLParseNode->getChild(2); 79 if ( SQL_ISRULE(pSelection,scalar_exp_commalist) ) 80 { 81 for (sal_uInt32 i = 0; i < pSelection->count(); i++) 82 { 83 OSQLParseNode *pColumnRef = pSelection->getChild(i)->getChild(0); 84 if ( ( SQL_ISRULE(pColumnRef,set_fct_spec) && pColumnRef->count() == 4 ) 85 || SQL_ISRULE(pColumnRef,char_value_fct) 86 || SQL_ISRULE(pColumnRef,char_substring_fct) 87 || SQL_ISRULE(pColumnRef,position_exp) 88 || SQL_ISRULE(pColumnRef,fold) 89 || SQL_ISRULE(pColumnRef,length_exp) 90 || SQL_ISRULE(pColumnRef,num_value_exp) 91 || SQL_ISRULE(pColumnRef,term) 92 || SQL_ISRULE(pColumnRef,factor) 93 || SQL_ISRULE(pColumnRef,set_fct_spec) ) 94 { 95 ::vos::ORef<OPredicateCompiler> pCompiler = new OPredicateCompiler(this); 96 pCompiler->setOrigColumns(m_aCompiler->getOrigColumns()); 97 ::vos::ORef<OPredicateInterpreter> pInterpreter = new OPredicateInterpreter(pCompiler); 98 pCompiler->execute( pColumnRef ); 99 m_aSelectionEvaluations.push_back( TPredicates(pCompiler,pInterpreter) ); 100 } 101 else if ( ( SQL_ISRULE(pColumnRef,general_set_fct) && pColumnRef->count() != 4 ) ) 102 { 103 m_pConnection->throwGenericSQLException(STR_QUERY_COMPLEX_COUNT,NULL); 104 } 105 else 106 { 107 if ( SQL_ISPUNCTUATION( pColumnRef, "*" ) 108 || ( SQL_ISRULE( pColumnRef, column_ref ) 109 && ( pColumnRef->count() == 3 ) 110 && ( pColumnRef->getChild(0)->getNodeType() == SQL_NODE_NAME ) 111 && SQL_ISPUNCTUATION( pColumnRef->getChild(1), "." ) 112 && SQL_ISRULE( pColumnRef->getChild(2), column_val ) 113 && SQL_ISPUNCTUATION( pColumnRef->getChild(2)->getChild(0), "*" ) 114 ) 115 ) 116 { 117 // push one element for each column of our table 118 const Reference< XNameAccess > xColumnNames( m_aCompiler->getOrigColumns() ); 119 const Sequence< ::rtl::OUString > aColumnNames( xColumnNames->getElementNames() ); 120 for ( sal_Int32 j=0; j<aColumnNames.getLength(); ++j ) 121 m_aSelectionEvaluations.push_back( TPredicates() ); 122 } 123 else 124 m_aSelectionEvaluations.push_back( TPredicates() ); 125 } 126 } 127 } 128 } 129 130 m_aCompiler->start(pSQLParseNode); 131 } 132 133 //------------------------------------------------------------------ 134 void OSQLAnalyzer::bindRow(OCodeList& rCodeList,const OValueRefRow& _pRow,OEvaluateSetList& _rEvaluateSetList) 135 { 136 // Zaehlen, wieviele Kriterien 137 // wenn nur ein Kriterium, und das entsprechende Feld ist indiziert 138 // dann wird der Index verwendet 139 140 OEvaluateSet* pEvaluateSet = NULL; 141 142 for (OCodeList::iterator aIter = rCodeList.begin(); aIter != rCodeList.end(); ++aIter) 143 { 144 OOperandAttr* pAttr = PTR_CAST(OOperandAttr,(*aIter)); 145 if (pAttr) 146 { 147 if (pAttr->isIndexed() && !m_aCompiler->hasORCondition()) 148 { 149 OCode* pCode1 = *(aIter + 1); 150 OCode* pCode2 = *(aIter + 2); 151 152 if (PTR_CAST(OOperand,pCode1)) 153 pEvaluateSet = pAttr->preProcess(PTR_CAST(OBoolOperator,pCode2), PTR_CAST(OOperand,pCode1)); 154 else 155 pEvaluateSet = pAttr->preProcess(PTR_CAST(OBoolOperator,pCode1)); 156 } 157 158 if (pEvaluateSet) 159 { 160 _rEvaluateSetList.push_back(pEvaluateSet); 161 pEvaluateSet = NULL; 162 } 163 pAttr->bindValue(_pRow); 164 } 165 } 166 } 167 //------------------------------------------------------------------ 168 void OSQLAnalyzer::bindSelectRow(const OValueRefRow& _pRow) 169 { 170 // first the select part 171 OEvaluateSetList aEvaluateSetList; 172 for ( ::std::vector< TPredicates >::iterator aIter = m_aSelectionEvaluations.begin(); aIter != m_aSelectionEvaluations.end();++aIter) 173 { 174 if ( aIter->first.isValid() ) 175 bindRow( aIter->first->m_aCodeList,_pRow,aEvaluateSetList); 176 } 177 } 178 //------------------------------------------------------------------ 179 ::std::vector<sal_Int32>* OSQLAnalyzer::bindEvaluationRow(OValueRefRow& _pRow) 180 { 181 OEvaluateSetList aEvaluateSetList; 182 bindRow( m_aCompiler->m_aCodeList,_pRow,aEvaluateSetList); 183 184 ::std::vector<sal_Int32>* pKeySet = NULL; 185 OEvaluateSet* pEvaluateSet = NULL; 186 187 // Keyset erzeugen mit kleinster Liste 188 if(!aEvaluateSetList.empty()) 189 { 190 // welche Liste hat den kleinsten count ? 191 OEvaluateSetList::iterator i = aEvaluateSetList.begin(); 192 pEvaluateSet = *(i); 193 for(++i; i != aEvaluateSetList.end();++i) 194 { 195 OEvaluateSet* pEvaluateSetComp = (*i); 196 for(OEvaluateSet::reverse_iterator j = pEvaluateSet->rbegin(); j != pEvaluateSet->rend(); ++j) 197 { 198 if (pEvaluateSetComp->find(j->second) != pEvaluateSetComp->end()) 199 pEvaluateSet->erase(j->second); 200 } 201 } 202 pKeySet = new ::std::vector<sal_Int32>(pEvaluateSet->size()); 203 sal_Int32 k=0; 204 for(OEvaluateSet::iterator j = pEvaluateSet->begin(); j != pEvaluateSet->end(); ++j,++k) 205 { 206 (*pKeySet)[k] = j->second; 207 } 208 209 // alle loeschen 210 for(i = aEvaluateSetList.begin(); i != aEvaluateSetList.end();++i) 211 delete (*i); 212 } 213 214 return pKeySet; 215 } 216 217 //------------------------------------------------------------------ 218 void OSQLAnalyzer::describeParam(::vos::ORef<OSQLColumns> rParameterColumns) 219 { 220 OCodeList& rCodeList = m_aCompiler->m_aCodeList; 221 OCodeStack aCodeStack; 222 223 if (!rCodeList.size()) 224 return; // kein Praedikat 225 if (!rParameterColumns->get().size()) 226 return; // keine Parameter 227 228 // Anlegen von Columns, die eine genauere Beschreibung fuer die enthalten 229 ::vos::ORef<OSQLColumns> aNewParamColumns = new OSQLColumns(*rParameterColumns); 230 231 232 // Anlegen einer Testzeile, wird benoetigt um die Parameter zu beschreiben 233 OValueRefRow aParameterRow = new OValueRefVector(rParameterColumns->get().size()); 234 bindParameterRow(aParameterRow); 235 236 OValueRefRow aTestRow = new OValueRefVector(Reference< XIndexAccess>(m_aCompiler->getOrigColumns(),UNO_QUERY)->getCount()); 237 delete bindEvaluationRow(aTestRow); // Binden der Attribute an die Values 238 239 for(OCodeList::iterator aIter = rCodeList.begin(); aIter != rCodeList.end(); ++aIter) 240 { 241 OOperand* pOperand = PTR_CAST(OOperand,(*aIter)); 242 OOperator* pOperator = PTR_CAST(OOperator,(*aIter)); 243 if (pOperand) 244 aCodeStack.push(pOperand); 245 else 246 { 247 if (pOperator->getRequestedOperands() == 2) // bei zwei Operatoren ist es moeglich 248 { // einen Parameter weiter zu spezifizieren 249 OOperandParam *pParam = PTR_CAST(OOperandParam,aCodeStack.top()); 250 if (pParam) // Anpassen des ParameterTyps, wenn der linke Operand ein Attribut ist 251 { 252 OOperandAttr *pLeft = PTR_CAST(OOperandAttr,*(rCodeList.end() - 2)); 253 if (pLeft) 254 { 255 Reference< XPropertySet> xCol; 256 Reference< XIndexAccess>(m_aCompiler->getOrigColumns(),UNO_QUERY)->getByIndex(pLeft->getRowPos()) >>= xCol; 257 OSL_ENSURE(xCol.is(), "Ungueltige Struktur"); 258 pParam->describe(xCol, aNewParamColumns); 259 } 260 } 261 } 262 pOperator->Exec(aCodeStack); 263 } 264 } 265 OOperand* pOperand = aCodeStack.top(); 266 aCodeStack.pop(); 267 268 OSL_ENSURE(aCodeStack.size() == 0, "StackFehler"); 269 OSL_ENSURE(pOperand, "StackFehler"); 270 if (IS_TYPE(OOperandResult,pOperand)) 271 delete pOperand; 272 else 273 OSL_ENSURE(0,"Illegal here!"); 274 275 rParameterColumns = aNewParamColumns; 276 // m_aCompiler->setParameterColumns(rParameterColumns); 277 } 278 279 // ----------------------------------------------------------------------------- 280 OOperandAttr* OSQLAnalyzer::createOperandAttr(sal_Int32 _nPos, 281 const Reference< XPropertySet>& _xCol, 282 const Reference< XNameAccess>& /*_xIndexes*/) 283 { 284 return new OOperandAttr(static_cast<sal_uInt16>(_nPos),_xCol); 285 } 286 // ----------------------------------------------------------------------------- 287 sal_Bool OSQLAnalyzer::hasRestriction() const 288 { 289 return m_aCompiler->hasCode(); 290 } 291 // ----------------------------------------------------------------------------- 292 sal_Bool OSQLAnalyzer::hasFunctions() const 293 { 294 if ( m_bSelectionFirstTime ) 295 { 296 m_bSelectionFirstTime = sal_False; 297 for ( ::std::vector< TPredicates >::const_iterator aIter = m_aSelectionEvaluations.begin(); aIter != m_aSelectionEvaluations.end() && !m_bHasSelectionCode ;++aIter) 298 { 299 if ( aIter->first.isValid() ) 300 m_bHasSelectionCode = aIter->first->hasCode(); 301 } 302 } 303 return m_bHasSelectionCode;; 304 } 305 // ----------------------------------------------------------------------------- 306 void OSQLAnalyzer::setSelectionEvaluationResult(OValueRefRow& _pRow,const ::std::vector<sal_Int32>& _rColumnMapping) 307 { 308 sal_Int32 nPos = 1; 309 for ( ::std::vector< TPredicates >::iterator aIter = m_aSelectionEvaluations.begin(); aIter != m_aSelectionEvaluations.end();++aIter,++nPos) 310 { 311 if ( aIter->second.isValid() ) 312 { 313 // the first column (index 0) is for convenience only. The first real select column is no 1. 314 sal_Int32 map = nPos; 315 if ( nPos < static_cast< sal_Int32 >( _rColumnMapping.size() ) ) 316 map = _rColumnMapping[nPos]; 317 if ( map > 0 ) 318 aIter->second->startSelection( (_pRow->get())[map] ); 319 } 320 } 321 } 322 // ----------------------------------------------------------------------------- 323 void OSQLAnalyzer::dispose() 324 { 325 m_aCompiler->dispose(); 326 for ( ::std::vector< TPredicates >::iterator aIter = m_aSelectionEvaluations.begin(); aIter != m_aSelectionEvaluations.end();++aIter) 327 { 328 if ( aIter->first.isValid() ) 329 aIter->first->dispose(); 330 } 331 } 332 // ----------------------------------------------------------------------------- 333 void OSQLAnalyzer::setOrigColumns(const OFileColumns& rCols) 334 { 335 m_aCompiler->setOrigColumns(rCols); 336 for ( ::std::vector< TPredicates >::iterator aIter = m_aSelectionEvaluations.begin(); aIter != m_aSelectionEvaluations.end();++aIter) 337 { 338 if ( aIter->first.isValid() ) 339 aIter->first->setOrigColumns(rCols); 340 } 341 } 342 // ----------------------------------------------------------------------------- 343