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 <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>
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
;
35 OCode::~OCode() = default;
37 OOperandRow::OOperandRow(sal_uInt16 _nPos
, sal_Int32 _rType
)
42 void OOperandRow::bindValue(const OValueRefRow
& _pRow
)
44 OSL_ENSURE(_pRow
.is(),"NO EMPTY row allowed!");
46 OSL_ENSURE(m_pRow
.is() && m_nRowPos
< m_pRow
->get().size(),"Invalid RowPos is >= vector.size()");
47 (m_pRow
->get())[m_nRowPos
]->setBound(true);
50 void OOperandRow::setValue(const ORowSetValue
& _rVal
)
52 OSL_ENSURE(m_pRow
.is() && m_nRowPos
< m_pRow
->get().size(),"Invalid RowPos is >= vector.size()");
53 (*(m_pRow
->get())[m_nRowPos
]) = _rVal
;
56 const ORowSetValue
& OOperandRow::getValue() const
58 OSL_ENSURE(m_pRow
.is() && m_nRowPos
< m_pRow
->get().size(),"Invalid RowPos is >= vector.size()");
59 return (m_pRow
->get())[m_nRowPos
]->getValue();
63 void OOperandValue::setValue(const ORowSetValue
& _rVal
)
68 OOperandParam::OOperandParam(OSQLParseNode
* pNode
, sal_Int32 _nPos
)
69 : OOperandRow(static_cast<sal_uInt16
>(_nPos
), DataType::VARCHAR
) // Standard-Type
71 OSL_ENSURE(SQL_ISRULE(pNode
,parameter
),"Argument ist kein Parameter");
72 OSL_ENSURE(pNode
->count() > 0,"Fehler im Parse Tree");
73 OSQLParseNode
*pMark
= pNode
->getChild(0);
75 OUString aParameterName
;
76 if (SQL_ISPUNCTUATION(pMark
, "?"))
78 else if (SQL_ISPUNCTUATION(pMark
, ":"))
79 aParameterName
= pNode
->getChild(1)->getTokenValue();
82 SAL_WARN( "connectivity.drivers","Fehler im Parse Tree");
85 // set up Parameter-Column with default type, can be specified more precisely later using Describe-Parameter
87 // save Identity (not escpecially necessary here, just for the sake of symmetry)
90 // OColumn* pColumn = new OFILEColumn(aParameterName,eDBType,255,0,SQL_FLAGS_NULLALLOWED);
91 // rParamColumns->AddColumn(pColumn);
93 // the value will be set just before the evaluation
97 const ORowSetValue
& OOperandValue::getValue() const
103 OOperandConst::OOperandConst(const OSQLParseNode
& rColumnRef
, const OUString
& aStrValue
)
105 switch (rColumnRef
.getNodeType())
107 case SQLNodeType::String
:
108 m_aValue
= aStrValue
;
109 m_eDBType
= DataType::VARCHAR
;
110 m_aValue
.setBound(true);
112 case SQLNodeType::IntNum
:
113 case SQLNodeType::ApproxNum
:
114 m_aValue
= aStrValue
.toDouble();
115 m_eDBType
= DataType::DOUBLE
;
116 m_aValue
.setBound(true);
122 if (SQL_ISTOKEN(&rColumnRef
, TRUE
))
125 m_eDBType
= DataType::BIT
;
127 else if (SQL_ISTOKEN(&rColumnRef
, FALSE
))
130 m_eDBType
= DataType::BIT
;
134 SAL_WARN( "connectivity.drivers", "Parse Error");
136 m_aValue
.setBound(true);
140 // Implementation of the operators
143 bool OBoolOperator::operate(const OOperand
*, const OOperand
*) const
149 void OBoolOperator::Exec(OCodeStack
& rCodeStack
)
151 OOperand
*pRight
= rCodeStack
.top();
153 OOperand
*pLeft
= rCodeStack
.top();
156 rCodeStack
.push(new OOperandResultBOOL(operate(pLeft
, pRight
)));
157 if( typeid(OOperandResult
) == typeid(*pLeft
))
159 if( typeid(OOperandResult
) == typeid(*pRight
))
163 bool OOp_NOT::operate(const OOperand
* pLeft
, const OOperand
* ) const
165 return !pLeft
->isValid();
168 void OOp_NOT::Exec(OCodeStack
& rCodeStack
)
170 OOperand
* pOperand
= rCodeStack
.top();
173 rCodeStack
.push(new OOperandResultBOOL(operate(pOperand
, nullptr)));
175 if( typeid(OOperandResult
) == typeid(*pOperand
))
179 bool OOp_AND::operate(const OOperand
* pLeft
, const OOperand
* pRight
) const
181 return pLeft
->isValid() && pRight
->isValid();
185 bool OOp_OR::operate(const OOperand
* pLeft
, const OOperand
* pRight
) const
187 return pLeft
->isValid() || pRight
->isValid();
191 void OOp_ISNULL::Exec(OCodeStack
& rCodeStack
)
193 OOperand
* pOperand
= rCodeStack
.top();
196 rCodeStack
.push(new OOperandResultBOOL(operate(pOperand
, nullptr)));
197 if( typeid(OOperandResult
) == typeid(*pOperand
))
202 bool OOp_ISNULL::operate(const OOperand
* pOperand
, const OOperand
*) const
204 return pOperand
->getValue().isNull();
208 bool OOp_ISNOTNULL::operate(const OOperand
* pOperand
, const OOperand
*) const
210 return !OOp_ISNULL::operate(pOperand
, nullptr);
214 bool OOp_LIKE::operate(const OOperand
* pLeft
, const OOperand
* pRight
) const
217 ORowSetValue
aLH(pLeft
->getValue());
218 ORowSetValue
aRH(pRight
->getValue());
220 if (aLH
.isNull() || aRH
.isNull())
224 bMatch
= match(aRH
.getString(), aLH
.getString(), cEscape
);
230 bool OOp_NOTLIKE::operate(const OOperand
* pLeft
, const OOperand
* pRight
) const
232 return !OOp_LIKE::operate(pLeft
, pRight
);
236 bool OOp_COMPARE::operate(const OOperand
* pLeft
, const OOperand
* pRight
) const
238 ORowSetValue
aLH(pLeft
->getValue());
239 ORowSetValue
aRH(pRight
->getValue());
241 if (aLH
.isNull() || aRH
.isNull()) // if (!aLH.getValue() || !aRH.getValue())
244 bool bResult
= false;
245 sal_Int32 eDBType
= pLeft
->getDBType();
247 // Comparison (depending on Data-type):
251 case DataType::VARCHAR
:
252 case DataType::LONGVARCHAR
:
254 OUString sLH
= aLH
, sRH
= aRH
;
255 sal_Int32 nRes
= sLH
.compareToIgnoreAsciiCase(sRH
);
256 switch(aPredicateType
)
258 case SQLFilterOperator::EQUAL
: bResult
= (nRes
== 0); break;
259 case SQLFilterOperator::NOT_EQUAL
: bResult
= (nRes
!= 0); break;
260 case SQLFilterOperator::LESS
: bResult
= (nRes
< 0); break;
261 case SQLFilterOperator::LESS_EQUAL
: bResult
= (nRes
<= 0); break;
262 case SQLFilterOperator::GREATER
: bResult
= (nRes
> 0); break;
263 case SQLFilterOperator::GREATER_EQUAL
: bResult
= (nRes
>= 0); break;
264 default: bResult
= false;
267 case DataType::TINYINT
:
268 case DataType::SMALLINT
:
269 case DataType::INTEGER
:
270 case DataType::DECIMAL
:
271 case DataType::NUMERIC
:
273 case DataType::DOUBLE
:
275 case DataType::TIMESTAMP
:
279 double n
= aLH
,m
= aRH
;
281 switch (aPredicateType
)
283 case SQLFilterOperator::EQUAL
: bResult
= (n
== m
); break;
284 case SQLFilterOperator::LIKE
: bResult
= (n
== m
); break;
285 case SQLFilterOperator::NOT_EQUAL
: bResult
= (n
!= m
); break;
286 case SQLFilterOperator::NOT_LIKE
: bResult
= (n
!= m
); break;
287 case SQLFilterOperator::LESS
: bResult
= (n
< m
); break;
288 case SQLFilterOperator::LESS_EQUAL
: bResult
= (n
<= m
); break;
289 case SQLFilterOperator::GREATER
: bResult
= (n
> m
); break;
290 case SQLFilterOperator::GREATER_EQUAL
: bResult
= (n
>= m
); break;
291 default: bResult
= false;
295 bResult
= aLH
== aRH
;
301 void ONumOperator::Exec(OCodeStack
& rCodeStack
)
303 OOperand
*pRight
= rCodeStack
.top();
305 OOperand
*pLeft
= rCodeStack
.top();
308 rCodeStack
.push(new OOperandResultNUM(operate(pLeft
->getValue(), pRight
->getValue())));
309 if( typeid(OOperandResult
) == typeid(*pLeft
))
311 if( typeid(OOperandResult
) == typeid(*pRight
))
315 double OOp_ADD::operate(const double& fLeft
,const double& fRight
) const
317 return fLeft
+ fRight
;
321 double OOp_SUB::operate(const double& fLeft
,const double& fRight
) const
323 return fLeft
- fRight
;
327 double OOp_MUL::operate(const double& fLeft
,const double& fRight
) const
329 return fLeft
* fRight
;
333 double OOp_DIV::operate(const double& fLeft
,const double& fRight
) const
335 return fLeft
/ fRight
;
338 void ONthOperator::Exec(OCodeStack
& rCodeStack
)
340 ::std::vector
<ORowSetValue
> aValues
;
341 ::std::vector
<OOperand
*> aOperands
;
345 OSL_ENSURE(!rCodeStack
.empty(),"Stack must be none empty!");
346 pOperand
= rCodeStack
.top();
349 if (pOperand
&& typeid(OStopOperand
) != typeid(*pOperand
))
350 aValues
.push_back( pOperand
->getValue() );
351 aOperands
.push_back( pOperand
);
353 while (pOperand
&& typeid(OStopOperand
) != typeid(*pOperand
));
355 rCodeStack
.push(new OOperandResult(operate(aValues
)));
357 ::std::vector
<OOperand
*>::iterator aIter
= aOperands
.begin();
358 ::std::vector
<OOperand
*>::const_iterator aEnd
= aOperands
.end();
359 for (; aIter
!= aEnd
; ++aIter
)
361 if (typeid(OOperandResult
) == typeid(*(*aIter
)))
366 void OBinaryOperator::Exec(OCodeStack
& rCodeStack
)
368 OOperand
*pRight
= rCodeStack
.top();
370 OOperand
*pLeft
= rCodeStack
.top();
373 if ( !rCodeStack
.empty() && typeid(OStopOperand
) == typeid(*rCodeStack
.top()) )
376 rCodeStack
.push(new OOperandResult(operate(pLeft
->getValue(),pRight
->getValue())));
377 if(typeid(OOperandResult
) == typeid(*pRight
))
379 if(typeid(OOperandResult
) == typeid(*pLeft
))
383 void OUnaryOperator::Exec(OCodeStack
& rCodeStack
)
385 OSL_ENSURE(!rCodeStack
.empty(),"Stack is empty!");
386 OOperand
* pOperand
= rCodeStack
.top();
389 rCodeStack
.push(new OOperandResult(operate(pOperand
->getValue())));
390 if (typeid(OOperandResult
) == typeid(*pOperand
))
395 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */