1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // CegoAttrCond.cc
4 // ---------------
5 // Cego database table field implementation
6 //
7 // Design and Implementation by Bjoern Lemke
8 //
9 // (C)opyright 2000-2019 Bjoern Lemke
10 //
11 // IMPLEMENTATION MODULE
12 //
13 // Class: CegoAttrCond
14 //
15 // Description: Attribute condition description used for index cursors
16 //
17 // Status: CLEAN
18 //
19 ///////////////////////////////////////////////////////////////////////////////
20 
21 // CEGO INCLUDES
22 #include "CegoAttrCond.h"
23 
24 // POSIX INCLUDES
25 #include <stdlib.h>
26 #include <string.h>
27 
CegoAttrCond()28 CegoAttrCond::CegoAttrCond()
29 {
30 }
31 
~CegoAttrCond()32 CegoAttrCond::~CegoAttrCond()
33 {
34 }
35 
getId() const36 Chain CegoAttrCond::getId() const
37 {
38     Chain s;
39 
40     CegoAttrComp *pAC = _attrCompSet.First();
41     while ( pAC )
42     {
43 	s += pAC->getId();
44 	pAC = _attrCompSet.Next();
45 	if ( pAC )
46 	    s += Chain("&");
47     }
48     return s;
49 }
50 
add(const CegoAttrComp & attrComp)51 void CegoAttrCond::add(const CegoAttrComp& attrComp)
52 {
53     CegoAttrComp *pAC;
54     if ( (pAC = _attrCompSet.Find(attrComp)) == 0 )
55     {
56 	_attrCompSet.Insert(attrComp);
57     }
58     /*
59     else
60     {
61 
62 	cout << "Adding " << attrComp << " failed, already exists  " << *pAC << endl;
63 	cout << "T1 = " << attrComp.getTableName() << endl;
64 	cout << "T2 = " << pAC->getTableName() << endl;
65 
66     }
67     */
68 }
69 
numComp() const70 int CegoAttrCond::numComp() const
71 {
72     return _attrCompSet.Size();
73 }
74 
getStrength() const75 int CegoAttrCond::getStrength() const
76 {
77     CegoAttrComp *pAC = _attrCompSet.First();
78     if ( pAC )
79     {
80 	if ( pAC->getCompMode() == CegoAttrComp::BTWN )
81 	    return 4;
82 	switch ( pAC->getComparison() )
83 	{
84 	case EQUAL:
85 	    return 5;
86 	case NOT_EQUAL:
87 	    return 1;
88 	case LESS_THAN:
89 	    return 3;
90 	case MORE_THAN:
91 	    return 3;
92 	case LESS_EQUAL_THAN:
93 	    return 2;
94 	case MORE_EQUAL_THAN:
95 	    return 2;
96 	}
97     }
98     return 0;
99 }
100 
getAttrCompSet() const101 const TreeT<CegoAttrComp>& CegoAttrCond::getAttrCompSet() const
102 {
103     return _attrCompSet;
104 }
105 
getFilterCond(const ListT<CegoField> & fl,bool ignoreNullComp) const106 CegoAttrCond CegoAttrCond::getFilterCond(const ListT<CegoField>& fl, bool ignoreNullComp) const
107 {
108     CegoAttrCond ac;
109 
110     CegoField *pF = fl.First();
111     while ( pF)
112     {
113 	CegoAttrComp *pAC = _attrCompSet.First();
114 	while ( pAC )
115 	{
116 	    if ( pF->getTableAlias() == pAC->getTableName() && pF->getAttrName() == pAC->getAttrName() )
117 	    {
118 		if ( ! ( ignoreNullComp && pAC->isNullComp() ) )
119 		    ac.add(*pAC);
120 		/*
121 		else
122 		    cout << "Ignoring comp " << *pAC << endl;
123 		*/
124 	    }
125 	    pAC = _attrCompSet.Next();
126 	}
127 
128 	pF = fl.Next();
129     }
130     return ac;
131 }
132 
getIndexCond(const ListT<CegoField> & fl) const133 CegoAttrCond CegoAttrCond::getIndexCond(const ListT<CegoField>& fl) const
134 {
135     CegoAttrCond ac;
136 
137     int pos = 0;
138     CegoField *pF = fl.First();
139 
140     while ( pF  )
141     {
142         CegoAttrComp *pAC = _attrCompSet.First();
143         while ( pAC )
144         {
145             if ( pF->getAttrName() == pAC->getAttrName()
146                  && ( pAC->getCompMode() == CegoAttrComp::VAL
147                       || pAC->getCompMode() == CegoAttrComp::ATTR
148                       || pAC->getCompMode() == CegoAttrComp::BTWN ) )
149             {
150                 pAC->setPos(pos);
151                 ac.add(*pAC);
152             }
153             pAC = _attrCompSet.Next();
154         }
155         pF = fl.Next();
156         pos++;
157     }
158 
159     return ac;
160 }
161 
setup(const ListT<CegoField> & fl)162 bool CegoAttrCond::setup(const ListT<CegoField>& fl)
163 {
164     CegoAttrComp *pAC = _attrCompSet.First();
165     while ( pAC )
166     {
167 	if ( pAC->getCompMode() == CegoAttrComp::ATTR )
168 	    if ( pAC->setup(fl) == false )
169 		return false;
170 	pAC = _attrCompSet.Next();
171     }
172     return true;
173 }
174 
setup(ListT<CegoField> ** pJoinBuf,int offset)175 bool CegoAttrCond::setup(ListT<CegoField>** pJoinBuf, int offset)
176 {
177 
178     CegoAttrComp *pAC = _attrCompSet.First();
179     while ( pAC )
180     {
181 	pAC->reset();
182 	if ( pAC->getCompMode() == CegoAttrComp::ATTR || pAC->getCompMode() == CegoAttrComp::BTWN )
183 	{
184 	    if ( pAC->setup(pJoinBuf, offset) == false )
185 	    {
186 		return false;
187 	    }
188 
189 	}
190 	pAC = _attrCompSet.Next();
191     }
192     return true;
193 }
194 
setup(ListT<CegoField> ** pParentJoinBuf,int parentOffset,ListT<CegoField> ** pJoinBuf,int offset)195 bool CegoAttrCond::setup(ListT<CegoField>** pParentJoinBuf, int parentOffset, ListT<CegoField>** pJoinBuf, int offset)
196 {
197 
198     CegoAttrComp *pAC = _attrCompSet.First();
199     while ( pAC )
200     {
201 	pAC->reset();
202 	if ( pAC->getCompMode() == CegoAttrComp::ATTR || pAC->getCompMode() == CegoAttrComp::BTWN )
203 	{
204 	    if ( pAC->isParentSetup() )
205 	    {
206 		if ( pAC->setup(pParentJoinBuf, parentOffset) == false )
207 		{
208 		    return false;
209 		}
210 	    }
211 	    else
212 	    {
213 		if ( pAC->setup(pJoinBuf, offset) == false )
214 		{
215 		    if ( pParentJoinBuf )
216 		    {
217 			if ( pAC->setup(pParentJoinBuf, parentOffset) == false )
218 			{
219 			    return false;
220 			}
221 			else
222 			{
223 			    pAC->setParentSetup();
224 			}
225 		    }
226 		    else
227 		    {
228 			return false;
229 		    }
230 		}
231 	    }
232 	}
233 
234 	pAC = _attrCompSet.Next();
235     }
236 
237     return true;
238 }
239 
asConjunctionList(const ListT<CegoExpr * > & exprList,ListT<CegoPredDesc * > & conjunctionList,ListT<CegoField> ** pFLA) const240 void CegoAttrCond::asConjunctionList(const ListT<CegoExpr*>& exprList, ListT<CegoPredDesc*>& conjunctionList, ListT<CegoField>** pFLA) const
241 {
242     CegoAttrComp *pAC = _attrCompSet.First();
243     while ( pAC )
244     {
245 	CegoPredDesc *pP;
246 
247 	CegoExpr *pExpr = getExpressionForAlias(exprList, pAC->getAttrName() );
248 
249 	if ( pExpr == 0 )
250 	{
251 	    pExpr = new CegoExpr(new CegoTerm(new CegoFactor( new CegoAttrDesc(pAC->getAttrName()))));
252 	    pExpr->setExternalFieldListArray(pFLA);
253 	}
254 
255 	if ( pAC->getCompMode() == CegoAttrComp::ATTR && pAC->isSetup() == false )
256 	{
257 	    CegoExpr* pExternExpr = new CegoExpr(new CegoTerm(new CegoFactor( pAC->getAttrDesc().clone())));
258 	    pExternExpr->setExternalFieldListArray(pFLA);
259 	    pP = new CegoPredDesc(pExpr,
260 				  pExternExpr,
261 				  pAC->getComparison());
262 
263 	}
264 	else if ( pAC->getCompMode() == CegoAttrComp::VAL ||
265 		  ( pAC->getCompMode() == CegoAttrComp::ATTR && pAC->isSetup() ) )
266 	{
267 	    pP = new CegoPredDesc(pExpr,
268 				  new CegoExpr(new CegoTerm(new CegoFactor( pAC->getFieldValue()))),
269 				  pAC->getComparison());
270 	}
271 	else if ( pAC->getCompMode() == CegoAttrComp::BTWN )
272 	{
273 	    pP = new CegoPredDesc(pExpr,
274 				  new CegoExpr(new CegoTerm(new CegoFactor( pAC->getFieldValue()))),
275 				  new CegoExpr(new CegoTerm(new CegoFactor( pAC->getFieldValue2()))));
276 	}
277 	else if ( pAC->getCompMode() == CegoAttrComp::ISLIKE )
278 	{
279 	    pP = new CegoPredDesc(pExpr,
280 				  pAC->getPattern(),
281 				  false);
282 	}
283 	else if ( pAC->getCompMode() == CegoAttrComp::ISNOTLIKE )
284 	{
285 	    pP = new CegoPredDesc(pExpr,
286 				  pAC->getPattern(),
287 				  true);
288 	}
289 
290 	conjunctionList.Insert(pP);
291 
292 	pAC = _attrCompSet.Next();
293     }
294 }
295 
getExpressionForAlias(const ListT<CegoExpr * > & exprList,const Chain & alias) const296 CegoExpr* CegoAttrCond::getExpressionForAlias(const ListT<CegoExpr*>& exprList, const Chain& alias) const
297 {
298     CegoExpr **pExpr = exprList.First();
299     while ( pExpr )
300     {
301 	if ( (*pExpr)->getAlias() == alias )
302 	    return (*pExpr)->clone();
303 	pExpr = exprList.Next();
304     }
305     return 0;
306 }
307 
checkIndex(const ListT<CegoField> & schema) const308 CegoAttrCond::IndexMatch CegoAttrCond::checkIndex(const ListT<CegoField>& schema) const
309 {
310     int numFound=0;
311 
312     bool hasLeak=false;
313     CegoField *pF = schema.First();
314 
315     while ( pF && hasLeak == false )
316     {
317 	bool isFound=false;
318 	CegoAttrComp *pComp = _attrCompSet.First();
319 	while ( pComp )
320 	{
321 	    if ( pComp->getAttrName() == pF->getAttrName()
322 		 && ( pComp->getCompMode() == CegoAttrComp::VAL
323 		      || pComp->getCompMode() == CegoAttrComp::ATTR
324 		      || pComp->getCompMode() == CegoAttrComp::BTWN ) )
325 	    {
326 		numFound++;
327 		isFound=true;
328 		pComp = _attrCompSet.Next();
329 	    }
330 	    else
331 	    {
332 		pComp = _attrCompSet.Next();
333 	    }
334 	}
335 
336 	if ( isFound == true )
337 	    hasLeak=false;
338 	else
339 	    hasLeak=true;
340 
341 	pF = schema.Next();
342     }
343 
344     if ( numFound == _attrCompSet.Size() )
345 	return FULL;
346 
347     if ( numFound < _attrCompSet.Size() && numFound > 0 )
348 	return PART;
349 
350     return INAPP;
351 }
352 
setIdxSchema(ListT<CegoField> & schema)353 void CegoAttrCond::setIdxSchema(ListT<CegoField>& schema)
354 {
355     _idxSchema = schema;
356 }
357 
setPrimaryComparison(CegoComparison comp)358 void CegoAttrCond::setPrimaryComparison(CegoComparison comp)
359 {
360     CegoAttrComp* pAC = _attrCompSet.First();
361     if ( pAC )
362     {
363 	pAC->setComparison(comp);
364     }
365     else
366     {
367 	throw Exception(EXLOC, "Cannot set primary comparison");
368     }
369 }
370 
getPrimaryCompMode() const371 CegoAttrComp::CompMode CegoAttrCond::getPrimaryCompMode() const
372 {
373     CegoAttrComp* pAC = _attrCompSet.First();
374     if ( pAC )
375     {
376 	return pAC->getCompMode();
377     }
378     else
379     {
380 	throw Exception(EXLOC, "Cannot get primary comp mode");
381     }
382 }
383 
getPrimaryComparison() const384 CegoComparison CegoAttrCond::getPrimaryComparison() const
385 {
386     CegoAttrComp* pAC = _attrCompSet.First();
387     if ( pAC )
388     {
389 	return pAC->getComparison();
390     }
391     else
392     {
393 	throw Exception(EXLOC, "Cannot get primary comparison");
394     }
395 }
396 
diff(const CegoAttrCond & ac) const397 bool CegoAttrCond::diff( const CegoAttrCond& ac) const
398 {
399     if ( ac._attrCompSet.Size() != _attrCompSet.Size() )
400 	return false;
401 
402     CegoAttrComp* pAC = ac._attrCompSet.First();
403     while ( pAC  )
404     {
405 	CegoAttrComp* pAC2 = findComp(pAC);
406 	if ( pAC2  )
407 	{
408 	    if ( pAC->getFieldValue() != pAC2->getFieldValue() )
409 		return false;
410 	}
411 	else
412 	{
413 	    return false;
414 	}
415 	pAC = ac._attrCompSet.Next();
416     }
417 
418     pAC = _attrCompSet.First();
419     while ( pAC  )
420     {
421 	CegoAttrComp* pAC2 = ac.findComp(pAC);
422 	if ( pAC2  )
423 	{
424 	    if ( pAC->getFieldValue() != pAC2->getFieldValue() )
425 		return false;
426 	}
427 	else
428 	{
429 	    return false;
430 	}
431 	pAC = _attrCompSet.Next();
432     }
433     return true;
434 }
435 
findComp(CegoAttrComp * pAttrComp) const436 CegoAttrComp* CegoAttrCond::findComp(CegoAttrComp* pAttrComp) const
437 {
438     // for searching attribute comparison, we use a dedicated loop, since for TreeT, just < and > operators are used.
439     // for comparison we have to use the = operator
440 
441     CegoAttrComp* pAC = _attrCompSet.First();
442     while ( pAC )
443     {
444 	if ( *pAC == *pAttrComp )
445 	    return pAC;
446 	pAC = _attrCompSet.Next();
447     }
448     return 0;
449 }
450 
update(const CegoAttrCond & ac)451 void CegoAttrCond::update( const CegoAttrCond& ac )
452 {
453     CegoAttrComp* pAC = _attrCompSet.First();
454     while ( pAC  )
455     {
456 	CegoAttrComp* pAC2 = ac.findComp(pAC);
457 	if ( pAC2  )
458 	{
459 	    pAC->setFieldValue(pAC2->getFieldValue());
460 	    if ( pAC->getCompMode() == CegoAttrComp::BTWN )
461 		pAC->setFieldValue2(pAC2->getFieldValue2());
462 	}
463 	else
464 	{
465 	    throw Exception(EXLOC, Chain("Cannot set up diff for attribute condition"));
466 	}
467 	pAC = _attrCompSet.Next();
468     }
469 }
470 
operator =(const CegoAttrCond & ac)471 CegoAttrCond& CegoAttrCond::operator = ( const CegoAttrCond& ac)
472 {
473     _idxSchema = ac._idxSchema;
474     _attrCompSet = ac._attrCompSet;
475     return (*this);
476 }
477 
operator ==(const CegoAttrCond & ac) const478 bool CegoAttrCond::operator == ( const CegoAttrCond& ac) const
479 {
480     if ( ac._attrCompSet.Size() != _attrCompSet.Size() )
481 	return false;
482 
483     CegoAttrComp* pAC = ac._attrCompSet.First();
484     while ( pAC  )
485     {
486 	if ( findComp(pAC) == 0 )
487 	    return false;
488 	pAC = ac._attrCompSet.Next();
489     }
490 
491     pAC = _attrCompSet.First();
492     while ( pAC  )
493     {
494 	if ( ac.findComp(pAC) == 0 )
495 	    return false;
496 	pAC = _attrCompSet.Next();
497     }
498     return true;
499 }
500 
operator !=(const CegoAttrCond & ac) const501 bool CegoAttrCond::operator != ( const CegoAttrCond& ac) const
502 {
503     if ( *this == ac )
504 	return false;
505     return true;
506 }
507 
operator +(const CegoAttrCond & ac1,const CegoAttrCond & ac2)508 CegoAttrCond operator + ( const CegoAttrCond& ac1, const CegoAttrCond& ac2 )
509 {
510     CegoAttrCond ac;
511     CegoAttrComp *pComp;
512     pComp = ac1._attrCompSet.First();
513     while ( pComp )
514     {
515 	ac.add(*pComp);
516 	pComp = ac1._attrCompSet.Next();
517     }
518     pComp = ac2._attrCompSet.First();
519     while ( pComp )
520     {
521 	ac.add(*pComp);
522 	pComp = ac2._attrCompSet.Next();
523     }
524     return ac;
525 }
526 
toChain() const527 Chain CegoAttrCond::toChain() const
528 {
529     Chain s;
530 
531     CegoAttrComp *pAC = _attrCompSet.First();
532     while ( pAC )
533     {
534 	s += pAC->toChain();
535 	pAC = _attrCompSet.Next();
536 	if ( pAC )
537 	    s += Chain(" and ");
538     }
539     return s;
540 }
541 
operator <<(ostream & s,const CegoAttrCond & ac)542 ostream& operator << (ostream& s, const CegoAttrCond& ac)
543 {
544     s << ac.toChain();
545     return s;
546 }
547