1 //////////////////////////////////////////////////////////////////////////
2 //
3 // pgAdmin III - PostgreSQL Tools
4 //
5 // Copyright (C) 2002 - 2016, The pgAdmin Development Team
6 // This software is released under the PostgreSQL Licence
7 //
8 // gqbQueryObjs.cpp - All objects used by a model of a query in the MVC Pattern model.
9 //
10 //////////////////////////////////////////////////////////////////////////
11 
12 #include "pgAdmin3.h"
13 
14 // wxWindows headers
15 #include <wx/wx.h>
16 #include <wx/textctrl.h>
17 #include <wx/regex.h>
18 
19 // App headers
20 #include "gqb/gqbTable.h"
21 #include "gqb/gqbColumn.h"
22 #include "gqb/gqbQueryObjs.h"
23 #include "gqb/gqbObjectCollection.h"
24 #include "gqb/gqbViewPanels.h"
25 
26 //
27 // Collections of Tables inside a Query, data structured used for query storage & later generation of SQL sentence
28 //
29 
gqbQueryObjs()30 gqbQueryObjs::gqbQueryObjs()
31 	: gqbObjectCollection(wxT(""), NULL, NULL)
32 {
33 	setType(GQB_QUERY);
34 }
35 
36 
addTable(gqbQueryObject * mtable)37 void gqbQueryObjs::addTable(gqbQueryObject *mtable)
38 {
39 	this->addObject(mtable);
40 }
41 
42 
removeTable(gqbQueryObject * mtable)43 void gqbQueryObjs::removeTable(gqbQueryObject *mtable)
44 {
45 	this->removeObject(mtable);
46 }
47 
48 
createQueryIterator()49 gqbIteratorBase  *gqbQueryObjs::createQueryIterator()
50 {
51 	return this->createIterator();
52 }
53 
createDownQueryIterator()54 gqbIteratorBase  *gqbQueryObjs::createDownQueryIterator()
55 {
56 	return this->createDownIterator();
57 }
58 
59 
tablesCount()60 int gqbQueryObjs::tablesCount()
61 {
62 	return this->countObjects();
63 }
64 
65 
removeAllQueryObjs()66 void gqbQueryObjs::removeAllQueryObjs()
67 {
68 	this->removeAll();
69 }
70 
71 
72 //
73 // An Object inside a query (A table object in the query), not equal to gqbTable
74 // Reason: Sometimes a table can be used twice or more times in a query with different columns selected
75 //         Because this we can not use directly the base table object
76 
gqbQueryObject(gqbTable * table)77 gqbQueryObject::gqbQueryObject(gqbTable *table)
78 	: gqbObjectCollection(table->getName(), table, table->getConnection())
79 {
80 	selected = false;
81 	parent = table;
82 
83 	//GQB-TODO: Calculate a good initial position
84 	position.x = 20;
85 	position.y = 20;
86 	haveJoins = false;
87 	haveRegisteredJoins = false;
88 	registeredCollection = NULL;
89 	joinsCollection = NULL;
90 	setType(GQB_QUERYOBJ);
91 }
92 
93 
94 // Destructor must empty collection to don't allow deleting of column items from tree
95 // because this collection doesn't owns it, and then shouldn't destroy it.
~gqbQueryObject()96 gqbQueryObject::~gqbQueryObject()
97 {
98 	this->removeAll();
99 
100 	// Remove item registered at this Query Object
101 	gqbQueryJoin *tmp;
102 	if(registeredCollection)
103 	{
104 		gqbIteratorBase *r = createRegJoinsIterator();
105 		while(r->HasNext())
106 		{
107 			tmp = (gqbQueryJoin *)r->Next();
108 			this->unregisterJoin(tmp, true);      // remove and unregister every join in every query object
109 			// which have registered at this query object
110 
111 			// On each iteration the structure of iterator change because
112 			// modified his own collection & should be reset
113 			r->ResetIterator();
114 		}
115 		delete r;
116 	}
117 
118 	if(joinsCollection)
119 	{
120 		gqbIteratorBase *j = createJoinsIterator();
121 		while(j->HasNext())
122 		{
123 			tmp = (gqbQueryJoin *)j->Next();
124 			this->removeJoin(tmp, true);          // removes & unregister Join which have like origin this
125 			// query object
126 			// On each iteration the structure of iterator change because
127 			// modified his own collection & should be reset
128 			j->ResetIterator();
129 		}
130 		delete j;
131 
132 	}
133 
134 	// removeJoin & unregisterJoin delete the collections where there aren't any items inside.
135 }
136 
137 
setSelected(bool value)138 void gqbQueryObject::setSelected(bool value)
139 {
140 	this->selected = value;
141 }
142 
143 
getSelected()144 bool gqbQueryObject::getSelected()
145 {
146 	return this->selected;
147 }
148 
149 
setWidth(int value)150 void gqbQueryObject::setWidth(int value)
151 {
152 	width = value;
153 }
154 
155 
getWidth()156 int gqbQueryObject::getWidth()
157 {
158 	return width;
159 }
160 
161 
setHeight(int value)162 void gqbQueryObject::setHeight(int value)
163 {
164 	height = value;
165 }
166 
167 
getHeight()168 int gqbQueryObject::getHeight()
169 {
170 	return height;
171 }
172 
173 
addColumn(gqbColumn * column)174 void gqbQueryObject::addColumn(gqbColumn *column)
175 {
176 	this->addObject(column);
177 }
178 
179 
removeColumn(gqbColumn * column)180 void gqbQueryObject::removeColumn(gqbColumn *column)
181 {
182 	this->removeObject(column);
183 }
184 
185 
existsColumn(gqbColumn * column)186 bool gqbQueryObject::existsColumn(gqbColumn *column)
187 {
188 	return this->existsObject(column);
189 }
190 
191 
createQueryTableIterator()192 gqbIteratorBase *gqbQueryObject::createQueryTableIterator()
193 {
194 	return this->createIterator();
195 }
196 
197 
createJoinsIterator()198 gqbIteratorBase *gqbQueryObject::createJoinsIterator()
199 {
200 	return joinsCollection->createIterator();
201 }
202 
203 
createRegJoinsIterator()204 gqbIteratorBase *gqbQueryObject::createRegJoinsIterator()
205 {
206 	return registeredCollection->createIterator();
207 }
208 
209 
210 // Create a Join from this table [owner] column to other table [observable] column
addJoin(gqbQueryObject * owner,gqbQueryObject * observable,gqbColumn * source,gqbColumn * destination,type_Join kind)211 gqbQueryJoin *gqbQueryObject::addJoin(gqbQueryObject *owner, gqbQueryObject *observable, gqbColumn *source, gqbColumn *destination, type_Join kind)
212 {
213 	if(!haveJoins)
214 	{
215 		implementationj = new gqbArrayCollection();
216 		joinsCollection =  new gqbCollection(implementationj);
217 		haveJoins = true;
218 	}
219 
220 	gqbQueryJoin *join = new gqbQueryJoin(owner, observable, source, destination, kind);
221 	joinsCollection->addItem(join);
222 	observable->registerJoin(join);
223 	return join;
224 }
225 
226 
227 // Remove the join from this query object [source table]
removeJoin(gqbQueryJoin * join,bool unRegister=false)228 void gqbQueryObject::removeJoin(gqbQueryJoin *join, bool unRegister = false)
229 {
230 	// Notify to observable that the join this object owns will be removed & then remove the join
231 	if(unRegister)
232 		join->getDestQTable()->unregisterJoin(join, false);
233 	joinsCollection->removeItem(join);
234 	if(join)
235 		delete join;                              // Join can be only delete Here by his owner
236 
237 	if(joinsCollection->count() <= 0)
238 	{
239 		delete joinsCollection;                   // implementation it's delete too inside collection.
240 		haveJoins = false;
241 		joinsCollection = NULL;
242 	}
243 }
244 
245 
246 // Register a Join created from other table [source] to this table [destination]
registerJoin(gqbQueryJoin * join)247 void gqbQueryObject::registerJoin(gqbQueryJoin *join)
248 {
249 	if(!haveRegisteredJoins)
250 	{
251 		implementationr = new gqbArrayCollection();
252 		registeredCollection =  new gqbCollection(implementationr);
253 		haveRegisteredJoins = true;
254 	}
255 	registeredCollection->addItem(join);
256 }
257 
258 
259 // Unregister a Join create from other table [source] to this table [destination] delete the join if need it..
unregisterJoin(gqbQueryJoin * join,bool removeIt=false)260 void gqbQueryObject::unregisterJoin(gqbQueryJoin *join, bool removeIt = false)
261 {
262 	// Notify to source/owner object of join about join removing & then remove
263 	registeredCollection->removeItem(join);
264 	if(removeIt)
265 		join->getSourceQTable()->removeJoin(join, false);
266 	if(registeredCollection->count() <= 0)
267 	{
268 		delete registeredCollection;              //implementation it's delete too inside collection.
269 		haveRegisteredJoins = false;
270 		registeredCollection = NULL;
271 	}
272 }
273 
274 
getColumnIndex(gqbColumn * column)275 int gqbQueryObject::getColumnIndex(gqbColumn *column)
276 {
277 	return parent->indexColumn(column);
278 }
279 
280 
getHaveJoins()281 bool gqbQueryObject::getHaveJoins()
282 {
283 	return haveJoins;
284 }
285 
286 
getHaveRegJoins()287 bool gqbQueryObject::getHaveRegJoins()
288 {
289 	return haveRegisteredJoins;
290 }
291 
292 // GQB-TODO if last join it's delete I MUST delete implementation & collection & put haveJoins in false;
293 // Same for registered joins
294 
295 //
296 //  A Join inside a query Object like Table or view [Stored at source, registered at destination]
297 //  I need to store the owner, destination because columns it's share between multiple joins
gqbQueryJoin(gqbQueryObject * _owner,gqbQueryObject * _destination,gqbColumn * sourceCol,gqbColumn * destCol,type_Join joinKind)298 gqbQueryJoin::gqbQueryJoin(gqbQueryObject *_owner, gqbQueryObject *_destination, gqbColumn *sourceCol, gqbColumn *destCol, type_Join joinKind)
299 	: gqbObject(wxT(""), _owner, NULL)
300 {
301 	kindofJoin = joinKind;
302 	sCol = sourceCol;
303 	dCol = destCol;
304 	owner = _owner;
305 	selected = false;
306 	destination = _destination;
307 	setType(GQB_JOIN);
308 }
309 
310 
setKindofJoin(type_Join kind)311 void gqbQueryJoin::setKindofJoin(type_Join kind)
312 {
313 	kindofJoin = kind;
314 }
315 
316 
getKindofJoin()317 type_Join gqbQueryJoin::getKindofJoin()
318 {
319 	return kindofJoin;
320 }
321 
322 
323 // Return the object where the join is stored
getSourceQTable()324 gqbQueryObject *gqbQueryJoin::getSourceQTable()
325 {
326 	return owner;
327 }
328 
329 
330 // Return the object where the join point to.
getDestQTable()331 gqbQueryObject *gqbQueryJoin::getDestQTable()
332 {
333 	return destination;
334 }
335 
336 
337 // Return the gqbObject of Destination Column
getDCol()338 gqbColumn *gqbQueryJoin::getDCol()
339 {
340 	return dCol;
341 }
342 
343 
344 // Return the gqbObject of Source Column
getSCol()345 gqbColumn *gqbQueryJoin::getSCol()
346 {
347 	return sCol;
348 }
349 
350 
getSourceTable()351 wxString gqbQueryJoin::getSourceTable()
352 {
353 	if (!owner)
354 		return wxEmptyString;
355 
356 	gqbTable *s = (gqbTable *)sCol->getOwner();
357 	return s->getName();
358 }
359 
360 
getDestTable()361 wxString gqbQueryJoin::getDestTable()
362 {
363 	if (!destination)
364 		return wxEmptyString;
365 
366 	gqbTable *d = (gqbTable *)dCol->getOwner();
367 	return d->getName();
368 }
369 
370 
getSourceCol()371 wxString gqbQueryJoin::getSourceCol()
372 {
373 	if (!sCol)
374 		return wxEmptyString;
375 
376 	return sCol->getName();
377 }
378 
379 
getDestCol()380 wxString gqbQueryJoin::getDestCol()
381 {
382 	if (!dCol)
383 		return wxEmptyString;
384 
385 	return dCol->getName();
386 }
387 
388 
setSourceAnchor(wxPoint pt)389 void gqbQueryJoin::setSourceAnchor(wxPoint pt)
390 {
391 	sAnchor = pt;
392 }
393 
394 
setDestAnchor(wxPoint pt)395 void gqbQueryJoin::setDestAnchor(wxPoint pt)
396 {
397 	dAnchor = pt;
398 }
399 
400 
getSourceAnchor()401 wxPoint &gqbQueryJoin::getSourceAnchor()
402 {
403 	return sAnchor;
404 }
405 
406 
getDestAnchor()407 wxPoint &gqbQueryJoin::getDestAnchor()
408 {
409 	return dAnchor;
410 }
411 
412 
setSelected(bool value)413 void gqbQueryJoin::setSelected(bool value)
414 {
415 	this->selected = value;
416 }
417 
418 
getSelected()419 bool gqbQueryJoin::getSelected()
420 {
421 	return this->selected;
422 }
423 
424 
setAnchorsUsed(wxPoint pt)425 void gqbQueryJoin::setAnchorsUsed(wxPoint pt)
426 {
427 	anchorsUsed = pt;
428 }
429 
430 
getAnchorsUsed()431 wxPoint &gqbQueryJoin::getAnchorsUsed()
432 {
433 	return anchorsUsed;
434 }
435 
436 
437 //
438 // A query restriction
439 //
440 
441 enum
442 {
443 	QRButton = 9000,
444 	QRValue,
445 	QRConnector,
446 	QRtype
447 };
448 
gqbQueryRestriction()449 gqbQueryRestriction::gqbQueryRestriction()
450 	: gqbObject(wxT(""), NULL, NULL)
451 {
452 	leftPart = wxT("");
453 	value_s = wxT("");
454 	connector = wxT("AND");
455 	restriction = wxT("=");
456 	setType(GQB_RESTRICTION);
457 }
458 
459 
gqbRestrictions()460 gqbRestrictions::gqbRestrictions()
461 	: gqbObjectCollection(wxT(""), NULL, NULL)
462 {
463 	setType(GQB_RESTRICTION);
464 }
465 
466 
~gqbRestrictions()467 gqbRestrictions::~gqbRestrictions()
468 {
469 	this->removeAll();
470 }
471 
472 
addRestriction(gqbQueryRestriction * r)473 void gqbRestrictions::addRestriction(gqbQueryRestriction *r)
474 {
475 	this->addObject(r);
476 }
477 
478 
addRestrictionAt(gqbQueryRestriction * r,int index)479 void gqbRestrictions::addRestrictionAt(gqbQueryRestriction *r, int index)
480 {
481 	this->insertObjectAt(r, index);
482 }
483 
484 
485 // Remove but don't delete restriction
removeRestriction(gqbQueryRestriction * r)486 void gqbRestrictions::removeRestriction(gqbQueryRestriction *r)
487 {
488 	this->removeObject(r);
489 }
490 
491 
deleteAllRestrictions()492 void gqbRestrictions::deleteAllRestrictions()
493 {
494 	this->deleteAll();
495 }
496 
497 
createRestrictionsIterator()498 gqbIteratorBase *gqbRestrictions::createRestrictionsIterator()
499 {
500 	return this->createIterator();
501 }
502 
503 
restrictionsCount()504 int gqbRestrictions::restrictionsCount()
505 {
506 	return this->getCount();
507 }
508 
509 
getRestrictionAt(int index)510 gqbQueryRestriction *gqbRestrictions::getRestrictionAt(int index)
511 {
512 	return (gqbQueryRestriction *)this->getObjectAtIndex(index);
513 }
514