xref: /trunk/main/connectivity/source/drivers/file/fanalyzer.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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