1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_connectivity.hxx"
30 #include "file/fcode.hxx"
31 #include <osl/diagnose.h>
32 #include "connectivity/sqlparse.hxx"
33 #include <i18npool/mslangid.hxx>
34 #include <tools/debug.hxx>
35 #include <tools/string.hxx>
36 #include "TConnection.hxx"
37 #include <com/sun/star/sdb/SQLFilterOperator.hpp>
38 #include <comphelper/types.hxx>
39 #include <com/sun/star/sdb/SQLFilterOperator.hpp>
40 #include <rtl/logfile.hxx>
41 
42 using namespace ::comphelper;
43 using namespace connectivity;
44 using namespace connectivity::file;
45 //using namespace ::com::sun::star::uno;
46 //using namespace ::com::sun::star::lang;
47 using namespace ::com::sun::star::sdbc;
48 using namespace ::com::sun::star::sdb;
49 //using namespace ::com::sun::star::container;
50 //using namespace ::com::sun::star::beans;
51 //using namespace ::com::sun::star::sdbcx;
52 
53 TYPEINIT0(OCode);
54 TYPEINIT1(OOperand, OCode);
55 TYPEINIT1(OOperandRow, OOperand);
56 TYPEINIT1(OOperandAttr, OOperandRow);
57 TYPEINIT1(OOperandParam, OOperandRow);
58 TYPEINIT1(OOperandValue, OOperand);
59 TYPEINIT1(OOperandConst, OOperandValue);
60 TYPEINIT1(OOperandResult, OOperandValue);
61 TYPEINIT1(OStopOperand, OOperandValue);
62 
63 TYPEINIT1(OOperator, OCode);
64 TYPEINIT1(OBoolOperator,OOperator);
65 TYPEINIT1(OOp_NOT, OBoolOperator);
66 TYPEINIT1(OOp_AND, OBoolOperator);
67 TYPEINIT1(OOp_OR, OBoolOperator);
68 TYPEINIT1(OOp_ISNULL, OBoolOperator);
69 TYPEINIT1(OOp_ISNOTNULL, OOp_ISNULL);
70 TYPEINIT1(OOp_LIKE, OBoolOperator);
71 TYPEINIT1(OOp_NOTLIKE, OOp_LIKE);
72 TYPEINIT1(OOp_COMPARE, OBoolOperator);
73 TYPEINIT1(ONumOperator, OOperator);
74 TYPEINIT1(ONthOperator, OOperator);
75 TYPEINIT1(OBinaryOperator, OOperator);
76 TYPEINIT1(OUnaryOperator, OOperator);
77 
78 //------------------------------------------------------------------
79 DBG_NAME(OCode )
80 OCode::OCode()
81 {
82 	DBG_CTOR(OCode ,NULL);
83 }
84 // -----------------------------------------------------------------------------
85 OCode::~OCode()
86 {
87 	DBG_DTOR(OCode,NULL);
88 }
89 
90 //------------------------------------------------------------------
91 OEvaluateSet* OOperand::preProcess(OBoolOperator* /*pOp*/, OOperand* /*pRight*/)
92 {
93 	return NULL;
94 }
95 // -----------------------------------------------------------------------------
96 OOperandRow::OOperandRow(sal_uInt16 _nPos, sal_Int32 _rType)
97 	: OOperand(_rType)
98 	, m_nRowPos(_nPos)
99 {}
100 //------------------------------------------------------------------
101 void OOperandRow::bindValue(const OValueRefRow& _pRow)
102 {
103     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOperandRow::OOperandRow" );
104 	OSL_ENSURE(_pRow.isValid(),"NO EMPTY row allowed!");
105 	m_pRow = _pRow;
106 	OSL_ENSURE(m_pRow.isValid() && m_nRowPos < m_pRow->get().size(),"Invalid RowPos is >= vector.size()");
107 	(m_pRow->get())[m_nRowPos]->setBound(sal_True);
108 }
109 // -----------------------------------------------------------------------------
110 void OOperandRow::setValue(const ORowSetValue& _rVal)
111 {
112     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOperandRow::setValue" );
113 	OSL_ENSURE(m_pRow.isValid() && m_nRowPos < m_pRow->get().size(),"Invalid RowPos is >= vector.size()");
114 	(*(m_pRow->get())[m_nRowPos]) = _rVal;
115 }
116 //------------------------------------------------------------------
117 const ORowSetValue& OOperandRow::getValue() const
118 {
119     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOperandRow::getValue" );
120 	OSL_ENSURE(m_pRow.isValid() && m_nRowPos < m_pRow->get().size(),"Invalid RowPos is >= vector.size()");
121 	return (m_pRow->get())[m_nRowPos]->getValue();
122 }
123 
124 // -----------------------------------------------------------------------------
125 void OOperandValue::setValue(const ORowSetValue& _rVal)
126 {
127     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOperandValue::setValue" );
128 	m_aValue = _rVal;
129 }
130 // -------------------------------------------------------------------------
131 sal_Bool OOperandAttr::isIndexed() const
132 {
133 	return sal_False;
134 }
135 //------------------------------------------------------------------
136 OOperandParam::OOperandParam(OSQLParseNode* pNode, sal_Int32 _nPos)
137 	: OOperandRow(static_cast<sal_uInt16>(_nPos), DataType::VARCHAR)		 // Standard-Typ
138 {
139 	OSL_ENSURE(SQL_ISRULE(pNode,parameter),"Argument ist kein Parameter");
140 	OSL_ENSURE(pNode->count() > 0,"Fehler im Parse Tree");
141 	OSQLParseNode *pMark = pNode->getChild(0);
142 
143 	String aParameterName;
144 	if (SQL_ISPUNCTUATION(pMark,"?"))
145 		aParameterName = '?';
146 	else if (SQL_ISPUNCTUATION(pMark,":"))
147 		aParameterName = pNode->getChild(1)->getTokenValue();
148 	else
149 	{
150 		OSL_ASSERT("Fehler im Parse Tree");
151 	}
152 
153     // Parameter-Column aufsetzen mit defult typ, kann zu einem spaeteren Zeitpunkt ueber DescribeParameter
154 	// genauer spezifiziert werden
155 
156 	// Identitaet merken (hier eigentlich nicht erforderlich, aber aus
157 	// Symmetriegruenden ...)
158 
159 	// todo
160 	//	OColumn* pColumn = new OFILEColumn(aParameterName,eDBType,255,0,SQL_FLAGS_NULLALLOWED);
161 	//	rParamColumns->AddColumn(pColumn);
162 
163 	// der Wert wird erst kurz vor der Auswertung gesetzt
164 }
165 
166 
167 //------------------------------------------------------------------
168 const ORowSetValue& OOperandValue::getValue() const
169 {
170     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOperandValue::getValue" );
171 	return m_aValue;
172 }
173 
174 //------------------------------------------------------------------
175 OOperandConst::OOperandConst(const OSQLParseNode& rColumnRef, const rtl::OUString& aStrValue)
176 {
177     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOperandConst::OOperandConst" );
178 	switch (rColumnRef.getNodeType())
179 	{
180 		case SQL_NODE_STRING:
181 			m_aValue	= aStrValue;
182 			m_eDBType	= DataType::VARCHAR;
183 			m_aValue.setBound(sal_True);
184 			return;
185 		case SQL_NODE_INTNUM:
186 		case SQL_NODE_APPROXNUM:
187 		{
188 			m_aValue	= aStrValue.toDouble();
189 			m_eDBType	= DataType::DOUBLE;
190 			m_aValue.setBound(sal_True);
191 			return;
192 		}
193         default:
194             break;
195 	}
196 
197 	if (SQL_ISTOKEN(&rColumnRef,TRUE))
198 	{
199 		m_aValue = 1.0;
200 		m_eDBType = DataType::BIT;
201 	}
202 	else if (SQL_ISTOKEN(&rColumnRef,FALSE))
203 	{
204 		m_aValue = 0.0;
205 		m_eDBType = DataType::BIT;
206 	}
207 	else
208 	{
209 		OSL_ASSERT("Parse Error");
210 	}
211 	m_aValue.setBound(sal_True);
212 }
213 
214 /////////////////////////////////////////////////////////////////////////////////////////
215 // Implementation of the operators
216 
217 //------------------------------------------------------------------
218 sal_uInt16 OOperator::getRequestedOperands() const {return 2;}
219 
220 //------------------------------------------------------------------
221 sal_Bool OBoolOperator::operate(const OOperand*, const OOperand*) const
222 {
223     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OBoolOperator::operate" );
224 	return sal_False;
225 }
226 
227 
228 //------------------------------------------------------------------
229 void OBoolOperator::Exec(OCodeStack& rCodeStack)
230 {
231     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OBoolOperator::Exec" );
232 	OOperand  *pRight	= rCodeStack.top();
233 	rCodeStack.pop();
234 	OOperand  *pLeft	= rCodeStack.top();
235 	rCodeStack.pop();
236 
237 	rCodeStack.push(new OOperandResultBOOL(operate(pLeft, pRight)));
238 	if (IS_TYPE(OOperandResult,pLeft))
239 		delete pLeft;
240 	if (IS_TYPE(OOperandResult,pRight))
241 		delete pRight;
242 }
243 //------------------------------------------------------------------
244 sal_Bool OOp_NOT::operate(const OOperand* pLeft, const OOperand* ) const
245 {
246     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOp_AND::operate" );
247 	return !pLeft->isValid();
248 }
249 //------------------------------------------------------------------
250 void OOp_NOT::Exec(OCodeStack& rCodeStack)
251 {
252     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOp_ISNULL::Exec" );
253 	OOperand* pOperand = rCodeStack.top();
254 	rCodeStack.pop();
255 
256 	rCodeStack.push(new OOperandResultBOOL(operate(pOperand)));
257 	if (IS_TYPE(OOperandResult,pOperand))
258 		delete pOperand;
259 }
260 //------------------------------------------------------------------
261 sal_uInt16 OOp_NOT::getRequestedOperands() const
262 {
263     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOp_NOT::getRequestedOperands" );
264     return 1;
265 }
266 
267 //------------------------------------------------------------------
268 sal_Bool OOp_AND::operate(const OOperand* pLeft, const OOperand* pRight) const
269 {
270     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOp_AND::operate" );
271 	return pLeft->isValid() && pRight->isValid();
272 }
273 
274 //------------------------------------------------------------------
275 sal_Bool OOp_OR::operate(const OOperand* pLeft, const OOperand* pRight) const
276 {
277     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOp_OR::operate" );
278 	return pLeft->isValid() || pRight->isValid();
279 }
280 
281 //------------------------------------------------------------------
282 sal_uInt16 OOp_ISNULL::getRequestedOperands() const
283 {
284     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOp_ISNULL::getRequestedOperands" );
285     return 1;
286 }
287 
288 //------------------------------------------------------------------
289 void OOp_ISNULL::Exec(OCodeStack& rCodeStack)
290 {
291     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOp_ISNULL::Exec" );
292 	OOperand* pOperand = rCodeStack.top();
293 	rCodeStack.pop();
294 
295 	rCodeStack.push(new OOperandResultBOOL(operate(pOperand)));
296 	if (IS_TYPE(OOperandResult,pOperand))
297 		delete pOperand;
298 }
299 
300 //------------------------------------------------------------------
301 sal_Bool OOp_ISNULL::operate(const OOperand* pOperand, const OOperand*) const
302 {
303     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOp_ISNULL::operate" );
304 	return pOperand->getValue().isNull();
305 }
306 
307 //------------------------------------------------------------------
308 sal_Bool OOp_ISNOTNULL::operate(const OOperand* pOperand, const OOperand*) const
309 {
310 	return !OOp_ISNULL::operate(pOperand);
311 }
312 
313 //------------------------------------------------------------------
314 sal_Bool OOp_LIKE::operate(const OOperand* pLeft, const OOperand* pRight) const
315 {
316     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOp_ISNULL::operate" );
317 	sal_Bool bMatch;
318 	ORowSetValue aLH(pLeft->getValue());
319 	ORowSetValue aRH(pRight->getValue());
320 
321 	if (aLH.isNull() || aRH.isNull())
322 		bMatch = sal_False;
323 	else
324 	{
325 		bMatch = match(aRH.getString(), aLH.getString(), cEscape);
326 	}
327 	return bMatch;
328 }
329 
330 //------------------------------------------------------------------
331 sal_Bool OOp_NOTLIKE::operate(const OOperand* pLeft, const OOperand* pRight) const
332 {
333     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOp_NOTLIKE::operate" );
334 	return !OOp_LIKE::operate(pLeft, pRight);
335 }
336 
337 //------------------------------------------------------------------
338 sal_Bool OOp_COMPARE::operate(const OOperand* pLeft, const OOperand* pRight) const
339 {
340     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOp_COMPARE::operate" );
341 	ORowSetValue aLH(pLeft->getValue());
342 	ORowSetValue aRH(pRight->getValue());
343 
344 	if (aLH.isNull() || aRH.isNull()) // if (!aLH.getValue() || !aRH.getValue())
345 		return sal_False;
346 
347 	sal_Bool bResult = sal_False;
348 	sal_Int32 eDBType = pLeft->getDBType();
349 
350 	// Vergleich (je nach Datentyp):
351 	switch (eDBType)
352 	{
353 		case DataType::CHAR:
354 		case DataType::VARCHAR:
355         case DataType::LONGVARCHAR:
356 		{
357 			rtl::OUString sLH = aLH, sRH = aRH;
358             sal_Int32 nRes = rtl_ustr_compareIgnoreAsciiCase_WithLength
359                 (
360                  sLH.pData->buffer,
361                  sLH.pData->length,
362                  sRH.pData->buffer,
363                  sRH.pData->length );
364 			switch(aPredicateType)
365 			{
366 				case SQLFilterOperator::EQUAL:			bResult = (nRes == 0); break;
367 				case SQLFilterOperator::NOT_EQUAL:			bResult = (nRes != 0); break;
368 				case SQLFilterOperator::LESS:				bResult = (nRes <  0); break;
369 				case SQLFilterOperator::LESS_EQUAL:		bResult = (nRes <= 0); break;
370 				case SQLFilterOperator::GREATER:			bResult = (nRes >  0); break;
371 				case SQLFilterOperator::GREATER_EQUAL:	bResult = (nRes >= 0); break;
372 				default:						bResult = sal_False;
373 			}
374 		} break;
375 		case DataType::TINYINT:
376 		case DataType::SMALLINT:
377 		case DataType::INTEGER:
378 		case DataType::DECIMAL:
379 		case DataType::NUMERIC:
380 		case DataType::REAL:
381 		case DataType::DOUBLE:
382 		case DataType::BIT:
383 		case DataType::TIMESTAMP:
384 		case DataType::DATE:
385 		case DataType::TIME:
386 		{
387 			double n = aLH ,m = aRH;
388 
389 			switch (aPredicateType)
390 			{
391 				case SQLFilterOperator::EQUAL:			bResult = (n == m); break;
392 				case SQLFilterOperator::LIKE:				bResult = (n == m); break;
393 				case SQLFilterOperator::NOT_EQUAL:			bResult = (n != m); break;
394 				case SQLFilterOperator::NOT_LIKE:			bResult = (n != m); break;
395 				case SQLFilterOperator::LESS:				bResult = (n < m); break;
396 				case SQLFilterOperator::LESS_EQUAL:		bResult = (n <= m); break;
397 				case SQLFilterOperator::GREATER:			bResult = (n > m); break;
398 				case SQLFilterOperator::GREATER_EQUAL:	bResult = (n >= m); break;
399 				default:						bResult = sal_False;
400 			}
401 		} break;
402 		default:
403 			bResult = aLH == aRH;
404 	}
405 	return bResult;
406 }
407 
408 //------------------------------------------------------------------
409 void ONumOperator::Exec(OCodeStack& rCodeStack)
410 {
411     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "ONumOperator::Exec" );
412 
413 	OOperand  *pRight	= rCodeStack.top();
414 	rCodeStack.pop();
415 	OOperand  *pLeft	= rCodeStack.top();
416 	rCodeStack.pop();
417 
418 	rCodeStack.push(new OOperandResultNUM(operate(pLeft->getValue(), pRight->getValue())));
419 	if (IS_TYPE(OOperandResult,pLeft))
420 		delete pLeft;
421 	if (IS_TYPE(OOperandResult,pRight))
422 		delete pRight;
423 }
424 //------------------------------------------------------------------
425 double OOp_ADD::operate(const double& fLeft,const double& fRight) const
426 {
427     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOp_ADD::operate" );
428 	return fLeft + fRight;
429 }
430 
431 //------------------------------------------------------------------
432 double OOp_SUB::operate(const double& fLeft,const double& fRight) const
433 {
434     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOp_SUB::operate" );
435 	return fLeft - fRight;
436 }
437 
438 //------------------------------------------------------------------
439 double OOp_MUL::operate(const double& fLeft,const double& fRight) const
440 {
441     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOp_MUL::operate" );
442 	return fLeft * fRight;
443 }
444 
445 //------------------------------------------------------------------
446 double OOp_DIV::operate(const double& fLeft,const double& fRight) const
447 {
448     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOp_DIV::operate" );
449 	return fLeft / fRight;
450 }
451 // -----------------------------------------------------------------------------
452 OEvaluateSet* OOperandAttr::preProcess(OBoolOperator* /*pOp*/, OOperand* /*pRight*/)
453 {
454     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OOperandAttr::preProcess" );
455 	return NULL;
456 }
457 //------------------------------------------------------------------
458 void ONthOperator::Exec(OCodeStack& rCodeStack)
459 {
460     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "ONthOperator::Exec" );
461 	::std::vector<ORowSetValue> aValues;
462 	::std::vector<OOperand*> aOperands;
463 	OOperand* pOperand;
464 	do
465 	{
466 		OSL_ENSURE(!rCodeStack.empty(),"Stack must be none empty!");
467 		pOperand	= rCodeStack.top();
468 		rCodeStack.pop();
469 		if ( !IS_TYPE(OStopOperand,pOperand) )
470 			aValues.push_back( pOperand->getValue() );
471 		aOperands.push_back( pOperand );
472 	}
473 	while ( !IS_TYPE(OStopOperand,pOperand) );
474 
475 	rCodeStack.push(new OOperandResult(operate(aValues)));
476 
477 	::std::vector<OOperand*>::iterator aIter = aOperands.begin();
478 	::std::vector<OOperand*>::iterator aEnd = aOperands.end();
479 	for (; aIter != aEnd; ++aIter)
480 	{
481 		if (IS_TYPE(OOperandResult,*aIter))
482 			delete *aIter;
483 	}
484 }
485 //------------------------------------------------------------------
486 void OBinaryOperator::Exec(OCodeStack& rCodeStack)
487 {
488     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OBinaryOperator::Exec" );
489 	OOperand  *pRight	= rCodeStack.top();
490 	rCodeStack.pop();
491 	OOperand  *pLeft	= rCodeStack.top();
492 	rCodeStack.pop();
493 
494 	if ( !rCodeStack.empty() && IS_TYPE(OStopOperand,rCodeStack.top()) )
495 		rCodeStack.pop();
496 
497 	rCodeStack.push(new OOperandResult(operate(pLeft->getValue(),pRight->getValue())));
498 	if (IS_TYPE(OOperandResult,pRight))
499 		delete pRight;
500 	if (IS_TYPE(OOperandResult,pLeft))
501 		delete pLeft;
502 }
503 //------------------------------------------------------------------
504 void OUnaryOperator::Exec(OCodeStack& rCodeStack)
505 {
506     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OUnaryOperator::Exec" );
507 	OSL_ENSURE(!rCodeStack.empty(),"Stack is empty!");
508 	OOperand* pOperand = rCodeStack.top();
509 	rCodeStack.pop();
510 
511 	rCodeStack.push(new OOperandResult(operate(pOperand->getValue())));
512 	if (IS_TYPE(OOperandResult,pOperand))
513 		delete pOperand;
514 }
515 // -----------------------------------------------------------------------------
516 sal_uInt16 OUnaryOperator::getRequestedOperands() const {return 1;}
517 
518 
519 
520