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