Version 4.3.0.0.beta1, tag libreoffice-4.3.0.0.beta1
[LibreOffice.git] / connectivity / source / drivers / file / fcode.cxx
blob9c18fb23579cb4d2e66636054048a97f6553a8f4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "file/fcode.hxx"
21 #include <osl/diagnose.h>
22 #include "connectivity/sqlparse.hxx"
23 #include <i18nlangtag/mslangid.hxx>
24 #include <tools/debug.hxx>
25 #include "TConnection.hxx"
26 #include <com/sun/star/sdb/SQLFilterOperator.hpp>
27 #include <comphelper/types.hxx>
29 using namespace ::comphelper;
30 using namespace connectivity;
31 using namespace connectivity::file;
32 using namespace ::com::sun::star::sdbc;
33 using namespace ::com::sun::star::sdb;
35 TYPEINIT0(OCode);
36 TYPEINIT1(OOperand, OCode);
37 TYPEINIT1(OOperandRow, OOperand);
38 TYPEINIT1(OOperandAttr, OOperandRow);
39 TYPEINIT1(OOperandParam, OOperandRow);
40 TYPEINIT1(OOperandValue, OOperand);
41 TYPEINIT1(OOperandConst, OOperandValue);
42 TYPEINIT1(OOperandResult, OOperandValue);
43 TYPEINIT1(OStopOperand, OOperandValue);
45 TYPEINIT1(OOperator, OCode);
46 TYPEINIT1(OBoolOperator,OOperator);
47 TYPEINIT1(OOp_NOT, OBoolOperator);
48 TYPEINIT1(OOp_AND, OBoolOperator);
49 TYPEINIT1(OOp_OR, OBoolOperator);
50 TYPEINIT1(OOp_ISNULL, OBoolOperator);
51 TYPEINIT1(OOp_ISNOTNULL, OOp_ISNULL);
52 TYPEINIT1(OOp_LIKE, OBoolOperator);
53 TYPEINIT1(OOp_NOTLIKE, OOp_LIKE);
54 TYPEINIT1(OOp_COMPARE, OBoolOperator);
55 TYPEINIT1(ONumOperator, OOperator);
56 TYPEINIT1(ONthOperator, OOperator);
57 TYPEINIT1(OBinaryOperator, OOperator);
58 TYPEINIT1(OUnaryOperator, OOperator);
60 OCode::OCode()
64 OCode::~OCode()
69 OEvaluateSet* OOperand::preProcess(OBoolOperator* /*pOp*/, OOperand* /*pRight*/)
71 return NULL;
74 OOperandRow::OOperandRow(sal_uInt16 _nPos, sal_Int32 _rType)
75 : OOperand(_rType)
76 , m_nRowPos(_nPos)
79 void OOperandRow::bindValue(const OValueRefRow& _pRow)
81 OSL_ENSURE(_pRow.is(),"NO EMPTY row allowed!");
82 m_pRow = _pRow;
83 OSL_ENSURE(m_pRow.is() && m_nRowPos < m_pRow->get().size(),"Invalid RowPos is >= vector.size()");
84 (m_pRow->get())[m_nRowPos]->setBound(true);
87 void OOperandRow::setValue(const ORowSetValue& _rVal)
89 OSL_ENSURE(m_pRow.is() && m_nRowPos < m_pRow->get().size(),"Invalid RowPos is >= vector.size()");
90 (*(m_pRow->get())[m_nRowPos]) = _rVal;
93 const ORowSetValue& OOperandRow::getValue() const
95 OSL_ENSURE(m_pRow.is() && m_nRowPos < m_pRow->get().size(),"Invalid RowPos is >= vector.size()");
96 return (m_pRow->get())[m_nRowPos]->getValue();
100 void OOperandValue::setValue(const ORowSetValue& _rVal)
102 m_aValue = _rVal;
105 bool OOperandAttr::isIndexed() const
107 return false;
110 OOperandParam::OOperandParam(OSQLParseNode* pNode, sal_Int32 _nPos)
111 : OOperandRow(static_cast<sal_uInt16>(_nPos), DataType::VARCHAR) // Standard-Type
113 OSL_ENSURE(SQL_ISRULE(pNode,parameter),"Argument ist kein Parameter");
114 OSL_ENSURE(pNode->count() > 0,"Fehler im Parse Tree");
115 OSQLParseNode *pMark = pNode->getChild(0);
117 OUString aParameterName;
118 if (SQL_ISPUNCTUATION(pMark, "?"))
119 aParameterName = "?";
120 else if (SQL_ISPUNCTUATION(pMark, ":"))
121 aParameterName = pNode->getChild(1)->getTokenValue();
122 else
124 SAL_WARN( "connectivity.drivers","Fehler im Parse Tree");
127 // set up Parameter-Column with default type, can be specified more precisely later using Describe-Parameter
129 // save Identity (not escpecially necessary here, just for the sake of symmetry)
131 // todo
132 // OColumn* pColumn = new OFILEColumn(aParameterName,eDBType,255,0,SQL_FLAGS_NULLALLOWED);
133 // rParamColumns->AddColumn(pColumn);
135 // the value will be set just before the evaluation
140 const ORowSetValue& OOperandValue::getValue() const
142 return m_aValue;
146 OOperandConst::OOperandConst(const OSQLParseNode& rColumnRef, const OUString& aStrValue)
148 switch (rColumnRef.getNodeType())
150 case SQL_NODE_STRING:
151 m_aValue = aStrValue;
152 m_eDBType = DataType::VARCHAR;
153 m_aValue.setBound(true);
154 return;
155 case SQL_NODE_INTNUM:
156 case SQL_NODE_APPROXNUM:
157 m_aValue = aStrValue.toDouble();
158 m_eDBType = DataType::DOUBLE;
159 m_aValue.setBound(true);
160 return;
161 default:
162 break;
165 if (SQL_ISTOKEN(&rColumnRef, TRUE))
167 m_aValue = 1.0;
168 m_eDBType = DataType::BIT;
170 else if (SQL_ISTOKEN(&rColumnRef, FALSE))
172 m_aValue = 0.0;
173 m_eDBType = DataType::BIT;
175 else
177 SAL_WARN( "connectivity.drivers", "Parse Error");
179 m_aValue.setBound(true);
183 // Implementation of the operators
186 sal_uInt16 OOperator::getRequestedOperands() const {return 2;}
189 bool OBoolOperator::operate(const OOperand*, const OOperand*) const
191 return false;
196 void OBoolOperator::Exec(OCodeStack& rCodeStack)
198 OOperand *pRight = rCodeStack.top();
199 rCodeStack.pop();
200 OOperand *pLeft = rCodeStack.top();
201 rCodeStack.pop();
203 rCodeStack.push(new OOperandResultBOOL(operate(pLeft, pRight)));
204 if (IS_TYPE(OOperandResult,pLeft))
205 delete pLeft;
206 if (IS_TYPE(OOperandResult,pRight))
207 delete pRight;
210 bool OOp_NOT::operate(const OOperand* pLeft, const OOperand* ) const
212 return !pLeft->isValid();
215 void OOp_NOT::Exec(OCodeStack& rCodeStack)
217 OOperand* pOperand = rCodeStack.top();
218 rCodeStack.pop();
220 rCodeStack.push(new OOperandResultBOOL(operate(pOperand)));
221 if (IS_TYPE(OOperandResult,pOperand))
222 delete pOperand;
225 sal_uInt16 OOp_NOT::getRequestedOperands() const
227 return 1;
231 bool OOp_AND::operate(const OOperand* pLeft, const OOperand* pRight) const
233 return pLeft->isValid() && pRight->isValid();
237 bool OOp_OR::operate(const OOperand* pLeft, const OOperand* pRight) const
239 return pLeft->isValid() || pRight->isValid();
243 sal_uInt16 OOp_ISNULL::getRequestedOperands() const
245 return 1;
249 void OOp_ISNULL::Exec(OCodeStack& rCodeStack)
251 OOperand* pOperand = rCodeStack.top();
252 rCodeStack.pop();
254 rCodeStack.push(new OOperandResultBOOL(operate(pOperand)));
255 if (IS_TYPE(OOperandResult,pOperand))
256 delete pOperand;
260 bool OOp_ISNULL::operate(const OOperand* pOperand, const OOperand*) const
262 return pOperand->getValue().isNull();
266 bool OOp_ISNOTNULL::operate(const OOperand* pOperand, const OOperand*) const
268 return !OOp_ISNULL::operate(pOperand);
272 bool OOp_LIKE::operate(const OOperand* pLeft, const OOperand* pRight) const
274 bool bMatch;
275 ORowSetValue aLH(pLeft->getValue());
276 ORowSetValue aRH(pRight->getValue());
278 if (aLH.isNull() || aRH.isNull())
279 bMatch = false;
280 else
282 bMatch = match(aRH.getString(), aLH.getString(), cEscape);
284 return bMatch;
288 bool OOp_NOTLIKE::operate(const OOperand* pLeft, const OOperand* pRight) const
290 return !OOp_LIKE::operate(pLeft, pRight);
294 bool OOp_COMPARE::operate(const OOperand* pLeft, const OOperand* pRight) const
296 ORowSetValue aLH(pLeft->getValue());
297 ORowSetValue aRH(pRight->getValue());
299 if (aLH.isNull() || aRH.isNull()) // if (!aLH.getValue() || !aRH.getValue())
300 return false;
302 bool bResult = false;
303 sal_Int32 eDBType = pLeft->getDBType();
305 // Comparison (depending on Data-type):
306 switch (eDBType)
308 case DataType::CHAR:
309 case DataType::VARCHAR:
310 case DataType::LONGVARCHAR:
312 OUString sLH = aLH, sRH = aRH;
313 sal_Int32 nRes = rtl_ustr_compareIgnoreAsciiCase_WithLength
315 sLH.pData->buffer,
316 sLH.pData->length,
317 sRH.pData->buffer,
318 sRH.pData->length );
319 switch(aPredicateType)
321 case SQLFilterOperator::EQUAL: bResult = (nRes == 0); break;
322 case SQLFilterOperator::NOT_EQUAL: bResult = (nRes != 0); break;
323 case SQLFilterOperator::LESS: bResult = (nRes < 0); break;
324 case SQLFilterOperator::LESS_EQUAL: bResult = (nRes <= 0); break;
325 case SQLFilterOperator::GREATER: bResult = (nRes > 0); break;
326 case SQLFilterOperator::GREATER_EQUAL: bResult = (nRes >= 0); break;
327 default: bResult = false;
329 } break;
330 case DataType::TINYINT:
331 case DataType::SMALLINT:
332 case DataType::INTEGER:
333 case DataType::DECIMAL:
334 case DataType::NUMERIC:
335 case DataType::REAL:
336 case DataType::DOUBLE:
337 case DataType::BIT:
338 case DataType::TIMESTAMP:
339 case DataType::DATE:
340 case DataType::TIME:
342 double n = aLH ,m = aRH;
344 switch (aPredicateType)
346 case SQLFilterOperator::EQUAL: bResult = (n == m); break;
347 case SQLFilterOperator::LIKE: bResult = (n == m); break;
348 case SQLFilterOperator::NOT_EQUAL: bResult = (n != m); break;
349 case SQLFilterOperator::NOT_LIKE: bResult = (n != m); break;
350 case SQLFilterOperator::LESS: bResult = (n < m); break;
351 case SQLFilterOperator::LESS_EQUAL: bResult = (n <= m); break;
352 case SQLFilterOperator::GREATER: bResult = (n > m); break;
353 case SQLFilterOperator::GREATER_EQUAL: bResult = (n >= m); break;
354 default: bResult = false;
356 } break;
357 default:
358 bResult = aLH == aRH;
360 return bResult;
364 void ONumOperator::Exec(OCodeStack& rCodeStack)
366 OOperand *pRight = rCodeStack.top();
367 rCodeStack.pop();
368 OOperand *pLeft = rCodeStack.top();
369 rCodeStack.pop();
371 rCodeStack.push(new OOperandResultNUM(operate(pLeft->getValue(), pRight->getValue())));
372 if (IS_TYPE(OOperandResult,pLeft))
373 delete pLeft;
374 if (IS_TYPE(OOperandResult,pRight))
375 delete pRight;
378 double OOp_ADD::operate(const double& fLeft,const double& fRight) const
380 return fLeft + fRight;
384 double OOp_SUB::operate(const double& fLeft,const double& fRight) const
386 return fLeft - fRight;
390 double OOp_MUL::operate(const double& fLeft,const double& fRight) const
392 return fLeft * fRight;
396 double OOp_DIV::operate(const double& fLeft,const double& fRight) const
398 return fLeft / fRight;
401 OEvaluateSet* OOperandAttr::preProcess(OBoolOperator* /*pOp*/, OOperand* /*pRight*/)
403 return NULL;
406 void ONthOperator::Exec(OCodeStack& rCodeStack)
408 ::std::vector<ORowSetValue> aValues;
409 ::std::vector<OOperand*> aOperands;
410 OOperand* pOperand;
413 OSL_ENSURE(!rCodeStack.empty(),"Stack must be none empty!");
414 pOperand = rCodeStack.top();
415 rCodeStack.pop();
416 if ( !IS_TYPE(OStopOperand,pOperand) )
417 aValues.push_back( pOperand->getValue() );
418 aOperands.push_back( pOperand );
420 while ( !IS_TYPE(OStopOperand,pOperand) );
422 rCodeStack.push(new OOperandResult(operate(aValues)));
424 ::std::vector<OOperand*>::iterator aIter = aOperands.begin();
425 ::std::vector<OOperand*>::iterator aEnd = aOperands.end();
426 for (; aIter != aEnd; ++aIter)
428 if (IS_TYPE(OOperandResult,*aIter))
429 delete *aIter;
433 void OBinaryOperator::Exec(OCodeStack& rCodeStack)
435 OOperand *pRight = rCodeStack.top();
436 rCodeStack.pop();
437 OOperand *pLeft = rCodeStack.top();
438 rCodeStack.pop();
440 if ( !rCodeStack.empty() && IS_TYPE(OStopOperand,rCodeStack.top()) )
441 rCodeStack.pop();
443 rCodeStack.push(new OOperandResult(operate(pLeft->getValue(),pRight->getValue())));
444 if (IS_TYPE(OOperandResult,pRight))
445 delete pRight;
446 if (IS_TYPE(OOperandResult,pLeft))
447 delete pLeft;
450 void OUnaryOperator::Exec(OCodeStack& rCodeStack)
452 OSL_ENSURE(!rCodeStack.empty(),"Stack is empty!");
453 OOperand* pOperand = rCodeStack.top();
454 rCodeStack.pop();
456 rCodeStack.push(new OOperandResult(operate(pOperand->getValue())));
457 if (IS_TYPE(OOperandResult,pOperand))
458 delete pOperand;
461 sal_uInt16 OUnaryOperator::getRequestedOperands() const {return 1;}
465 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */