xref: /AOO42X/main/connectivity/source/drivers/file/fcode.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/fcode.hxx"
31 #include <osl/diagnose.h>
32 #include "connectivity/sqlparse.hxx"
33 #include <i18npool/mslangid.hxx>
34 #include <tools/debug.hxx>
35 #include <tools/string.hxx>
36 #include "TConnection.hxx"
37 #include <com/sun/star/sdb/SQLFilterOperator.hpp>
38 #include <comphelper/types.hxx>
39 #include <com/sun/star/sdb/SQLFilterOperator.hpp>
40 #include <rtl/logfile.hxx>
41 
42 using namespace ::comphelper;
43 using namespace connectivity;
44 using namespace connectivity::file;
45 //using namespace ::com::sun::star::uno;
46 //using namespace ::com::sun::star::lang;
47 using namespace ::com::sun::star::sdbc;
48 using namespace ::com::sun::star::sdb;
49 //using namespace ::com::sun::star::container;
50 //using namespace ::com::sun::star::beans;
51 //using namespace ::com::sun::star::sdbcx;
52 
53 TYPEINIT0(OCode);
54 TYPEINIT1(OOperand, OCode);
55 TYPEINIT1(OOperandRow, OOperand);
56 TYPEINIT1(OOperandAttr, OOperandRow);
57 TYPEINIT1(OOperandParam, OOperandRow);
58 TYPEINIT1(OOperandValue, OOperand);
59 TYPEINIT1(OOperandConst, OOperandValue);
60 TYPEINIT1(OOperandResult, OOperandValue);
61 TYPEINIT1(OStopOperand, OOperandValue);
62 
63 TYPEINIT1(OOperator, OCode);
64 TYPEINIT1(OBoolOperator,OOperator);
65 TYPEINIT1(OOp_NOT, OBoolOperator);
66 TYPEINIT1(OOp_AND, OBoolOperator);
67 TYPEINIT1(OOp_OR, OBoolOperator);
68 TYPEINIT1(OOp_ISNULL, OBoolOperator);
69 TYPEINIT1(OOp_ISNOTNULL, OOp_ISNULL);
70 TYPEINIT1(OOp_LIKE, OBoolOperator);
71 TYPEINIT1(OOp_NOTLIKE, OOp_LIKE);
72 TYPEINIT1(OOp_COMPARE, OBoolOperator);
73 TYPEINIT1(ONumOperator, OOperator);
74 TYPEINIT1(ONthOperator, OOperator);
75 TYPEINIT1(OBinaryOperator, OOperator);
76 TYPEINIT1(OUnaryOperator, OOperator);
77 
78 //------------------------------------------------------------------
79 DBG_NAME(OCode )
80 OCode::OCode()
81 {
82     DBG_CTOR(OCode ,NULL);
83 }
84 // -----------------------------------------------------------------------------
85 OCode::~OCode()
86 {
87     DBG_DTOR(OCode,NULL);
88 }
89 
90 //------------------------------------------------------------------
91 OEvaluateSet* OOperand::preProcess(OBoolOperator* /*pOp*/, OOperand* /*pRight*/)
92 {
93     return NULL;
94 }
95 // -----------------------------------------------------------------------------
96 OOperandRow::OOperandRow(sal_uInt16 _nPos, sal_Int32 _rType)
97     : OOperand(_rType)
98     , m_nRowPos(_nPos)
99 {}
100 //------------------------------------------------------------------
101 void OOperandRow::bindValue(const OValueRefRow& _pRow)
102 {
103     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOperandRow::OOperandRow" );
104     OSL_ENSURE(_pRow.isValid(),"NO EMPTY row allowed!");
105     m_pRow = _pRow;
106     OSL_ENSURE(m_pRow.isValid() && m_nRowPos < m_pRow->get().size(),"Invalid RowPos is >= vector.size()");
107     (m_pRow->get())[m_nRowPos]->setBound(sal_True);
108 }
109 // -----------------------------------------------------------------------------
110 void OOperandRow::setValue(const ORowSetValue& _rVal)
111 {
112     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOperandRow::setValue" );
113     OSL_ENSURE(m_pRow.isValid() && m_nRowPos < m_pRow->get().size(),"Invalid RowPos is >= vector.size()");
114     (*(m_pRow->get())[m_nRowPos]) = _rVal;
115 }
116 //------------------------------------------------------------------
117 const ORowSetValue& OOperandRow::getValue() const
118 {
119     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOperandRow::getValue" );
120     OSL_ENSURE(m_pRow.isValid() && m_nRowPos < m_pRow->get().size(),"Invalid RowPos is >= vector.size()");
121     return (m_pRow->get())[m_nRowPos]->getValue();
122 }
123 
124 // -----------------------------------------------------------------------------
125 void OOperandValue::setValue(const ORowSetValue& _rVal)
126 {
127     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOperandValue::setValue" );
128     m_aValue = _rVal;
129 }
130 // -------------------------------------------------------------------------
131 sal_Bool OOperandAttr::isIndexed() const
132 {
133     return sal_False;
134 }
135 //------------------------------------------------------------------
136 OOperandParam::OOperandParam(OSQLParseNode* pNode, sal_Int32 _nPos)
137     : OOperandRow(static_cast<sal_uInt16>(_nPos), DataType::VARCHAR)         // Standard-Typ
138 {
139     OSL_ENSURE(SQL_ISRULE(pNode,parameter),"Argument ist kein Parameter");
140     OSL_ENSURE(pNode->count() > 0,"Fehler im Parse Tree");
141     OSQLParseNode *pMark = pNode->getChild(0);
142 
143     String aParameterName;
144     if (SQL_ISPUNCTUATION(pMark,"?"))
145         aParameterName = '?';
146     else if (SQL_ISPUNCTUATION(pMark,":"))
147         aParameterName = pNode->getChild(1)->getTokenValue();
148     else
149     {
150         OSL_ASSERT("Fehler im Parse Tree");
151     }
152 
153     // Parameter-Column aufsetzen mit defult typ, kann zu einem spaeteren Zeitpunkt ueber DescribeParameter
154     // genauer spezifiziert werden
155 
156     // Identitaet merken (hier eigentlich nicht erforderlich, aber aus
157     // Symmetriegruenden ...)
158 
159     // todo
160     //  OColumn* pColumn = new OFILEColumn(aParameterName,eDBType,255,0,SQL_FLAGS_NULLALLOWED);
161     //  rParamColumns->AddColumn(pColumn);
162 
163     // der Wert wird erst kurz vor der Auswertung gesetzt
164 }
165 
166 
167 //------------------------------------------------------------------
168 const ORowSetValue& OOperandValue::getValue() const
169 {
170     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOperandValue::getValue" );
171     return m_aValue;
172 }
173 
174 //------------------------------------------------------------------
175 OOperandConst::OOperandConst(const OSQLParseNode& rColumnRef, const rtl::OUString& aStrValue)
176 {
177     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOperandConst::OOperandConst" );
178     switch (rColumnRef.getNodeType())
179     {
180         case SQL_NODE_STRING:
181             m_aValue    = aStrValue;
182             m_eDBType   = DataType::VARCHAR;
183             m_aValue.setBound(sal_True);
184             return;
185         case SQL_NODE_INTNUM:
186         case SQL_NODE_APPROXNUM:
187         {
188             m_aValue    = aStrValue.toDouble();
189             m_eDBType   = DataType::DOUBLE;
190             m_aValue.setBound(sal_True);
191             return;
192         }
193         default:
194             break;
195     }
196 
197     if (SQL_ISTOKEN(&rColumnRef,TRUE))
198     {
199         m_aValue = 1.0;
200         m_eDBType = DataType::BIT;
201     }
202     else if (SQL_ISTOKEN(&rColumnRef,FALSE))
203     {
204         m_aValue = 0.0;
205         m_eDBType = DataType::BIT;
206     }
207     else
208     {
209         OSL_ASSERT("Parse Error");
210     }
211     m_aValue.setBound(sal_True);
212 }
213 
214 /////////////////////////////////////////////////////////////////////////////////////////
215 // Implementation of the operators
216 
217 //------------------------------------------------------------------
218 sal_uInt16 OOperator::getRequestedOperands() const {return 2;}
219 
220 //------------------------------------------------------------------
221 sal_Bool OBoolOperator::operate(const OOperand*, const OOperand*) const
222 {
223     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OBoolOperator::operate" );
224     return sal_False;
225 }
226 
227 
228 //------------------------------------------------------------------
229 void OBoolOperator::Exec(OCodeStack& rCodeStack)
230 {
231     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OBoolOperator::Exec" );
232     OOperand  *pRight   = rCodeStack.top();
233     rCodeStack.pop();
234     OOperand  *pLeft    = rCodeStack.top();
235     rCodeStack.pop();
236 
237     rCodeStack.push(new OOperandResultBOOL(operate(pLeft, pRight)));
238     if (IS_TYPE(OOperandResult,pLeft))
239         delete pLeft;
240     if (IS_TYPE(OOperandResult,pRight))
241         delete pRight;
242 }
243 //------------------------------------------------------------------
244 sal_Bool OOp_NOT::operate(const OOperand* pLeft, const OOperand* ) const
245 {
246     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOp_AND::operate" );
247     return !pLeft->isValid();
248 }
249 //------------------------------------------------------------------
250 void OOp_NOT::Exec(OCodeStack& rCodeStack)
251 {
252     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOp_ISNULL::Exec" );
253     OOperand* pOperand = rCodeStack.top();
254     rCodeStack.pop();
255 
256     rCodeStack.push(new OOperandResultBOOL(operate(pOperand)));
257     if (IS_TYPE(OOperandResult,pOperand))
258         delete pOperand;
259 }
260 //------------------------------------------------------------------
261 sal_uInt16 OOp_NOT::getRequestedOperands() const
262 {
263     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOp_NOT::getRequestedOperands" );
264     return 1;
265 }
266 
267 //------------------------------------------------------------------
268 sal_Bool OOp_AND::operate(const OOperand* pLeft, const OOperand* pRight) const
269 {
270     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOp_AND::operate" );
271     return pLeft->isValid() && pRight->isValid();
272 }
273 
274 //------------------------------------------------------------------
275 sal_Bool OOp_OR::operate(const OOperand* pLeft, const OOperand* pRight) const
276 {
277     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOp_OR::operate" );
278     return pLeft->isValid() || pRight->isValid();
279 }
280 
281 //------------------------------------------------------------------
282 sal_uInt16 OOp_ISNULL::getRequestedOperands() const
283 {
284     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOp_ISNULL::getRequestedOperands" );
285     return 1;
286 }
287 
288 //------------------------------------------------------------------
289 void OOp_ISNULL::Exec(OCodeStack& rCodeStack)
290 {
291     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOp_ISNULL::Exec" );
292     OOperand* pOperand = rCodeStack.top();
293     rCodeStack.pop();
294 
295     rCodeStack.push(new OOperandResultBOOL(operate(pOperand)));
296     if (IS_TYPE(OOperandResult,pOperand))
297         delete pOperand;
298 }
299 
300 //------------------------------------------------------------------
301 sal_Bool OOp_ISNULL::operate(const OOperand* pOperand, const OOperand*) const
302 {
303     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOp_ISNULL::operate" );
304     return pOperand->getValue().isNull();
305 }
306 
307 //------------------------------------------------------------------
308 sal_Bool OOp_ISNOTNULL::operate(const OOperand* pOperand, const OOperand*) const
309 {
310     return !OOp_ISNULL::operate(pOperand);
311 }
312 
313 //------------------------------------------------------------------
314 sal_Bool OOp_LIKE::operate(const OOperand* pLeft, const OOperand* pRight) const
315 {
316     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOp_ISNULL::operate" );
317     sal_Bool bMatch;
318     ORowSetValue aLH(pLeft->getValue());
319     ORowSetValue aRH(pRight->getValue());
320 
321     if (aLH.isNull() || aRH.isNull())
322         bMatch = sal_False;
323     else
324     {
325         bMatch = match(aRH.getString(), aLH.getString(), cEscape);
326     }
327     return bMatch;
328 }
329 
330 //------------------------------------------------------------------
331 sal_Bool OOp_NOTLIKE::operate(const OOperand* pLeft, const OOperand* pRight) const
332 {
333     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOp_NOTLIKE::operate" );
334     return !OOp_LIKE::operate(pLeft, pRight);
335 }
336 
337 //------------------------------------------------------------------
338 sal_Bool OOp_COMPARE::operate(const OOperand* pLeft, const OOperand* pRight) const
339 {
340     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOp_COMPARE::operate" );
341     ORowSetValue aLH(pLeft->getValue());
342     ORowSetValue aRH(pRight->getValue());
343 
344     if (aLH.isNull() || aRH.isNull()) // if (!aLH.getValue() || !aRH.getValue())
345         return sal_False;
346 
347     sal_Bool bResult = sal_False;
348     sal_Int32 eDBType = pLeft->getDBType();
349 
350     // Vergleich (je nach Datentyp):
351     switch (eDBType)
352     {
353         case DataType::CHAR:
354         case DataType::VARCHAR:
355         case DataType::LONGVARCHAR:
356         {
357             rtl::OUString sLH = aLH, sRH = aRH;
358             sal_Int32 nRes = rtl_ustr_compareIgnoreAsciiCase_WithLength
359                 (
360                  sLH.pData->buffer,
361                  sLH.pData->length,
362                  sRH.pData->buffer,
363                  sRH.pData->length );
364             switch(aPredicateType)
365             {
366                 case SQLFilterOperator::EQUAL:          bResult = (nRes == 0); break;
367                 case SQLFilterOperator::NOT_EQUAL:          bResult = (nRes != 0); break;
368                 case SQLFilterOperator::LESS:               bResult = (nRes <  0); break;
369                 case SQLFilterOperator::LESS_EQUAL:     bResult = (nRes <= 0); break;
370                 case SQLFilterOperator::GREATER:            bResult = (nRes >  0); break;
371                 case SQLFilterOperator::GREATER_EQUAL:  bResult = (nRes >= 0); break;
372                 default:                        bResult = sal_False;
373             }
374         } break;
375         case DataType::TINYINT:
376         case DataType::SMALLINT:
377         case DataType::INTEGER:
378         case DataType::DECIMAL:
379         case DataType::NUMERIC:
380         case DataType::REAL:
381         case DataType::DOUBLE:
382         case DataType::BIT:
383         case DataType::TIMESTAMP:
384         case DataType::DATE:
385         case DataType::TIME:
386         {
387             double n = aLH ,m = aRH;
388 
389             switch (aPredicateType)
390             {
391                 case SQLFilterOperator::EQUAL:          bResult = (n == m); break;
392                 case SQLFilterOperator::LIKE:               bResult = (n == m); break;
393                 case SQLFilterOperator::NOT_EQUAL:          bResult = (n != m); break;
394                 case SQLFilterOperator::NOT_LIKE:           bResult = (n != m); break;
395                 case SQLFilterOperator::LESS:               bResult = (n < m); break;
396                 case SQLFilterOperator::LESS_EQUAL:     bResult = (n <= m); break;
397                 case SQLFilterOperator::GREATER:            bResult = (n > m); break;
398                 case SQLFilterOperator::GREATER_EQUAL:  bResult = (n >= m); break;
399                 default:                        bResult = sal_False;
400             }
401         } break;
402         default:
403             bResult = aLH == aRH;
404     }
405     return bResult;
406 }
407 
408 //------------------------------------------------------------------
409 void ONumOperator::Exec(OCodeStack& rCodeStack)
410 {
411     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "ONumOperator::Exec" );
412 
413     OOperand  *pRight   = rCodeStack.top();
414     rCodeStack.pop();
415     OOperand  *pLeft    = rCodeStack.top();
416     rCodeStack.pop();
417 
418     rCodeStack.push(new OOperandResultNUM(operate(pLeft->getValue(), pRight->getValue())));
419     if (IS_TYPE(OOperandResult,pLeft))
420         delete pLeft;
421     if (IS_TYPE(OOperandResult,pRight))
422         delete pRight;
423 }
424 //------------------------------------------------------------------
425 double OOp_ADD::operate(const double& fLeft,const double& fRight) const
426 {
427     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOp_ADD::operate" );
428     return fLeft + fRight;
429 }
430 
431 //------------------------------------------------------------------
432 double OOp_SUB::operate(const double& fLeft,const double& fRight) const
433 {
434     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOp_SUB::operate" );
435     return fLeft - fRight;
436 }
437 
438 //------------------------------------------------------------------
439 double OOp_MUL::operate(const double& fLeft,const double& fRight) const
440 {
441     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOp_MUL::operate" );
442     return fLeft * fRight;
443 }
444 
445 //------------------------------------------------------------------
446 double OOp_DIV::operate(const double& fLeft,const double& fRight) const
447 {
448     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOp_DIV::operate" );
449     return fLeft / fRight;
450 }
451 // -----------------------------------------------------------------------------
452 OEvaluateSet* OOperandAttr::preProcess(OBoolOperator* /*pOp*/, OOperand* /*pRight*/)
453 {
454     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOperandAttr::preProcess" );
455     return NULL;
456 }
457 //------------------------------------------------------------------
458 void ONthOperator::Exec(OCodeStack& rCodeStack)
459 {
460     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "ONthOperator::Exec" );
461     ::std::vector<ORowSetValue> aValues;
462     ::std::vector<OOperand*> aOperands;
463     OOperand* pOperand;
464     do
465     {
466         OSL_ENSURE(!rCodeStack.empty(),"Stack must be none empty!");
467         pOperand    = rCodeStack.top();
468         rCodeStack.pop();
469         if ( !IS_TYPE(OStopOperand,pOperand) )
470             aValues.push_back( pOperand->getValue() );
471         aOperands.push_back( pOperand );
472     }
473     while ( !IS_TYPE(OStopOperand,pOperand) );
474 
475     rCodeStack.push(new OOperandResult(operate(aValues)));
476 
477     ::std::vector<OOperand*>::iterator aIter = aOperands.begin();
478     ::std::vector<OOperand*>::iterator aEnd = aOperands.end();
479     for (; aIter != aEnd; ++aIter)
480     {
481         if (IS_TYPE(OOperandResult,*aIter))
482             delete *aIter;
483     }
484 }
485 //------------------------------------------------------------------
486 void OBinaryOperator::Exec(OCodeStack& rCodeStack)
487 {
488     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OBinaryOperator::Exec" );
489     OOperand  *pRight   = rCodeStack.top();
490     rCodeStack.pop();
491     OOperand  *pLeft    = rCodeStack.top();
492     rCodeStack.pop();
493 
494     if ( !rCodeStack.empty() && IS_TYPE(OStopOperand,rCodeStack.top()) )
495         rCodeStack.pop();
496 
497     rCodeStack.push(new OOperandResult(operate(pLeft->getValue(),pRight->getValue())));
498     if (IS_TYPE(OOperandResult,pRight))
499         delete pRight;
500     if (IS_TYPE(OOperandResult,pLeft))
501         delete pLeft;
502 }
503 //------------------------------------------------------------------
504 void OUnaryOperator::Exec(OCodeStack& rCodeStack)
505 {
506     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OUnaryOperator::Exec" );
507     OSL_ENSURE(!rCodeStack.empty(),"Stack is empty!");
508     OOperand* pOperand = rCodeStack.top();
509     rCodeStack.pop();
510 
511     rCodeStack.push(new OOperandResult(operate(pOperand->getValue())));
512     if (IS_TYPE(OOperandResult,pOperand))
513         delete pOperand;
514 }
515 // -----------------------------------------------------------------------------
516 sal_uInt16 OUnaryOperator::getRequestedOperands() const {return 1;}
517 
518 
519 
520