LibreOffice Module connectivity (master) 1
fcode.cxx
Go to the documentation of this file.
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 <sal/log.hxx>
24#include <sqlbison.hxx>
25#include <com/sun/star/sdb/SQLFilterOperator.hpp>
26
27using namespace ::comphelper;
28using namespace connectivity;
29using namespace connectivity::file;
30using namespace ::com::sun::star::sdbc;
31using namespace ::com::sun::star::sdb;
32
33OCode::~OCode() = default;
34
35OOperandRow::OOperandRow(sal_uInt16 _nPos, sal_Int32 _rType)
36 : OOperand(_rType)
37 , m_nRowPos(_nPos)
38{}
39
41{
42 OSL_ENSURE(_pRow.is(),"NO EMPTY row allowed!");
43 m_pRow = _pRow;
44 OSL_ENSURE(m_pRow.is() && m_nRowPos < m_pRow->size(),"Invalid RowPos is >= vector.size()");
45 (*m_pRow)[m_nRowPos]->setBound(true);
46}
47
49{
50 OSL_ENSURE(m_pRow.is() && m_nRowPos < m_pRow->size(),"Invalid RowPos is >= vector.size()");
51 (*(*m_pRow)[m_nRowPos]) = _rVal;
52}
53
55{
56 OSL_ENSURE(m_pRow.is() && m_nRowPos < m_pRow->size(),"Invalid RowPos is >= vector.size()");
57 return (*m_pRow)[m_nRowPos]->getValue();
58}
59
60
62{
63 m_aValue = _rVal;
64}
65
67 : OOperandRow(static_cast<sal_uInt16>(_nPos), DataType::VARCHAR) // Standard-Type
68{
69 //TODO: Actually do something here (the current state of OOperandParam appears to be "the
70 // remains of the very beginnings of a never finished implementation of support for parameters
71 // in this code", as Lionel put it in the comments at <https://gerrit.libreoffice.org/c/core/+/
72 // 116839/1#message-7b2bbf3543f559a0b67dc35cd940e2ab8829c274> "-Werror,-Wunused-but-set-variable
73 // (Clang 13 trunk)").
74}
75
76
78{
79 return m_aValue;
80}
81
82
83OOperandConst::OOperandConst(const OSQLParseNode& rColumnRef, const OUString& aStrValue)
84{
85 switch (rColumnRef.getNodeType())
86 {
88 m_aValue = aStrValue;
89 m_eDBType = DataType::VARCHAR;
90 m_aValue.setBound(true);
91 return;
94 m_aValue = aStrValue.toDouble();
95 m_eDBType = DataType::DOUBLE;
96 m_aValue.setBound(true);
97 return;
98 default:
99 break;
100 }
101
102 if (SQL_ISTOKEN(&rColumnRef, TRUE))
103 {
104 m_aValue = 1.0;
105 m_eDBType = DataType::BIT;
106 }
107 else if (SQL_ISTOKEN(&rColumnRef, FALSE))
108 {
109 m_aValue = 0.0;
110 m_eDBType = DataType::BIT;
111 }
112 else
113 {
114 SAL_WARN( "connectivity.drivers", "Parse Error");
115 }
116 m_aValue.setBound(true);
117}
118
119
120// Implementation of the operators
121
122
123bool OBoolOperator::operate(const OOperand*, const OOperand*) const
124{
125 return false;
126}
127
128
130{
131 OOperand *pRight = rCodeStack.top();
132 rCodeStack.pop();
133 OOperand *pLeft = rCodeStack.top();
134 rCodeStack.pop();
135
136 rCodeStack.push(new OOperandResultBOOL(operate(pLeft, pRight)));
137 if( typeid(OOperandResult) == typeid(*pLeft))
138 delete pLeft;
139 if( typeid(OOperandResult) == typeid(*pRight))
140 delete pRight;
141}
142
143bool OOp_NOT::operate(const OOperand* pLeft, const OOperand* ) const
144{
145 return !pLeft->isValid();
146}
147
148void OOp_NOT::Exec(OCodeStack& rCodeStack)
149{
150 OOperand* pOperand = rCodeStack.top();
151 rCodeStack.pop();
152
153 rCodeStack.push(new OOperandResultBOOL(operate(pOperand, nullptr)));
154
155 if( typeid(OOperandResult) == typeid(*pOperand))
156 delete pOperand;
157}
158
159bool OOp_AND::operate(const OOperand* pLeft, const OOperand* pRight) const
160{
161 return pLeft->isValid() && pRight->isValid();
162}
163
164
165bool OOp_OR::operate(const OOperand* pLeft, const OOperand* pRight) const
166{
167 return pLeft->isValid() || pRight->isValid();
168}
169
170
172{
173 OOperand* pOperand = rCodeStack.top();
174 rCodeStack.pop();
175
176 rCodeStack.push(new OOperandResultBOOL(operate(pOperand, nullptr)));
177 if( typeid(OOperandResult) == typeid(*pOperand))
178 delete pOperand;
179}
180
181
182bool OOp_ISNULL::operate(const OOperand* pOperand, const OOperand*) const
183{
184 return pOperand->getValue().isNull();
185}
186
187
188bool OOp_ISNOTNULL::operate(const OOperand* pOperand, const OOperand*) const
189{
190 return !OOp_ISNULL::operate(pOperand, nullptr);
191}
192
193
194bool OOp_LIKE::operate(const OOperand* pLeft, const OOperand* pRight) const
195{
196 bool bMatch;
197 const ORowSetValue& aLH(pLeft->getValue());
198 const ORowSetValue& aRH(pRight->getValue());
199
200 if (aLH.isNull() || aRH.isNull())
201 bMatch = false;
202 else
203 {
204 bMatch = match(aRH.getString(), aLH.getString(), cEscape);
205 }
206 return bMatch;
207}
208
209
210bool OOp_NOTLIKE::operate(const OOperand* pLeft, const OOperand* pRight) const
211{
212 return !OOp_LIKE::operate(pLeft, pRight);
213}
214
215
216bool OOp_COMPARE::operate(const OOperand* pLeft, const OOperand* pRight) const
217{
218 const ORowSetValue& aLH(pLeft->getValue());
219 const ORowSetValue& aRH(pRight->getValue());
220
221 if (aLH.isNull() || aRH.isNull()) // if (!aLH.getValue() || !aRH.getValue())
222 return false;
223
224 bool bResult = false;
225 sal_Int32 eDBType = pLeft->getDBType();
226
227 // Comparison (depending on Data-type):
228 switch (eDBType)
229 {
230 case DataType::CHAR:
231 case DataType::VARCHAR:
232 case DataType::LONGVARCHAR:
233 {
234 OUString sLH = aLH.getString(), sRH = aRH.getString();
235 sal_Int32 nRes = sLH.compareToIgnoreAsciiCase(sRH);
236 switch(aPredicateType)
237 {
238 case SQLFilterOperator::EQUAL: bResult = (nRes == 0); break;
239 case SQLFilterOperator::NOT_EQUAL: bResult = (nRes != 0); break;
240 case SQLFilterOperator::LESS: bResult = (nRes < 0); break;
241 case SQLFilterOperator::LESS_EQUAL: bResult = (nRes <= 0); break;
242 case SQLFilterOperator::GREATER: bResult = (nRes > 0); break;
243 case SQLFilterOperator::GREATER_EQUAL: bResult = (nRes >= 0); break;
244 default: bResult = false;
245 }
246 } break;
247 case DataType::TINYINT:
248 case DataType::SMALLINT:
249 case DataType::INTEGER:
250 case DataType::DECIMAL:
251 case DataType::NUMERIC:
252 case DataType::REAL:
253 case DataType::DOUBLE:
254 case DataType::BIT:
255 case DataType::TIMESTAMP:
256 case DataType::DATE:
257 case DataType::TIME:
258 {
259 double n = aLH.getDouble(), m = aRH.getDouble();
260
261 switch (aPredicateType)
262 {
263 case SQLFilterOperator::EQUAL: bResult = (n == m); break;
264 case SQLFilterOperator::LIKE: bResult = (n == m); break;
265 case SQLFilterOperator::NOT_EQUAL: bResult = (n != m); break;
266 case SQLFilterOperator::NOT_LIKE: bResult = (n != m); break;
267 case SQLFilterOperator::LESS: bResult = (n < m); break;
268 case SQLFilterOperator::LESS_EQUAL: bResult = (n <= m); break;
269 case SQLFilterOperator::GREATER: bResult = (n > m); break;
270 case SQLFilterOperator::GREATER_EQUAL: bResult = (n >= m); break;
271 default: bResult = false;
272 }
273 } break;
274 default:
275 bResult = aLH == aRH;
276 }
277 return bResult;
278}
279
280
282{
283 OOperand *pRight = rCodeStack.top();
284 rCodeStack.pop();
285 OOperand *pLeft = rCodeStack.top();
286 rCodeStack.pop();
287
288 rCodeStack.push(new OOperandResultNUM(operate(pLeft->getValue().getDouble(), pRight->getValue().getDouble())));
289 if( typeid(OOperandResult) == typeid(*pLeft))
290 delete pLeft;
291 if( typeid(OOperandResult) == typeid(*pRight))
292 delete pRight;
293}
294
295double OOp_ADD::operate(const double& fLeft,const double& fRight) const
296{
297 return fLeft + fRight;
298}
299
300
301double OOp_SUB::operate(const double& fLeft,const double& fRight) const
302{
303 return fLeft - fRight;
304}
305
306
307double OOp_MUL::operate(const double& fLeft,const double& fRight) const
308{
309 return fLeft * fRight;
310}
311
312
313double OOp_DIV::operate(const double& fLeft,const double& fRight) const
314{
315 return fLeft / fRight;
316}
317
319{
320 std::vector<ORowSetValue> aValues;
321 std::vector<OOperand*> aOperands;
322 OOperand* pOperand;
323 do
324 {
325 OSL_ENSURE(!rCodeStack.empty(),"Stack must be none empty!");
326 pOperand = rCodeStack.top();
327 rCodeStack.pop();
328 assert(pOperand);
329 if (pOperand && typeid(OStopOperand) != typeid(*pOperand))
330 aValues.push_back( pOperand->getValue() );
331 aOperands.push_back( pOperand );
332 }
333 while (pOperand && typeid(OStopOperand) != typeid(*pOperand));
334
335 rCodeStack.push(new OOperandResult(operate(aValues)));
336
337 for (const auto& rpOperand : aOperands)
338 {
339 if (typeid(OOperandResult) == typeid(*rpOperand))
340 delete rpOperand;
341 }
342}
343
345{
346 OOperand *pRight = rCodeStack.top();
347 rCodeStack.pop();
348 OOperand *pLeft = rCodeStack.top();
349 rCodeStack.pop();
350
351 if ( !rCodeStack.empty() && typeid(OStopOperand) == typeid(*rCodeStack.top()) )
352 rCodeStack.pop();
353
354 rCodeStack.push(new OOperandResult(operate(pLeft->getValue(),pRight->getValue())));
355 if(typeid(OOperandResult) == typeid(*pRight))
356 delete pRight;
357 if(typeid(OOperandResult) == typeid(*pLeft))
358 delete pLeft;
359}
360
362{
363 OSL_ENSURE(!rCodeStack.empty(),"Stack is empty!");
364 OOperand* pOperand = rCodeStack.top();
365 rCodeStack.pop();
366
367 rCodeStack.push(new OOperandResult(operate(pOperand->getValue())));
368 if (typeid(OOperandResult) == typeid(*pOperand))
369 delete pOperand;
370}
371
372
373/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
OUString getString() const
Definition: FValue.cxx:933
void setBound(bool _bBound)
Definition: FValue.hxx:332
double getDouble() const
Definition: FValue.cxx:1745
SQLNodeType getNodeType() const
Definition: sqlnode.hxx:339
virtual void Exec(OCodeStack &) override
Definition: fcode.cxx:344
virtual ORowSetValue operate(const ORowSetValue &lhs, const ORowSetValue &rhs) const =0
virtual bool operate(const OOperand *, const OOperand *) const
Definition: fcode.cxx:123
virtual void Exec(OCodeStack &) override
Definition: fcode.cxx:129
virtual void Exec(OCodeStack &) override
Definition: fcode.cxx:318
virtual ORowSetValue operate(const std::vector< ORowSetValue > &lhs) const =0
virtual double operate(const double &fLeft, const double &fRight) const =0
virtual void Exec(OCodeStack &) override
Definition: fcode.cxx:281
virtual double operate(const double &fLeft, const double &fRight) const override
Definition: fcode.cxx:295
virtual bool operate(const OOperand *, const OOperand *) const override
Definition: fcode.cxx:159
virtual bool operate(const OOperand *, const OOperand *) const override
Definition: fcode.cxx:216
virtual double operate(const double &fLeft, const double &fRight) const override
Definition: fcode.cxx:313
virtual bool operate(const OOperand *, const OOperand *) const override
Definition: fcode.cxx:188
virtual void Exec(OCodeStack &) override
Definition: fcode.cxx:171
virtual bool operate(const OOperand *, const OOperand *) const override
Definition: fcode.cxx:182
virtual bool operate(const OOperand *, const OOperand *) const override
Definition: fcode.cxx:194
const sal_Unicode cEscape
Definition: fcode.hxx:230
virtual double operate(const double &fLeft, const double &fRight) const override
Definition: fcode.cxx:307
virtual bool operate(const OOperand *, const OOperand *) const override
Definition: fcode.cxx:210
virtual void Exec(OCodeStack &) override
Definition: fcode.cxx:148
virtual bool operate(const OOperand *, const OOperand *) const override
Definition: fcode.cxx:143
virtual bool operate(const OOperand *, const OOperand *) const override
Definition: fcode.cxx:165
virtual double operate(const double &fLeft, const double &fRight) const override
Definition: fcode.cxx:301
OOperandConst(const connectivity::OSQLParseNode &rColumnRef, const OUString &aStrValue)
Definition: fcode.cxx:83
OOperandParam(sal_Int32 _nPos)
Definition: fcode.cxx:66
virtual const ORowSetValue & getValue() const override
Definition: fcode.cxx:54
virtual void setValue(const ORowSetValue &_rVal) override
Definition: fcode.cxx:48
void bindValue(const OValueRefRow &_pRow)
Definition: fcode.cxx:40
virtual const ORowSetValue & getValue() const override
Definition: fcode.cxx:77
virtual void setValue(const ORowSetValue &_rVal) override
Definition: fcode.cxx:61
sal_Int32 getDBType() const
Definition: fcode.hxx:68
virtual const ORowSetValue & getValue() const =0
special stop operand is appended when a list of arguments ends
Definition: fcode.hxx:169
virtual void Exec(OCodeStack &) override
Definition: fcode.cxx:361
virtual ORowSetValue operate(const ORowSetValue &lhs) const =0
#define TRUE
#define FALSE
sal_Int64 n
#define SAL_WARN(area, stream)
size
std::stack< OOperand * > OCodeStack
Definition: fcode.hxx:36
bool match(const sal_Unicode *pWild, const sal_Unicode *pStr, const sal_Unicode cEscape)
Definition: CommonTools.cxx:51
m
DataType
#define SQL_ISTOKEN(pParseNode, token)
Definition: sqlnode.hxx:447
sal_Int32 _nPos