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