xref: /AOO41X/main/connectivity/source/drivers/file/fanalyzer.cxx (revision 9b5730f6ddef7eb82608ca4d31dc0d7678e652cf)
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 
DBG_NAME(file_OSQLAnalyzer)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 // -----------------------------------------------------------------------------
~OSQLAnalyzer()56 OSQLAnalyzer::~OSQLAnalyzer()
57 {
58     DBG_DTOR( file_OSQLAnalyzer, NULL );
59 }
60 
61 // -----------------------------------------------------------------------------
setIndexes(const Reference<XNameAccess> & _xIndexes)62 void OSQLAnalyzer::setIndexes(const Reference< XNameAccess>& _xIndexes)
63 {
64     m_aCompiler->m_xIndexes = _xIndexes;
65 }
66 //------------------------------------------------------------------
start(OSQLParseNode * pSQLParseNode)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 //------------------------------------------------------------------
bindRow(OCodeList & rCodeList,const OValueRefRow & _pRow,OEvaluateSetList & _rEvaluateSetList)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 //------------------------------------------------------------------
bindSelectRow(const OValueRefRow & _pRow)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 //------------------------------------------------------------------
bindEvaluationRow(OValueRefRow & _pRow)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 //------------------------------------------------------------------
describeParam(::vos::ORef<OSQLColumns> rParameterColumns)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 // -----------------------------------------------------------------------------
createOperandAttr(sal_Int32 _nPos,const Reference<XPropertySet> & _xCol,const Reference<XNameAccess> &)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 // -----------------------------------------------------------------------------
hasRestriction() const283 sal_Bool OSQLAnalyzer::hasRestriction() const
284 {
285     return m_aCompiler->hasCode();
286 }
287 // -----------------------------------------------------------------------------
hasFunctions() const288 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 // -----------------------------------------------------------------------------
setSelectionEvaluationResult(OValueRefRow & _pRow,const::std::vector<sal_Int32> & _rColumnMapping)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 // -----------------------------------------------------------------------------
dispose()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 // -----------------------------------------------------------------------------
setOrigColumns(const OFileColumns & rCols)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