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