1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <sal/log.hxx>
23 #include <connectivity/sqlnode.hxx>
24 #include <sqlbison.hxx>
25 #include <com/sun/star/sdb/SQLFilterOperator.hpp>
27 using namespace connectivity
;
28 using namespace connectivity::file
;
29 using namespace ::com::sun::star::sdbc
;
30 using namespace ::com::sun::star::sdb
;
32 OCode::~OCode() = default;
34 OOperandRow::OOperandRow(sal_uInt16 _nPos
, sal_Int32 _rType
)
39 void OOperandRow::bindValue(const OValueRefRow
& _pRow
)
41 OSL_ENSURE(_pRow
.is(),"NO EMPTY row allowed!");
43 OSL_ENSURE(m_pRow
.is() && m_nRowPos
< m_pRow
->size(),"Invalid RowPos is >= vector.size()");
44 (*m_pRow
)[m_nRowPos
]->setBound(true);
47 void OOperandRow::setValue(const ORowSetValue
& _rVal
)
49 OSL_ENSURE(m_pRow
.is() && m_nRowPos
< m_pRow
->size(),"Invalid RowPos is >= vector.size()");
50 (*(*m_pRow
)[m_nRowPos
]) = _rVal
;
53 const ORowSetValue
& OOperandRow::getValue() const
55 OSL_ENSURE(m_pRow
.is() && m_nRowPos
< m_pRow
->size(),"Invalid RowPos is >= vector.size()");
56 return (*m_pRow
)[m_nRowPos
]->getValue();
60 void OOperandValue::setValue(const ORowSetValue
& _rVal
)
65 OOperandParam::OOperandParam(sal_Int32 _nPos
)
66 : OOperandRow(static_cast<sal_uInt16
>(_nPos
), DataType::VARCHAR
) // Standard-Type
68 //TODO: Actually do something here (the current state of OOperandParam appears to be "the
69 // remains of the very beginnings of a never finished implementation of support for parameters
70 // in this code", as Lionel put it in the comments at <https://gerrit.libreoffice.org/c/core/+/
71 // 116839/1#message-7b2bbf3543f559a0b67dc35cd940e2ab8829c274> "-Werror,-Wunused-but-set-variable
72 // (Clang 13 trunk)").
76 const ORowSetValue
& OOperandValue::getValue() const
82 OOperandConst::OOperandConst(const OSQLParseNode
& rColumnRef
, const OUString
& aStrValue
)
84 switch (rColumnRef
.getNodeType())
86 case SQLNodeType::String
:
88 m_eDBType
= DataType::VARCHAR
;
89 m_aValue
.setBound(true);
91 case SQLNodeType::IntNum
:
92 case SQLNodeType::ApproxNum
:
93 m_aValue
= aStrValue
.toDouble();
94 m_eDBType
= DataType::DOUBLE
;
95 m_aValue
.setBound(true);
101 if (SQL_ISTOKEN(&rColumnRef
, TRUE
))
104 m_eDBType
= DataType::BIT
;
106 else if (SQL_ISTOKEN(&rColumnRef
, FALSE
))
109 m_eDBType
= DataType::BIT
;
113 SAL_WARN( "connectivity.drivers", "Parse Error");
115 m_aValue
.setBound(true);
119 // Implementation of the operators
122 bool OBoolOperator::operate(const OOperand
*, const OOperand
*) const
128 void OBoolOperator::Exec(OCodeStack
& rCodeStack
)
130 OOperand
*pRight
= rCodeStack
.top();
132 OOperand
*pLeft
= rCodeStack
.top();
135 rCodeStack
.push(new OOperandResultBOOL(operate(pLeft
, pRight
)));
136 if( typeid(OOperandResult
) == typeid(*pLeft
))
138 if( typeid(OOperandResult
) == typeid(*pRight
))
142 bool OOp_NOT::operate(const OOperand
* pLeft
, const OOperand
* ) const
144 return !pLeft
->isValid();
147 void OOp_NOT::Exec(OCodeStack
& rCodeStack
)
149 OOperand
* pOperand
= rCodeStack
.top();
152 rCodeStack
.push(new OOperandResultBOOL(operate(pOperand
, nullptr)));
154 if( typeid(OOperandResult
) == typeid(*pOperand
))
158 bool OOp_AND::operate(const OOperand
* pLeft
, const OOperand
* pRight
) const
160 return pLeft
->isValid() && pRight
->isValid();
164 bool OOp_OR::operate(const OOperand
* pLeft
, const OOperand
* pRight
) const
166 return pLeft
->isValid() || pRight
->isValid();
170 void OOp_ISNULL::Exec(OCodeStack
& rCodeStack
)
172 OOperand
* pOperand
= rCodeStack
.top();
175 rCodeStack
.push(new OOperandResultBOOL(operate(pOperand
, nullptr)));
176 if( typeid(OOperandResult
) == typeid(*pOperand
))
181 bool OOp_ISNULL::operate(const OOperand
* pOperand
, const OOperand
*) const
183 return pOperand
->getValue().isNull();
187 bool OOp_ISNOTNULL::operate(const OOperand
* pOperand
, const OOperand
*) const
189 return !OOp_ISNULL::operate(pOperand
, nullptr);
193 bool OOp_LIKE::operate(const OOperand
* pLeft
, const OOperand
* pRight
) const
196 const ORowSetValue
& aLH(pLeft
->getValue());
197 const ORowSetValue
& aRH(pRight
->getValue());
199 if (aLH
.isNull() || aRH
.isNull())
203 bMatch
= match(aRH
.getString(), aLH
.getString(), cEscape
);
209 bool OOp_NOTLIKE::operate(const OOperand
* pLeft
, const OOperand
* pRight
) const
211 return !OOp_LIKE::operate(pLeft
, pRight
);
215 bool OOp_COMPARE::operate(const OOperand
* pLeft
, const OOperand
* pRight
) const
217 const ORowSetValue
& aLH(pLeft
->getValue());
218 const ORowSetValue
& aRH(pRight
->getValue());
220 if (aLH
.isNull() || aRH
.isNull()) // if (!aLH.getValue() || !aRH.getValue())
223 bool bResult
= false;
224 sal_Int32 eDBType
= pLeft
->getDBType();
226 // Comparison (depending on Data-type):
230 case DataType::VARCHAR
:
231 case DataType::LONGVARCHAR
:
233 OUString sLH
= aLH
.getString(), sRH
= aRH
.getString();
234 sal_Int32 nRes
= sLH
.compareToIgnoreAsciiCase(sRH
);
235 switch(aPredicateType
)
237 case SQLFilterOperator::EQUAL
: bResult
= (nRes
== 0); break;
238 case SQLFilterOperator::NOT_EQUAL
: bResult
= (nRes
!= 0); break;
239 case SQLFilterOperator::LESS
: bResult
= (nRes
< 0); break;
240 case SQLFilterOperator::LESS_EQUAL
: bResult
= (nRes
<= 0); break;
241 case SQLFilterOperator::GREATER
: bResult
= (nRes
> 0); break;
242 case SQLFilterOperator::GREATER_EQUAL
: bResult
= (nRes
>= 0); break;
243 default: bResult
= false;
246 case DataType::TINYINT
:
247 case DataType::SMALLINT
:
248 case DataType::INTEGER
:
249 case DataType::DECIMAL
:
250 case DataType::NUMERIC
:
252 case DataType::DOUBLE
:
254 case DataType::TIMESTAMP
:
258 double n
= aLH
.getDouble(), m
= aRH
.getDouble();
260 switch (aPredicateType
)
262 case SQLFilterOperator::EQUAL
: bResult
= (n
== m
); break;
263 case SQLFilterOperator::LIKE
: bResult
= (n
== m
); break;
264 case SQLFilterOperator::NOT_EQUAL
: bResult
= (n
!= m
); break;
265 case SQLFilterOperator::NOT_LIKE
: bResult
= (n
!= m
); break;
266 case SQLFilterOperator::LESS
: bResult
= (n
< m
); break;
267 case SQLFilterOperator::LESS_EQUAL
: bResult
= (n
<= m
); break;
268 case SQLFilterOperator::GREATER
: bResult
= (n
> m
); break;
269 case SQLFilterOperator::GREATER_EQUAL
: bResult
= (n
>= m
); break;
270 default: bResult
= false;
274 bResult
= aLH
== aRH
;
280 void ONumOperator::Exec(OCodeStack
& rCodeStack
)
282 OOperand
*pRight
= rCodeStack
.top();
284 OOperand
*pLeft
= rCodeStack
.top();
287 rCodeStack
.push(new OOperandResultNUM(operate(pLeft
->getValue().getDouble(), pRight
->getValue().getDouble())));
288 if( typeid(OOperandResult
) == typeid(*pLeft
))
290 if( typeid(OOperandResult
) == typeid(*pRight
))
294 double OOp_ADD::operate(const double& fLeft
,const double& fRight
) const
296 return fLeft
+ fRight
;
300 double OOp_SUB::operate(const double& fLeft
,const double& fRight
) const
302 return fLeft
- fRight
;
306 double OOp_MUL::operate(const double& fLeft
,const double& fRight
) const
308 return fLeft
* fRight
;
312 double OOp_DIV::operate(const double& fLeft
,const double& fRight
) const
314 return fLeft
/ fRight
;
317 void ONthOperator::Exec(OCodeStack
& rCodeStack
)
319 std::vector
<ORowSetValue
> aValues
;
320 std::vector
<OOperand
*> aOperands
;
324 OSL_ENSURE(!rCodeStack
.empty(),"Stack must be none empty!");
325 pOperand
= rCodeStack
.top();
328 if (pOperand
&& typeid(OStopOperand
) != typeid(*pOperand
))
329 aValues
.push_back( pOperand
->getValue() );
330 aOperands
.push_back( pOperand
);
332 while (pOperand
&& typeid(OStopOperand
) != typeid(*pOperand
));
334 rCodeStack
.push(new OOperandResult(operate(aValues
)));
336 for (const auto& rpOperand
: aOperands
)
338 if (typeid(OOperandResult
) == typeid(*rpOperand
))
343 void OBinaryOperator::Exec(OCodeStack
& rCodeStack
)
345 OOperand
*pRight
= rCodeStack
.top();
347 OOperand
*pLeft
= rCodeStack
.top();
350 if ( !rCodeStack
.empty() && typeid(OStopOperand
) == typeid(*rCodeStack
.top()) )
353 rCodeStack
.push(new OOperandResult(operate(pLeft
->getValue(),pRight
->getValue())));
354 if(typeid(OOperandResult
) == typeid(*pRight
))
356 if(typeid(OOperandResult
) == typeid(*pLeft
))
360 void OUnaryOperator::Exec(OCodeStack
& rCodeStack
)
362 OSL_ENSURE(!rCodeStack
.empty(),"Stack is empty!");
363 OOperand
* pOperand
= rCodeStack
.top();
366 rCodeStack
.push(new OOperandResult(operate(pOperand
->getValue())));
367 if (typeid(OOperandResult
) == typeid(*pOperand
))
372 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */