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/sqlparse.hxx>
24 #include <sqlbison.hxx>
25 #include <com/sun/star/sdb/SQLFilterOperator.hpp>
27 using namespace ::comphelper
;
28 using namespace connectivity
;
29 using namespace connectivity::file
;
30 using namespace ::com::sun::star::sdbc
;
31 using namespace ::com::sun::star::sdb
;
33 OCode::~OCode() = default;
35 OOperandRow::OOperandRow(sal_uInt16 _nPos
, sal_Int32 _rType
)
40 void OOperandRow::bindValue(const OValueRefRow
& _pRow
)
42 OSL_ENSURE(_pRow
.is(),"NO EMPTY row allowed!");
44 OSL_ENSURE(m_pRow
.is() && m_nRowPos
< m_pRow
->size(),"Invalid RowPos is >= vector.size()");
45 (*m_pRow
)[m_nRowPos
]->setBound(true);
48 void OOperandRow::setValue(const ORowSetValue
& _rVal
)
50 OSL_ENSURE(m_pRow
.is() && m_nRowPos
< m_pRow
->size(),"Invalid RowPos is >= vector.size()");
51 (*(*m_pRow
)[m_nRowPos
]) = _rVal
;
54 const ORowSetValue
& OOperandRow::getValue() const
56 OSL_ENSURE(m_pRow
.is() && m_nRowPos
< m_pRow
->size(),"Invalid RowPos is >= vector.size()");
57 return (*m_pRow
)[m_nRowPos
]->getValue();
61 void OOperandValue::setValue(const ORowSetValue
& _rVal
)
66 OOperandParam::OOperandParam(OSQLParseNode
const * pNode
, sal_Int32 _nPos
)
67 : OOperandRow(static_cast<sal_uInt16
>(_nPos
), DataType::VARCHAR
) // Standard-Type
69 OSL_ENSURE(SQL_ISRULE(pNode
,parameter
),"Argument is not a parameter");
70 OSL_ENSURE(pNode
->count() > 0,"Error in Parse Tree");
71 OSQLParseNode
*pMark
= pNode
->getChild(0);
73 OUString aParameterName
;
74 if (SQL_ISPUNCTUATION(pMark
, "?"))
76 else if (SQL_ISPUNCTUATION(pMark
, ":"))
77 aParameterName
= pNode
->getChild(1)->getTokenValue();
80 SAL_WARN( "connectivity.drivers","Error in Parse Tree");
83 // set up Parameter-Column with default type, can be specified more precisely later using Describe-Parameter
85 // save Identity (not especially necessary here, just for the sake of symmetry)
88 // OColumn* pColumn = new OFILEColumn(aParameterName,eDBType,255,0,SQL_FLAGS_NULLALLOWED);
89 // rParamColumns->AddColumn(pColumn);
91 // the value will be set just before the evaluation
95 const ORowSetValue
& OOperandValue::getValue() const
101 OOperandConst::OOperandConst(const OSQLParseNode
& rColumnRef
, const OUString
& aStrValue
)
103 switch (rColumnRef
.getNodeType())
105 case SQLNodeType::String
:
106 m_aValue
= aStrValue
;
107 m_eDBType
= DataType::VARCHAR
;
108 m_aValue
.setBound(true);
110 case SQLNodeType::IntNum
:
111 case SQLNodeType::ApproxNum
:
112 m_aValue
= aStrValue
.toDouble();
113 m_eDBType
= DataType::DOUBLE
;
114 m_aValue
.setBound(true);
120 if (SQL_ISTOKEN(&rColumnRef
, TRUE
))
123 m_eDBType
= DataType::BIT
;
125 else if (SQL_ISTOKEN(&rColumnRef
, FALSE
))
128 m_eDBType
= DataType::BIT
;
132 SAL_WARN( "connectivity.drivers", "Parse Error");
134 m_aValue
.setBound(true);
138 // Implementation of the operators
141 bool OBoolOperator::operate(const OOperand
*, const OOperand
*) const
147 void OBoolOperator::Exec(OCodeStack
& rCodeStack
)
149 OOperand
*pRight
= rCodeStack
.top();
151 OOperand
*pLeft
= rCodeStack
.top();
154 rCodeStack
.push(new OOperandResultBOOL(operate(pLeft
, pRight
)));
155 if( typeid(OOperandResult
) == typeid(*pLeft
))
157 if( typeid(OOperandResult
) == typeid(*pRight
))
161 bool OOp_NOT::operate(const OOperand
* pLeft
, const OOperand
* ) const
163 return !pLeft
->isValid();
166 void OOp_NOT::Exec(OCodeStack
& rCodeStack
)
168 OOperand
* pOperand
= rCodeStack
.top();
171 rCodeStack
.push(new OOperandResultBOOL(operate(pOperand
, nullptr)));
173 if( typeid(OOperandResult
) == typeid(*pOperand
))
177 bool OOp_AND::operate(const OOperand
* pLeft
, const OOperand
* pRight
) const
179 return pLeft
->isValid() && pRight
->isValid();
183 bool OOp_OR::operate(const OOperand
* pLeft
, const OOperand
* pRight
) const
185 return pLeft
->isValid() || pRight
->isValid();
189 void OOp_ISNULL::Exec(OCodeStack
& rCodeStack
)
191 OOperand
* pOperand
= rCodeStack
.top();
194 rCodeStack
.push(new OOperandResultBOOL(operate(pOperand
, nullptr)));
195 if( typeid(OOperandResult
) == typeid(*pOperand
))
200 bool OOp_ISNULL::operate(const OOperand
* pOperand
, const OOperand
*) const
202 return pOperand
->getValue().isNull();
206 bool OOp_ISNOTNULL::operate(const OOperand
* pOperand
, const OOperand
*) const
208 return !OOp_ISNULL::operate(pOperand
, nullptr);
212 bool OOp_LIKE::operate(const OOperand
* pLeft
, const OOperand
* pRight
) const
215 const ORowSetValue
& aLH(pLeft
->getValue());
216 const ORowSetValue
& aRH(pRight
->getValue());
218 if (aLH
.isNull() || aRH
.isNull())
222 bMatch
= match(aRH
.getString(), aLH
.getString(), cEscape
);
228 bool OOp_NOTLIKE::operate(const OOperand
* pLeft
, const OOperand
* pRight
) const
230 return !OOp_LIKE::operate(pLeft
, pRight
);
234 bool OOp_COMPARE::operate(const OOperand
* pLeft
, const OOperand
* pRight
) const
236 const ORowSetValue
& aLH(pLeft
->getValue());
237 const ORowSetValue
& aRH(pRight
->getValue());
239 if (aLH
.isNull() || aRH
.isNull()) // if (!aLH.getValue() || !aRH.getValue())
242 bool bResult
= false;
243 sal_Int32 eDBType
= pLeft
->getDBType();
245 // Comparison (depending on Data-type):
249 case DataType::VARCHAR
:
250 case DataType::LONGVARCHAR
:
252 OUString sLH
= aLH
, sRH
= aRH
;
253 sal_Int32 nRes
= sLH
.compareToIgnoreAsciiCase(sRH
);
254 switch(aPredicateType
)
256 case SQLFilterOperator::EQUAL
: bResult
= (nRes
== 0); break;
257 case SQLFilterOperator::NOT_EQUAL
: bResult
= (nRes
!= 0); break;
258 case SQLFilterOperator::LESS
: bResult
= (nRes
< 0); break;
259 case SQLFilterOperator::LESS_EQUAL
: bResult
= (nRes
<= 0); break;
260 case SQLFilterOperator::GREATER
: bResult
= (nRes
> 0); break;
261 case SQLFilterOperator::GREATER_EQUAL
: bResult
= (nRes
>= 0); break;
262 default: bResult
= false;
265 case DataType::TINYINT
:
266 case DataType::SMALLINT
:
267 case DataType::INTEGER
:
268 case DataType::DECIMAL
:
269 case DataType::NUMERIC
:
271 case DataType::DOUBLE
:
273 case DataType::TIMESTAMP
:
277 double n
= aLH
,m
= aRH
;
279 switch (aPredicateType
)
281 case SQLFilterOperator::EQUAL
: bResult
= (n
== m
); break;
282 case SQLFilterOperator::LIKE
: bResult
= (n
== m
); break;
283 case SQLFilterOperator::NOT_EQUAL
: bResult
= (n
!= m
); break;
284 case SQLFilterOperator::NOT_LIKE
: bResult
= (n
!= m
); break;
285 case SQLFilterOperator::LESS
: bResult
= (n
< m
); break;
286 case SQLFilterOperator::LESS_EQUAL
: bResult
= (n
<= m
); break;
287 case SQLFilterOperator::GREATER
: bResult
= (n
> m
); break;
288 case SQLFilterOperator::GREATER_EQUAL
: bResult
= (n
>= m
); break;
289 default: bResult
= false;
293 bResult
= aLH
== aRH
;
299 void ONumOperator::Exec(OCodeStack
& rCodeStack
)
301 OOperand
*pRight
= rCodeStack
.top();
303 OOperand
*pLeft
= rCodeStack
.top();
306 rCodeStack
.push(new OOperandResultNUM(operate(pLeft
->getValue(), pRight
->getValue())));
307 if( typeid(OOperandResult
) == typeid(*pLeft
))
309 if( typeid(OOperandResult
) == typeid(*pRight
))
313 double OOp_ADD::operate(const double& fLeft
,const double& fRight
) const
315 return fLeft
+ fRight
;
319 double OOp_SUB::operate(const double& fLeft
,const double& fRight
) const
321 return fLeft
- fRight
;
325 double OOp_MUL::operate(const double& fLeft
,const double& fRight
) const
327 return fLeft
* fRight
;
331 double OOp_DIV::operate(const double& fLeft
,const double& fRight
) const
333 return fLeft
/ fRight
;
336 void ONthOperator::Exec(OCodeStack
& rCodeStack
)
338 std::vector
<ORowSetValue
> aValues
;
339 std::vector
<OOperand
*> aOperands
;
343 OSL_ENSURE(!rCodeStack
.empty(),"Stack must be none empty!");
344 pOperand
= rCodeStack
.top();
347 if (pOperand
&& typeid(OStopOperand
) != typeid(*pOperand
))
348 aValues
.push_back( pOperand
->getValue() );
349 aOperands
.push_back( pOperand
);
351 while (pOperand
&& typeid(OStopOperand
) != typeid(*pOperand
));
353 rCodeStack
.push(new OOperandResult(operate(aValues
)));
355 for (const auto& rpOperand
: aOperands
)
357 if (typeid(OOperandResult
) == typeid(*rpOperand
))
362 void OBinaryOperator::Exec(OCodeStack
& rCodeStack
)
364 OOperand
*pRight
= rCodeStack
.top();
366 OOperand
*pLeft
= rCodeStack
.top();
369 if ( !rCodeStack
.empty() && typeid(OStopOperand
) == typeid(*rCodeStack
.top()) )
372 rCodeStack
.push(new OOperandResult(operate(pLeft
->getValue(),pRight
->getValue())));
373 if(typeid(OOperandResult
) == typeid(*pRight
))
375 if(typeid(OOperandResult
) == typeid(*pLeft
))
379 void OUnaryOperator::Exec(OCodeStack
& rCodeStack
)
381 OSL_ENSURE(!rCodeStack
.empty(),"Stack is empty!");
382 OOperand
* pOperand
= rCodeStack
.top();
385 rCodeStack
.push(new OOperandResult(operate(pOperand
->getValue())));
386 if (typeid(OOperandResult
) == typeid(*pOperand
))
391 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */