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 <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>
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
;
36 TYPEINIT1(OOperand
, OCode
);
37 TYPEINIT1(OOperandRow
, OOperand
);
38 TYPEINIT1(OOperandAttr
, OOperandRow
);
39 TYPEINIT1(OOperandParam
, OOperandRow
);
40 TYPEINIT1(OOperandValue
, OOperand
);
41 TYPEINIT1(OOperandConst
, OOperandValue
);
42 TYPEINIT1(OOperandResult
, OOperandValue
);
43 TYPEINIT1(OStopOperand
, OOperandValue
);
45 TYPEINIT1(OOperator
, OCode
);
46 TYPEINIT1(OBoolOperator
,OOperator
);
47 TYPEINIT1(OOp_NOT
, OBoolOperator
);
48 TYPEINIT1(OOp_AND
, OBoolOperator
);
49 TYPEINIT1(OOp_OR
, OBoolOperator
);
50 TYPEINIT1(OOp_ISNULL
, OBoolOperator
);
51 TYPEINIT1(OOp_ISNOTNULL
, OOp_ISNULL
);
52 TYPEINIT1(OOp_LIKE
, OBoolOperator
);
53 TYPEINIT1(OOp_NOTLIKE
, OOp_LIKE
);
54 TYPEINIT1(OOp_COMPARE
, OBoolOperator
);
55 TYPEINIT1(ONumOperator
, OOperator
);
56 TYPEINIT1(ONthOperator
, OOperator
);
57 TYPEINIT1(OBinaryOperator
, OOperator
);
58 TYPEINIT1(OUnaryOperator
, OOperator
);
69 OEvaluateSet
* OOperand::preProcess(OBoolOperator
* /*pOp*/, OOperand
* /*pRight*/)
74 OOperandRow::OOperandRow(sal_uInt16 _nPos
, sal_Int32 _rType
)
79 void OOperandRow::bindValue(const OValueRefRow
& _pRow
)
81 OSL_ENSURE(_pRow
.is(),"NO EMPTY row allowed!");
83 OSL_ENSURE(m_pRow
.is() && m_nRowPos
< m_pRow
->get().size(),"Invalid RowPos is >= vector.size()");
84 (m_pRow
->get())[m_nRowPos
]->setBound(true);
87 void OOperandRow::setValue(const ORowSetValue
& _rVal
)
89 OSL_ENSURE(m_pRow
.is() && m_nRowPos
< m_pRow
->get().size(),"Invalid RowPos is >= vector.size()");
90 (*(m_pRow
->get())[m_nRowPos
]) = _rVal
;
93 const ORowSetValue
& OOperandRow::getValue() const
95 OSL_ENSURE(m_pRow
.is() && m_nRowPos
< m_pRow
->get().size(),"Invalid RowPos is >= vector.size()");
96 return (m_pRow
->get())[m_nRowPos
]->getValue();
100 void OOperandValue::setValue(const ORowSetValue
& _rVal
)
105 bool OOperandAttr::isIndexed() const
110 OOperandParam::OOperandParam(OSQLParseNode
* pNode
, sal_Int32 _nPos
)
111 : OOperandRow(static_cast<sal_uInt16
>(_nPos
), DataType::VARCHAR
) // Standard-Type
113 OSL_ENSURE(SQL_ISRULE(pNode
,parameter
),"Argument ist kein Parameter");
114 OSL_ENSURE(pNode
->count() > 0,"Fehler im Parse Tree");
115 OSQLParseNode
*pMark
= pNode
->getChild(0);
117 OUString aParameterName
;
118 if (SQL_ISPUNCTUATION(pMark
, "?"))
119 aParameterName
= "?";
120 else if (SQL_ISPUNCTUATION(pMark
, ":"))
121 aParameterName
= pNode
->getChild(1)->getTokenValue();
124 SAL_WARN( "connectivity.drivers","Fehler im Parse Tree");
127 // set up Parameter-Column with default type, can be specified more precisely later using Describe-Parameter
129 // save Identity (not escpecially necessary here, just for the sake of symmetry)
132 // OColumn* pColumn = new OFILEColumn(aParameterName,eDBType,255,0,SQL_FLAGS_NULLALLOWED);
133 // rParamColumns->AddColumn(pColumn);
135 // the value will be set just before the evaluation
140 const ORowSetValue
& OOperandValue::getValue() const
146 OOperandConst::OOperandConst(const OSQLParseNode
& rColumnRef
, const OUString
& aStrValue
)
148 switch (rColumnRef
.getNodeType())
150 case SQL_NODE_STRING
:
151 m_aValue
= aStrValue
;
152 m_eDBType
= DataType::VARCHAR
;
153 m_aValue
.setBound(true);
155 case SQL_NODE_INTNUM
:
156 case SQL_NODE_APPROXNUM
:
157 m_aValue
= aStrValue
.toDouble();
158 m_eDBType
= DataType::DOUBLE
;
159 m_aValue
.setBound(true);
165 if (SQL_ISTOKEN(&rColumnRef
, TRUE
))
168 m_eDBType
= DataType::BIT
;
170 else if (SQL_ISTOKEN(&rColumnRef
, FALSE
))
173 m_eDBType
= DataType::BIT
;
177 SAL_WARN( "connectivity.drivers", "Parse Error");
179 m_aValue
.setBound(true);
183 // Implementation of the operators
186 sal_uInt16
OOperator::getRequestedOperands() const {return 2;}
189 bool OBoolOperator::operate(const OOperand
*, const OOperand
*) const
196 void OBoolOperator::Exec(OCodeStack
& rCodeStack
)
198 OOperand
*pRight
= rCodeStack
.top();
200 OOperand
*pLeft
= rCodeStack
.top();
203 rCodeStack
.push(new OOperandResultBOOL(operate(pLeft
, pRight
)));
204 if (IS_TYPE(OOperandResult
,pLeft
))
206 if (IS_TYPE(OOperandResult
,pRight
))
210 bool OOp_NOT::operate(const OOperand
* pLeft
, const OOperand
* ) const
212 return !pLeft
->isValid();
215 void OOp_NOT::Exec(OCodeStack
& rCodeStack
)
217 OOperand
* pOperand
= rCodeStack
.top();
220 rCodeStack
.push(new OOperandResultBOOL(operate(pOperand
)));
221 if (IS_TYPE(OOperandResult
,pOperand
))
225 sal_uInt16
OOp_NOT::getRequestedOperands() const
231 bool OOp_AND::operate(const OOperand
* pLeft
, const OOperand
* pRight
) const
233 return pLeft
->isValid() && pRight
->isValid();
237 bool OOp_OR::operate(const OOperand
* pLeft
, const OOperand
* pRight
) const
239 return pLeft
->isValid() || pRight
->isValid();
243 sal_uInt16
OOp_ISNULL::getRequestedOperands() const
249 void OOp_ISNULL::Exec(OCodeStack
& rCodeStack
)
251 OOperand
* pOperand
= rCodeStack
.top();
254 rCodeStack
.push(new OOperandResultBOOL(operate(pOperand
)));
255 if (IS_TYPE(OOperandResult
,pOperand
))
260 bool OOp_ISNULL::operate(const OOperand
* pOperand
, const OOperand
*) const
262 return pOperand
->getValue().isNull();
266 bool OOp_ISNOTNULL::operate(const OOperand
* pOperand
, const OOperand
*) const
268 return !OOp_ISNULL::operate(pOperand
);
272 bool OOp_LIKE::operate(const OOperand
* pLeft
, const OOperand
* pRight
) const
275 ORowSetValue
aLH(pLeft
->getValue());
276 ORowSetValue
aRH(pRight
->getValue());
278 if (aLH
.isNull() || aRH
.isNull())
282 bMatch
= match(aRH
.getString(), aLH
.getString(), cEscape
);
288 bool OOp_NOTLIKE::operate(const OOperand
* pLeft
, const OOperand
* pRight
) const
290 return !OOp_LIKE::operate(pLeft
, pRight
);
294 bool OOp_COMPARE::operate(const OOperand
* pLeft
, const OOperand
* pRight
) const
296 ORowSetValue
aLH(pLeft
->getValue());
297 ORowSetValue
aRH(pRight
->getValue());
299 if (aLH
.isNull() || aRH
.isNull()) // if (!aLH.getValue() || !aRH.getValue())
302 bool bResult
= false;
303 sal_Int32 eDBType
= pLeft
->getDBType();
305 // Comparison (depending on Data-type):
309 case DataType::VARCHAR
:
310 case DataType::LONGVARCHAR
:
312 OUString sLH
= aLH
, sRH
= aRH
;
313 sal_Int32 nRes
= rtl_ustr_compareIgnoreAsciiCase_WithLength
319 switch(aPredicateType
)
321 case SQLFilterOperator::EQUAL
: bResult
= (nRes
== 0); break;
322 case SQLFilterOperator::NOT_EQUAL
: bResult
= (nRes
!= 0); break;
323 case SQLFilterOperator::LESS
: bResult
= (nRes
< 0); break;
324 case SQLFilterOperator::LESS_EQUAL
: bResult
= (nRes
<= 0); break;
325 case SQLFilterOperator::GREATER
: bResult
= (nRes
> 0); break;
326 case SQLFilterOperator::GREATER_EQUAL
: bResult
= (nRes
>= 0); break;
327 default: bResult
= false;
330 case DataType::TINYINT
:
331 case DataType::SMALLINT
:
332 case DataType::INTEGER
:
333 case DataType::DECIMAL
:
334 case DataType::NUMERIC
:
336 case DataType::DOUBLE
:
338 case DataType::TIMESTAMP
:
342 double n
= aLH
,m
= aRH
;
344 switch (aPredicateType
)
346 case SQLFilterOperator::EQUAL
: bResult
= (n
== m
); break;
347 case SQLFilterOperator::LIKE
: bResult
= (n
== m
); break;
348 case SQLFilterOperator::NOT_EQUAL
: bResult
= (n
!= m
); break;
349 case SQLFilterOperator::NOT_LIKE
: bResult
= (n
!= m
); break;
350 case SQLFilterOperator::LESS
: bResult
= (n
< m
); break;
351 case SQLFilterOperator::LESS_EQUAL
: bResult
= (n
<= m
); break;
352 case SQLFilterOperator::GREATER
: bResult
= (n
> m
); break;
353 case SQLFilterOperator::GREATER_EQUAL
: bResult
= (n
>= m
); break;
354 default: bResult
= false;
358 bResult
= aLH
== aRH
;
364 void ONumOperator::Exec(OCodeStack
& rCodeStack
)
366 OOperand
*pRight
= rCodeStack
.top();
368 OOperand
*pLeft
= rCodeStack
.top();
371 rCodeStack
.push(new OOperandResultNUM(operate(pLeft
->getValue(), pRight
->getValue())));
372 if (IS_TYPE(OOperandResult
,pLeft
))
374 if (IS_TYPE(OOperandResult
,pRight
))
378 double OOp_ADD::operate(const double& fLeft
,const double& fRight
) const
380 return fLeft
+ fRight
;
384 double OOp_SUB::operate(const double& fLeft
,const double& fRight
) const
386 return fLeft
- fRight
;
390 double OOp_MUL::operate(const double& fLeft
,const double& fRight
) const
392 return fLeft
* fRight
;
396 double OOp_DIV::operate(const double& fLeft
,const double& fRight
) const
398 return fLeft
/ fRight
;
401 OEvaluateSet
* OOperandAttr::preProcess(OBoolOperator
* /*pOp*/, OOperand
* /*pRight*/)
406 void ONthOperator::Exec(OCodeStack
& rCodeStack
)
408 ::std::vector
<ORowSetValue
> aValues
;
409 ::std::vector
<OOperand
*> aOperands
;
413 OSL_ENSURE(!rCodeStack
.empty(),"Stack must be none empty!");
414 pOperand
= rCodeStack
.top();
416 if ( !IS_TYPE(OStopOperand
,pOperand
) )
417 aValues
.push_back( pOperand
->getValue() );
418 aOperands
.push_back( pOperand
);
420 while ( !IS_TYPE(OStopOperand
,pOperand
) );
422 rCodeStack
.push(new OOperandResult(operate(aValues
)));
424 ::std::vector
<OOperand
*>::iterator aIter
= aOperands
.begin();
425 ::std::vector
<OOperand
*>::iterator aEnd
= aOperands
.end();
426 for (; aIter
!= aEnd
; ++aIter
)
428 if (IS_TYPE(OOperandResult
,*aIter
))
433 void OBinaryOperator::Exec(OCodeStack
& rCodeStack
)
435 OOperand
*pRight
= rCodeStack
.top();
437 OOperand
*pLeft
= rCodeStack
.top();
440 if ( !rCodeStack
.empty() && IS_TYPE(OStopOperand
,rCodeStack
.top()) )
443 rCodeStack
.push(new OOperandResult(operate(pLeft
->getValue(),pRight
->getValue())));
444 if (IS_TYPE(OOperandResult
,pRight
))
446 if (IS_TYPE(OOperandResult
,pLeft
))
450 void OUnaryOperator::Exec(OCodeStack
& rCodeStack
)
452 OSL_ENSURE(!rCodeStack
.empty(),"Stack is empty!");
453 OOperand
* pOperand
= rCodeStack
.top();
456 rCodeStack
.push(new OOperandResult(operate(pOperand
->getValue())));
457 if (IS_TYPE(OOperandResult
,pOperand
))
461 sal_uInt16
OUnaryOperator::getRequestedOperands() const {return 1;}
465 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */