Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include "file/fcode.hxx"
21 : #include <osl/diagnose.h>
22 : #include <connectivity/sqlparse.hxx>
23 : #include <i18nlangtag/mslangid.hxx>
24 : #include "TConnection.hxx"
25 : #include <com/sun/star/sdb/SQLFilterOperator.hpp>
26 : #include <comphelper/types.hxx>
27 :
28 : using namespace ::comphelper;
29 : using namespace connectivity;
30 : using namespace connectivity::file;
31 : using namespace ::com::sun::star::sdbc;
32 : using namespace ::com::sun::star::sdb;
33 :
34 168 : TYPEINIT0(OCode);
35 300 : TYPEINIT1(OOperand, OCode);
36 192 : TYPEINIT1(OOperandRow, OOperand);
37 252 : TYPEINIT1(OOperandAttr, OOperandRow);
38 252 : TYPEINIT1(OOperandParam, OOperandRow);
39 0 : TYPEINIT1(OOperandValue, OOperand);
40 0 : TYPEINIT1(OOperandConst, OOperandValue);
41 144 : TYPEINIT1(OOperandResult, OOperandValue);
42 0 : TYPEINIT1(OStopOperand, OOperandValue);
43 :
44 120 : TYPEINIT1(OOperator, OCode);
45 120 : TYPEINIT1(OBoolOperator,OOperator);
46 0 : TYPEINIT1(OOp_NOT, OBoolOperator);
47 0 : TYPEINIT1(OOp_AND, OBoolOperator);
48 0 : TYPEINIT1(OOp_OR, OBoolOperator);
49 0 : TYPEINIT1(OOp_ISNULL, OBoolOperator);
50 0 : TYPEINIT1(OOp_ISNOTNULL, OOp_ISNULL);
51 0 : TYPEINIT1(OOp_LIKE, OBoolOperator);
52 0 : TYPEINIT1(OOp_NOTLIKE, OOp_LIKE);
53 180 : TYPEINIT1(OOp_COMPARE, OBoolOperator);
54 0 : TYPEINIT1(ONumOperator, OOperator);
55 0 : TYPEINIT1(ONthOperator, OOperator);
56 0 : TYPEINIT1(OBinaryOperator, OOperator);
57 0 : TYPEINIT1(OUnaryOperator, OOperator);
58 :
59 222 : OCode::OCode()
60 : {
61 222 : }
62 :
63 222 : OCode::~OCode()
64 : {
65 222 : }
66 :
67 :
68 0 : OEvaluateSet* OOperand::preProcess(OBoolOperator* /*pOp*/, OOperand* /*pRight*/)
69 : {
70 0 : return NULL;
71 : }
72 :
73 24 : OOperandRow::OOperandRow(sal_uInt16 _nPos, sal_Int32 _rType)
74 : : OOperand(_rType)
75 24 : , m_nRowPos(_nPos)
76 24 : {}
77 :
78 24 : void OOperandRow::bindValue(const OValueRefRow& _pRow)
79 : {
80 : OSL_ENSURE(_pRow.is(),"NO EMPTY row allowed!");
81 24 : m_pRow = _pRow;
82 : OSL_ENSURE(m_pRow.is() && m_nRowPos < m_pRow->get().size(),"Invalid RowPos is >= vector.size()");
83 24 : (m_pRow->get())[m_nRowPos]->setBound(true);
84 24 : }
85 :
86 0 : void OOperandRow::setValue(const ORowSetValue& _rVal)
87 : {
88 : OSL_ENSURE(m_pRow.is() && m_nRowPos < m_pRow->get().size(),"Invalid RowPos is >= vector.size()");
89 0 : (*(m_pRow->get())[m_nRowPos]) = _rVal;
90 0 : }
91 :
92 72 : const ORowSetValue& OOperandRow::getValue() const
93 : {
94 : OSL_ENSURE(m_pRow.is() && m_nRowPos < m_pRow->get().size(),"Invalid RowPos is >= vector.size()");
95 72 : return (m_pRow->get())[m_nRowPos]->getValue();
96 : }
97 :
98 :
99 0 : void OOperandValue::setValue(const ORowSetValue& _rVal)
100 : {
101 0 : m_aValue = _rVal;
102 0 : }
103 :
104 12 : bool OOperandAttr::isIndexed() const
105 : {
106 12 : return false;
107 : }
108 :
109 12 : OOperandParam::OOperandParam(OSQLParseNode* pNode, sal_Int32 _nPos)
110 12 : : OOperandRow(static_cast<sal_uInt16>(_nPos), DataType::VARCHAR) // Standard-Type
111 : {
112 : OSL_ENSURE(SQL_ISRULE(pNode,parameter),"Argument ist kein Parameter");
113 : OSL_ENSURE(pNode->count() > 0,"Fehler im Parse Tree");
114 12 : OSQLParseNode *pMark = pNode->getChild(0);
115 :
116 12 : OUString aParameterName;
117 12 : if (SQL_ISPUNCTUATION(pMark, "?"))
118 0 : aParameterName = "?";
119 12 : else if (SQL_ISPUNCTUATION(pMark, ":"))
120 12 : aParameterName = pNode->getChild(1)->getTokenValue();
121 : else
122 : {
123 : SAL_WARN( "connectivity.drivers","Fehler im Parse Tree");
124 12 : }
125 :
126 : // set up Parameter-Column with default type, can be specified more precisely later using Describe-Parameter
127 :
128 : // save Identity (not escpecially necessary here, just for the sake of symmetry)
129 :
130 : // todo
131 : // OColumn* pColumn = new OFILEColumn(aParameterName,eDBType,255,0,SQL_FLAGS_NULLALLOWED);
132 : // rParamColumns->AddColumn(pColumn);
133 :
134 : // the value will be set just before the evaluation
135 12 : }
136 :
137 :
138 :
139 36 : const ORowSetValue& OOperandValue::getValue() const
140 : {
141 36 : return m_aValue;
142 : }
143 :
144 :
145 96 : OOperandConst::OOperandConst(const OSQLParseNode& rColumnRef, const OUString& aStrValue)
146 : {
147 96 : switch (rColumnRef.getNodeType())
148 : {
149 : case SQL_NODE_STRING:
150 0 : m_aValue = aStrValue;
151 0 : m_eDBType = DataType::VARCHAR;
152 0 : m_aValue.setBound(true);
153 0 : return;
154 : case SQL_NODE_INTNUM:
155 : case SQL_NODE_APPROXNUM:
156 96 : m_aValue = aStrValue.toDouble();
157 96 : m_eDBType = DataType::DOUBLE;
158 96 : m_aValue.setBound(true);
159 96 : return;
160 : default:
161 0 : break;
162 : }
163 :
164 0 : if (SQL_ISTOKEN(&rColumnRef, TRUE))
165 : {
166 0 : m_aValue = 1.0;
167 0 : m_eDBType = DataType::BIT;
168 : }
169 0 : else if (SQL_ISTOKEN(&rColumnRef, FALSE))
170 : {
171 0 : m_aValue = 0.0;
172 0 : m_eDBType = DataType::BIT;
173 : }
174 : else
175 : {
176 : SAL_WARN( "connectivity.drivers", "Parse Error");
177 : }
178 0 : m_aValue.setBound(true);
179 : }
180 :
181 :
182 : // Implementation of the operators
183 :
184 :
185 0 : sal_uInt16 OOperator::getRequestedOperands() const {return 2;}
186 :
187 :
188 0 : bool OBoolOperator::operate(const OOperand*, const OOperand*) const
189 : {
190 0 : return false;
191 : }
192 :
193 :
194 :
195 36 : void OBoolOperator::Exec(OCodeStack& rCodeStack)
196 : {
197 36 : OOperand *pRight = rCodeStack.top();
198 36 : rCodeStack.pop();
199 36 : OOperand *pLeft = rCodeStack.top();
200 36 : rCodeStack.pop();
201 :
202 36 : rCodeStack.push(new OOperandResultBOOL(operate(pLeft, pRight)));
203 36 : if (IS_TYPE(OOperandResult,pLeft))
204 0 : delete pLeft;
205 36 : if (IS_TYPE(OOperandResult,pRight))
206 0 : delete pRight;
207 36 : }
208 :
209 0 : bool OOp_NOT::operate(const OOperand* pLeft, const OOperand* ) const
210 : {
211 0 : return !pLeft->isValid();
212 : }
213 :
214 0 : void OOp_NOT::Exec(OCodeStack& rCodeStack)
215 : {
216 0 : OOperand* pOperand = rCodeStack.top();
217 0 : rCodeStack.pop();
218 :
219 0 : rCodeStack.push(new OOperandResultBOOL(operate(pOperand)));
220 0 : if (IS_TYPE(OOperandResult,pOperand))
221 0 : delete pOperand;
222 0 : }
223 :
224 0 : sal_uInt16 OOp_NOT::getRequestedOperands() const
225 : {
226 0 : return 1;
227 : }
228 :
229 :
230 0 : bool OOp_AND::operate(const OOperand* pLeft, const OOperand* pRight) const
231 : {
232 0 : return pLeft->isValid() && pRight->isValid();
233 : }
234 :
235 :
236 0 : bool OOp_OR::operate(const OOperand* pLeft, const OOperand* pRight) const
237 : {
238 0 : return pLeft->isValid() || pRight->isValid();
239 : }
240 :
241 :
242 0 : sal_uInt16 OOp_ISNULL::getRequestedOperands() const
243 : {
244 0 : return 1;
245 : }
246 :
247 :
248 0 : void OOp_ISNULL::Exec(OCodeStack& rCodeStack)
249 : {
250 0 : OOperand* pOperand = rCodeStack.top();
251 0 : rCodeStack.pop();
252 :
253 0 : rCodeStack.push(new OOperandResultBOOL(operate(pOperand)));
254 0 : if (IS_TYPE(OOperandResult,pOperand))
255 0 : delete pOperand;
256 0 : }
257 :
258 :
259 0 : bool OOp_ISNULL::operate(const OOperand* pOperand, const OOperand*) const
260 : {
261 0 : return pOperand->getValue().isNull();
262 : }
263 :
264 :
265 0 : bool OOp_ISNOTNULL::operate(const OOperand* pOperand, const OOperand*) const
266 : {
267 0 : return !OOp_ISNULL::operate(pOperand);
268 : }
269 :
270 :
271 0 : bool OOp_LIKE::operate(const OOperand* pLeft, const OOperand* pRight) const
272 : {
273 : bool bMatch;
274 0 : ORowSetValue aLH(pLeft->getValue());
275 0 : ORowSetValue aRH(pRight->getValue());
276 :
277 0 : if (aLH.isNull() || aRH.isNull())
278 0 : bMatch = false;
279 : else
280 : {
281 0 : bMatch = match(aRH.getString(), aLH.getString(), cEscape);
282 : }
283 0 : return bMatch;
284 : }
285 :
286 :
287 0 : bool OOp_NOTLIKE::operate(const OOperand* pLeft, const OOperand* pRight) const
288 : {
289 0 : return !OOp_LIKE::operate(pLeft, pRight);
290 : }
291 :
292 :
293 36 : bool OOp_COMPARE::operate(const OOperand* pLeft, const OOperand* pRight) const
294 : {
295 36 : ORowSetValue aLH(pLeft->getValue());
296 72 : ORowSetValue aRH(pRight->getValue());
297 :
298 36 : if (aLH.isNull() || aRH.isNull()) // if (!aLH.getValue() || !aRH.getValue())
299 12 : return false;
300 :
301 24 : bool bResult = false;
302 24 : sal_Int32 eDBType = pLeft->getDBType();
303 :
304 : // Comparison (depending on Data-type):
305 24 : switch (eDBType)
306 : {
307 : case DataType::CHAR:
308 : case DataType::VARCHAR:
309 : case DataType::LONGVARCHAR:
310 : {
311 48 : OUString sLH = aLH, sRH = aRH;
312 : sal_Int32 nRes = rtl_ustr_compareIgnoreAsciiCase_WithLength
313 : (
314 : sLH.pData->buffer,
315 : sLH.pData->length,
316 : sRH.pData->buffer,
317 24 : sRH.pData->length );
318 24 : switch(aPredicateType)
319 : {
320 24 : case SQLFilterOperator::EQUAL: bResult = (nRes == 0); break;
321 0 : case SQLFilterOperator::NOT_EQUAL: bResult = (nRes != 0); break;
322 0 : case SQLFilterOperator::LESS: bResult = (nRes < 0); break;
323 0 : case SQLFilterOperator::LESS_EQUAL: bResult = (nRes <= 0); break;
324 0 : case SQLFilterOperator::GREATER: bResult = (nRes > 0); break;
325 0 : case SQLFilterOperator::GREATER_EQUAL: bResult = (nRes >= 0); break;
326 0 : default: bResult = false;
327 24 : }
328 24 : } break;
329 : case DataType::TINYINT:
330 : case DataType::SMALLINT:
331 : case DataType::INTEGER:
332 : case DataType::DECIMAL:
333 : case DataType::NUMERIC:
334 : case DataType::REAL:
335 : case DataType::DOUBLE:
336 : case DataType::BIT:
337 : case DataType::TIMESTAMP:
338 : case DataType::DATE:
339 : case DataType::TIME:
340 : {
341 0 : double n = aLH ,m = aRH;
342 :
343 0 : switch (aPredicateType)
344 : {
345 0 : case SQLFilterOperator::EQUAL: bResult = (n == m); break;
346 0 : case SQLFilterOperator::LIKE: bResult = (n == m); break;
347 0 : case SQLFilterOperator::NOT_EQUAL: bResult = (n != m); break;
348 0 : case SQLFilterOperator::NOT_LIKE: bResult = (n != m); break;
349 0 : case SQLFilterOperator::LESS: bResult = (n < m); break;
350 0 : case SQLFilterOperator::LESS_EQUAL: bResult = (n <= m); break;
351 0 : case SQLFilterOperator::GREATER: bResult = (n > m); break;
352 0 : case SQLFilterOperator::GREATER_EQUAL: bResult = (n >= m); break;
353 0 : default: bResult = false;
354 : }
355 0 : } break;
356 : default:
357 0 : bResult = aLH == aRH;
358 : }
359 60 : return bResult;
360 : }
361 :
362 :
363 0 : void ONumOperator::Exec(OCodeStack& rCodeStack)
364 : {
365 0 : OOperand *pRight = rCodeStack.top();
366 0 : rCodeStack.pop();
367 0 : OOperand *pLeft = rCodeStack.top();
368 0 : rCodeStack.pop();
369 :
370 0 : rCodeStack.push(new OOperandResultNUM(operate(pLeft->getValue(), pRight->getValue())));
371 0 : if (IS_TYPE(OOperandResult,pLeft))
372 0 : delete pLeft;
373 0 : if (IS_TYPE(OOperandResult,pRight))
374 0 : delete pRight;
375 0 : }
376 :
377 0 : double OOp_ADD::operate(const double& fLeft,const double& fRight) const
378 : {
379 0 : return fLeft + fRight;
380 : }
381 :
382 :
383 0 : double OOp_SUB::operate(const double& fLeft,const double& fRight) const
384 : {
385 0 : return fLeft - fRight;
386 : }
387 :
388 :
389 0 : double OOp_MUL::operate(const double& fLeft,const double& fRight) const
390 : {
391 0 : return fLeft * fRight;
392 : }
393 :
394 :
395 0 : double OOp_DIV::operate(const double& fLeft,const double& fRight) const
396 : {
397 0 : return fLeft / fRight;
398 : }
399 :
400 0 : OEvaluateSet* OOperandAttr::preProcess(OBoolOperator* /*pOp*/, OOperand* /*pRight*/)
401 : {
402 0 : return NULL;
403 : }
404 :
405 0 : void ONthOperator::Exec(OCodeStack& rCodeStack)
406 : {
407 0 : ::std::vector<ORowSetValue> aValues;
408 0 : ::std::vector<OOperand*> aOperands;
409 : OOperand* pOperand;
410 0 : do
411 : {
412 : OSL_ENSURE(!rCodeStack.empty(),"Stack must be none empty!");
413 0 : pOperand = rCodeStack.top();
414 0 : rCodeStack.pop();
415 : assert(pOperand);
416 0 : if (pOperand && !IS_TYPE(OStopOperand,pOperand))
417 0 : aValues.push_back( pOperand->getValue() );
418 0 : aOperands.push_back( pOperand );
419 : }
420 0 : while (pOperand && !IS_TYPE(OStopOperand,pOperand));
421 :
422 0 : rCodeStack.push(new OOperandResult(operate(aValues)));
423 :
424 0 : ::std::vector<OOperand*>::iterator aIter = aOperands.begin();
425 0 : ::std::vector<OOperand*>::iterator aEnd = aOperands.end();
426 0 : for (; aIter != aEnd; ++aIter)
427 : {
428 0 : if (IS_TYPE(OOperandResult,*aIter))
429 0 : delete *aIter;
430 0 : }
431 0 : }
432 :
433 0 : void OBinaryOperator::Exec(OCodeStack& rCodeStack)
434 : {
435 0 : OOperand *pRight = rCodeStack.top();
436 0 : rCodeStack.pop();
437 0 : OOperand *pLeft = rCodeStack.top();
438 0 : rCodeStack.pop();
439 :
440 0 : if ( !rCodeStack.empty() && IS_TYPE(OStopOperand,rCodeStack.top()) )
441 0 : rCodeStack.pop();
442 :
443 0 : rCodeStack.push(new OOperandResult(operate(pLeft->getValue(),pRight->getValue())));
444 0 : if (IS_TYPE(OOperandResult,pRight))
445 0 : delete pRight;
446 0 : if (IS_TYPE(OOperandResult,pLeft))
447 0 : delete pLeft;
448 0 : }
449 :
450 0 : void OUnaryOperator::Exec(OCodeStack& rCodeStack)
451 : {
452 : OSL_ENSURE(!rCodeStack.empty(),"Stack is empty!");
453 0 : OOperand* pOperand = rCodeStack.top();
454 0 : rCodeStack.pop();
455 :
456 0 : rCodeStack.push(new OOperandResult(operate(pOperand->getValue())));
457 0 : if (IS_TYPE(OOperandResult,pOperand))
458 0 : delete pOperand;
459 0 : }
460 :
461 0 : sal_uInt16 OUnaryOperator::getRequestedOperands() const {return 1;}
462 :
463 :
464 :
465 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|