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