1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: fcode.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_connectivity.hxx"
33 #include "file/fcode.hxx"
34 #include <osl/diagnose.h>
35 #include "connectivity/sqlparse.hxx"
36 #include <i18npool/mslangid.hxx>
37 #include <vcl/svapp.hxx>
38 #include <tools/debug.hxx>
39 #include "TConnection.hxx"
40 #include <com/sun/star/sdb/SQLFilterOperator.hpp>
41 #include <comphelper/types.hxx>
42 #include <com/sun/star/sdb/SQLFilterOperator.hpp>
43 #include <rtl/logfile.hxx>
45 using namespace ::comphelper
;
46 using namespace connectivity
;
47 using namespace connectivity::file
;
48 //using namespace ::com::sun::star::uno;
49 //using namespace ::com::sun::star::lang;
50 using namespace ::com::sun::star::sdbc
;
51 using namespace ::com::sun::star::sdb
;
52 //using namespace ::com::sun::star::container;
53 //using namespace ::com::sun::star::beans;
54 //using namespace ::com::sun::star::sdbcx;
57 TYPEINIT1(OOperand
, OCode
);
58 TYPEINIT1(OOperandRow
, OOperand
);
59 TYPEINIT1(OOperandAttr
, OOperandRow
);
60 TYPEINIT1(OOperandParam
, OOperandRow
);
61 TYPEINIT1(OOperandValue
, OOperand
);
62 TYPEINIT1(OOperandConst
, OOperandValue
);
63 TYPEINIT1(OOperandResult
, OOperandValue
);
64 TYPEINIT1(OStopOperand
, OOperandValue
);
66 TYPEINIT1(OOperator
, OCode
);
67 TYPEINIT1(OBoolOperator
,OOperator
);
68 TYPEINIT1(OOp_NOT
, OBoolOperator
);
69 TYPEINIT1(OOp_AND
, OBoolOperator
);
70 TYPEINIT1(OOp_OR
, OBoolOperator
);
71 TYPEINIT1(OOp_ISNULL
, OBoolOperator
);
72 TYPEINIT1(OOp_ISNOTNULL
, OOp_ISNULL
);
73 TYPEINIT1(OOp_LIKE
, OBoolOperator
);
74 TYPEINIT1(OOp_NOTLIKE
, OOp_LIKE
);
75 TYPEINIT1(OOp_COMPARE
, OBoolOperator
);
76 TYPEINIT1(ONumOperator
, OOperator
);
77 TYPEINIT1(ONthOperator
, OOperator
);
78 TYPEINIT1(OBinaryOperator
, OOperator
);
79 TYPEINIT1(OUnaryOperator
, OOperator
);
81 //------------------------------------------------------------------
85 DBG_CTOR(OCode
,NULL
);
87 // -----------------------------------------------------------------------------
93 //------------------------------------------------------------------
94 OEvaluateSet
* OOperand::preProcess(OBoolOperator
* /*pOp*/, OOperand
* /*pRight*/)
98 // -----------------------------------------------------------------------------
99 OOperandRow::OOperandRow(sal_uInt16 _nPos
, sal_Int32 _rType
)
103 //------------------------------------------------------------------
104 void OOperandRow::bindValue(const OValueRefRow
& _pRow
)
106 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "file", "Ocke.Janssen@sun.com", "OOperandRow::OOperandRow" );
107 OSL_ENSURE(_pRow
.isValid(),"NO EMPTY row allowed!");
109 OSL_ENSURE(m_pRow
.isValid() && m_nRowPos
< m_pRow
->get().size(),"Invalid RowPos is >= vector.size()");
110 (m_pRow
->get())[m_nRowPos
]->setBound(sal_True
);
112 // -----------------------------------------------------------------------------
113 void OOperandRow::setValue(const ORowSetValue
& _rVal
)
115 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "file", "Ocke.Janssen@sun.com", "OOperandRow::setValue" );
116 OSL_ENSURE(m_pRow
.isValid() && m_nRowPos
< m_pRow
->get().size(),"Invalid RowPos is >= vector.size()");
117 (*(m_pRow
->get())[m_nRowPos
]) = _rVal
;
119 //------------------------------------------------------------------
120 const ORowSetValue
& OOperandRow::getValue() const
122 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "file", "Ocke.Janssen@sun.com", "OOperandRow::getValue" );
123 OSL_ENSURE(m_pRow
.isValid() && m_nRowPos
< m_pRow
->get().size(),"Invalid RowPos is >= vector.size()");
124 return (m_pRow
->get())[m_nRowPos
]->getValue();
127 // -----------------------------------------------------------------------------
128 void OOperandValue::setValue(const ORowSetValue
& _rVal
)
130 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "file", "Ocke.Janssen@sun.com", "OOperandValue::setValue" );
133 // -------------------------------------------------------------------------
134 sal_Bool
OOperandAttr::isIndexed() const
138 //------------------------------------------------------------------
139 OOperandParam::OOperandParam(OSQLParseNode
* pNode
, sal_Int32 _nPos
)
140 : OOperandRow(static_cast<sal_uInt16
>(_nPos
), DataType::VARCHAR
) // Standard-Typ
142 OSL_ENSURE(SQL_ISRULE(pNode
,parameter
),"Argument ist kein Parameter");
143 OSL_ENSURE(pNode
->count() > 0,"Fehler im Parse Tree");
144 OSQLParseNode
*pMark
= pNode
->getChild(0);
146 String aParameterName
;
147 if (SQL_ISPUNCTUATION(pMark
,"?"))
148 aParameterName
= '?';
149 else if (SQL_ISPUNCTUATION(pMark
,":"))
150 aParameterName
= pNode
->getChild(1)->getTokenValue();
153 OSL_ASSERT("Fehler im Parse Tree");
156 // Parameter-Column aufsetzen mit defult typ, kann zu einem spaeteren Zeitpunkt ueber DescribeParameter
157 // genauer spezifiziert werden
159 // Identitaet merken (hier eigentlich nicht erforderlich, aber aus
160 // Symmetriegruenden ...)
163 // OColumn* pColumn = new OFILEColumn(aParameterName,eDBType,255,0,SQL_FLAGS_NULLALLOWED);
164 // rParamColumns->AddColumn(pColumn);
166 // der Wert wird erst kurz vor der Auswertung gesetzt
170 //------------------------------------------------------------------
171 const ORowSetValue
& OOperandValue::getValue() const
173 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "file", "Ocke.Janssen@sun.com", "OOperandValue::getValue" );
177 //------------------------------------------------------------------
178 OOperandConst::OOperandConst(const OSQLParseNode
& rColumnRef
, const rtl::OUString
& aStrValue
)
180 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "file", "Ocke.Janssen@sun.com", "OOperandConst::OOperandConst" );
181 switch (rColumnRef
.getNodeType())
183 case SQL_NODE_STRING
:
184 m_aValue
= aStrValue
;
185 m_eDBType
= DataType::VARCHAR
;
186 m_aValue
.setBound(sal_True
);
188 case SQL_NODE_INTNUM
:
189 case SQL_NODE_APPROXNUM
:
191 m_aValue
= aStrValue
.toDouble();
192 m_eDBType
= DataType::DOUBLE
;
193 m_aValue
.setBound(sal_True
);
200 if (SQL_ISTOKEN(&rColumnRef
,TRUE
))
203 m_eDBType
= DataType::BIT
;
205 else if (SQL_ISTOKEN(&rColumnRef
,FALSE
))
208 m_eDBType
= DataType::BIT
;
212 OSL_ASSERT("Parse Error");
214 m_aValue
.setBound(sal_True
);
217 /////////////////////////////////////////////////////////////////////////////////////////
218 // Implementation of the operators
220 //------------------------------------------------------------------
221 sal_uInt16
OOperator::getRequestedOperands() const {return 2;}
223 //------------------------------------------------------------------
224 sal_Bool
OBoolOperator::operate(const OOperand
*, const OOperand
*) const
226 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "file", "Ocke.Janssen@sun.com", "OBoolOperator::operate" );
231 //------------------------------------------------------------------
232 void OBoolOperator::Exec(OCodeStack
& rCodeStack
)
234 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "file", "Ocke.Janssen@sun.com", "OBoolOperator::Exec" );
235 OOperand
*pRight
= rCodeStack
.top();
237 OOperand
*pLeft
= rCodeStack
.top();
240 rCodeStack
.push(new OOperandResultBOOL(operate(pLeft
, pRight
)));
241 if (IS_TYPE(OOperandResult
,pLeft
))
243 if (IS_TYPE(OOperandResult
,pRight
))
246 //------------------------------------------------------------------
247 sal_Bool
OOp_NOT::operate(const OOperand
* pLeft
, const OOperand
* ) const
249 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "file", "Ocke.Janssen@sun.com", "OOp_AND::operate" );
250 return !pLeft
->isValid();
252 //------------------------------------------------------------------
253 void OOp_NOT::Exec(OCodeStack
& rCodeStack
)
255 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "file", "Ocke.Janssen@sun.com", "OOp_ISNULL::Exec" );
256 OOperand
* pOperand
= rCodeStack
.top();
259 rCodeStack
.push(new OOperandResultBOOL(operate(pOperand
)));
260 if (IS_TYPE(OOperandResult
,pOperand
))
263 //------------------------------------------------------------------
264 sal_uInt16
OOp_NOT::getRequestedOperands() const
266 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "file", "Ocke.Janssen@sun.com", "OOp_NOT::getRequestedOperands" );
270 //------------------------------------------------------------------
271 sal_Bool
OOp_AND::operate(const OOperand
* pLeft
, const OOperand
* pRight
) const
273 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "file", "Ocke.Janssen@sun.com", "OOp_AND::operate" );
274 return pLeft
->isValid() && pRight
->isValid();
277 //------------------------------------------------------------------
278 sal_Bool
OOp_OR::operate(const OOperand
* pLeft
, const OOperand
* pRight
) const
280 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "file", "Ocke.Janssen@sun.com", "OOp_OR::operate" );
281 return pLeft
->isValid() || pRight
->isValid();
284 //------------------------------------------------------------------
285 sal_uInt16
OOp_ISNULL::getRequestedOperands() const
287 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "file", "Ocke.Janssen@sun.com", "OOp_ISNULL::getRequestedOperands" );
291 //------------------------------------------------------------------
292 void OOp_ISNULL::Exec(OCodeStack
& rCodeStack
)
294 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "file", "Ocke.Janssen@sun.com", "OOp_ISNULL::Exec" );
295 OOperand
* pOperand
= rCodeStack
.top();
298 rCodeStack
.push(new OOperandResultBOOL(operate(pOperand
)));
299 if (IS_TYPE(OOperandResult
,pOperand
))
303 //------------------------------------------------------------------
304 sal_Bool
OOp_ISNULL::operate(const OOperand
* pOperand
, const OOperand
*) const
306 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "file", "Ocke.Janssen@sun.com", "OOp_ISNULL::operate" );
307 return pOperand
->getValue().isNull();
310 //------------------------------------------------------------------
311 sal_Bool
OOp_ISNOTNULL::operate(const OOperand
* pOperand
, const OOperand
*) const
313 return !OOp_ISNULL::operate(pOperand
);
316 //------------------------------------------------------------------
317 sal_Bool
OOp_LIKE::operate(const OOperand
* pLeft
, const OOperand
* pRight
) const
319 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "file", "Ocke.Janssen@sun.com", "OOp_ISNULL::operate" );
321 ORowSetValue
aLH(pLeft
->getValue());
322 ORowSetValue
aRH(pRight
->getValue());
324 if (aLH
.isNull() || aRH
.isNull())
328 bMatch
= match(aRH
.getString(), aLH
.getString(), cEscape
);
333 //------------------------------------------------------------------
334 sal_Bool
OOp_NOTLIKE::operate(const OOperand
* pLeft
, const OOperand
* pRight
) const
336 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "file", "Ocke.Janssen@sun.com", "OOp_NOTLIKE::operate" );
337 return !OOp_LIKE::operate(pLeft
, pRight
);
340 //------------------------------------------------------------------
341 sal_Bool
OOp_COMPARE::operate(const OOperand
* pLeft
, const OOperand
* pRight
) const
343 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "file", "Ocke.Janssen@sun.com", "OOp_COMPARE::operate" );
344 ORowSetValue
aLH(pLeft
->getValue());
345 ORowSetValue
aRH(pRight
->getValue());
347 if (aLH
.isNull() || aRH
.isNull()) // if (!aLH.getValue() || !aRH.getValue())
350 sal_Bool bResult
= sal_False
;
351 sal_Int32 eDBType
= pLeft
->getDBType();
353 // Vergleich (je nach Datentyp):
357 case DataType::VARCHAR
:
358 case DataType::LONGVARCHAR
:
360 rtl::OUString sLH
= aLH
, sRH
= aRH
;
361 INT32 nRes
= rtl_ustr_compareIgnoreAsciiCase_WithLength
367 switch(aPredicateType
)
369 case SQLFilterOperator::EQUAL
: bResult
= (nRes
== 0); break;
370 case SQLFilterOperator::NOT_EQUAL
: bResult
= (nRes
!= 0); break;
371 case SQLFilterOperator::LESS
: bResult
= (nRes
< 0); break;
372 case SQLFilterOperator::LESS_EQUAL
: bResult
= (nRes
<= 0); break;
373 case SQLFilterOperator::GREATER
: bResult
= (nRes
> 0); break;
374 case SQLFilterOperator::GREATER_EQUAL
: bResult
= (nRes
>= 0); break;
375 default: bResult
= sal_False
;
378 case DataType::TINYINT
:
379 case DataType::SMALLINT
:
380 case DataType::INTEGER
:
381 case DataType::DECIMAL
:
382 case DataType::NUMERIC
:
384 case DataType::DOUBLE
:
386 case DataType::TIMESTAMP
:
390 double n
= aLH
,m
= aRH
;
392 switch (aPredicateType
)
394 case SQLFilterOperator::EQUAL
: bResult
= (n
== m
); break;
395 case SQLFilterOperator::LIKE
: bResult
= (n
== m
); break;
396 case SQLFilterOperator::NOT_EQUAL
: bResult
= (n
!= m
); break;
397 case SQLFilterOperator::NOT_LIKE
: bResult
= (n
!= m
); break;
398 case SQLFilterOperator::LESS
: bResult
= (n
< m
); break;
399 case SQLFilterOperator::LESS_EQUAL
: bResult
= (n
<= m
); break;
400 case SQLFilterOperator::GREATER
: bResult
= (n
> m
); break;
401 case SQLFilterOperator::GREATER_EQUAL
: bResult
= (n
>= m
); break;
402 default: bResult
= sal_False
;
406 bResult
= aLH
== aRH
;
411 //------------------------------------------------------------------
412 void ONumOperator::Exec(OCodeStack
& rCodeStack
)
414 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "file", "Ocke.Janssen@sun.com", "ONumOperator::Exec" );
416 OOperand
*pRight
= rCodeStack
.top();
418 OOperand
*pLeft
= rCodeStack
.top();
421 rCodeStack
.push(new OOperandResultNUM(operate(pLeft
->getValue(), pRight
->getValue())));
422 if (IS_TYPE(OOperandResult
,pLeft
))
424 if (IS_TYPE(OOperandResult
,pRight
))
427 //------------------------------------------------------------------
428 double OOp_ADD::operate(const double& fLeft
,const double& fRight
) const
430 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "file", "Ocke.Janssen@sun.com", "OOp_ADD::operate" );
431 return fLeft
+ fRight
;
434 //------------------------------------------------------------------
435 double OOp_SUB::operate(const double& fLeft
,const double& fRight
) const
437 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "file", "Ocke.Janssen@sun.com", "OOp_SUB::operate" );
438 return fLeft
- fRight
;
441 //------------------------------------------------------------------
442 double OOp_MUL::operate(const double& fLeft
,const double& fRight
) const
444 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "file", "Ocke.Janssen@sun.com", "OOp_MUL::operate" );
445 return fLeft
* fRight
;
448 //------------------------------------------------------------------
449 double OOp_DIV::operate(const double& fLeft
,const double& fRight
) const
451 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "file", "Ocke.Janssen@sun.com", "OOp_DIV::operate" );
452 return fLeft
/ fRight
;
454 // -----------------------------------------------------------------------------
455 OEvaluateSet
* OOperandAttr::preProcess(OBoolOperator
* /*pOp*/, OOperand
* /*pRight*/)
457 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "file", "Ocke.Janssen@sun.com", "OOperandAttr::preProcess" );
460 //------------------------------------------------------------------
461 void ONthOperator::Exec(OCodeStack
& rCodeStack
)
463 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "file", "Ocke.Janssen@sun.com", "ONthOperator::Exec" );
464 ::std::vector
<ORowSetValue
> aValues
;
465 ::std::vector
<OOperand
*> aOperands
;
469 OSL_ENSURE(!rCodeStack
.empty(),"Stack must be none empty!");
470 pOperand
= rCodeStack
.top();
472 if ( !IS_TYPE(OStopOperand
,pOperand
) )
473 aValues
.push_back( pOperand
->getValue() );
474 aOperands
.push_back( pOperand
);
476 while ( !IS_TYPE(OStopOperand
,pOperand
) );
478 rCodeStack
.push(new OOperandResult(operate(aValues
)));
480 ::std::vector
<OOperand
*>::iterator aIter
= aOperands
.begin();
481 ::std::vector
<OOperand
*>::iterator aEnd
= aOperands
.end();
482 for (; aIter
!= aEnd
; ++aIter
)
484 if (IS_TYPE(OOperandResult
,*aIter
))
488 //------------------------------------------------------------------
489 void OBinaryOperator::Exec(OCodeStack
& rCodeStack
)
491 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "file", "Ocke.Janssen@sun.com", "OBinaryOperator::Exec" );
492 OOperand
*pRight
= rCodeStack
.top();
494 OOperand
*pLeft
= rCodeStack
.top();
497 if ( !rCodeStack
.empty() && IS_TYPE(OStopOperand
,rCodeStack
.top()) )
500 rCodeStack
.push(new OOperandResult(operate(pLeft
->getValue(),pRight
->getValue())));
501 if (IS_TYPE(OOperandResult
,pRight
))
503 if (IS_TYPE(OOperandResult
,pLeft
))
506 //------------------------------------------------------------------
507 void OUnaryOperator::Exec(OCodeStack
& rCodeStack
)
509 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "file", "Ocke.Janssen@sun.com", "OUnaryOperator::Exec" );
510 OSL_ENSURE(!rCodeStack
.empty(),"Stack is empty!");
511 OOperand
* pOperand
= rCodeStack
.top();
514 rCodeStack
.push(new OOperandResult(operate(pOperand
->getValue())));
515 if (IS_TYPE(OOperandResult
,pOperand
))
518 // -----------------------------------------------------------------------------
519 sal_uInt16
OUnaryOperator::getRequestedOperands() const {return 1;}