1 /*
2 # PostgreSQL Database Modeler (pgModeler)
3 #
4 # Copyright 2006-2020 - Raphael Araújo e Silva <raphael@pgmodeler.io>
5 #
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation version 3.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # The complete text of GPLv3 is at LICENSE file on source code root directory.
16 # Also, you can get the complete GNU General Public License at <http://www.gnu.org/licenses/>
17 */
18 
19 #include "databasemodel.h"
20 #include "pgmodelerns.h"
21 #include "defaultlanguages.h"
22 #include "operation.h"
23 #include <QtDebug>
24 #include "qtcompat/splitbehaviorcompat.h"
25 #include "qtcompat/qtextstreamcompat.h"
26 
27 unsigned DatabaseModel::dbmodel_id=2000;
28 
DatabaseModel()29 DatabaseModel::DatabaseModel()
30 {
31 	this->model_wgt=nullptr;
32 	object_id=DatabaseModel::dbmodel_id++;
33 	obj_type=ObjectType::Database;
34 
35 	persist_changelog = false;
36 	is_template = false;
37 	allow_conns = true;
38 
39 	encoding=BaseType::Null;
40 	BaseObject::setName(QObject::tr("new_database"));
41 
42 	default_objs[ObjectType::Schema]=nullptr;
43 	default_objs[ObjectType::Role]=nullptr;
44 	default_objs[ObjectType::Tablespace]=nullptr;
45 	default_objs[ObjectType::Collation]=nullptr;
46 
47 	conn_limit=-1;
48 	last_zoom=1;
49 	loading_model=invalidated=append_at_eod=prepend_at_bod=false;
50 	attributes[Attributes::Encoding]="";
51 	attributes[Attributes::TemplateDb]="";
52 	attributes[Attributes::ConnLimit]="";
53 	attributes[Attributes::LcCollate]="";
54 	attributes[Attributes::LcCtype]="";
55 	attributes[Attributes::AppendAtEod]="";
56 	attributes[Attributes::PrependAtBod]="";
57 	attributes[Attributes::AllowConns]="";
58 	attributes[Attributes::IsTemplate]="";
59 	attributes[Attributes::UseChangelog]="";
60 	attributes[Attributes::Changelog]="";
61 
62 	obj_lists = {
63 		{ ObjectType::Textbox, &textboxes },
64 		{ ObjectType::Table, &tables },
65 		{ ObjectType::Function, &functions },
66 		{ ObjectType::Aggregate, &aggregates },
67 		{ ObjectType::Schema, &schemas },
68 		{ ObjectType::View, &views },
69 		{ ObjectType::Type, &types },
70 		{ ObjectType::Role, &roles },
71 		{ ObjectType::Tablespace, &tablespaces },
72 		{ ObjectType::Language, &languages },
73 		{ ObjectType::Cast, &casts },
74 		{ ObjectType::Conversion, &conversions },
75 		{ ObjectType::Operator, &operators },
76 		{ ObjectType::OpClass, &op_classes },
77 		{ ObjectType::OpFamily, &op_families },
78 		{ ObjectType::Domain, &domains },
79 		{ ObjectType::Sequence, &sequences },
80 		{ ObjectType::BaseRelationship, &base_relationships },
81 		{ ObjectType::Relationship, &relationships },
82 		{ ObjectType::Permission, &permissions },
83 		{ ObjectType::Collation, &collations },
84 		{ ObjectType::Extension, &extensions },
85 		{ ObjectType::Tag, &tags },
86 		{ ObjectType::EventTrigger, &eventtriggers },
87 		{ ObjectType::GenericSql, &genericsqls },
88 		{ ObjectType::ForeignDataWrapper, &fdata_wrappers },
89 		{ ObjectType::ForeignServer, &foreign_servers },
90 		{ ObjectType::UserMapping, &usermappings },
91 		{ ObjectType::ForeignTable, &foreign_tables }
92 	};
93 }
94 
DatabaseModel(ModelWidget * model_wgt)95 DatabaseModel::DatabaseModel(ModelWidget *model_wgt):DatabaseModel()
96 {
97 	this->model_wgt=model_wgt;
98 }
99 
~DatabaseModel()100 DatabaseModel::~DatabaseModel()
101 {
102 	this->blockSignals(true);
103 	destroyObjects();
104 }
105 
getModelWidget()106 ModelWidget *DatabaseModel::getModelWidget()
107 {
108 	return model_wgt;
109 }
110 
setEncoding(EncodingType encod)111 void DatabaseModel::setEncoding(EncodingType encod)
112 {
113 	encoding=encod;
114 }
115 
setLocalization(unsigned localiz_id,const QString & value)116 void DatabaseModel::setLocalization(unsigned localiz_id, const QString &value)
117 {
118 	if(localiz_id > Collation::LcCollate)
119 		throw Exception(ErrorCode::RefElementInvalidIndex,__PRETTY_FUNCTION__,__FILE__,__LINE__);
120 
121 	localizations[localiz_id]=value;
122 }
123 
setConnectionLimit(int conn_lim)124 void DatabaseModel::setConnectionLimit(int conn_lim)
125 {
126 	if(conn_lim < -1) conn_lim=-1;
127 	this->conn_limit=conn_lim;
128 }
129 
setTemplateDB(const QString & temp_db)130 void DatabaseModel::setTemplateDB(const QString &temp_db)
131 {
132 	if(!temp_db.isEmpty() && !BaseObject::isValidName(temp_db))
133 		throw Exception(ErrorCode::AsgInvalidNameObject,__PRETTY_FUNCTION__,__FILE__,__LINE__);
134 
135 	this->template_db=temp_db;
136 }
137 
setAuthor(const QString & author)138 void DatabaseModel::setAuthor(const QString &author)
139 {
140 	this->author=author;
141 }
142 
getObjectList(ObjectType obj_type)143 vector<BaseObject *> *DatabaseModel::getObjectList(ObjectType obj_type)
144 {
145 	if(obj_lists.count(obj_type) == 0)
146 		return nullptr;
147 
148 	return obj_lists[obj_type];
149 }
150 
addObject(BaseObject * object,int obj_idx)151 void DatabaseModel::addObject(BaseObject *object, int obj_idx)
152 {
153 	ObjectType obj_type;
154 
155 	if(!object)
156 		return;
157 
158 	try
159 	{
160 		obj_type=object->getObjectType();
161 
162 		if(obj_type==ObjectType::Relationship || obj_type==ObjectType::BaseRelationship)
163 			addRelationship(dynamic_cast<BaseRelationship *>(object), obj_idx);
164 		else if(obj_type==ObjectType::Textbox)
165 			addTextbox(dynamic_cast<Textbox *>(object), obj_idx);
166 		else if(obj_type==ObjectType::Table)
167 			addTable(dynamic_cast<Table *>(object), obj_idx);
168 		else if(obj_type==ObjectType::Function)
169 			addFunction(dynamic_cast<Function *>(object), obj_idx);
170 		else if(obj_type==ObjectType::Aggregate)
171 			addAggregate(dynamic_cast<Aggregate *>(object), obj_idx);
172 		else if(obj_type==ObjectType::Schema)
173 			addSchema(dynamic_cast<Schema *>(object), obj_idx);
174 		else if(obj_type==ObjectType::View)
175 			addView(dynamic_cast<View *>(object), obj_idx);
176 		else if(obj_type==ObjectType::Type)
177 			addType(dynamic_cast<Type *>(object), obj_idx);
178 		else if(obj_type==ObjectType::Role)
179 			addRole(dynamic_cast<Role *>(object), obj_idx);
180 		else if(obj_type==ObjectType::Tablespace)
181 			addTablespace(dynamic_cast<Tablespace *>(object), obj_idx);
182 		else if(obj_type==ObjectType::Language)
183 			addLanguage(dynamic_cast<Language *>(object), obj_idx);
184 		else if(obj_type==ObjectType::Cast)
185 			addCast(dynamic_cast<Cast *>(object), obj_idx);
186 		else if(obj_type==ObjectType::Conversion)
187 			addConversion(dynamic_cast<Conversion *>(object), obj_idx);
188 		else if(obj_type==ObjectType::Operator)
189 			addOperator(dynamic_cast<Operator *>(object), obj_idx);
190 		else if(obj_type==ObjectType::OpClass)
191 			addOperatorClass(dynamic_cast<OperatorClass *>(object), obj_idx);
192 		else if(obj_type==ObjectType::OpFamily)
193 			addOperatorFamily(dynamic_cast<OperatorFamily *>(object), obj_idx);
194 		else if(obj_type==ObjectType::Domain)
195 			addDomain(dynamic_cast<Domain *>(object), obj_idx);
196 		else if(obj_type==ObjectType::Sequence)
197 			addSequence(dynamic_cast<Sequence *>(object), obj_idx);
198 		else if(obj_type==ObjectType::Collation)
199 			addCollation(dynamic_cast<Collation *>(object), obj_idx);
200 		else if(obj_type==ObjectType::Extension)
201 			addExtension(dynamic_cast<Extension *>(object), obj_idx);
202 		else if(obj_type==ObjectType::Tag)
203 			addTag(dynamic_cast<Tag *>(object), obj_idx);
204 		else if(obj_type==ObjectType::Permission)
205 			addPermission(dynamic_cast<Permission *>(object));
206 		else if(obj_type==ObjectType::EventTrigger)
207 			addEventTrigger(dynamic_cast<EventTrigger *>(object));
208 		else if(obj_type==ObjectType::GenericSql)
209 			addGenericSQL(dynamic_cast<GenericSQL *>(object));
210 		else if(obj_type==ObjectType::ForeignDataWrapper)
211 			addForeignDataWrapper(dynamic_cast<ForeignDataWrapper *>(object));
212 		else if(obj_type==ObjectType::ForeignServer)
213 			addForeignServer(dynamic_cast<ForeignServer *>(object));
214 		else if(obj_type==ObjectType::UserMapping)
215 			addUserMapping(dynamic_cast<UserMapping *>(object));
216 		else if(obj_type==ObjectType::ForeignTable)
217 			addForeignTable(dynamic_cast<ForeignTable *>(object));
218 	}
219 	catch(Exception &e)
220 	{
221 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
222 	}
223 }
224 
removeObject(BaseObject * object,int obj_idx)225 void DatabaseModel::removeObject(BaseObject *object, int obj_idx)
226 {
227 	ObjectType obj_type;
228 
229 	if(!object)
230 		return;
231 
232 	try
233 	{
234 		obj_type=object->getObjectType();
235 
236 		if(obj_type==ObjectType::Relationship || obj_type==ObjectType::BaseRelationship)
237 			removeRelationship(dynamic_cast<BaseRelationship *>(object), obj_idx);
238 		else if(obj_type==ObjectType::Textbox)
239 			removeTextbox(dynamic_cast<Textbox *>(object), obj_idx);
240 		else if(obj_type==ObjectType::Table)
241 			removeTable(dynamic_cast<Table *>(object), obj_idx);
242 		else if(obj_type==ObjectType::Function)
243 			removeFunction(dynamic_cast<Function *>(object), obj_idx);
244 		else if(obj_type==ObjectType::Aggregate)
245 			removeAggregate(dynamic_cast<Aggregate *>(object), obj_idx);
246 		else if(obj_type==ObjectType::Schema)
247 			removeSchema(dynamic_cast<Schema *>(object), obj_idx);
248 		else if(obj_type==ObjectType::View)
249 			removeView(dynamic_cast<View *>(object), obj_idx);
250 		else if(obj_type==ObjectType::Type)
251 			removeType(dynamic_cast<Type *>(object), obj_idx);
252 		else if(obj_type==ObjectType::Role)
253 			removeRole(dynamic_cast<Role *>(object), obj_idx);
254 		else if(obj_type==ObjectType::Tablespace)
255 			removeTablespace(dynamic_cast<Tablespace *>(object), obj_idx);
256 		else if(obj_type==ObjectType::Language)
257 			removeLanguage(dynamic_cast<Language *>(object), obj_idx);
258 		else if(obj_type==ObjectType::Cast)
259 			removeCast(dynamic_cast<Cast *>(object), obj_idx);
260 		else if(obj_type==ObjectType::Conversion)
261 			removeConversion(dynamic_cast<Conversion *>(object), obj_idx);
262 		else if(obj_type==ObjectType::Operator)
263 			removeOperator(dynamic_cast<Operator *>(object), obj_idx);
264 		else if(obj_type==ObjectType::OpClass)
265 			removeOperatorClass(dynamic_cast<OperatorClass *>(object), obj_idx);
266 		else if(obj_type==ObjectType::OpFamily)
267 			removeOperatorFamily(dynamic_cast<OperatorFamily *>(object), obj_idx);
268 		else if(obj_type==ObjectType::Domain)
269 			removeDomain(dynamic_cast<Domain *>(object), obj_idx);
270 		else if(obj_type==ObjectType::Sequence)
271 			removeSequence(dynamic_cast<Sequence *>(object), obj_idx);
272 		else if(obj_type==ObjectType::Collation)
273 			removeCollation(dynamic_cast<Collation *>(object), obj_idx);
274 		else if(obj_type==ObjectType::Extension)
275 			removeExtension(dynamic_cast<Extension *>(object), obj_idx);
276 		else if(obj_type==ObjectType::Tag)
277 			removeTag(dynamic_cast<Tag *>(object), obj_idx);
278 		else if(obj_type==ObjectType::Permission)
279 			removePermission(dynamic_cast<Permission *>(object));
280 		else if(obj_type==ObjectType::EventTrigger)
281 			removeEventTrigger(dynamic_cast<EventTrigger *>(object));
282 		else if(obj_type==ObjectType::GenericSql)
283 			removeGenericSQL(dynamic_cast<GenericSQL *>(object));
284 		else if(obj_type==ObjectType::ForeignDataWrapper)
285 			removeForeignDataWrapper(dynamic_cast<ForeignDataWrapper *>(object));
286 		else if(obj_type==ObjectType::ForeignServer)
287 			removeForeignServer(dynamic_cast<ForeignServer *>(object));
288 		else if(obj_type==ObjectType::UserMapping)
289 			removeUserMapping(dynamic_cast<UserMapping *>(object));
290 		else if(obj_type==ObjectType::ForeignTable)
291 			removeForeignTable(dynamic_cast<ForeignTable *>(object));
292 	}
293 	catch(Exception &e)
294 	{
295 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
296 	}
297 
298 }
299 
removeObject(unsigned obj_idx,ObjectType obj_type)300 void DatabaseModel::removeObject(unsigned obj_idx, ObjectType obj_type)
301 {
302 	if(TableObject::isTableObject(obj_type) ||
303 			obj_type==ObjectType::BaseObject || obj_type==ObjectType::BaseRelationship ||
304 			obj_type==ObjectType::Database)
305 		throw Exception(ErrorCode::RemObjectInvalidType,__PRETTY_FUNCTION__,__FILE__,__LINE__);
306 
307 	vector<BaseObject *> *obj_list=nullptr;
308 	BaseObject *object=nullptr;
309 
310 	obj_list=getObjectList(obj_type);
311 	if(obj_idx >= obj_list->size())
312 		throw Exception(ErrorCode::RefObjectInvalidIndex,__PRETTY_FUNCTION__,__FILE__,__LINE__);
313 
314 	object=(*obj_list)[obj_idx];
315 	if(obj_type==ObjectType::Textbox)
316 		removeTextbox(dynamic_cast<Textbox *>(object), obj_idx);
317 	else if(obj_type==ObjectType::Table)
318 		removeTable(dynamic_cast<Table *>(object), obj_idx);
319 	else if(obj_type==ObjectType::Function)
320 		removeFunction(dynamic_cast<Function *>(object), obj_idx);
321 	else if(obj_type==ObjectType::Aggregate)
322 		removeAggregate(dynamic_cast<Aggregate *>(object), obj_idx);
323 	else if(obj_type==ObjectType::Schema)
324 		removeSchema(dynamic_cast<Schema *>(object), obj_idx);
325 	else if(obj_type==ObjectType::View)
326 		removeView(dynamic_cast<View *>(object), obj_idx);
327 	else if(obj_type==ObjectType::Type)
328 		removeType(dynamic_cast<Type *>(object), obj_idx);
329 	else if(obj_type==ObjectType::Role)
330 		removeRole(dynamic_cast<Role *>(object), obj_idx);
331 	else if(obj_type==ObjectType::Tablespace)
332 		removeTablespace(dynamic_cast<Tablespace *>(object), obj_idx);
333 	else if(obj_type==ObjectType::Language)
334 		removeLanguage(dynamic_cast<Language *>(object), obj_idx);
335 	else if(obj_type==ObjectType::Cast)
336 		removeCast(dynamic_cast<Cast *>(object), obj_idx);
337 	else if(obj_type==ObjectType::Conversion)
338 		removeConversion(dynamic_cast<Conversion *>(object), obj_idx);
339 	else if(obj_type==ObjectType::Operator)
340 		removeOperator(dynamic_cast<Operator *>(object), obj_idx);
341 	else if(obj_type==ObjectType::OpClass)
342 		removeOperatorClass(dynamic_cast<OperatorClass *>(object), obj_idx);
343 	else if(obj_type==ObjectType::OpFamily)
344 		removeOperatorFamily(dynamic_cast<OperatorFamily *>(object), obj_idx);
345 	else if(obj_type==ObjectType::Domain)
346 		removeDomain(dynamic_cast<Domain *>(object), obj_idx);
347 	else if(obj_type==ObjectType::Sequence)
348 		removeSequence(dynamic_cast<Sequence *>(object), obj_idx);
349 	else if(obj_type==ObjectType::Collation)
350 		removeCollation(dynamic_cast<Collation *>(object), obj_idx);
351 	else if(obj_type==ObjectType::Relationship || obj_type==ObjectType::BaseRelationship)
352 		removeRelationship(dynamic_cast<BaseRelationship *>(object), obj_idx);
353 	else if(obj_type==ObjectType::Permission)
354 		removePermission(dynamic_cast<Permission *>(object));
355 	else if(obj_type==ObjectType::EventTrigger)
356 		removeEventTrigger(dynamic_cast<EventTrigger *>(object), obj_idx);
357 	else if(obj_type==ObjectType::GenericSql)
358 		removeGenericSQL(dynamic_cast<GenericSQL *>(object), obj_idx);
359 	else if(obj_type==ObjectType::ForeignDataWrapper)
360 		removeForeignDataWrapper(dynamic_cast<ForeignDataWrapper *>(object), obj_idx);
361 	else if(obj_type==ObjectType::UserMapping)
362 		removeUserMapping(dynamic_cast<UserMapping *>(object), obj_idx);
363 	else if(obj_type==ObjectType::ForeignTable)
364 		removeForeignTable(dynamic_cast<ForeignTable *>(object), obj_idx);
365 }
366 
__addObject(BaseObject * object,int obj_idx)367 void DatabaseModel::__addObject(BaseObject *object, int obj_idx)
368 {
369 	int idx;
370 	ObjectType obj_type;
371 	vector<BaseObject *> *obj_list=nullptr;
372 	vector<BaseObject *>::iterator itr, itr_end;
373 
374 	if(!object)
375 		throw Exception(ErrorCode::AsgNotAllocattedObject,__PRETTY_FUNCTION__,__FILE__,__LINE__);
376 
377 	obj_type=object->getObjectType();
378 
379 #ifdef DEMO_VERSION
380 #warning "DEMO VERSION: database model object creation limit."
381 	obj_list=getObjectList(obj_type);
382 	if(obj_list && obj_list->size() >= GlobalAttributes::MaxObjectCount)
383 		throw Exception(tr("The demonstration version can create only `%1' instances of each object type! You've reach this limit for the type: `%2'")
384 						.arg(GlobalAttributes::MaxObjectCount)
385 						.arg(BaseObject::getTypeName(obj_type)),
386 						ErrorCode::Custom,__PRETTY_FUNCTION__,__FILE__,__LINE__);
387 
388 #endif
389 
390 	if(obj_type==ObjectType::Tablespace)
391 	{
392 		Tablespace *tabspc=nullptr, *aux_tabspc=nullptr;
393 
394 		obj_list=getObjectList(obj_type);
395 		itr=obj_list->begin();
396 		itr_end=obj_list->end();
397 		tabspc=dynamic_cast<Tablespace *>(object);
398 
399 		while(itr!=itr_end)
400 		{
401 			aux_tabspc=dynamic_cast<Tablespace *>(*itr);
402 
403 			/* Raises an error if the object to be added is a tablespace and
404 			there is some other tablespace pointing to the same directory */
405 			if(tabspc->getDirectory()==aux_tabspc->getDirectory())
406 			{
407 				throw Exception(Exception::getErrorMessage(ErrorCode::AsgTablespaceDuplicatedDirectory)
408 								.arg(tabspc->getName())
409 								.arg(aux_tabspc->getName()),
410 								ErrorCode::AsgTablespaceDuplicatedDirectory,__PRETTY_FUNCTION__,__FILE__,__LINE__);
411 			}
412 
413 			itr++;
414 		}
415 	}
416 
417 	/* Raises an error if there is an object with the same name.
418 		 Special cases are for: functions/operator that are search by signature and views
419 		 that are search on tables and views list */
420 	if(((obj_type==ObjectType::View ||
421 			 obj_type==ObjectType::Table ||
422 			 obj_type==ObjectType::ForeignTable) &&
423 			(getObject(object->getName(true), ObjectType::View, idx) ||
424 			 getObject(object->getName(true), ObjectType::Table, idx) ||
425 			 getObject(object->getName(true), ObjectType::ForeignTable, idx))) ||
426 			(obj_type==ObjectType::Extension &&	(getObject(object->getName(false), obj_type, idx))) ||
427 			(getObject(object->getSignature(), obj_type, idx)))
428 	{
429 		QString str_aux;
430 
431 		str_aux=Exception::getErrorMessage(ErrorCode::AsgDuplicatedObject)
432 				.arg(object->getName(obj_type != ObjectType::Extension))
433 				.arg(object->getTypeName())
434 				.arg(this->getName(true))
435 				.arg(this->getTypeName());
436 
437 		throw Exception(str_aux,ErrorCode::AsgDuplicatedObject,__PRETTY_FUNCTION__,__FILE__,__LINE__);
438 	}
439 
440 	try
441 	{
442 		if(obj_type==ObjectType::Textbox || obj_type==ObjectType::BaseRelationship)
443 			object->getCodeDefinition(SchemaParser::XmlDefinition);
444 		else
445 			object->getCodeDefinition(SchemaParser::SqlDefinition);
446 	}
447 	catch(Exception &e)
448 	{
449 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
450 	}
451 
452 	obj_list=getObjectList(object->getObjectType());
453 
454 	if(obj_idx < 0 || obj_idx >= static_cast<int>(obj_list->size()))
455 		obj_list->push_back(object);
456 	else
457 	{
458 		if(obj_idx >=0 && idx < 0)
459 			idx=obj_idx;
460 		else if(obj_idx < 0 && idx < 0)
461 			idx=0;
462 
463 		if(obj_list->size() > 0)
464 			obj_list->insert((obj_list->begin() + idx), object);
465 		else
466 			obj_list->push_back(object);
467 	}
468 
469 	object->setDatabase(this);
470 	emit s_objectAdded(object);
471 	this->setInvalidated(true);
472 }
473 
__removeObject(BaseObject * object,int obj_idx,bool check_refs)474 void DatabaseModel::__removeObject(BaseObject *object, int obj_idx, bool check_refs)
475 {
476 	if(!object)
477 		throw Exception(ErrorCode::RemNotAllocatedObject,__PRETTY_FUNCTION__,__FILE__,__LINE__);
478 	else
479 	{
480 		vector<BaseObject *> *obj_list=nullptr;
481 		ObjectType obj_type;
482 
483 		obj_type=object->getObjectType();
484 		obj_list=getObjectList(obj_type);
485 
486 		if(!obj_list)
487 			throw Exception(ErrorCode::ObtObjectInvalidType,__PRETTY_FUNCTION__,__FILE__,__LINE__);
488 		else
489 		{
490 			vector<BaseObject *> refs;
491 
492 			//Get the table references
493 			if(check_refs)
494 				getObjectReferences(object, refs, true, true);
495 
496 			//If there are objects referencing the table
497 			if(!refs.empty())
498 			{
499 				ErrorCode err_code;
500 
501 				//Raises an error indicating the object that is referencing the table
502 				if(!dynamic_cast<TableObject *>(refs[0]))
503 				{
504 					err_code=ErrorCode::RemDirectReference;
505 					throw Exception(Exception::getErrorMessage(err_code)
506 									.arg(object->getName(true))
507 									.arg(object->getTypeName())
508 									.arg(refs[0]->getName(true))
509 							.arg(refs[0]->getTypeName()),
510 							err_code,__PRETTY_FUNCTION__,__FILE__,__LINE__);
511 				}
512 				else
513 				{
514 					BaseObject *ref_obj_parent=dynamic_cast<TableObject *>(refs[0])->getParentTable();
515 
516 					err_code=ErrorCode::RemInderectReference;
517 					throw Exception(Exception::getErrorMessage(err_code)
518 									.arg(object->getName(true))
519 									.arg(object->getTypeName())
520 									.arg(refs[0]->getName(true))
521 							.arg(refs[0]->getTypeName())
522 							.arg(ref_obj_parent->getName(true))
523 							.arg(ref_obj_parent->getTypeName()),
524 							err_code,__PRETTY_FUNCTION__,__FILE__,__LINE__);
525 				}
526 			}
527 
528 			if(obj_idx < 0 || obj_idx >= static_cast<int>(obj_list->size()))
529 				getObject(object->getSignature(), obj_type, obj_idx);
530 
531 			if(obj_idx >= 0)
532 			{
533 				if(Permission::acceptsPermission(obj_type))
534 					removePermissions(object);
535 
536 				obj_list->erase(obj_list->begin() + obj_idx);
537 			}
538 		}
539 
540 		object->setDatabase(nullptr);
541 		emit s_objectRemoved(object);
542 	}
543 }
544 
getObjects(ObjectType obj_type,BaseObject * schema)545 vector<BaseObject *> DatabaseModel::getObjects(ObjectType obj_type, BaseObject *schema)
546 {
547 	vector<BaseObject *> *obj_list=nullptr, sel_list;
548 	vector<BaseObject *>::iterator itr, itr_end;
549 	BaseRelationship *rel=nullptr;
550 
551 	obj_list=getObjectList(obj_type);
552 
553 	if(!obj_list)
554 		throw Exception(ErrorCode::ObtObjectInvalidType,__PRETTY_FUNCTION__,__FILE__,__LINE__);
555 
556 	itr=obj_list->begin();
557 	itr_end=obj_list->end();
558 
559 	while(itr!=itr_end)
560 	{
561 		rel=dynamic_cast<BaseRelationship *>(*itr);
562 
563 		if((!rel && (*itr)->getSchema()==schema) ||
564 				(rel && (rel->getTable(BaseRelationship::SrcTable)->getSchema()==schema ||
565 						 rel->getTable(BaseRelationship::DstTable)->getSchema()==schema)))
566 			sel_list.push_back(*itr);
567 
568 		itr++;
569 	}
570 
571 	return sel_list;
572 }
573 
getObjects(BaseObject * schema)574 vector<BaseObject *> DatabaseModel::getObjects(BaseObject *schema)
575 {
576 	vector<BaseObject *> *obj_list=nullptr, sel_list;
577 	vector<ObjectType> types = BaseObject::getChildObjectTypes(ObjectType::Schema);
578 
579 	for(auto &type : types)
580 	{
581 		obj_list = getObjectList(type);
582 
583 		for(auto &obj : *obj_list)
584 		{
585 			if(obj->getSchema() == schema)
586 				sel_list.push_back(obj);
587 		}
588 	}
589 
590 	return sel_list;
591 }
592 
getObject(const QString & name,ObjectType obj_type,int & obj_idx)593 BaseObject *DatabaseModel::getObject(const QString &name, ObjectType obj_type, int &obj_idx)
594 {
595 	BaseObject *object=nullptr;
596 	vector<BaseObject *> *obj_list=nullptr;
597 	vector<BaseObject *>::iterator itr, itr_end;
598 	bool found=false;
599 	QString aux_name1;
600 
601 	obj_list=getObjectList(obj_type);
602 
603 	if(!obj_list)
604 		throw Exception(ErrorCode::ObtObjectInvalidType,__PRETTY_FUNCTION__,__FILE__,__LINE__);
605 	else
606 	{
607 		QString signature;
608 
609 		itr=obj_list->begin();
610 		itr_end=obj_list->end();
611 		obj_idx=-1;
612 		aux_name1=QString(name).remove('"');
613 
614 		while(itr!=itr_end && !found)
615 		{
616 			signature=(*itr)->getSignature().remove("\"");
617 			found=(signature==aux_name1);
618 			if(!found) itr++;
619 		}
620 
621 		if(found)
622 		{
623 			object=(*itr);
624 			obj_idx=(itr - obj_list->begin());
625 		}
626 		else obj_idx=-1;
627 	}
628 
629 	return object;
630 }
631 
getObject(const QString & name,const vector<ObjectType> & types)632 BaseObject *DatabaseModel::getObject(const QString &name, const vector<ObjectType> &types)
633 {
634 	BaseObject *object = nullptr;
635 
636 	for(auto &type : types)
637 	{
638 		object = getObject(name, type);
639 		if(object) break;
640 	}
641 
642 	return object;
643 }
644 
getObject(unsigned obj_idx,ObjectType obj_type)645 BaseObject *DatabaseModel::getObject(unsigned obj_idx, ObjectType obj_type)
646 {
647 	vector<BaseObject *> *obj_list=nullptr;
648 
649 	obj_list=getObjectList(obj_type);
650 
651 	if(!obj_list)
652 		throw Exception(ErrorCode::ObtObjectInvalidType,__PRETTY_FUNCTION__,__FILE__,__LINE__);
653 	else if(obj_idx >= obj_list->size())
654 		throw Exception(ErrorCode::RefObjectInvalidIndex,__PRETTY_FUNCTION__,__FILE__,__LINE__);
655 	else
656 		return obj_list->at(obj_idx);
657 }
658 
getObjectCount(ObjectType obj_type)659 unsigned DatabaseModel::getObjectCount(ObjectType obj_type)
660 {
661 	vector<BaseObject *> *obj_list=nullptr;
662 
663 	obj_list=getObjectList(obj_type);
664 
665 	if(!obj_list)
666 		throw Exception(ErrorCode::ObtObjectInvalidType,__PRETTY_FUNCTION__,__FILE__,__LINE__);
667 	else
668 		return obj_list->size();
669 }
670 
getMaxObjectCount()671 unsigned DatabaseModel::getMaxObjectCount()
672 {
673 	vector<ObjectType> types = getObjectTypes(false, {ObjectType::Database});
674   unsigned count = 0, max = 0;
675 
676   for(auto &type : types)
677   {
678 	 count = getObjectList(type)->size();
679 	 if(count > max) max = count;
680   }
681 
682 	return max;
683 }
684 
getObjectCount()685 unsigned DatabaseModel::getObjectCount()
686 {
687 	vector<ObjectType> types= getObjectTypes(false, {ObjectType::Database});
688 	unsigned count=0;
689 
690 	for(auto &type : types)
691 		count+=getObjectList(type)->size();
692 
693 	return count;
694 }
695 
getLocalization(unsigned localiz_id)696 QString DatabaseModel::getLocalization(unsigned localiz_id)
697 {
698 	if(localiz_id > Collation::LcCollate)
699 		throw Exception(ErrorCode::RefElementInvalidIndex,__PRETTY_FUNCTION__,__FILE__,__LINE__);
700 
701 	return localizations[localiz_id];
702 }
703 
getConnectionLimit()704 int DatabaseModel::getConnectionLimit()
705 {
706 	return conn_limit;
707 }
708 
getTemplateDB()709 QString DatabaseModel::getTemplateDB()
710 {
711 	return template_db;
712 }
713 
getEncoding()714 EncodingType DatabaseModel::getEncoding()
715 {
716 	return encoding;
717 }
718 
getDefaultObject(ObjectType obj_type)719 BaseObject *DatabaseModel::getDefaultObject(ObjectType obj_type)
720 {
721 	if(default_objs.count(obj_type)==0)
722 		throw Exception(ErrorCode::RefObjectInvalidType, __PRETTY_FUNCTION__,__FILE__,__LINE__);
723 
724 	return default_objs[obj_type];
725 }
726 
getAuthor()727 QString DatabaseModel::getAuthor()
728 {
729 	return author;
730 }
731 
setProtected(bool value)732 void DatabaseModel::setProtected(bool value)
733 {
734 	for(auto &itr : obj_lists)
735 	{
736 		for(auto &object :  *itr.second)
737 		{
738 			object->setProtected(value);
739 		}
740 	}
741 
742 	BaseObject::setProtected(value);
743 }
744 
destroyObjects()745 void DatabaseModel::destroyObjects()
746 {
747 	ObjectType graph_types[]={ ObjectType::Schema, ObjectType::BaseRelationship, ObjectType::Relationship,
748 														 ObjectType::Table, ObjectType::ForeignTable, ObjectType::View };
749 	BaseObject *object=nullptr;
750 	map<unsigned, BaseObject *> objects;
751 	map<unsigned, BaseObject *>::reverse_iterator ritr, ritr_end;
752 	vector<ObjectType> rem_obj_types;
753 	BaseGraphicObject *graph_obj = nullptr;
754 
755 	//Blocking signals of all graphical objects to avoid uneeded updates in the destruction
756 	this->blockSignals(true);
757 
758 	for(unsigned i=0; i < 5; i++)
759 	{
760 		for(auto &object : *this->getObjectList(graph_types[i]))
761 		{
762 			graph_obj = dynamic_cast<BaseGraphicObject *>(object);
763 
764 			if(graph_obj)
765 				dynamic_cast<BaseGraphicObject *>(object)->blockSignals(true);
766 		}
767 	}
768 
769 	try
770 	{
771 		//Removing the special objects first
772 		storeSpecialObjectsXML();
773 		disconnectRelationships();
774 	}
775 	catch(Exception &e)
776 	{
777 		/* DEBUG: An exception at this point shouldn't never occur but if
778 		 * it is raised, we spit out the error to the stdout in order to try to
779 		 * find out the problem! */
780 		qDebug() << "** FAIL TO DESTROY ALL OBJECTS **" << QtCompat::endl;
781 		qDebug() << e.getExceptionsText().toStdString().c_str() << QtCompat::endl;
782 	}
783 
784 	objects = getCreationOrder(SchemaParser::XmlDefinition, true);
785 	ritr = objects.rbegin();
786 	ritr_end = objects.rend();
787 
788 	while(ritr != ritr_end)
789 	{
790 		object = ritr->second;
791 		ritr++;
792 
793 		// We ignore the database itself, permission objects (destroyed separetely) and table children objects
794 		if(object->getObjectType() == ObjectType::Database ||
795 			 object->getObjectType() == ObjectType::Permission ||
796 			 TableObject::isTableObject(object->getObjectType()))
797 			continue;
798 
799 		// Register the type of the object being removed so the respective list can be cleaned in the end
800 		rem_obj_types.push_back(object->getObjectType());
801 
802 		/* If the object is graphical destroy using the __removeObject in order
803 		emit the signal to object scene to remove the graphical representation
804 		of the to-be-destroyed object */
805 		if(dynamic_cast<BaseGraphicObject *>(object))
806 		{
807 			__removeObject(object,-1,false);
808 
809 			if(object->getObjectType()==ObjectType::Relationship)
810 				dynamic_cast<Relationship *>(object)->destroyObjects();
811 		}
812 
813 		delete object;
814 	}
815 
816 	PgSqlType::removeUserTypes(this);
817 
818 	for(auto &perm : 	permissions)
819 		delete perm;
820 
821 	permissions.clear();
822 
823 	for(auto &inv_obj : invalid_special_objs)
824 		delete inv_obj;
825 
826 	invalid_special_objs.clear();
827 
828 	//Cleaning out the list of removed objects to avoid segfaults while calling this method again
829 	if(!rem_obj_types.empty())
830 	{
831 		std::sort(rem_obj_types.begin(), rem_obj_types.end());
832 		vector<ObjectType>::iterator end = std::unique(rem_obj_types.begin(), rem_obj_types.end());
833 		rem_obj_types.erase(end, rem_obj_types.end());
834 
835 		for(auto type : rem_obj_types)
836 			getObjectList(type)->clear();
837 	}
838 }
839 
addTable(Table * table,int obj_idx)840 void DatabaseModel::addTable(Table *table, int obj_idx)
841 {
842 	try
843 	{
844 		__addObject(table, obj_idx);
845 
846 		PgSqlType::addUserType(table->getName(true), table, this, UserTypeConfig::TableType);
847 
848 		updateTableFKRelationships(table);
849 
850 		dynamic_cast<Schema *>(table->getSchema())->setModified(true);
851 	}
852 	catch(Exception &e)
853 	{
854 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
855 	}
856 }
857 
getTable(unsigned obj_idx)858 Table *DatabaseModel::getTable(unsigned obj_idx)
859 {
860 	return dynamic_cast<Table *>(getObject(obj_idx, ObjectType::Table));
861 }
862 
getTable(const QString & name)863 Table *DatabaseModel::getTable(const QString &name)
864 {
865 	return dynamic_cast<Table *>(getObject(name, ObjectType::Table));
866 }
867 
removeTable(Table * table,int obj_idx)868 void DatabaseModel::removeTable(Table *table, int obj_idx)
869 {
870 	try
871 	{
872 		__removeObject(table, obj_idx);
873 		PgSqlType::removeUserType(table->getName(true), table);
874 		updateTableFKRelationships(table);
875 	}
876 	catch(Exception &e)
877 	{
878 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
879 	}
880 }
881 
addSequence(Sequence * sequence,int obj_idx)882 void DatabaseModel::addSequence(Sequence *sequence, int obj_idx)
883 {
884 	try
885 	{
886 		__addObject(sequence, obj_idx);
887 		PgSqlType::addUserType(sequence->getName(true), sequence, this, UserTypeConfig::SequenceType);
888 	}
889 	catch(Exception &e)
890 	{
891 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
892 	}
893 }
894 
getSequence(unsigned obj_idx)895 Sequence *DatabaseModel::getSequence(unsigned obj_idx)
896 {
897 	return dynamic_cast<Sequence *>(getObject(obj_idx, ObjectType::Sequence));
898 }
899 
getSequence(const QString & name)900 Sequence *DatabaseModel::getSequence(const QString &name)
901 {
902 	return dynamic_cast<Sequence *>(getObject(name, ObjectType::Sequence));
903 }
904 
removeSequence(Sequence * sequence,int obj_idx)905 void DatabaseModel::removeSequence(Sequence *sequence, int obj_idx)
906 {
907 	try
908 	{
909 		removeUserType(sequence, obj_idx);
910 	}
911 	catch(Exception &e)
912 	{
913 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
914 	}
915 }
916 
addCollation(Collation * collation,int obj_idx)917 void DatabaseModel::addCollation(Collation *collation, int obj_idx)
918 {
919 	try
920 	{
921 		__addObject(collation, obj_idx);
922 	}
923 	catch(Exception &e)
924 	{
925 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
926 	}
927 }
928 
getCollation(unsigned obj_idx)929 Collation *DatabaseModel::getCollation(unsigned obj_idx)
930 {
931 	return dynamic_cast<Collation *>(getObject(obj_idx, ObjectType::Collation));
932 }
933 
getCollation(const QString & name)934 Collation *DatabaseModel::getCollation(const QString &name)
935 {
936 	return dynamic_cast<Collation *>(getObject(name, ObjectType::Collation));
937 }
938 
removeCollation(Collation * collation,int obj_idx)939 void DatabaseModel::removeCollation(Collation *collation, int obj_idx)
940 {
941 	try
942 	{
943 		__removeObject(collation, obj_idx);
944 	}
945 	catch(Exception &e)
946 	{
947 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
948 	}
949 }
950 
addExtension(Extension * extension,int obj_idx)951 void DatabaseModel::addExtension(Extension *extension, int obj_idx)
952 {
953 	try
954 	{
955 		__addObject(extension, obj_idx);
956 
957 		if(extension->handlesType())
958 			PgSqlType::addUserType(extension->getName(true), extension, this, UserTypeConfig::ExtensionType);
959 	}
960 	catch(Exception &e)
961 	{
962 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
963 	}
964 }
965 
getExtension(unsigned obj_idx)966 Extension *DatabaseModel::getExtension(unsigned obj_idx)
967 {
968 	return dynamic_cast<Extension *>(getObject(obj_idx, ObjectType::Collation));
969 }
970 
getExtension(const QString & name)971 Extension *DatabaseModel::getExtension(const QString &name)
972 {
973 	return dynamic_cast<Extension *>(getObject(name, ObjectType::Extension));
974 }
975 
addTag(Tag * tag,int obj_idx)976 void DatabaseModel::addTag(Tag *tag, int obj_idx)
977 {
978 	try
979 	{
980 		__addObject(tag, obj_idx);
981 	}
982 	catch(Exception &e)
983 	{
984 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
985 	}
986 }
987 
removeTag(Tag * tag,int obj_idx)988 void DatabaseModel::removeTag(Tag *tag, int obj_idx)
989 {
990 	try
991 	{
992 		__removeObject(tag, obj_idx);
993 	}
994 	catch(Exception &e)
995 	{
996 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
997 	}
998 }
999 
getTag(unsigned obj_idx)1000 Tag *DatabaseModel::getTag(unsigned obj_idx)
1001 {
1002 	return dynamic_cast<Tag *>(getObject(obj_idx, ObjectType::Tag));
1003 }
1004 
getTag(const QString & name)1005 Tag *DatabaseModel::getTag(const QString &name)
1006 {
1007 	return dynamic_cast<Tag *>(getObject(name, ObjectType::Tag));
1008 }
1009 
addEventTrigger(EventTrigger * evnttrig,int obj_idx)1010 void DatabaseModel::addEventTrigger(EventTrigger *evnttrig, int obj_idx)
1011 {
1012 	try
1013 	{
1014 		__addObject(evnttrig, obj_idx);
1015 	}
1016 	catch(Exception &e)
1017 	{
1018 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
1019 	}
1020 }
1021 
removeEventTrigger(EventTrigger * evnttrig,int obj_idx)1022 void DatabaseModel::removeEventTrigger(EventTrigger *evnttrig, int obj_idx)
1023 {
1024 	try
1025 	{
1026 		__removeObject(evnttrig, obj_idx);
1027 	}
1028 	catch(Exception &e)
1029 	{
1030 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
1031 	}
1032 }
1033 
getEventTrigger(unsigned obj_idx)1034 EventTrigger *DatabaseModel::getEventTrigger(unsigned obj_idx)
1035 {
1036 	return dynamic_cast<EventTrigger *>(getObject(obj_idx, ObjectType::EventTrigger));
1037 }
1038 
getEventTrigger(const QString & name)1039 EventTrigger *DatabaseModel::getEventTrigger(const QString &name)
1040 {
1041 	return dynamic_cast<EventTrigger *>(getObject(name, ObjectType::EventTrigger));
1042 }
1043 
addGenericSQL(GenericSQL * genericsql,int obj_idx)1044 void DatabaseModel::addGenericSQL(GenericSQL *genericsql, int obj_idx)
1045 {
1046 	try
1047 	{
1048 		__addObject(genericsql, obj_idx);
1049 	}
1050 	catch(Exception &e)
1051 	{
1052 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
1053 	}
1054 }
1055 
removeGenericSQL(GenericSQL * genericsql,int obj_idx)1056 void DatabaseModel::removeGenericSQL(GenericSQL *genericsql, int obj_idx)
1057 {
1058 	try
1059 	{
1060 		__removeObject(genericsql, obj_idx);
1061 	}
1062 	catch(Exception &e)
1063 	{
1064 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
1065 	}
1066 }
1067 
getGenericSQL(unsigned obj_idx)1068 GenericSQL *DatabaseModel::getGenericSQL(unsigned obj_idx)
1069 {
1070 	return dynamic_cast<GenericSQL *>(getObject(obj_idx, ObjectType::GenericSql));
1071 }
1072 
getGenericSQL(const QString & name)1073 GenericSQL *DatabaseModel::getGenericSQL(const QString &name)
1074 {
1075 	return dynamic_cast<GenericSQL *>(getObject(name, ObjectType::GenericSql));
1076 }
1077 
addForeignDataWrapper(ForeignDataWrapper * fdata_wrapper,int obj_idx)1078 void DatabaseModel::addForeignDataWrapper(ForeignDataWrapper *fdata_wrapper, int obj_idx)
1079 {
1080 	try
1081 	{
1082 		__addObject(fdata_wrapper, obj_idx);
1083 	}
1084 	catch(Exception &e)
1085 	{
1086 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
1087 	}
1088 }
1089 
removeForeignDataWrapper(ForeignDataWrapper * fdata_wrapper,int obj_idx)1090 void DatabaseModel::removeForeignDataWrapper(ForeignDataWrapper *fdata_wrapper, int obj_idx)
1091 {
1092 	try
1093 	{
1094 		__removeObject(fdata_wrapper, obj_idx);
1095 	}
1096 	catch(Exception &e)
1097 	{
1098 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
1099 	}
1100 }
1101 
getForeignDataWrapper(unsigned obj_idx)1102 ForeignDataWrapper *DatabaseModel::getForeignDataWrapper(unsigned obj_idx)
1103 {
1104 	return dynamic_cast<ForeignDataWrapper *>(getObject(obj_idx, ObjectType::ForeignDataWrapper));
1105 }
1106 
getForeignDataWrapper(const QString & name)1107 ForeignDataWrapper *DatabaseModel::getForeignDataWrapper(const QString &name)
1108 {
1109 	return dynamic_cast<ForeignDataWrapper *>(getObject(name, ObjectType::ForeignDataWrapper));
1110 }
1111 
addForeignServer(ForeignServer * server,int obj_idx)1112 void DatabaseModel::addForeignServer(ForeignServer *server, int obj_idx)
1113 {
1114 	try
1115 	{
1116 		__addObject(server, obj_idx);
1117 	}
1118 	catch(Exception &e)
1119 	{
1120 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
1121 	}
1122 }
1123 
removeForeignServer(ForeignServer * server,int obj_idx)1124 void DatabaseModel::removeForeignServer(ForeignServer *server, int obj_idx)
1125 {
1126 	try
1127 	{
1128 		__removeObject(server, obj_idx);
1129 	}
1130 	catch(Exception &e)
1131 	{
1132 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
1133 	}
1134 }
1135 
getForeignServer(unsigned obj_idx)1136 ForeignServer *DatabaseModel::getForeignServer(unsigned obj_idx)
1137 {
1138 	return dynamic_cast<ForeignServer *>(getObject(obj_idx, ObjectType::ForeignServer));
1139 }
1140 
getForeignServer(const QString & name)1141 ForeignServer *DatabaseModel::getForeignServer(const QString &name)
1142 {
1143 	return dynamic_cast<ForeignServer *>(getObject(name, ObjectType::ForeignServer));
1144 }
1145 
addUserMapping(UserMapping * usrmap,int obj_idx)1146 void DatabaseModel::addUserMapping(UserMapping *usrmap, int obj_idx)
1147 {
1148 	try
1149 	{
1150 		__addObject(usrmap, obj_idx);
1151 	}
1152 	catch(Exception &e)
1153 	{
1154 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
1155 	}
1156 }
1157 
removeUserMapping(UserMapping * usrmap,int obj_idx)1158 void DatabaseModel::removeUserMapping(UserMapping *usrmap, int obj_idx)
1159 {
1160 	try
1161 	{
1162 		__removeObject(usrmap, obj_idx);
1163 	}
1164 	catch(Exception &e)
1165 	{
1166 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
1167 	}
1168 }
1169 
getUserMapping(unsigned obj_idx)1170 UserMapping *DatabaseModel::getUserMapping(unsigned obj_idx)
1171 {
1172 	return dynamic_cast<UserMapping *>(getObject(obj_idx, ObjectType::UserMapping));
1173 }
1174 
getUserMapping(const QString & name)1175 UserMapping *DatabaseModel::getUserMapping(const QString &name)
1176 {
1177 	return dynamic_cast<UserMapping *>(getObject(name, ObjectType::UserMapping));
1178 }
1179 
addForeignTable(ForeignTable * table,int obj_idx)1180 void DatabaseModel::addForeignTable(ForeignTable *table, int obj_idx)
1181 {
1182 	try
1183 	{
1184 		__addObject(table, obj_idx);
1185 
1186 		PgSqlType::addUserType(table->getName(true), table, this, UserTypeConfig::ForeignTableType);
1187 		dynamic_cast<Schema *>(table->getSchema())->setModified(true);
1188 	}
1189 	catch(Exception &e)
1190 	{
1191 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
1192 	}
1193 }
1194 
getForeignTable(unsigned obj_idx)1195 ForeignTable *DatabaseModel::getForeignTable(unsigned obj_idx)
1196 {
1197 	return dynamic_cast<ForeignTable *>(getObject(obj_idx, ObjectType::ForeignTable));
1198 }
1199 
getForeignTable(const QString & name)1200 ForeignTable *DatabaseModel::getForeignTable(const QString &name)
1201 {
1202 	return dynamic_cast<ForeignTable *>(getObject(name, ObjectType::ForeignTable));
1203 }
1204 
removeForeignTable(ForeignTable * table,int obj_idx)1205 void DatabaseModel::removeForeignTable(ForeignTable *table, int obj_idx)
1206 {
1207 	try
1208 	{
1209 		__removeObject(table, obj_idx);
1210 		PgSqlType::removeUserType(table->getName(true), table);
1211 	}
1212 	catch(Exception &e)
1213 	{
1214 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
1215 	}
1216 }
1217 
removeExtension(Extension * extension,int obj_idx)1218 void DatabaseModel::removeExtension(Extension *extension, int obj_idx)
1219 {
1220 	try
1221 	{
1222 		if(extension->handlesType())
1223 			removeUserType(extension, obj_idx);
1224 		else
1225 			__removeObject(extension, obj_idx);
1226 	}
1227 	catch(Exception &e)
1228 	{
1229 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
1230 	}
1231 }
1232 
addView(View * view,int obj_idx)1233 void DatabaseModel::addView(View *view, int obj_idx)
1234 {
1235 	try
1236 	{
1237 		__addObject(view, obj_idx);
1238 		PgSqlType::addUserType(view->getName(true), view, this, UserTypeConfig::ViewType);
1239 
1240 		updateViewRelationships(view);
1241 		dynamic_cast<Schema *>(view->getSchema())->setModified(true);
1242 	}
1243 	catch(Exception &e)
1244 	{
1245 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
1246 	}
1247 }
1248 
getView(unsigned obj_idx)1249 View *DatabaseModel::getView(unsigned obj_idx)
1250 {
1251 	return dynamic_cast<View *>(getObject(obj_idx, ObjectType::View));
1252 }
1253 
getView(const QString & name)1254 View *DatabaseModel::getView(const QString &name)
1255 {
1256 	return dynamic_cast<View *>(getObject(name, ObjectType::View));
1257 }
1258 
removeView(View * view,int obj_idx)1259 void DatabaseModel::removeView(View *view, int obj_idx)
1260 {
1261 	try
1262 	{
1263 		//The relationships that links tables to the view must be removed before erase the view itself
1264 		updateViewRelationships(view, true);
1265 
1266 		__removeObject(view, obj_idx);
1267 		PgSqlType::removeUserType(view->getName(true), view);
1268 	}
1269 	catch(Exception &e)
1270 	{
1271 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
1272 	}
1273 }
1274 
updateTableFKRelationships(Table * table)1275 void DatabaseModel::updateTableFKRelationships(Table *table)
1276 {
1277 	if(!table)
1278 		throw Exception(ErrorCode::OprNotAllocatedObject,__PRETTY_FUNCTION__,__FILE__,__LINE__);
1279 
1280 	if(table->getDatabase()==this)
1281 	{
1282 		Table *ref_tab=nullptr;
1283 		BaseRelationship *rel=nullptr;
1284 		unsigned idx;
1285 		vector<Constraint *> fks;
1286 		vector<BaseObject *>::iterator itr1, itr1_end;
1287 
1288 		table->getForeignKeys(fks);
1289 
1290 		/* First remove the invalid relationships (the foreign key that generates the
1291 			relationship no longer exists) */
1292 		itr1=base_relationships.begin();
1293 		itr1_end=base_relationships.end();
1294 
1295 		idx=0;
1296 		while(itr1!=itr1_end)
1297 		{
1298 			rel=dynamic_cast<BaseRelationship *>(*itr1);
1299 
1300 			if(rel->getRelationshipType()==BaseRelationship::RelationshipFk &&
1301 					(rel->getTable(BaseRelationship::SrcTable)==table ||
1302 					 rel->getTable(BaseRelationship::DstTable)==table))
1303 			{
1304 				Constraint *fk = rel->getReferenceForeignKey();
1305 
1306 				if(rel->getTable(BaseRelationship::SrcTable)==table)
1307 					ref_tab=dynamic_cast<Table *>(rel->getTable(BaseRelationship::DstTable));
1308 				else
1309 					ref_tab=dynamic_cast<Table *>(rel->getTable(BaseRelationship::SrcTable));
1310 
1311 				/* Removes the relationship if the following cases happen:
1312 				 * 1) The foreign key references a table different from ref_tab, which means, the user
1313 				 *		have changed the fk manually by setting a new referenced table but the relationship tied to the fk
1314 				 *		does not reflect the new reference.
1315 				 *
1316 				 * 2) The fk references the correct table but the source table does not own the fk anymore, which means,
1317 				 *		the fk as removed manually by the user. */
1318 				if((table->getObjectIndex(fk) >= 0 && fk->getReferencedTable() != ref_tab) ||
1319 					 (table->getObjectIndex(fk) < 0 && fk->getReferencedTable() == ref_tab))
1320 				{
1321 					removeRelationship(rel);
1322 					itr1=base_relationships.begin() + idx;
1323 					itr1_end=base_relationships.end();
1324 				}
1325 				else
1326 				{
1327 					rel->setModified(!loading_model);
1328 					itr1++; idx++;
1329 				}
1330 			}
1331 			else
1332 			{
1333 				itr1++; idx++;
1334 			}
1335 		}
1336 
1337 		//Creating the relationships from the foreign keys
1338 		for(auto &fk : fks)
1339 		{
1340 			ref_tab=dynamic_cast<Table *>(fk->getReferencedTable());
1341 
1342 			//Only creates the relationship if does'nt exist one between the tables
1343 			rel=getRelationship(table, ref_tab, fk);
1344 
1345 			if(!rel && ref_tab->getDatabase()==this)
1346 			{
1347 				bool ref_mandatory = false;
1348 
1349 				for(auto &col : fk->getColumns(Constraint::SourceCols))
1350 				{
1351 					if(col->isNotNull())
1352 					{
1353 						ref_mandatory = true;
1354 						break;
1355 					}
1356 				}
1357 
1358 				rel = new BaseRelationship(BaseRelationship::RelationshipFk, table, ref_tab, false, ref_mandatory);
1359 				rel->setReferenceForeignKey(fk);
1360 				rel->setCustomColor(Qt::transparent);
1361 
1362 				/* Workaround: In some cases the combination of the two tablenames can generate a duplicated relationship
1363 					 name so it`s necessary to check if a relationship with the same name already exists. If exists changes
1364 					 the name of the new one */
1365 				if(getObjectIndex(rel->getName(), ObjectType::BaseRelationship) >= 0)
1366 					rel->setName(PgModelerNs::generateUniqueName(rel, base_relationships));
1367 
1368 				addRelationship(rel);
1369 			}
1370 		}
1371 	}
1372 }
1373 
updateTablesFKRelationships()1374 void DatabaseModel::updateTablesFKRelationships()
1375 {
1376 	vector<BaseObject *>::iterator itr=tables.begin();
1377 
1378 	while(itr!=tables.end())
1379 	{
1380 		updateTableFKRelationships(dynamic_cast<Table *>(*itr));
1381 		itr++;
1382 	}
1383 }
1384 
updateViewRelationships(View * view,bool force_rel_removal)1385 void DatabaseModel::updateViewRelationships(View *view, bool force_rel_removal)
1386 {
1387 	PhysicalTable *table=nullptr;
1388 	BaseRelationship *rel=nullptr;
1389 	Reference ref;
1390 	unsigned i, ref_count, idx;
1391 	vector<BaseObject *>::iterator itr, itr_end;
1392 	vector<PhysicalTable *> tables;
1393 
1394 	if(!view)
1395 		throw Exception(ErrorCode::OprNotAllocatedObject,__PRETTY_FUNCTION__,__FILE__,__LINE__);
1396 
1397 	if(getObjectIndex(view) < 0 || force_rel_removal)
1398 	{
1399 		//Remove all the relationship related to the view when this latter no longer exists
1400 		itr=base_relationships.begin();
1401 		itr_end=base_relationships.end();
1402 
1403 		idx=0;
1404 		while(itr!=itr_end)
1405 		{
1406 			rel=dynamic_cast<BaseRelationship *>(*itr);
1407 
1408 			if(rel->getTable(BaseRelationship::SrcTable)==view ||
1409 					rel->getTable(BaseRelationship::DstTable)==view)
1410 			{
1411 				removeRelationship(rel);
1412 				itr=base_relationships.begin() + idx;
1413 				itr_end=base_relationships.end();
1414 			}
1415 			else
1416 			{
1417 				itr++; idx++;
1418 			}
1419 		}
1420 	}
1421 	else
1422 	{
1423 		/* Remove the relationships between tables and the view
1424 		 when this latter doesn't reference the first */
1425 		itr=base_relationships.begin();
1426 		itr_end=base_relationships.end();
1427 
1428 		idx=0;
1429 		while(itr!=itr_end)
1430 		{
1431 			rel=dynamic_cast<BaseRelationship *>(*itr);
1432 
1433 			if(rel->getTable(BaseRelationship::SrcTable)==view ||
1434 					rel->getTable(BaseRelationship::DstTable)==view)
1435 			{
1436 				if(rel->getTable(BaseRelationship::SrcTable)->getObjectType()==ObjectType::Table)
1437 					table=dynamic_cast<PhysicalTable *>(rel->getTable(BaseRelationship::SrcTable));
1438 				else
1439 					table=dynamic_cast<PhysicalTable *>(rel->getTable(BaseRelationship::DstTable));
1440 
1441 				if(!view->isReferencingTable(table))
1442 				{
1443 					removeRelationship(rel);
1444 					itr=base_relationships.begin() + idx;
1445 					itr_end=base_relationships.end();
1446 				}
1447 				else
1448 				{
1449 					itr++; idx++;
1450 				}
1451 			}
1452 			else
1453 			{
1454 				itr++; idx++;
1455 			}
1456 		}
1457 
1458 		/* Creates the relationships from the view references
1459 		 * First we try to create relationship from referecences in SELECT portion of view's definition */
1460 		ref_count=view->getReferenceCount(Reference::SqlReferSelect);
1461 		for(i=0; i < ref_count; i++)
1462 		{
1463 			table = view->getReference(i, Reference::SqlReferSelect).getTable();
1464 			if(table) tables.push_back(table);
1465 		}
1466 
1467 		/* If the view does have tables referenced from SELECT portion we check if
1468 		 * the table was constructed from a single reference (Reference::SqlViewDefinition). In
1469 		 * that case we use the list of referenced tables configured in that view reference object */
1470 		if(tables.empty() && view->getReferenceCount(Reference::SqlViewDefinition) > 0)
1471 			tables = view->getReference(0, Reference::SqlViewDefinition).getReferencedTables();
1472 
1473 		// Effectively creating the relationships
1474 		for(auto &tab : tables)
1475 		{
1476 			rel = getRelationship(view, tab);
1477 
1478 			if(!rel)
1479 			{
1480 				rel=new BaseRelationship(BaseRelationship::RelationshipDep, view, tab, false, false);
1481 				rel->setName(PgModelerNs::generateUniqueName(rel, base_relationships));
1482 				addRelationship(rel);
1483 			}
1484 		}
1485 	}
1486 }
1487 
disconnectRelationships()1488 void DatabaseModel::disconnectRelationships()
1489 {
1490 	try
1491 	{
1492 		BaseRelationship *base_rel=nullptr;
1493 		Relationship *rel=nullptr;
1494 		vector<BaseObject *>::reverse_iterator ritr_rel, ritr_rel_end;
1495 
1496 		//The relationships must be disconnected from the last to the first
1497 		ritr_rel=relationships.rbegin();
1498 		ritr_rel_end=relationships.rend();
1499 
1500 		while(ritr_rel!=ritr_rel_end)
1501 		{
1502 			base_rel=dynamic_cast<BaseRelationship *>(*ritr_rel);
1503 			ritr_rel++;
1504 			base_rel->blockSignals(loading_model);
1505 
1506 			if(base_rel->getObjectType()==ObjectType::Relationship)
1507 			{
1508 				rel=dynamic_cast<Relationship *>(base_rel);
1509 				rel->disconnectRelationship();
1510 			}
1511 			else
1512 				base_rel->disconnectRelationship();
1513 
1514 			base_rel->blockSignals(false);
1515 		}
1516 	}
1517 	catch(Exception &e)
1518 	{
1519 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
1520 	}
1521 }
1522 
validateRelationships()1523 void DatabaseModel::validateRelationships()
1524 {
1525 	vector<BaseObject *>::iterator itr, itr_end, itr_ant;
1526 	Relationship *rel=nullptr;
1527 	BaseRelationship *base_rel=nullptr;
1528 	vector<BaseObject *> vet_rel, vet_rel_inv, rels, fail_rels;
1529 	bool found_inval_rel, valid_fail_rels=false;
1530 	vector<Exception> errors;
1531 	map<unsigned, QString>::iterator itr1, itr1_end;
1532 	map<unsigned, Exception> error_map;
1533 	map<unsigned, Exception>::iterator itr2, itr2_end;
1534 	map<BaseObject *, unsigned> conn_tries;
1535 	unsigned idx, rels_gen_pk=0;
1536 	vector<Schema *> schemas;
1537 	BaseTable *tab1=nullptr, *tab2=nullptr;
1538 
1539 	itr=relationships.begin();
1540 	itr_end=relationships.end();
1541 
1542 	/* Calculates the quantity of referece tables which has primary keys added by relationship.
1543 	This type of primary key may cause unexpected relationship invalidation during the validation process
1544 	because all relationship are disconnected and when reconnecting them the primary key sometimes is not yet
1545 	created causing other relationships to be broken. This counter is used to try revalidate any relationship
1546 	that emits ERR_LINK_TABLES_NO_PK exception during its connection */
1547 	while(itr!=itr_end)
1548 	{
1549 		rel=dynamic_cast<Relationship *>(*itr);
1550 		itr++;
1551 
1552 		if(rel &&
1553 				(rel->getRelationshipType()==Relationship::Relationship11 ||
1554 				 rel->getRelationshipType()==Relationship::Relationship1n) &&
1555 				rel->getReferenceTable()->getPrimaryKey() &&
1556 				rel->getReferenceTable()->getPrimaryKey()->isAddedByRelationship())
1557 			rels_gen_pk++;
1558 	}
1559 
1560 	itr=relationships.begin();
1561 	itr_end=relationships.end();
1562 
1563 	do
1564 	{
1565 		found_inval_rel=false;
1566 
1567 		while(itr!=itr_end)
1568 		{
1569 			base_rel=dynamic_cast<BaseRelationship *>(*itr);
1570 			itr++;
1571 
1572 			//Validates only table-table relationships
1573 			if(base_rel->getObjectType()==ObjectType::Relationship)
1574 			{
1575 				//Makes a cast to the correct object class
1576 				rel=dynamic_cast<Relationship *>(base_rel);
1577 
1578 				//If the relationships is invalid
1579 				if(rel->isInvalidated())
1580 				{
1581 					//Inserts it to the invalid relationship vector
1582 					vet_rel_inv.push_back(base_rel);
1583 
1584 					//Marks the flag indicating the at least one relationship was found invalidated
1585 					found_inval_rel=true;
1586 				}
1587 				else
1588 					//Otherwise inserts the relationship on the valid relationships
1589 					vet_rel.push_back(base_rel);
1590 			}
1591 		}
1592 
1593 		//If there is some invalidated relationship or special objects to be recreated
1594 		if(found_inval_rel || !xml_special_objs.empty())
1595 		{
1596 			//Stores the special objects definition if there is some invalidated relationships
1597 			if(!loading_model && xml_special_objs.empty())
1598 				storeSpecialObjectsXML();
1599 
1600 			if(found_inval_rel)
1601 			{
1602 				//Disconnects all the relationship
1603 				disconnectRelationships();
1604 
1605 				/* Merges the two lists (valid and invalid relationships),
1606 					 taking care to insert the invalid ones at the end of the list */
1607 				rels=vet_rel;
1608 				rels.insert(rels.end(), vet_rel_inv.begin(), vet_rel_inv.end());
1609 				vet_rel.clear();
1610 				vet_rel_inv.clear();
1611 
1612 				//Walking through the created list connecting the relationships
1613 				itr=rels.begin();
1614 				itr_end=rels.end();
1615 				idx=0;
1616 
1617 				while(itr!=itr_end)
1618 				{
1619 					rel=dynamic_cast<Relationship *>(*itr);
1620 
1621 					//Stores the current iterator in a auxiliary one to remove from list in case of error
1622 					itr_ant=itr;
1623 					itr++;
1624 
1625 					try
1626 					{
1627 						//Try to connect the relationship
1628 						rel->connectRelationship();
1629 
1630 						//Storing the schemas on a auxiliary vector to update them later
1631 						tab1=rel->getTable(BaseRelationship::SrcTable);
1632 						tab2=rel->getTable(BaseRelationship::DstTable);
1633 						schemas.push_back(dynamic_cast<Schema *>(tab1->getSchema()));
1634 
1635 						if(tab2 != tab1)
1636 							schemas.push_back(dynamic_cast<Schema *>(tab2->getSchema()));
1637 
1638 						idx++;
1639 
1640 						/* Removes the relationship from the current position and inserts it
1641 							 into the next position after the next relationship to try the reconnection */
1642 						rels.erase(itr_ant);
1643 						idx=0;
1644 
1645 						/* If the list was emptied and there is relationship that fails to validate,
1646 							 the method will try to validate them one last time */
1647 						if(rels.size()==0 && !fail_rels.empty() && !valid_fail_rels)
1648 						{
1649 							rels.insert(rels.end(), fail_rels.begin(), fail_rels.end());
1650 							//Check this flag indicates that the fail_rels list must be copied only one time
1651 							valid_fail_rels=true;
1652 						}
1653 
1654 						itr=rels.begin();
1655 						itr_end=rels.end();
1656 					}
1657 					/* Case some error is raised during the connection the relationship is
1658 						 permanently invalidated and need to be removed from the model */
1659 					catch(Exception &e)
1660 					{
1661 						/* If the relationship connection failed after 'rels_gen_pk' times at the
1662 						different errors or exists on the fail_rels vector (already tried to be validated)
1663 						it will be deleted from model */
1664 						if((e.getErrorCode() != ErrorCode::InvLinkTablesNoPrimaryKey && conn_tries[rel] > rels_gen_pk) ||
1665 								(std::find(fail_rels.begin(), fail_rels.end(), rel)!=fail_rels.end()))
1666 						{
1667 							//Removes the relationship
1668 							__removeObject(rel);
1669 
1670 							//Removes the iterator that stores the relationship from the list
1671 							rels.erase(itr_ant);
1672 
1673 							//Stores the error raised in a list
1674 							errors.push_back(e);
1675 						}
1676 						/* If the relationship connection fails with the ERR_LINK_TABLES_NO_PK error and
1677 								the connection tries exceed the size of the relationship the relationship is isolated
1678 								on a "failed to validate" list. This list will be appended to the main rel list when
1679 								there is only one relationship to be validated */
1680 						else if(e.getErrorCode()==ErrorCode::InvLinkTablesNoPrimaryKey &&
1681 								(conn_tries[rel] > rels.size() ||
1682 								 rel->getRelationshipType()==BaseRelationship::RelationshipNn))
1683 						{
1684 							fail_rels.push_back(rel);
1685 							rels.erase(itr_ant);
1686 							conn_tries[rel]=0;
1687 
1688 							/* If the list was emptied and there is relationship that fails to validate,
1689 								 the method will try to validate them one last time */
1690 							if(rels.size()==0 && !valid_fail_rels)
1691 							{
1692 								rels.insert(rels.end(), fail_rels.begin(), fail_rels.end());
1693 								valid_fail_rels=true;
1694 							}
1695 						}
1696 						else
1697 						{
1698 							//Increments the connection tries
1699 							conn_tries[rel]++;
1700 
1701 							/* Removes the relationship from the current position and inserts it
1702 								 into the next position after the next relationship to try the reconnection */
1703 							rels.erase(itr_ant);
1704 
1705 							//If the next index doesn't extrapolates the list size insert it on the next position
1706 							if(idx+1 < rels.size())
1707 								rels.insert(rels.begin() + idx + 1,rel);
1708 							else
1709 								rels.push_back(rel);
1710 						}
1711 
1712 						/* Points the searching to the iterator immediately after the removed iterator
1713 						evicting to walk on the list from the first item */
1714 						itr_end=rels.end();
1715 						itr=rels.begin() + idx;
1716 					}
1717 				}
1718 
1719 				itr=rels.begin();
1720 			}
1721 
1722 			//Recreating the special objects
1723 			itr1=xml_special_objs.begin();
1724 			itr1_end=xml_special_objs.end();
1725 
1726 			//The special objects are created only when the model is not being loaded
1727 			if(!loading_model && itr1!=itr1_end)
1728 			{
1729 				do
1730 				{
1731 					try
1732 					{
1733 						//Try to create the special object
1734 						createSpecialObject(itr1->second, itr1->first);
1735 
1736 						/* If the special object is successfully created, remove the errors
1737 							 related to a previous attempt to create it */
1738 						if(error_map.count(itr1->first))
1739 							error_map.erase(error_map.find(itr1->first));
1740 
1741 						//Removes the definition of the special object when it is created successfully
1742 						xml_special_objs.erase(itr1);
1743 
1744 						//Restart the special object creation
1745 						itr1=xml_special_objs.begin();
1746 						itr1_end=xml_special_objs.end();
1747 					}
1748 					catch(Exception &e)
1749 					{
1750 						//If some error related to the special object is raised, stores it for latter creation attempts
1751 						error_map[itr1->first]=e;
1752 						itr1++; idx++;
1753 					}
1754 				}
1755 				while(itr1!=itr1_end);
1756 			}
1757 		}
1758 	}
1759 	//The validation continues until there is some invalid relationship
1760 	while(found_inval_rel);
1761 
1762 	if(!loading_model && !schemas.empty())
1763 	{
1764 		std::sort(schemas.begin(), schemas.end());
1765 		vector<Schema *>::iterator end = std::unique(schemas.begin(), schemas.end());
1766 		schemas.erase(end, schemas.end());
1767 
1768 		//Updates the schemas to ajdust its sizes due to the tables resizings
1769 		for(auto &sch : schemas)
1770 			sch->setModified(true);
1771 	}
1772 
1773 	//Stores the errors related to creation of special objects on the general error vector
1774 	itr2=error_map.begin();
1775 	itr2_end=error_map.end();
1776 	while(itr2!=itr2_end)
1777 	{
1778 		errors.push_back(itr2->second);
1779 		itr2++;
1780 	}
1781 
1782 	//If errors were caught on the above executions they will be redirected to the user
1783 	if(!errors.empty())
1784 	{
1785 		if(!loading_model)
1786 			xml_special_objs.clear();
1787 
1788 		/* Revalidates the fk relationships at this points because some fks must be removed due
1789 		 to special object invalidation */
1790 		itr=base_relationships.begin();
1791 		itr_end=base_relationships.end();
1792 
1793 		while(itr!=itr_end)
1794 		{
1795 			base_rel=dynamic_cast<BaseRelationship *>(*itr);
1796 
1797 			if(base_rel->getRelationshipType()==BaseRelationship::RelationshipFk)
1798 				this->updateTableFKRelationships(dynamic_cast<Table *>(base_rel->getTable(BaseRelationship::SrcTable)));
1799 
1800 			itr++;
1801 		}
1802 
1803 		//Set all the model objects as modified to force the redraw of the entire model
1804 		this->setObjectsModified();
1805 
1806 		//Redirects all the errors captured on the revalidation
1807 		throw Exception(ErrorCode::RemInvalidatedObjects,__PRETTY_FUNCTION__,__FILE__,__LINE__,errors);
1808 	}
1809 
1810 	if(!loading_model)
1811 	{
1812 		for(auto &tab : tables)
1813 			dynamic_cast<PhysicalTable *>(tab)->restoreRelObjectsIndexes();
1814 
1815 		for(auto &tab : foreign_tables)
1816 			dynamic_cast<PhysicalTable *>(tab)->restoreRelObjectsIndexes();
1817 
1818 		xml_special_objs.clear();
1819 	}
1820 }
1821 
checkRelationshipRedundancy(Relationship * rel)1822 void DatabaseModel::checkRelationshipRedundancy(Relationship *rel)
1823 {
1824 	try
1825 	{
1826 		unsigned rel_type;
1827 
1828 		//Raises an error if the user try to check the redundancy starting from a unnallocated relationship
1829 		if(!rel)
1830 			throw Exception(ErrorCode::OprNotAllocatedObject,__PRETTY_FUNCTION__,__FILE__,__LINE__);
1831 
1832 		rel_type=rel->getRelationshipType();
1833 
1834 		/* Only identifier relationships or relationship that has identifier
1835 		 attributes (primary keys) are checked */
1836 		if((!rel->isSelfRelationship() &&
1837 				(rel->isIdentifier() ||
1838 				 rel->hasIndentifierAttribute())) ||
1839 				(rel_type==Relationship::RelationshipGen ||
1840 				 rel_type==Relationship::RelationshipDep ||
1841 				 rel_type==Relationship::RelationshipPart))
1842 		{
1843 			BaseTable *ref_table=nullptr, *src_table=nullptr;
1844 			PhysicalTable *recv_table=nullptr;
1845 			Relationship *rel_aux=nullptr;
1846 			BaseRelationship *base_rel=nullptr;
1847 			vector<BaseObject *>::iterator itr, itr_end;
1848 			bool found_cycle=false;
1849 			unsigned aux_rel_type;
1850 			QString str_aux, msg;
1851 
1852 			//Gets the tables from the relationship
1853 			recv_table=rel->getReceiverTable();
1854 			ref_table=rel->getReferenceTable();
1855 
1856 			itr=relationships.begin();
1857 			itr_end=relationships.end();
1858 
1859 			/* Based on the obtained tables, scans the list of relationships in search of the cycle.
1860 			A cycle is detected when a reference table from a relationship is the receiver table of
1861 			the relationship used in the validation. */
1862 			while(itr!=itr_end && !found_cycle)
1863 			{
1864 				base_rel=dynamic_cast<BaseRelationship *>(*itr);
1865 				itr++;
1866 
1867 				if(base_rel->getObjectType()==ObjectType::Relationship)
1868 				{
1869 					rel_aux=dynamic_cast<Relationship *>(base_rel);
1870 					aux_rel_type=rel_aux->getRelationshipType();
1871 					src_table=rel_aux->getReferenceTable();
1872 
1873 					/* Case the reference table is equal to the receiver table of the relationship used
1874 				as the start of validation and the current relationship type is the same as the
1875 				latter relationship, this can indicate a principle of closing cycle, in this way
1876 				the validation will proceed with the receiver table from the current relationship
1877 				until que receiver table is the reference table of the initial relationship */
1878 					if(recv_table==src_table &&  aux_rel_type==rel_type &&
1879 							((!rel_aux->isSelfRelationship() &&
1880 							  (rel_aux->isIdentifier() ||
1881 							   rel_aux->hasIndentifierAttribute())) ||
1882 							 (aux_rel_type==Relationship::RelationshipGen ||
1883 								aux_rel_type==Relationship::RelationshipDep ||
1884 								aux_rel_type==Relationship::RelationshipPart)))
1885 
1886 					{
1887 						//The receiver table will be the receiver from the current relationship
1888 						recv_table=rel_aux->getReceiverTable();
1889 
1890 						//Stores the relationship name to raise an error in case of closing cycle
1891 						str_aux+=rel_aux->getName() + QString(", ");
1892 
1893 						//Checking the closing cycle
1894 						found_cycle=(recv_table==ref_table);
1895 
1896 						//Restart the validation
1897 						itr=relationships.begin();
1898 					}
1899 				}
1900 			}
1901 
1902 			//Raises an error indicating the relationship names that close the cycle
1903 			if(found_cycle)
1904 			{
1905 				str_aux+=rel->getName();
1906 				msg=Exception::getErrorMessage(ErrorCode::InsRelationshipRedundancy)
1907 					.arg(rel->getName())
1908 					.arg(str_aux);
1909 				throw Exception(msg,ErrorCode::InsRelationshipRedundancy,__PRETTY_FUNCTION__,__FILE__,__LINE__);
1910 			}
1911 		}
1912 	}
1913 	catch(Exception &e)
1914 	{
1915 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
1916 	}
1917 }
1918 
storeSpecialObjectsXML()1919 void DatabaseModel::storeSpecialObjectsXML()
1920 {
1921 	unsigned count=0, i=0, type_id=0;
1922 	vector<BaseObject *>::iterator itr, itr_end;
1923 	Sequence *sequence=nullptr;
1924 	Permission *permission=nullptr;
1925 	PhysicalTable *table=nullptr;
1926 	TableObject *tab_obj=nullptr;
1927 	Constraint *constr=nullptr;
1928 	Index *index=nullptr;
1929 	Trigger *trigger=nullptr;
1930 	View *view=nullptr;
1931 	BaseRelationship *rel=nullptr;
1932 	GenericSQL *generic_sql=nullptr;
1933 	Reference ref;
1934 	ObjectType tab_obj_type[3]={ ObjectType::Constraint, ObjectType::Trigger, ObjectType::Index };
1935 	bool found=false;
1936 	vector<BaseObject *> objects, rem_objects, upd_tables_rels, aux_tables;
1937 
1938 	try
1939 	{
1940 		aux_tables = tables;
1941 		aux_tables.insert(aux_tables.end(), foreign_tables.begin(), foreign_tables.end());
1942 		itr=aux_tables.begin();
1943 		itr_end=aux_tables.end();
1944 
1945 		/* Check on tables if there is some constraint/index/trigger that is referencing
1946 		 some column added by relationship */
1947 		while(itr!=itr_end)
1948 		{
1949 			table=dynamic_cast<PhysicalTable *>(*itr);
1950 			itr++;
1951 
1952 			for(type_id=0; type_id < 3; type_id++)
1953 			{
1954 				// Ignoring index type if we are dealing with foreign table
1955 				if(table->getObjectType() == ObjectType::ForeignTable &&
1956 					 tab_obj_type[type_id] == ObjectType::Index)
1957 					continue;
1958 
1959 				//Gets the table object count for the curret object type
1960 				count=table->getObjectCount(tab_obj_type[type_id]);
1961 
1962 				for(i=0; i < count; i++)
1963 				{
1964 					tab_obj=dynamic_cast<TableObject *>(table->getObject(i, tab_obj_type[type_id]));
1965 					found=false;
1966 
1967 					if(tab_obj_type[type_id]==ObjectType::Constraint)
1968 					{
1969 						constr=dynamic_cast<Constraint *>(tab_obj);
1970 
1971 						/* A constraint is considered special in this case when it is referencing
1972 							 relationship added column and the constraint itself was not added by
1973 							 relationship (created manually by the user) */
1974 						found=(!constr->isAddedByRelationship() &&
1975 									 constr->isReferRelationshipAddedColumn() &&
1976 									 constr->getConstraintType()!=ConstraintType::PrimaryKey);
1977 
1978 						//When found some special object, stores is xml definition
1979 						if(found)
1980 							xml_special_objs[constr->getObjectId()]=constr->getCodeDefinition(SchemaParser::XmlDefinition, true);
1981 					}
1982 					else if(tab_obj_type[type_id]==ObjectType::Trigger)
1983 					{
1984 						trigger=dynamic_cast<Trigger *>(tab_obj);
1985 						found=trigger->isReferRelationshipAddedColumn();
1986 
1987 						if(found)
1988 							xml_special_objs[trigger->getObjectId()]=trigger->getCodeDefinition(SchemaParser::XmlDefinition);
1989 					}
1990 					else
1991 					{
1992 						index=dynamic_cast<Index *>(tab_obj);
1993 						found=index->isReferRelationshipAddedColumn();
1994 
1995 						if(found)
1996 							xml_special_objs[index->getObjectId()]=index->getCodeDefinition(SchemaParser::XmlDefinition);
1997 					}
1998 
1999 					if(found)
2000 					{
2001 						constr = dynamic_cast<Constraint *>(tab_obj);
2002 
2003 						//When found the special object must be removed from the parent table
2004 						table->removeObject(tab_obj->getName(), tab_obj->getObjectType());
2005 
2006 						//We need to store the table which fk was referencing relationship added columns in order to update the fk relationships of that table
2007 						if(constr && constr->getConstraintType() == ConstraintType::ForeignKey)
2008 							upd_tables_rels.push_back(table);
2009 
2010 						//Removes the permission from the table object
2011 						removePermissions(tab_obj);
2012 
2013 						i--; count--;
2014 					}
2015 				}
2016 			}
2017 		}
2018 
2019 		//Updating fk rels of tables which had fks referencing relationship added columns
2020 		if(!upd_tables_rels.empty())
2021 		{
2022 			vector<BaseObject *>::iterator end;
2023 
2024 			if(upd_tables_rels.size() > 1)
2025 			{
2026 				std::sort(upd_tables_rels.begin(), upd_tables_rels.end());
2027 				end = std::unique(upd_tables_rels.begin(), upd_tables_rels.end());
2028 				upd_tables_rels.erase(end, upd_tables_rels.end());
2029 			}
2030 
2031 			for(auto &tab : upd_tables_rels)
2032 				updateTableFKRelationships(dynamic_cast<Table *>(tab));
2033 		}
2034 
2035 		//Making a copy of the sequences list to avoid iterator invalidation when removing an object
2036 		rem_objects.assign(sequences.begin(), sequences.end());
2037 		itr=rem_objects.begin();
2038 		itr_end=rem_objects.end();
2039 
2040 		while(itr!=itr_end)
2041 		{
2042 			sequence=dynamic_cast<Sequence *>(*itr);
2043 			itr++;
2044 
2045 			if(sequence->isReferRelationshipAddedColumn())
2046 			{
2047 				xml_special_objs[sequence->getObjectId()]=sequence->getCodeDefinition(SchemaParser::XmlDefinition);
2048 				removeSequence(sequence);
2049 				invalid_special_objs.push_back(sequence);
2050 				//delete sequence;
2051 			}
2052 		}
2053 
2054 		//Making a copy of the view list to avoid iterator invalidation when removing an object
2055 		rem_objects.assign(views.begin(), views.end());
2056 		itr=rem_objects.begin();
2057 		itr_end=rem_objects.end();
2058 
2059 		while(itr!=itr_end)
2060 		{
2061 			view=dynamic_cast<View *>(*itr);
2062 			itr++;
2063 
2064 			if(view->isReferRelationshipAddedColumn())
2065 			{
2066 				xml_special_objs[view->getObjectId()]=view->getCodeDefinition(SchemaParser::XmlDefinition);
2067 
2068 				/* Relationships linking the view and the referenced tables are considered as
2069 			 special objects in this case only to be recreated more easely latter */
2070 
2071 				count=view->getReferenceCount(Reference::SqlReferSelect);
2072 
2073 				for(i=0; i < count; i++)
2074 				{
2075 					ref=view->getReference(i, Reference::SqlReferSelect);
2076 					table=ref.getTable();
2077 
2078 					if(table)
2079 					{
2080 						//Get the relationship between the view and the referenced table
2081 						rel=getRelationship(view, table);
2082 
2083 						if(rel)
2084 						{
2085 							xml_special_objs[rel->getObjectId()]=rel->getCodeDefinition(SchemaParser::XmlDefinition);
2086 							removeRelationship(rel);
2087 							invalid_special_objs.push_back(rel);
2088 							//delete rel;
2089 						}
2090 					}
2091 				}
2092 
2093 				/* Removing child objects from view and including them in the list of objects to be recreated,
2094 		   this will avoid errors when removing the view from model */
2095 				objects=view->getObjects();
2096 				for(auto &obj : objects)
2097 				{
2098 					xml_special_objs[obj->getObjectId()]=obj->getCodeDefinition(SchemaParser::XmlDefinition);
2099 					view->removeObject(obj);
2100 					invalid_special_objs.push_back(obj);
2101 					//delete obj;
2102 				}
2103 
2104 				removeView(view);
2105 				invalid_special_objs.push_back(view);
2106 				//delete view;
2107 			}
2108 		}
2109 
2110 		//Making a copy of the permissions list to avoid iterator invalidation when removing an object
2111 		rem_objects.assign(permissions.begin(), permissions.end());
2112 		itr=rem_objects.begin();
2113 		itr_end=rem_objects.end();
2114 
2115 		while(itr!=itr_end)
2116 		{
2117 			permission=dynamic_cast<Permission *>(*itr);
2118 			tab_obj=dynamic_cast<TableObject *>(permission->getObject());
2119 			itr++;
2120 
2121 			if(tab_obj)
2122 			{
2123 				xml_special_objs[permission->getObjectId()]=permission->getCodeDefinition(SchemaParser::XmlDefinition);
2124 				removePermission(permission);
2125 				invalid_special_objs.push_back(permission);
2126 				//delete permission;
2127 			}
2128 		}
2129 
2130 		//Making a copy of the generic SQL objects list to avoid iterator invalidation when removing an object
2131 		rem_objects.assign(genericsqls.begin(), genericsqls.end());
2132 		itr=rem_objects.begin();
2133 		itr_end=rem_objects.end();
2134 
2135 		while(itr!=itr_end)
2136 		{
2137 			generic_sql = dynamic_cast<GenericSQL *>(*itr);
2138 			itr++;
2139 
2140 			if(generic_sql->isReferRelationshipAddedObject())
2141 			{
2142 				xml_special_objs[generic_sql->getObjectId()] = generic_sql->getCodeDefinition(SchemaParser::XmlDefinition);
2143 				removeGenericSQL(generic_sql);
2144 				invalid_special_objs.push_back(generic_sql);
2145 				//delete generic_sql;
2146 			}
2147 		}
2148 	}
2149 	catch(Exception &e)
2150 	{
2151 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
2152 	}
2153 }
2154 
createSpecialObject(const QString & xml_def,unsigned obj_id)2155 void DatabaseModel::createSpecialObject(const QString &xml_def, unsigned obj_id)
2156 {
2157 	ObjectType obj_type;
2158 	BaseObject *object=nullptr;
2159 
2160 	try
2161 	{
2162 		//Restart the XML parser to read the passed xml buffer
2163 		xmlparser.restartParser();
2164 		xmlparser.loadXMLBuffer(xml_def);
2165 
2166 		//Identifies the object type through the start element on xml buffer
2167 		obj_type=BaseObject::getObjectType(xmlparser.getElementName());
2168 
2169 		if(obj_type==ObjectType::Sequence)
2170 			object=createSequence(true);
2171 		else
2172 			object=createObject(obj_type);
2173 
2174 		if(obj_type==ObjectType::Sequence)
2175 			addSequence(dynamic_cast<Sequence *>(object));
2176 		else if(obj_type==ObjectType::View)
2177 			addView(dynamic_cast<View *>(object));
2178 		else if(obj_type==ObjectType::Permission)
2179 			addPermission(createPermission());
2180 
2181 		/* When the special object is recreated it receive a new id but to maintain
2182 		 the correct creation order, the object has its id restored with the passed
2183 		 id (obj_id) if it is specified */
2184 		if(object && obj_id!=0)
2185 			object->object_id=obj_id;
2186 	}
2187 	catch(Exception &e)
2188 	{
2189 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e, xml_def);
2190 	}
2191 }
2192 
addRelationship(BaseRelationship * rel,int obj_idx)2193 void DatabaseModel::addRelationship(BaseRelationship *rel, int obj_idx)
2194 {
2195 	try
2196 	{
2197 		BaseTable *tab1=nullptr, *tab2=nullptr;
2198 		QString msg;
2199 
2200 		if(rel)
2201 		{
2202 			tab1=rel->getTable(BaseRelationship::SrcTable);
2203 			tab2=rel->getTable(BaseRelationship::DstTable);
2204 
2205 			//Raises an error if already exists an relationship between the tables
2206 			if(rel->getRelationshipType() != Relationship::Relationship1n &&
2207 				 rel->getRelationshipType() != Relationship::RelationshipNn &&
2208 				 rel->getRelationshipType() != Relationship::RelationshipFk &&
2209 				 getRelationship(tab1,tab2))
2210 			{
2211 				msg=Exception::getErrorMessage(ErrorCode::InsDuplicatedRelationship)
2212 					.arg(tab1->getName(true))
2213 					.arg(tab1->getTypeName())
2214 					.arg(tab2->getName(true))
2215 					.arg(tab2->getTypeName());
2216 				throw Exception(msg,ErrorCode::InsDuplicatedRelationship,__PRETTY_FUNCTION__,__FILE__,__LINE__);
2217 			}
2218 		}
2219 
2220 		//Before add the relationship, checks if a redundancy can occur case the relationship is added
2221 		if(rel->getObjectType()==ObjectType::Relationship)
2222 			checkRelationshipRedundancy(dynamic_cast<Relationship *>(rel));
2223 
2224 		rel->blockSignals(loading_model);
2225 		__addObject(rel, obj_idx);
2226 
2227 		if(rel->getObjectType()==ObjectType::Relationship)
2228 		{
2229 			dynamic_cast<Relationship *>(rel)->connectRelationship();
2230 			validateRelationships();
2231 		}
2232 		else
2233 			rel->connectRelationship();
2234 
2235 		rel->blockSignals(false);
2236 	}
2237 	catch(Exception &e)
2238 	{
2239 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
2240 	}
2241 }
2242 
removeRelationship(BaseRelationship * rel,int obj_idx)2243 void DatabaseModel::removeRelationship(BaseRelationship *rel, int obj_idx)
2244 {
2245 	try
2246 	{
2247 		if(getObjectIndex(rel) >= 0)
2248 		{
2249 			PhysicalTable *recv_tab=nullptr;
2250 
2251 			if(rel->getObjectType()==ObjectType::Relationship)
2252 			{
2253 				/* If the relationship is not a many-to-many we store the receiver table in order to
2254 				 * update the fk relationships (if there are any) */
2255 				if(rel->getRelationshipType()!=Relationship::RelationshipNn)
2256 					recv_tab=dynamic_cast<Relationship *>(rel)->getReceiverTable();
2257 
2258 				storeSpecialObjectsXML();
2259 				disconnectRelationships();
2260 			}
2261 			else if(rel->getObjectType()==ObjectType::BaseRelationship)
2262 			{
2263 				rel->blockSignals(loading_model);
2264 				rel->disconnectRelationship();
2265 				rel->blockSignals(false);
2266 			}
2267 
2268 			__removeObject(rel, obj_idx);
2269 
2270 			if(rel->getObjectType()==ObjectType::Relationship)
2271 				validateRelationships();
2272 
2273 			//Updating the fk relationships for the receiver table after removing the old relationship
2274 			if(recv_tab && recv_tab->getObjectType() == ObjectType::Table)
2275 				updateTableFKRelationships(dynamic_cast<Table *>(recv_tab));
2276 		}
2277 	}
2278 	catch(Exception &e)
2279 	{
2280 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
2281 	}
2282 }
2283 
getRelationship(unsigned obj_idx,ObjectType rel_type)2284 BaseRelationship *DatabaseModel::getRelationship(unsigned obj_idx, ObjectType rel_type)
2285 {
2286 	//Raises an error if the object type used to get a relationship is invalid
2287 	if(rel_type!=ObjectType::Relationship && rel_type!=ObjectType::BaseRelationship)
2288 		throw Exception(ErrorCode::ObtObjectInvalidType,__PRETTY_FUNCTION__,__FILE__,__LINE__);
2289 
2290 	return dynamic_cast<BaseRelationship *>(getObject(obj_idx, rel_type));
2291 }
2292 
getRelationship(const QString & name)2293 BaseRelationship *DatabaseModel::getRelationship(const QString &name)
2294 {
2295 	BaseRelationship *rel=dynamic_cast<BaseRelationship *>(getObject(name, ObjectType::BaseRelationship));
2296 
2297 	if(!rel)
2298 		rel=dynamic_cast<BaseRelationship *>(getObject(name, ObjectType::Relationship));
2299 
2300 	return rel;
2301 }
2302 
getRelationship(BaseTable * src_tab,BaseTable * dst_tab,Constraint * ref_fk)2303 BaseRelationship *DatabaseModel::getRelationship(BaseTable *src_tab, BaseTable *dst_tab, Constraint *ref_fk)
2304 {
2305 	vector<BaseObject *>::iterator itr, itr_end;
2306 	vector<BaseObject *> rel_list;
2307 	BaseRelationship *rel=nullptr;
2308 	bool found=false, search_uniq_tab=false;
2309 	BaseTable *tab1=nullptr, *tab2=nullptr;
2310 
2311 	if(src_tab)
2312 	{
2313 		if(!dst_tab)
2314 		{
2315 			dst_tab=src_tab;
2316 			search_uniq_tab=true;
2317 		}
2318 
2319 		if(ref_fk || src_tab->getObjectType()==ObjectType::View || dst_tab->getObjectType()==ObjectType::View)
2320 		{
2321 			itr=base_relationships.begin();
2322 			itr_end=base_relationships.end();
2323 		}
2324 		else
2325 		{
2326 			rel_list.assign(base_relationships.begin(), base_relationships.end());
2327 			rel_list.insert(rel_list.end(), relationships.begin(), relationships.end());
2328 			itr=rel_list.begin();
2329 			itr_end=rel_list.end();
2330 		}
2331 
2332 		while(itr!=itr_end && !found)
2333 		{
2334 			rel=dynamic_cast<BaseRelationship *>(*itr);
2335 			tab1=rel->getTable(BaseRelationship::SrcTable);
2336 			tab2=rel->getTable(BaseRelationship::DstTable);
2337 
2338 			found=((!ref_fk || (ref_fk && rel->getReferenceForeignKey() == ref_fk)) &&
2339 						 ((tab1==src_tab && tab2==dst_tab) ||
2340 							(tab2==src_tab && tab1==dst_tab) ||
2341 							(search_uniq_tab && (tab1==src_tab || tab2==src_tab))));
2342 
2343 			if(!found)
2344 			{ rel=nullptr; itr++; }
2345 		}
2346 	}
2347 
2348 	return rel;
2349 }
2350 
getRelationships(BaseTable * tab)2351 vector<BaseRelationship *> DatabaseModel::getRelationships(BaseTable *tab)
2352 {
2353 	vector<BaseRelationship *> aux_rels;
2354 	vector<BaseObject *> rels;
2355 	BaseRelationship *base_rel=nullptr;
2356 
2357 	rels=base_relationships;
2358 	rels.insert(rels.end(), relationships.begin(), relationships.end());
2359 
2360 	for(auto &obj : rels)
2361 	{
2362 		base_rel=dynamic_cast<BaseRelationship *>(obj);
2363 
2364 		if(base_rel->getTable(BaseRelationship::SrcTable)==tab ||
2365 			 base_rel->getTable(BaseRelationship::DstTable)==tab)
2366 			aux_rels.push_back(base_rel);
2367 	}
2368 
2369 	return aux_rels;
2370 }
2371 
addTextbox(Textbox * txtbox,int obj_idx)2372 void DatabaseModel::addTextbox(Textbox *txtbox, int obj_idx)
2373 {
2374 	try
2375 	{
2376 		__addObject(txtbox, obj_idx);
2377 	}
2378 	catch(Exception &e)
2379 	{
2380 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
2381 	}
2382 }
2383 
removeTextbox(Textbox * txtbox,int obj_idx)2384 void DatabaseModel::removeTextbox(Textbox *txtbox, int obj_idx)
2385 {
2386 	try
2387 	{
2388 		__removeObject(txtbox, obj_idx);
2389 	}
2390 	catch(Exception &e)
2391 	{
2392 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
2393 	}
2394 }
2395 
getTextbox(unsigned obj_idx)2396 Textbox *DatabaseModel::getTextbox(unsigned obj_idx)
2397 {
2398 	return dynamic_cast<Textbox *>(getObject(obj_idx, ObjectType::Textbox));
2399 }
2400 
getTextbox(const QString & name)2401 Textbox *DatabaseModel::getTextbox(const QString &name)
2402 {
2403 	return dynamic_cast<Textbox *>(getObject(name, ObjectType::Textbox));
2404 }
2405 
addSchema(Schema * schema,int obj_idx)2406 void DatabaseModel::addSchema(Schema *schema, int obj_idx)
2407 {
2408 	try
2409 	{
2410 		__addObject(schema, obj_idx);
2411 	}
2412 	catch(Exception &e)
2413 	{
2414 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
2415 	}
2416 }
2417 
getSchema(unsigned obj_idx)2418 Schema *DatabaseModel::getSchema(unsigned obj_idx)
2419 {
2420 	return dynamic_cast<Schema *>(getObject(obj_idx, ObjectType::Schema));
2421 }
2422 
getSchema(const QString & name)2423 Schema *DatabaseModel::getSchema(const QString &name)
2424 {
2425 	return dynamic_cast<Schema *>(getObject(name, ObjectType::Schema));
2426 }
2427 
removeSchema(Schema * schema,int obj_idx)2428 void DatabaseModel::removeSchema(Schema *schema, int obj_idx)
2429 {
2430 	try
2431 	{
2432 		__removeObject(schema, obj_idx);
2433 	}
2434 	catch(Exception &e)
2435 	{
2436 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
2437 	}
2438 }
2439 
addRole(Role * role,int obj_idx)2440 void DatabaseModel::addRole(Role *role, int obj_idx)
2441 {
2442 	try
2443 	{
2444 		__addObject(role, obj_idx);
2445 	}
2446 	catch(Exception &e)
2447 	{
2448 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
2449 	}
2450 }
2451 
getRole(unsigned obj_idx)2452 Role *DatabaseModel::getRole(unsigned obj_idx)
2453 {
2454 	return dynamic_cast<Role *>(getObject(obj_idx, ObjectType::Role));
2455 }
2456 
getRole(const QString & name)2457 Role *DatabaseModel::getRole(const QString &name)
2458 {
2459 	return dynamic_cast<Role *>(getObject(name, ObjectType::Role));
2460 }
2461 
removeRole(Role * role,int obj_idx)2462 void DatabaseModel::removeRole(Role *role, int obj_idx)
2463 {
2464 	try
2465 	{
2466 		__removeObject(role, obj_idx);
2467 	}
2468 	catch(Exception &e)
2469 	{
2470 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
2471 	}
2472 }
2473 
addTablespace(Tablespace * tabspc,int obj_idx)2474 void DatabaseModel::addTablespace(Tablespace *tabspc, int obj_idx)
2475 {
2476 	try
2477 	{
2478 		__addObject(tabspc, obj_idx);
2479 	}
2480 	catch(Exception &e)
2481 	{
2482 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
2483 	}
2484 }
2485 
getTablespace(unsigned obj_idx)2486 Tablespace *DatabaseModel::getTablespace(unsigned obj_idx)
2487 {
2488 	return dynamic_cast<Tablespace *>(getObject(obj_idx, ObjectType::Tablespace));
2489 }
2490 
getTablespace(const QString & name)2491 Tablespace *DatabaseModel::getTablespace(const QString &name)
2492 {
2493 	return dynamic_cast<Tablespace *>(getObject(name, ObjectType::Tablespace));
2494 }
2495 
removeTablespace(Tablespace * tabspc,int obj_idx)2496 void DatabaseModel::removeTablespace(Tablespace *tabspc, int obj_idx)
2497 {
2498 	try
2499 	{
2500 		__removeObject(tabspc, obj_idx);
2501 	}
2502 	catch(Exception &e)
2503 	{
2504 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
2505 	}
2506 }
2507 
addCast(Cast * cast,int obj_idx)2508 void DatabaseModel::addCast(Cast *cast, int obj_idx)
2509 {
2510 	try
2511 	{
2512 		__addObject(cast, obj_idx);
2513 	}
2514 	catch(Exception &e)
2515 	{
2516 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
2517 	}
2518 }
2519 
removeCast(Cast * cast,int obj_idx)2520 void DatabaseModel::removeCast(Cast *cast, int obj_idx)
2521 {
2522 	try
2523 	{
2524 		__removeObject(cast, obj_idx);
2525 	}
2526 	catch(Exception &e)
2527 	{
2528 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
2529 	}
2530 }
2531 
getCast(unsigned obj_idx)2532 Cast *DatabaseModel::getCast(unsigned obj_idx)
2533 {
2534 	return dynamic_cast<Cast *>(getObject(obj_idx, ObjectType::Cast));
2535 }
2536 
getCast(const QString & name)2537 Cast *DatabaseModel::getCast(const QString &name)
2538 {
2539 	return dynamic_cast<Cast *>(getObject(name, ObjectType::Cast));
2540 }
2541 
addConversion(Conversion * conv,int obj_idx)2542 void DatabaseModel::addConversion(Conversion *conv, int obj_idx)
2543 {
2544 	try
2545 	{
2546 		__addObject(conv, obj_idx);
2547 	}
2548 	catch(Exception &e)
2549 	{
2550 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
2551 	}
2552 }
2553 
removeConversion(Conversion * conv,int obj_idx)2554 void DatabaseModel::removeConversion(Conversion *conv, int obj_idx)
2555 {
2556 	try
2557 	{
2558 		__removeObject(conv, obj_idx);
2559 	}
2560 	catch(Exception &e)
2561 	{
2562 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
2563 	}
2564 }
2565 
getConversion(unsigned obj_idx)2566 Conversion *DatabaseModel::getConversion(unsigned obj_idx)
2567 {
2568 	return dynamic_cast<Conversion *>(getObject(obj_idx, ObjectType::Conversion));
2569 }
2570 
getConversion(const QString & name)2571 Conversion *DatabaseModel::getConversion(const QString &name)
2572 {
2573 	return dynamic_cast<Conversion *>(getObject(name, ObjectType::Conversion));
2574 }
2575 
addLanguage(Language * lang,int obj_idx)2576 void DatabaseModel::addLanguage(Language *lang, int obj_idx)
2577 {
2578 	try
2579 	{
2580 		__addObject(lang, obj_idx);
2581 	}
2582 	catch(Exception &e)
2583 	{
2584 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
2585 	}
2586 }
2587 
getLanguage(unsigned obj_idx)2588 Language *DatabaseModel::getLanguage(unsigned obj_idx)
2589 {
2590 	return dynamic_cast<Language *>(getObject(obj_idx, ObjectType::Language));
2591 }
2592 
getLanguage(const QString & name)2593 Language *DatabaseModel::getLanguage(const QString &name)
2594 {
2595 	return dynamic_cast<Language *>(getObject(name, ObjectType::Language));
2596 }
2597 
removeLanguage(Language * lang,int obj_idx)2598 void DatabaseModel::removeLanguage(Language *lang, int obj_idx)
2599 {
2600 	try
2601 	{
2602 		__removeObject(lang, obj_idx);
2603 	}
2604 	catch(Exception &e)
2605 	{
2606 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
2607 	}
2608 }
2609 
addFunction(Function * func,int obj_idx)2610 void DatabaseModel::addFunction(Function *func, int obj_idx)
2611 {
2612 	try
2613 	{
2614 		__addObject(func, obj_idx);
2615 	}
2616 	catch(Exception &e)
2617 	{
2618 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
2619 	}
2620 }
2621 
getFunction(unsigned obj_idx)2622 Function *DatabaseModel::getFunction(unsigned obj_idx)
2623 {
2624 	return dynamic_cast<Function *>(getObject(obj_idx, ObjectType::Function));
2625 }
2626 
getFunction(const QString & signature)2627 Function *DatabaseModel::getFunction(const QString &signature)
2628 {
2629 	return dynamic_cast<Function *>(getObject(signature, ObjectType::Function));
2630 }
2631 
removeFunction(Function * func,int obj_idx)2632 void DatabaseModel::removeFunction(Function *func, int obj_idx)
2633 {
2634 	try
2635 	{
2636 		__removeObject(func, obj_idx);
2637 	}
2638 	catch(Exception &e)
2639 	{
2640 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
2641 	}
2642 }
2643 
addAggregate(Aggregate * aggreg,int obj_idx)2644 void DatabaseModel::addAggregate(Aggregate *aggreg, int obj_idx)
2645 {
2646 	try
2647 	{
2648 		__addObject(aggreg, obj_idx);
2649 	}
2650 	catch(Exception &e)
2651 	{
2652 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
2653 	}
2654 }
2655 
getAggregate(unsigned obj_idx)2656 Aggregate *DatabaseModel::getAggregate(unsigned obj_idx)
2657 {
2658 	return dynamic_cast<Aggregate *>(getObject(obj_idx, ObjectType::Aggregate));
2659 }
2660 
getAggregate(const QString & name)2661 Aggregate *DatabaseModel::getAggregate(const QString &name)
2662 {
2663 	return dynamic_cast<Aggregate *>(getObject(name, ObjectType::Aggregate));
2664 }
2665 
removeAggregate(Aggregate * aggreg,int obj_idx)2666 void DatabaseModel::removeAggregate(Aggregate *aggreg, int obj_idx)
2667 {
2668 	try
2669 	{
2670 		__removeObject(aggreg, obj_idx);
2671 	}
2672 	catch(Exception &e)
2673 	{
2674 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
2675 	}
2676 }
2677 
addDomain(Domain * domain,int obj_idx)2678 void DatabaseModel::addDomain(Domain *domain, int obj_idx)
2679 {
2680 	if(domain)
2681 	{
2682 		vector<BaseObject *>::iterator itr, itr_end;
2683 		bool found=false;
2684 		QString str_aux;
2685 
2686 		/* Before insert the domain checks if there is some user defined type
2687 		 with the same name as the domain. */
2688 		itr=types.begin();
2689 		itr_end=types.end();
2690 		while(itr!=itr_end && !found)
2691 		{
2692 			found=((*itr)->getName(true)==domain->getName(true));
2693 			itr++;
2694 		}
2695 
2696 		//Raises an error if found a type with the same name as the domain
2697 		if(found)
2698 		{
2699 			str_aux=Exception::getErrorMessage(ErrorCode::AsgDuplicatedObject)
2700 					.arg(domain->getName(true))
2701 					.arg(domain->getTypeName())
2702 					.arg(this->getName(true))
2703 					.arg(this->getTypeName());
2704 			throw Exception(str_aux, ErrorCode::AsgDuplicatedObject,__PRETTY_FUNCTION__,__FILE__,__LINE__);
2705 		}
2706 
2707 		try
2708 		{
2709 			__addObject(domain, obj_idx);
2710 
2711 			//When added to the model the domain is inserted on the pgsql base type list to be used as a column type
2712 			PgSqlType::addUserType(domain->getName(true), domain, this, UserTypeConfig::DomainType);
2713 		}
2714 		catch(Exception &e)
2715 		{
2716 			throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
2717 		}
2718 	}
2719 }
2720 
removeDomain(Domain * domain,int obj_idx)2721 void DatabaseModel::removeDomain(Domain *domain, int obj_idx)
2722 {
2723 	try
2724 	{
2725 		removeUserType(domain, obj_idx);
2726 	}
2727 	catch(Exception &e)
2728 	{
2729 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
2730 	}
2731 }
2732 
getDomain(unsigned obj_idx)2733 Domain *DatabaseModel::getDomain(unsigned obj_idx)
2734 {
2735 	return dynamic_cast<Domain *>(getObject(obj_idx, ObjectType::Domain));
2736 }
2737 
getDomain(const QString & name)2738 Domain *DatabaseModel::getDomain(const QString &name)
2739 {
2740 	return dynamic_cast<Domain *>(getObject(name, ObjectType::Domain));
2741 }
2742 
addOperatorFamily(OperatorFamily * op_family,int obj_idx)2743 void DatabaseModel::addOperatorFamily(OperatorFamily *op_family, int obj_idx)
2744 {
2745 	try
2746 	{
2747 		__addObject(op_family, obj_idx);
2748 	}
2749 	catch(Exception &e)
2750 	{
2751 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
2752 	}
2753 }
2754 
getOperatorFamily(unsigned obj_idx)2755 OperatorFamily *DatabaseModel::getOperatorFamily(unsigned obj_idx)
2756 {
2757 	return dynamic_cast<OperatorFamily *>(getObject(obj_idx, ObjectType::OpFamily));
2758 }
2759 
getOperatorFamily(const QString & name)2760 OperatorFamily *DatabaseModel::getOperatorFamily(const QString &name)
2761 {
2762 	return dynamic_cast<OperatorFamily *>(getObject(name, ObjectType::OpFamily));
2763 }
2764 
removeOperatorFamily(OperatorFamily * op_family,int obj_idx)2765 void DatabaseModel::removeOperatorFamily(OperatorFamily *op_family, int obj_idx)
2766 {
2767 	try
2768 	{
2769 		__removeObject(op_family, obj_idx);
2770 	}
2771 	catch(Exception &e)
2772 	{
2773 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
2774 	}
2775 }
2776 
addOperatorClass(OperatorClass * op_class,int obj_idx)2777 void DatabaseModel::addOperatorClass(OperatorClass *op_class, int obj_idx)
2778 {
2779 	try
2780 	{
2781 		__addObject(op_class, obj_idx);
2782 	}
2783 	catch(Exception &e)
2784 	{
2785 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
2786 	}
2787 }
2788 
removeOperatorClass(OperatorClass * op_class,int obj_idx)2789 void DatabaseModel::removeOperatorClass(OperatorClass *op_class, int obj_idx)
2790 {
2791 	try
2792 	{
2793 		__removeObject(op_class, obj_idx);
2794 	}
2795 	catch(Exception &e)
2796 	{
2797 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
2798 	}
2799 }
2800 
getOperatorClass(unsigned obj_idx)2801 OperatorClass *DatabaseModel::getOperatorClass(unsigned obj_idx)
2802 {
2803 	return dynamic_cast<OperatorClass *>(getObject(obj_idx, ObjectType::OpClass));
2804 }
2805 
getOperatorClass(const QString & name)2806 OperatorClass *DatabaseModel::getOperatorClass(const QString &name)
2807 {
2808 	return dynamic_cast<OperatorClass *>(getObject(name, ObjectType::OpClass));
2809 }
2810 
addOperator(Operator * oper,int obj_idx)2811 void DatabaseModel::addOperator(Operator *oper, int obj_idx)
2812 {
2813 	try
2814 	{
2815 		__addObject(oper, obj_idx);
2816 	}
2817 	catch(Exception &e)
2818 	{
2819 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
2820 	}
2821 }
2822 
removeOperator(Operator * oper,int obj_idx)2823 void DatabaseModel::removeOperator(Operator *oper, int obj_idx)
2824 {
2825 	try
2826 	{
2827 		__removeObject(oper, obj_idx);
2828 	}
2829 	catch(Exception &e)
2830 	{
2831 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
2832 	}
2833 }
2834 
getOperator(unsigned obj_idx)2835 Operator *DatabaseModel::getOperator(unsigned obj_idx)
2836 {
2837 	return dynamic_cast<Operator *>(getObject(obj_idx, ObjectType::Operator));
2838 }
2839 
getOperator(const QString & signature)2840 Operator *DatabaseModel::getOperator(const QString &signature)
2841 {
2842 	return dynamic_cast<Operator *>(getObject(signature, ObjectType::Operator));
2843 }
2844 
addType(Type * type,int obj_idx)2845 void DatabaseModel::addType(Type *type, int obj_idx)
2846 {
2847 	if(type)
2848 	{
2849 		vector<BaseObject *>::iterator itr, itr_end;
2850 		bool found=false;
2851 		QString str_aux;
2852 
2853 		/* Before insert the type checks if there is some domain
2854 		 with the same name as the type. */
2855 		itr=domains.begin();
2856 		itr_end=domains.end();
2857 		while(itr!=itr_end && !found)
2858 		{
2859 			found=((*itr)->getName(true)==type->getName(true));
2860 			itr++;
2861 		}
2862 
2863 		if(found)
2864 		{
2865 			str_aux=Exception::getErrorMessage(ErrorCode::AsgDuplicatedObject)
2866 					.arg(type->getName(true))
2867 					.arg(type->getTypeName())
2868 					.arg(this->getName(true))
2869 					.arg(this->getTypeName());
2870 			throw Exception(str_aux, ErrorCode::AsgDuplicatedObject,__PRETTY_FUNCTION__,__FILE__,__LINE__);
2871 		}
2872 
2873 		try
2874 		{
2875 			__addObject(type, obj_idx);
2876 
2877 			//When added to the model the user type is inserted on the pgsql base type list to be used as a column type
2878 			PgSqlType::addUserType(type->getName(true), type, this, UserTypeConfig::BaseType);
2879 		}
2880 		catch(Exception &e)
2881 		{
2882 			throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
2883 		}
2884 	}
2885 }
2886 
removeType(Type * type,int obj_idx)2887 void DatabaseModel::removeType(Type *type, int obj_idx)
2888 {
2889 	try
2890 	{
2891 		removeUserType(type, obj_idx);
2892 	}
2893 	catch(Exception &e)
2894 	{
2895 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
2896 	}
2897 }
2898 
getType(unsigned obj_idx)2899 Type *DatabaseModel::getType(unsigned obj_idx)
2900 {
2901 	return dynamic_cast<Type *>(getObject(obj_idx, ObjectType::Type));
2902 }
2903 
getType(const QString & name)2904 Type *DatabaseModel::getType(const QString &name)
2905 {
2906 	return dynamic_cast<Type *>(getObject(name, ObjectType::Type));
2907 }
2908 
removeUserType(BaseObject * object,int obj_idx)2909 void DatabaseModel::removeUserType(BaseObject *object, int obj_idx)
2910 {
2911 	try
2912 	{
2913 		__removeObject(object, obj_idx);
2914 
2915 		//Removes the user type from the list of base types of pgsql
2916 		PgSqlType::removeUserType(object->getName(true), object);
2917 	}
2918 	catch(Exception &e)
2919 	{
2920 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
2921 	}
2922 }
2923 
addPermissions(const vector<Permission * > & perms)2924 void DatabaseModel::addPermissions(const vector<Permission *> &perms)
2925 {
2926 	vector<Permission *>::const_iterator itr=perms.cbegin(), itr_end=perms.cend();
2927 
2928 	try
2929 	{
2930 		while(itr!=itr_end)
2931 		{
2932 			addPermission(*itr);
2933 			itr++;
2934 		}
2935 	}
2936 	catch(Exception &e)
2937 	{
2938 		//In case of errors removes the added permissions
2939 		itr=perms.begin();
2940 		itr_end=perms.end();
2941 
2942 		while(itr!=itr_end)
2943 		{
2944 			removePermission(*itr);
2945 			itr++;
2946 		}
2947 
2948 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
2949 	}
2950 }
2951 
addPermission(Permission * perm)2952 void DatabaseModel::addPermission(Permission *perm)
2953 {
2954 	try
2955 	{
2956 		if(!perm)
2957 			throw Exception(ErrorCode::AsgNotAllocattedObject,__PRETTY_FUNCTION__,__FILE__,__LINE__);
2958 
2959 		TableObject *tab_obj=dynamic_cast<TableObject *>(perm->getObject());
2960 
2961 		if(getPermissionIndex(perm, false) >=0)
2962 		{
2963 			throw Exception(Exception::getErrorMessage(ErrorCode::AsgDuplicatedPermission)
2964 							.arg(perm->getObject()->getName())
2965 							.arg(perm->getObject()->getTypeName()),
2966 							ErrorCode::AsgDuplicatedPermission,__PRETTY_FUNCTION__,__FILE__,__LINE__);
2967 		}
2968 		//Raises an error if the permission is referencing an object that does not exists on model
2969 		else if(perm->getObject()!=this &&
2970 				((tab_obj && (getObjectIndex(tab_obj->getParentTable()) < 0)) ||
2971 				 (!tab_obj && (getObjectIndex(perm->getObject()) < 0))))
2972 			throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
2973 							.arg(perm->getName())
2974 							.arg(perm->getObject()->getTypeName())
2975 							.arg(perm->getObject()->getName())
2976 							.arg(perm->getObject()->getTypeName()),
2977 							ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
2978 
2979 		permissions.push_back(perm);
2980 		perm->setDatabase(this);
2981 	}
2982 	catch(Exception &e)
2983 	{
2984 		if(e.getErrorCode()==ErrorCode::AsgDuplicatedObject)
2985 			throw
2986 			Exception(Exception::getErrorMessage(ErrorCode::AsgDuplicatedPermission)
2987 					  .arg(perm->getObject()->getName())
2988 					  .arg(perm->getObject()->getTypeName()),
2989 						ErrorCode::AsgDuplicatedPermission,__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
2990 
2991 		else
2992 			throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
2993 	}
2994 }
2995 
removePermission(Permission * perm)2996 void DatabaseModel::removePermission(Permission *perm)
2997 {
2998 	try
2999 	{
3000 		__removeObject(perm);
3001 	}
3002 	catch(Exception &e)
3003 	{
3004 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
3005 	}
3006 }
3007 
removePermissions(BaseObject * object)3008 void DatabaseModel::removePermissions(BaseObject *object)
3009 {
3010 	vector<BaseObject *>::iterator itr, itr_end;
3011 	Permission *perm=nullptr;
3012 	unsigned idx=0;
3013 
3014 	if(!object)
3015 		throw Exception(ErrorCode::OprNotAllocatedObject,__PRETTY_FUNCTION__,__FILE__,__LINE__);
3016 
3017 	itr=permissions.begin();
3018 	itr_end=permissions.end();
3019 
3020 	while(itr!=itr_end)
3021 	{
3022 		perm=dynamic_cast<Permission *>(*itr);
3023 
3024 		if(perm->getObject()==object)
3025 		{
3026 			invalid_special_objs.push_back(perm);
3027 
3028 			permissions.erase(itr);
3029 			itr=itr_end=permissions.end();
3030 
3031 			if(!permissions.empty())
3032 				itr=permissions.begin() + idx;
3033 		}
3034 		else
3035 		{ itr++; idx++; }
3036 	}
3037 }
3038 
getPermissions(BaseObject * object,vector<Permission * > & perms)3039 void DatabaseModel::getPermissions(BaseObject *object, vector<Permission *> &perms)
3040 {
3041 	vector<BaseObject *>::iterator itr, itr_end;
3042 	Permission *perm=nullptr;
3043 
3044 	if(!object)
3045 		throw Exception(ErrorCode::OprNotAllocatedObject,__PRETTY_FUNCTION__,__FILE__,__LINE__);
3046 
3047 	itr=permissions.begin();
3048 	itr_end=permissions.end();
3049 
3050 	perms.clear();
3051 
3052 	while(itr!=itr_end)
3053 	{
3054 		perm=dynamic_cast<Permission *>(*itr);
3055 
3056 		if(perm->getObject()==object)
3057 			perms.push_back(perm);
3058 
3059 		itr++;
3060 	}
3061 }
3062 
getPermissionIndex(Permission * perm,bool exact_match)3063 int DatabaseModel::getPermissionIndex(Permission *perm, bool exact_match)
3064 {
3065 	int perm_idx=-1;
3066 
3067 	if(perm)
3068 	{
3069 		Permission *perm_aux=nullptr;
3070 		vector<BaseObject *>::iterator itr, itr_end;
3071 
3072 		itr=permissions.begin();
3073 		itr_end=permissions.end();
3074 
3075 		if(exact_match)
3076 		{
3077 			while(itr!=itr_end)
3078 			{
3079 				perm_aux=dynamic_cast<Permission *>(*itr);
3080 
3081 				if(perm->isSimilarTo(perm_aux))
3082 				{
3083 					perm_idx=itr-permissions.begin();
3084 					break;
3085 				}
3086 
3087 				itr++;
3088 			}
3089 		}
3090 		else
3091 		{
3092 			BaseObject *object=nullptr;
3093 			Role *role=nullptr;
3094 			unsigned count, i;
3095 			bool ref_role=false;
3096 
3097 			object=perm->getObject();
3098 
3099 			while(itr!=itr_end)
3100 			{
3101 				perm_aux=dynamic_cast<Permission *>(*itr);
3102 
3103 				/* When the object of the auxiliary permission is the same as the
3104 		   specified permission it will be check if the existant roles are
3105 		   the same on both permissions */
3106 				if(object==perm_aux->getObject())
3107 				{
3108 					count=perm->getRoleCount();
3109 
3110 					for(i=0; i < count && !ref_role; i++)
3111 					{
3112 						role=perm->getRole(i);
3113 						ref_role=perm_aux->isRoleExists(role);
3114 					}
3115 				}
3116 
3117 				//If the permissions references the same roles but one is a REVOKE and other GRANT they a considered different
3118 				if(perm==perm_aux || (ref_role && perm->isRevoke()==perm_aux->isRevoke()))
3119 				{
3120 					perm_idx=itr-permissions.begin();
3121 					break;
3122 				}
3123 
3124 				itr++;
3125 			}
3126 		}
3127 	}
3128 
3129 	return perm_idx;
3130 }
3131 
getObject(const QString & name,ObjectType obj_type)3132 BaseObject *DatabaseModel::getObject(const QString &name, ObjectType obj_type)
3133 {
3134 	int idx;
3135 	return getObject(name, obj_type, idx);
3136 }
3137 
getObjectIndex(const QString & name,ObjectType obj_type)3138 int DatabaseModel::getObjectIndex(const QString &name, ObjectType obj_type)
3139 {
3140 	int idx;
3141 	getObject(name, obj_type, idx);
3142 	return idx;
3143 }
3144 
getObjectIndex(BaseObject * object)3145 int DatabaseModel::getObjectIndex(BaseObject *object)
3146 {
3147 	if(!object)
3148 		return -1;
3149 	else
3150 	{
3151 		ObjectType obj_type=object->getObjectType();
3152 		vector<BaseObject *> *obj_list=nullptr;
3153 		vector<BaseObject *>::iterator itr, itr_end;
3154 		bool found=false;
3155 
3156 		obj_list=getObjectList(obj_type);
3157 
3158 		if(!obj_list)
3159 			throw Exception(ErrorCode::ObtObjectInvalidType,__PRETTY_FUNCTION__,__FILE__,__LINE__);
3160 		else
3161 		{
3162 			itr=obj_list->begin();
3163 			itr_end=obj_list->end();
3164 
3165 			while(itr!=itr_end && !found)
3166 			{
3167 				found=((*itr)==object);
3168 				if(!found) itr++;
3169 			}
3170 
3171 			if(found)
3172 				return itr - obj_list->begin();
3173 			else
3174 				return -1;
3175 		}
3176 	}
3177 }
3178 
configureDatabase(attribs_map & attribs)3179 void DatabaseModel::configureDatabase(attribs_map &attribs)
3180 {
3181 	encoding=attribs[Attributes::Encoding];
3182 	template_db=attribs[Attributes::TemplateDb];
3183 	localizations[0]=attribs[Attributes::LcCtype];
3184 	localizations[1]=attribs[Attributes::LcCollate];
3185 	append_at_eod=attribs[Attributes::AppendAtEod]==Attributes::True;
3186 	prepend_at_bod=attribs[Attributes::PrependAtBod]==Attributes::True;
3187 	is_template=attribs[Attributes::IsTemplate]==Attributes::True;
3188 	allow_conns=attribs[Attributes::AllowConns] != Attributes::False;
3189 
3190 	if(!attribs[Attributes::ConnLimit].isEmpty())
3191 		conn_limit=attribs[Attributes::ConnLimit].toInt();
3192 
3193 	setBasicAttributes(this);
3194 }
3195 
loadModel(const QString & filename)3196 void DatabaseModel::loadModel(const QString &filename)
3197 {
3198 	if(!filename.isEmpty())
3199 	{
3200 		QString dtd_file, str_aux, elem_name;
3201 		ObjectType obj_type;
3202 		attribs_map attribs;
3203 		BaseObject *object=nullptr;
3204 		bool protected_model=false, found_inh_rel = false;
3205 		QStringList pos_str;
3206 		map<ObjectType, QString> def_objs;
3207 
3208 		//Configuring the path to the base path for objects DTD
3209 		dtd_file=GlobalAttributes::getSchemasRootDir() +
3210 						 GlobalAttributes::DirSeparator +
3211 						 GlobalAttributes::XMLSchemaDir +
3212 						 GlobalAttributes::DirSeparator +
3213 						 GlobalAttributes::ObjectDTDDir +
3214 						 GlobalAttributes::DirSeparator;
3215 
3216 		try
3217 		{
3218 			loading_model=true;
3219 			xmlparser.restartParser();
3220 
3221 			//Loads the root DTD
3222 			xmlparser.setDTDFile(dtd_file + GlobalAttributes::RootDTD +
3223 								 GlobalAttributes::ObjectDTDExt,
3224 								 GlobalAttributes::RootDTD);
3225 
3226 			//Loads the file validating it against the root DTD
3227 			xmlparser.loadXMLFile(filename);
3228 
3229 			//Gets the basic model information
3230 			xmlparser.getElementAttributes(attribs);
3231 
3232 			setObjectListsCapacity(attribs[Attributes::MaxObjCount].toUInt());
3233 
3234 			this->author=attribs[Attributes::ModelAuthor];
3235 
3236 			pos_str=attribs[Attributes::LastPosition].split(',');
3237 
3238 			if(pos_str.size()>=2)
3239 				this->last_pos=QPoint(pos_str[0].toUInt(),pos_str[1].toUInt());
3240 
3241 			this->last_zoom=attribs[Attributes::LastZoom].toDouble();
3242 			if(this->last_zoom <= 0) this->last_zoom=1;
3243 
3244 			this->is_template = attribs[Attributes::IsTemplate] == Attributes::True;
3245 			this->allow_conns = (attribs[Attributes::AllowConns].isEmpty() ||
3246 													 attribs[Attributes::AllowConns] == Attributes::True);
3247 
3248 			persist_changelog = attribs[Attributes::UseChangelog] == Attributes::True;
3249 			layers = attribs[Attributes::Layers].split(';', QtCompat::SkipEmptyParts);
3250 			active_layers.clear();
3251 
3252 			/* Compatibility with models created prior the layers features:
3253 			 * If the "active-layers" is absent we make the default layer always visible */
3254 			if(!attribs.count(Attributes::ActiveLayers))
3255 				active_layers.push_back(0);
3256 			else
3257 			{
3258 				for(auto &layer_id : attribs[Attributes::ActiveLayers].split(';', QtCompat::SkipEmptyParts))
3259 					active_layers.push_back(layer_id.toInt());
3260 			}
3261 
3262 			protected_model=(attribs[Attributes::Protected]==Attributes::True);
3263 
3264 			def_objs[ObjectType::Schema]=attribs[Attributes::DefaultSchema];
3265 			def_objs[ObjectType::Role]=attribs[Attributes::DefaultOwner];
3266 			def_objs[ObjectType::Collation]=attribs[Attributes::DefaultCollation];
3267 			def_objs[ObjectType::Tablespace]=attribs[Attributes::DefaultTablespace];
3268 
3269 			if(xmlparser.accessElement(XmlParser::ChildElement))
3270 			{
3271 				do
3272 				{
3273 					if(xmlparser.getElementType()==XML_ELEMENT_NODE)
3274 					{
3275 						elem_name=xmlparser.getElementName();
3276 
3277 						//Indentifies the object type to be load according to the current element on the parser
3278 						obj_type=getObjectType(elem_name);
3279 
3280 						if(elem_name == Attributes::Changelog)
3281 						{
3282 							attribs_map entry_attr;
3283 							xmlparser.savePosition();
3284 
3285 							if(xmlparser.accessElement(XmlParser::ChildElement))
3286 							{
3287 								do
3288 								{
3289 									xmlparser.getElementAttributes(entry_attr);
3290 									addChangelogEntry(entry_attr[Attributes::Signature], entry_attr[Attributes::Type],
3291 																		entry_attr[Attributes::Action], entry_attr[Attributes::Date]);
3292 								}
3293 								while(xmlparser.accessElement(XmlParser::NextElement));
3294 							}
3295 
3296 							xmlparser.restorePosition();
3297 						}
3298 						else if(obj_type==ObjectType::Database)
3299 						{
3300 							xmlparser.getElementAttributes(attribs);
3301 							configureDatabase(attribs);
3302 						}
3303 						else
3304 						{
3305 							try
3306 							{
3307 								//Saves the current position of the parser before create any object
3308 								xmlparser.savePosition();
3309 								object=createObject(obj_type);
3310 
3311 								if(object)
3312 								{
3313 									if(!dynamic_cast<TableObject *>(object) && obj_type!=ObjectType::Relationship && obj_type!=ObjectType::BaseRelationship)
3314 										addObject(object);
3315 
3316 									/* If there is at least one inheritance relationship we need to flag this situation
3317 									 in order to do an addtional rel. validation in the end of loading */
3318 									if(!found_inh_rel && object->getObjectType()==ObjectType::Relationship &&
3319 											dynamic_cast<Relationship *>(object)->getRelationshipType()==BaseRelationship::RelationshipGen)
3320 										found_inh_rel=true;
3321 
3322 									emit s_objectLoaded((xmlparser.getCurrentBufferLine()/static_cast<double>(xmlparser.getBufferLineCount()))*100,
3323 														tr("Loading: `%1' (%2)")
3324 														.arg(object->getName())
3325 														.arg(object->getTypeName()),
3326 														enum_cast(obj_type));
3327 								}
3328 
3329 								xmlparser.restorePosition();
3330 							}
3331 							catch(Exception &e)
3332 							{
3333 								QString info_adicional=QString(QObject::tr("%1 (line: %2)")).arg(xmlparser.getLoadedFilename()).arg(xmlparser.getCurrentElement()->line);
3334 								throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, info_adicional);
3335 							}
3336 						}
3337 					}
3338 				}
3339 				while(xmlparser.accessElement(XmlParser::NextElement));
3340 			}
3341 
3342 			this->BaseObject::setProtected(protected_model);
3343 
3344 			//Validating default objects
3345 			for(auto &itr : def_objs)
3346 			{
3347 				if(!itr.second.isEmpty())
3348 				{
3349 					object=this->getObject(itr.second, itr.first);
3350 
3351 					if(!object)
3352 						throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
3353 										.arg(this->getName())
3354 										.arg(this->getTypeName())
3355 										.arg(itr.second)
3356 										.arg(BaseObject::getTypeName(itr.first)),
3357 										ErrorCode::AsgDuplicatedPermission,__PRETTY_FUNCTION__,__FILE__,__LINE__);
3358 
3359 					this->setDefaultObject(object);
3360 				}
3361 				else
3362 					this->setDefaultObject(nullptr, itr.first);
3363 			}
3364 
3365 			loading_model=false;
3366 
3367 			//If there are relationship make a relationship validation to recreate any special object left behind
3368 			if(!relationships.empty())
3369 			{
3370 				emit s_objectLoaded(100, tr("Validating relationships..."), enum_cast(ObjectType::Relationship));
3371 				storeSpecialObjectsXML();
3372 				disconnectRelationships();
3373 				validateRelationships();
3374 			}
3375 
3376 			this->setInvalidated(false);
3377 			emit s_objectLoaded(100, tr("Validating relationships..."), enum_cast(ObjectType::Relationship));
3378 
3379 			//Doing another relationship validation when there are inheritances to avoid incomplete tables
3380 			if(found_inh_rel)
3381 			{
3382 				emit s_objectLoaded(100, tr("Validating relationships..."), enum_cast(ObjectType::Relationship));
3383 				validateRelationships();
3384 			}
3385 
3386 			updateTablesFKRelationships();
3387 			emit s_objectLoaded(100, tr("Rendering database model..."), enum_cast(ObjectType::BaseObject));
3388 			this->setObjectsModified();
3389 		}
3390 		catch(Exception &e)
3391 		{
3392 			QString extra_info;
3393 			loading_model=false;
3394 
3395 			if(xmlparser.getCurrentElement())
3396 				extra_info=QString(QObject::tr("%1 (line: %2)")).arg(xmlparser.getLoadedFilename()).arg(xmlparser.getCurrentElement()->line);
3397 
3398 			if(e.getErrorCode()>=ErrorCode::InvalidSyntax)
3399 			{
3400 				str_aux=Exception::getErrorMessage(ErrorCode::InvModelFileNotLoaded).arg(filename);
3401 				throw Exception(str_aux,ErrorCode::InvModelFileNotLoaded,__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, extra_info);
3402 			}
3403 			else
3404 				throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, extra_info);
3405 		}
3406 	}
3407 }
3408 
createObject(ObjectType obj_type)3409 BaseObject *DatabaseModel::createObject(ObjectType obj_type)
3410 {
3411 	BaseObject *object=nullptr;
3412 
3413 	if(obj_type!=ObjectType::BaseObject)
3414 	{
3415 		if(obj_type==ObjectType::Role)
3416 			object=createRole();
3417 		else if(obj_type==ObjectType::Tablespace)
3418 			object=createTablespace();
3419 		else if(obj_type==ObjectType::Schema)
3420 			object=createSchema();
3421 		else if(obj_type==ObjectType::Language)
3422 			object=createLanguage();
3423 		else if(obj_type==ObjectType::Function)
3424 			object=createFunction();
3425 		else if(obj_type==ObjectType::Type)
3426 			object=createType();
3427 		else if(obj_type==ObjectType::Domain)
3428 			object=createDomain();
3429 		else if(obj_type==ObjectType::Cast)
3430 			object=createCast();
3431 		else if(obj_type==ObjectType::Conversion)
3432 			object=createConversion();
3433 		else if(obj_type==ObjectType::Operator)
3434 			object=createOperator();
3435 		else if(obj_type==ObjectType::OpFamily)
3436 			object=createOperatorFamily();
3437 		else if(obj_type==ObjectType::OpClass)
3438 			object=createOperatorClass();
3439 		else if(obj_type==ObjectType::Aggregate)
3440 			object=createAggregate();
3441 		else if(obj_type==ObjectType::Table)
3442 			object=createTable();
3443 		else if(obj_type==ObjectType::Sequence)
3444 			object=createSequence();
3445 		else if(obj_type==ObjectType::View)
3446 			object=createView();
3447 		else if(obj_type==ObjectType::Textbox)
3448 			object=createTextbox();
3449 		else if(obj_type==ObjectType::Constraint)
3450 			object=createConstraint(nullptr);
3451 		else if(obj_type==ObjectType::Trigger)
3452 			object=createTrigger();
3453 		else if(obj_type==ObjectType::Index)
3454 			object=createIndex();
3455 		else if(obj_type==ObjectType::Column)
3456 			object=createColumn();
3457 		else if(obj_type==ObjectType::Rule)
3458 			object=createRule();
3459 		else if(obj_type==ObjectType::Relationship ||
3460 				obj_type==ObjectType::BaseRelationship)
3461 			object=createRelationship();
3462 		else if(obj_type==ObjectType::Collation)
3463 			object=createCollation();
3464 		else if(obj_type==ObjectType::Extension)
3465 			object=createExtension();
3466 		else if(obj_type==ObjectType::Tag)
3467 			object=createTag();
3468 		else if(obj_type==ObjectType::Permission)
3469 			object=createPermission();
3470 		else if(obj_type==ObjectType::EventTrigger)
3471 			object=createEventTrigger();
3472 		else if(obj_type==ObjectType::GenericSql)
3473 			object=createGenericSQL();
3474 		else if(obj_type==ObjectType::Policy)
3475 			object=createPolicy();
3476 		else if(obj_type==ObjectType::ForeignDataWrapper)
3477 			object=createForeignDataWrapper();
3478 		else if(obj_type==ObjectType::ForeignServer)
3479 			object=createForeignServer();
3480 		else if(obj_type==ObjectType::UserMapping)
3481 			object=createUserMapping();
3482 		else if(obj_type==ObjectType::ForeignTable)
3483 			object=createForeignTable();
3484 	}
3485 
3486 	return object;
3487 }
3488 
setBasicAttributes(BaseObject * object)3489 void DatabaseModel::setBasicAttributes(BaseObject *object)
3490 {
3491 	attribs_map attribs, attribs_aux;
3492 	QString elem_name;
3493 	BaseObject *tabspc=nullptr, *owner=nullptr, *collation=nullptr;
3494 	Schema *schema=nullptr;
3495 	ObjectType obj_type=ObjectType::BaseObject, obj_type_aux;
3496 	bool has_error=false, protected_obj=false, sql_disabled=false;
3497 	ForeignObject *frn_object = dynamic_cast<ForeignObject *>(object);
3498 
3499 	if(!object)
3500 		throw Exception(ErrorCode::OprNotAllocatedObject,__PRETTY_FUNCTION__,__FILE__,__LINE__);
3501 
3502 	xmlparser.getElementAttributes(attribs);
3503 	obj_type_aux=object->getObjectType();
3504 
3505 	if(obj_type_aux!=ObjectType::Cast && obj_type_aux != ObjectType::UserMapping)
3506 		object->setName(attribs[Attributes::Name]);
3507 
3508 	if(BaseGraphicObject::isGraphicObject(obj_type_aux) && !attribs[Attributes::ZValue].isEmpty())
3509 		dynamic_cast<BaseGraphicObject *>(object)->setZValue(attribs[Attributes::ZValue].toInt());
3510 
3511 	if(BaseObject::acceptsAlias(obj_type_aux))
3512 		object->setAlias(attribs[Attributes::Alias]);
3513 
3514 	protected_obj=attribs[Attributes::Protected]==Attributes::True;
3515 	sql_disabled=attribs[Attributes::SqlDisabled]==Attributes::True;
3516 
3517 	if(frn_object)
3518 	{
3519 		QStringList opt_val;
3520 
3521 		for(auto &option : attribs[Attributes::Options].split(ForeignObject::OptionsSeparator))
3522 		{
3523 			opt_val = option.split(UserMapping::OptionValueSeparator);
3524 
3525 			if(opt_val.size() < 2)
3526 				continue;
3527 
3528 			frn_object->setOption(opt_val[0], opt_val[1]);
3529 		}
3530 	}
3531 
3532 	xmlparser.savePosition();
3533 
3534 	if(xmlparser.accessElement(XmlParser::ChildElement))
3535 	{
3536 		do
3537 		{
3538 			if(xmlparser.getElementType()==XML_ELEMENT_NODE)
3539 			{
3540 				elem_name=xmlparser.getElementName();
3541 
3542 				//Defines the object's comment
3543 				if(elem_name==Attributes::Comment)
3544 				{
3545 					xmlparser.savePosition();
3546 					xmlparser.accessElement(XmlParser::ChildElement);
3547 					object->setComment(xmlparser.getElementContent());
3548 					xmlparser.restorePosition();
3549 				}
3550 				//Defines the object's schema
3551 				else if(elem_name==Attributes::Schema)
3552 				{
3553 					obj_type=ObjectType::Schema;
3554 					xmlparser.getElementAttributes(attribs_aux);
3555 					schema=dynamic_cast<Schema *>(getObject(attribs_aux[Attributes::Name], obj_type));
3556 					object->setSchema(schema);
3557 					has_error=(!schema && !attribs_aux[Attributes::Name].isEmpty());
3558 				}
3559 				//Defines the object's tablespace
3560 				else if(elem_name==Attributes::Tablespace)
3561 				{
3562 					obj_type=ObjectType::Tablespace;
3563 					xmlparser.getElementAttributes(attribs_aux);
3564 					tabspc=getObject(attribs_aux[Attributes::Name], obj_type);
3565 					object->setTablespace(tabspc);
3566 					has_error=(!tabspc && !attribs_aux[Attributes::Name].isEmpty());
3567 				}
3568 				//Defines the object's owner
3569 				else if(elem_name==Attributes::Role)
3570 				{
3571 					obj_type=ObjectType::Role;
3572 					xmlparser.getElementAttributes(attribs_aux);
3573 					owner=getObject(attribs_aux[Attributes::Name], obj_type);
3574 					object->setOwner(owner);
3575 					has_error=(!owner && !attribs_aux[Attributes::Name].isEmpty());
3576 				}
3577 				//Defines the object's schema
3578 				else if(elem_name==Attributes::Collation)
3579 				{
3580 					obj_type=ObjectType::Collation;
3581 					xmlparser.getElementAttributes(attribs_aux);
3582 					collation=getObject(attribs_aux[Attributes::Name], obj_type);
3583 					object->setCollation(collation);
3584 					has_error=(!collation && !attribs_aux[Attributes::Name].isEmpty());
3585 				}
3586 				else if(elem_name==Attributes::AppendedSql)
3587 				{
3588 					xmlparser.savePosition();
3589 					xmlparser.accessElement(XmlParser::ChildElement);
3590 					object->setAppendedSQL(xmlparser.getElementContent());
3591 					xmlparser.restorePosition();
3592 				}
3593 				else if(elem_name==Attributes::PrependedSql)
3594 				{
3595 					xmlparser.savePosition();
3596 					xmlparser.accessElement(XmlParser::ChildElement);
3597 					object->setPrependedSQL(xmlparser.getElementContent());
3598 					xmlparser.restorePosition();
3599 				}
3600 				//Defines the object's position (only for graphical objects)
3601 				else if(elem_name==Attributes::Position)
3602 				{
3603 					xmlparser.getElementAttributes(attribs);
3604 
3605 					if(elem_name==Attributes::Position &&
3606 							(obj_type_aux!=ObjectType::Relationship &&
3607 							 obj_type_aux!=ObjectType::BaseRelationship))
3608 					{
3609 						dynamic_cast<BaseGraphicObject *>(object)->setPosition(QPointF(attribs[Attributes::XPos].toDouble(),
3610 																				 attribs[Attributes::YPos].toDouble()));
3611 
3612 
3613 					}
3614 				}
3615 			}
3616 		}
3617 		while(!has_error && xmlparser.accessElement(XmlParser::NextElement));
3618 	}
3619 
3620 	xmlparser.restorePosition();
3621 	object->setProtected(protected_obj);
3622 	object->setSQLDisabled(sql_disabled);
3623 
3624 	if(has_error)
3625 	{
3626 		throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
3627 						.arg(object->getName())
3628 						.arg(object->getTypeName())
3629 						.arg(attribs_aux[Attributes::Name])
3630 				.arg(BaseObject::getTypeName(obj_type)),
3631 				ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
3632 	}
3633 	//Schema on extensions are optional
3634 	else if(!object->getSchema() && (BaseObject::acceptsSchema(obj_type_aux) && obj_type_aux != ObjectType::Extension))
3635 	{
3636 		throw Exception(Exception::getErrorMessage(ErrorCode::InvObjectAllocationNoSchema)
3637 						.arg(object->getName())
3638 						.arg(object->getTypeName()),
3639 						ErrorCode::InvObjectAllocationNoSchema,__PRETTY_FUNCTION__,__FILE__,__LINE__);
3640 	}
3641 }
3642 
getErrorExtraInfo()3643 QString DatabaseModel::getErrorExtraInfo()
3644 {
3645 	QString extra_info;
3646 
3647 	if(!xmlparser.getLoadedFilename().isEmpty())
3648 		extra_info=QString(QObject::tr("%1 (line: %2)")).arg(xmlparser.getLoadedFilename())
3649 				   .arg(xmlparser.getCurrentElement()->line);
3650 	else
3651 		extra_info=xmlparser.getXMLBuffer();
3652 
3653 	return extra_info;
3654 }
3655 
setLoadingModel(bool value)3656 void DatabaseModel::setLoadingModel(bool value)
3657 {
3658   loading_model = value;
3659 }
3660 
setObjectListsCapacity(unsigned capacity)3661 void DatabaseModel::setObjectListsCapacity(unsigned capacity)
3662 {
3663   if(capacity < BaseObject::DefMaxObjectCount ||
3664 	 capacity > (BaseObject::DefMaxObjectCount * 1000))
3665 	capacity = BaseObject::DefMaxObjectCount;
3666 
3667   unsigned half_cap = capacity/2, one_fourth_cap = capacity/4;
3668 
3669   views.reserve(capacity);
3670   tables.reserve(capacity);
3671   relationships.reserve(capacity);
3672   base_relationships.reserve(capacity);
3673   sequences.reserve(capacity);
3674   permissions.reserve(capacity);
3675   schemas.reserve(half_cap);
3676   roles.reserve(half_cap);
3677   functions.reserve(half_cap);
3678   types.reserve(half_cap);
3679   textboxes.reserve(half_cap);
3680   aggregates.reserve(half_cap);
3681   operators.reserve(half_cap);
3682   op_classes.reserve(half_cap);
3683   op_families.reserve(half_cap);
3684   domains.reserve(half_cap);
3685   collations.reserve(half_cap);
3686   extensions.reserve(half_cap);
3687   tags.reserve(half_cap);
3688   genericsqls.reserve(half_cap);
3689   tablespaces.reserve(one_fourth_cap);
3690   languages.reserve(one_fourth_cap);
3691   casts.reserve(one_fourth_cap);
3692   conversions.reserve(one_fourth_cap);
3693   eventtriggers.reserve(one_fourth_cap);
3694 }
3695 
setLastPosition(const QPoint & pnt)3696 void DatabaseModel::setLastPosition(const QPoint &pnt)
3697 {
3698 	last_pos=pnt;
3699 }
3700 
getLastPosition()3701 QPoint DatabaseModel::getLastPosition()
3702 {
3703 	return last_pos;
3704 }
3705 
setLastZoomFactor(double zoom)3706 void DatabaseModel::setLastZoomFactor(double zoom)
3707 {
3708 	last_zoom=zoom;
3709 }
3710 
getLastZoomFactor()3711 double DatabaseModel::getLastZoomFactor()
3712 {
3713 	return last_zoom;
3714 }
3715 
createRole()3716 Role *DatabaseModel::createRole()
3717 {
3718 	attribs_map attribs, attribs_aux;
3719 	Role *role=nullptr, *ref_role=nullptr;
3720 	int i, len;
3721 	bool marked;
3722 	QStringList list;
3723 	QString elem_name;
3724 	unsigned role_type;
3725 
3726 	QString op_attribs[]={ Attributes::Superuser, Attributes::CreateDb,
3727 							 Attributes::CreateRole, Attributes::Inherit,
3728 							 Attributes::Login, Attributes::Encrypted,
3729 							 Attributes::Replication, Attributes::BypassRls };
3730 
3731 	unsigned op_vect[]={ Role::OpSuperuser, Role::OpCreateDb,
3732 						 Role::OpCreateRole, Role::OpInherit,
3733 						 Role::OpLogin, Role::OpEncrypted,
3734 						 Role::OpReplication, Role::OpBypassRls };
3735 
3736 	try
3737 	{
3738 		role=new Role;
3739 		setBasicAttributes(role);
3740 
3741 		//Gets all the attributes values from the XML
3742 		xmlparser.getElementAttributes(attribs);
3743 
3744 		role->setPassword(attribs[Attributes::Password]);
3745 		role->setValidity(attribs[Attributes::Validity]);
3746 
3747 		if(!attribs[Attributes::ConnLimit].isEmpty())
3748 			role->setConnectionLimit(attribs[Attributes::ConnLimit].toInt());
3749 
3750 		//Setting up the role options according to the configured on the XML
3751 		for(i=0; i < 8; i++)
3752 		{
3753 			marked=attribs[op_attribs[i]]==Attributes::True;
3754 			role->setOption(op_vect[i], marked);
3755 		}
3756 
3757 		if(xmlparser.accessElement(XmlParser::ChildElement))
3758 		{
3759 			do
3760 			{
3761 				if(xmlparser.getElementType()==XML_ELEMENT_NODE)
3762 				{
3763 					elem_name=xmlparser.getElementName();
3764 
3765 					//Getting the member roles
3766 					if(elem_name==Attributes::Roles)
3767 					{
3768 						//Gets the member roles attributes
3769 						xmlparser.getElementAttributes(attribs_aux);
3770 
3771 						//The member roles names are separated by comma, so it is needed to split them
3772 						list=attribs_aux[Attributes::Names].split(',');
3773 						len=list.size();
3774 
3775 						//Identifying the member role type
3776 						if(attribs_aux[Attributes::RoleType]==Attributes::Refer)
3777 							role_type=Role::RefRole;
3778 						else if(attribs_aux[Attributes::RoleType]==Attributes::Member)
3779 							role_type=Role::MemberRole;
3780 						else
3781 							role_type=Role::AdminRole;
3782 
3783 						for(i=0; i < len; i++)
3784 						{
3785 							//Gets the role using the name from the model using the name from the list
3786 							ref_role=dynamic_cast<Role *>(getObject(list[i].trimmed(),ObjectType::Role));
3787 
3788 							//Raises an error if the roles doesn't exists
3789 							if(!ref_role)
3790 							{
3791 								throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
3792 												.arg(role->getName())
3793 												.arg(BaseObject::getTypeName(ObjectType::Role))
3794 												.arg(list[i])
3795 												.arg(BaseObject::getTypeName(ObjectType::Role)),
3796 												ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
3797 							}
3798 
3799 							role->addRole(role_type, ref_role);
3800 						}
3801 					}
3802 				}
3803 			}
3804 			while(xmlparser.accessElement(XmlParser::NextElement));
3805 		}
3806 	}
3807 	catch(Exception &e)
3808 	{
3809 		if(role) delete role;
3810 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, getErrorExtraInfo());
3811 	}
3812 
3813 	return role;
3814 }
3815 
createTablespace()3816 Tablespace *DatabaseModel::createTablespace()
3817 {
3818 	attribs_map attribs;
3819 	Tablespace *tabspc=nullptr;
3820 
3821 	try
3822 	{
3823 		tabspc=new Tablespace;
3824 		setBasicAttributes(tabspc);
3825 		xmlparser.getElementAttributes(attribs);
3826 		tabspc->setDirectory(attribs[Attributes::Directory]);
3827 	}
3828 	catch(Exception &e)
3829 	{
3830 		if(tabspc) delete tabspc;
3831 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, getErrorExtraInfo());
3832 	}
3833 
3834 	return tabspc;
3835 }
3836 
createSchema()3837 Schema *DatabaseModel::createSchema()
3838 {
3839 	Schema *schema=nullptr;
3840 	attribs_map attribs;
3841 
3842 	try
3843 	{
3844 		schema=new Schema;
3845 		xmlparser.getElementAttributes(attribs);
3846 		setBasicAttributes(schema);
3847 		schema->setFillColor(QColor(attribs[Attributes::FillColor]));
3848 		schema->setRectVisible(attribs[Attributes::RectVisible]==Attributes::True);
3849 		schema->setFadedOut(attribs[Attributes::FadedOut]==Attributes::True);
3850 		schema->setLayer(attribs[Attributes::Layer].toUInt());
3851 	}
3852 	catch(Exception &e)
3853 	{
3854 		if(schema) delete schema;
3855 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, getErrorExtraInfo());
3856 	}
3857 
3858 	return schema;
3859 }
3860 
createLanguage()3861 Language *DatabaseModel::createLanguage()
3862 {
3863 	attribs_map attribs;
3864 	Language *lang=nullptr;
3865 	BaseObject *func=nullptr;
3866 	QString signature, ref_type;
3867 	ObjectType obj_type;
3868 
3869 	try
3870 	{
3871 		lang=new Language;
3872 		xmlparser.getElementAttributes(attribs);
3873 		setBasicAttributes(lang);
3874 
3875 		lang->setTrusted(attribs[Attributes::Trusted]==Attributes::True);
3876 
3877 		if(xmlparser.accessElement(XmlParser::ChildElement))
3878 		{
3879 			do
3880 			{
3881 				if(xmlparser.getElementType()==XML_ELEMENT_NODE)
3882 				{
3883 					obj_type=BaseObject::getObjectType(xmlparser.getElementName());
3884 
3885 					if(obj_type==ObjectType::Function)
3886 					{
3887 						xmlparser.getElementAttributes(attribs);
3888 
3889 						//Gets the function reference type
3890 						ref_type=attribs[Attributes::RefType];
3891 
3892 						//Only VALIDATOR, HANDLER and INLINE functions are accepted for the language
3893 						if(ref_type==Attributes::ValidatorFunc ||
3894 								ref_type==Attributes::HandlerFunc ||
3895 								ref_type==Attributes::InlineFunc)
3896 						{
3897 							//Gets the function signature and tries to retrieve it from the model
3898 							signature=attribs[Attributes::Signature];
3899 							func=getObject(signature, ObjectType::Function);
3900 
3901 							//Raises an error if the function doesn't exists
3902 							if(!func)
3903 								throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
3904 												.arg(lang->getName())
3905 												.arg(lang->getTypeName())
3906 												.arg(signature)
3907 												.arg(BaseObject::getTypeName(ObjectType::Function)),
3908 												ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
3909 
3910 							if(ref_type==Attributes::ValidatorFunc)
3911 								lang->setFunction(dynamic_cast<Function *>(func), Language::ValidatorFunc);
3912 							else if(ref_type==Attributes::HandlerFunc)
3913 								lang->setFunction(dynamic_cast<Function *>(func), Language::HandlerFunc);
3914 							else
3915 								lang->setFunction(dynamic_cast<Function *>(func), Language::InlineFunc);
3916 
3917 						}
3918 						else
3919 							//Raises an error if the function type is invalid
3920 							throw Exception(ErrorCode::RefFunctionInvalidType,__PRETTY_FUNCTION__,__FILE__,__LINE__);
3921 					}
3922 				}
3923 			}
3924 			while(xmlparser.accessElement(XmlParser::NextElement));
3925 		}
3926 
3927 	}
3928 	catch(Exception &e)
3929 	{
3930 		if(lang) delete lang;
3931 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, getErrorExtraInfo());
3932 	}
3933 
3934 	return lang;
3935 }
3936 
createFunction()3937 Function *DatabaseModel::createFunction()
3938 {
3939 	attribs_map attribs, attribs_aux;
3940 	Function *func=nullptr;
3941 	ObjectType obj_type;
3942 	BaseObject *object=nullptr;
3943 	PgSqlType type;
3944 	Parameter param;
3945 	QString str_aux, elem;
3946 
3947 	try
3948 	{
3949 		func=new Function;
3950 		setBasicAttributes(func);
3951 		xmlparser.getElementAttributes(attribs);
3952 
3953 		if(!attribs[Attributes::ReturnsSetOf].isEmpty())
3954 			func->setReturnSetOf(attribs[Attributes::ReturnsSetOf]==
3955 					Attributes::True);
3956 
3957 		if(!attribs[Attributes::WindowFunc].isEmpty())
3958 			func->setWindowFunction(attribs[Attributes::WindowFunc]==
3959 					Attributes::True);
3960 
3961 		if(!attribs[Attributes::LeakProof].isEmpty())
3962 			func->setLeakProof(attribs[Attributes::LeakProof]==
3963 					Attributes::True);
3964 
3965 		if(!attribs[Attributes::BehaviorType].isEmpty())
3966 			func->setBehaviorType(BehaviorType(attribs[Attributes::BehaviorType]));
3967 
3968 		if(!attribs[Attributes::FunctionType].isEmpty())
3969 			func->setFunctionType(FunctionType(attribs[Attributes::FunctionType]));
3970 
3971 		if(!attribs[Attributes::SecurityType].isEmpty())
3972 			func->setSecurityType(SecurityType(attribs[Attributes::SecurityType]));
3973 
3974 		if(!attribs[Attributes::ExecutionCost].isEmpty())
3975 			func->setExecutionCost(attribs[Attributes::ExecutionCost].toInt());
3976 
3977 		if(!attribs[Attributes::RowAmount].isEmpty())
3978 			func->setRowAmount(attribs[Attributes::RowAmount].toInt());
3979 
3980 		if(xmlparser.accessElement(XmlParser::ChildElement))
3981 		{
3982 			do
3983 			{
3984 				if(xmlparser.getElementType()==XML_ELEMENT_NODE)
3985 				{
3986 					elem=xmlparser.getElementName();
3987 					obj_type=BaseObject::getObjectType(elem);
3988 
3989 					//Gets the function return type from the XML
3990 					if(elem==Attributes::ReturnType)
3991 					{
3992 						xmlparser.savePosition();
3993 
3994 						try
3995 						{
3996 							xmlparser.accessElement(XmlParser::ChildElement);
3997 
3998 							do
3999 							{
4000 								if(xmlparser.getElementType()==XML_ELEMENT_NODE)
4001 								{
4002 									//when the element found is a TYPE indicates that the function return type is a single one
4003 									if(xmlparser.getElementName()==Attributes::Type)
4004 									{
4005 										type=createPgSQLType();
4006 										func->setReturnType(type);
4007 									}
4008 									//when the element found is a PARAMETER indicates that the function return type is a table
4009 									else if(xmlparser.getElementName()==Attributes::Parameter)
4010 									{
4011 										param=createParameter();
4012 										func->addReturnedTableColumn(param.getName(), param.getType());
4013 									}
4014 								}
4015 							}
4016 							while(xmlparser.accessElement(XmlParser::NextElement));
4017 
4018 							xmlparser.restorePosition();
4019 						}
4020 						catch(Exception &e)
4021 						{
4022 							xmlparser.restorePosition();
4023 							throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
4024 						}
4025 					}
4026 					//Gets the function language
4027 					else if(obj_type==ObjectType::Language)
4028 					{
4029 						xmlparser.getElementAttributes(attribs);
4030 						object=getObject(attribs[Attributes::Name], obj_type);
4031 
4032 						//Raises an error if the function doesn't exisits
4033 						if(!object)
4034 							throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
4035 											.arg(func->getName())
4036 											.arg(func->getTypeName())
4037 											.arg(attribs[Attributes::Name])
4038 								.arg(BaseObject::getTypeName(ObjectType::Language)),
4039 								ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
4040 
4041 						func->setLanguage(dynamic_cast<Language *>(object));
4042 					}
4043 					//Gets a function parameter
4044 					else if(xmlparser.getElementName()==Attributes::Parameter)
4045 					{
4046 						param=createParameter();
4047 						func->addParameter(param);
4048 					}
4049 					//Gets the function code definition
4050 					else if(xmlparser.getElementName()==Attributes::Definition)
4051 					{
4052 						xmlparser.savePosition();
4053 						xmlparser.getElementAttributes(attribs_aux);
4054 
4055 						if(!attribs_aux[Attributes::Library].isEmpty())
4056 						{
4057 							func->setLibrary(attribs_aux[Attributes::Library]);
4058 							func->setSymbol(attribs_aux[Attributes::Symbol]);
4059 						}
4060 						else if(xmlparser.accessElement(XmlParser::ChildElement))
4061 							func->setSourceCode(xmlparser.getElementContent());
4062 
4063 						xmlparser.restorePosition();
4064 					}
4065 				}
4066 			}
4067 			while(xmlparser.accessElement(XmlParser::NextElement));
4068 		}
4069 	}
4070 	catch(Exception &e)
4071 	{
4072 		if(func)
4073 		{
4074 			str_aux=func->getName(true);
4075 			delete func;
4076 		}
4077 
4078 		if(e.getErrorCode()==ErrorCode::RefUserTypeInexistsModel)
4079 			throw Exception(Exception::getErrorMessage(ErrorCode::AsgObjectInvalidDefinition)
4080 							.arg(str_aux)
4081 							.arg(BaseObject::getTypeName(ObjectType::Function)),
4082 							ErrorCode::AsgObjectInvalidDefinition,__PRETTY_FUNCTION__,__FILE__,__LINE__,&e, getErrorExtraInfo());
4083 		else
4084 			throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, getErrorExtraInfo());
4085 	}
4086 
4087 	return func;
4088 }
4089 
createParameter()4090 Parameter DatabaseModel::createParameter()
4091 {
4092 	Parameter param;
4093 	attribs_map attribs;
4094 	QString elem;
4095 
4096 	try
4097 	{
4098 		xmlparser.savePosition();
4099 		xmlparser.getElementAttributes(attribs);
4100 
4101 		param.setName(attribs[Attributes::Name]);
4102 		param.setDefaultValue(attribs[Attributes::DefaultValue]);
4103 
4104 		if(xmlparser.accessElement(XmlParser::ChildElement))
4105 		{
4106 			do
4107 			{
4108 				if(xmlparser.getElementType()==XML_ELEMENT_NODE)
4109 				{
4110 					elem=xmlparser.getElementName();
4111 
4112 					if(elem==Attributes::Type)
4113 					{
4114 						param.setType(createPgSQLType());
4115 					}
4116 				}
4117 			}
4118 			while(xmlparser.accessElement(XmlParser::NextElement));
4119 		}
4120 
4121 		param.setIn(attribs[Attributes::ParamIn]==Attributes::True);
4122 		param.setOut(attribs[Attributes::ParamOut]==Attributes::True);
4123 		param.setVariadic(attribs[Attributes::ParamVariadic]==Attributes::True);
4124 
4125 		xmlparser.restorePosition();
4126 	}
4127 	catch(Exception &e)
4128 	{
4129 		QString extra_info=getErrorExtraInfo();
4130 		xmlparser.restorePosition();
4131 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, extra_info);
4132 	}
4133 
4134 	return param;
4135 }
4136 
createTypeAttribute()4137 TypeAttribute DatabaseModel::createTypeAttribute()
4138 {
4139 	TypeAttribute tpattrib;
4140 	attribs_map attribs;
4141 	QString elem;
4142 	BaseObject *collation=nullptr;
4143 
4144 	try
4145 	{
4146 		xmlparser.savePosition();
4147 		xmlparser.getElementAttributes(attribs);
4148 
4149 		tpattrib.setName(attribs[Attributes::Name]);
4150 
4151 		if(xmlparser.accessElement(XmlParser::ChildElement))
4152 		{
4153 			do
4154 			{
4155 				if(xmlparser.getElementType()==XML_ELEMENT_NODE)
4156 				{
4157 					elem=xmlparser.getElementName();
4158 
4159 					if(elem==Attributes::Type)
4160 					{
4161 						tpattrib.setType(createPgSQLType());
4162 					}
4163 					else if(elem==Attributes::Collation)
4164 					{
4165 						xmlparser.getElementAttributes(attribs);
4166 
4167 						collation=getObject(attribs[Attributes::Name], ObjectType::Collation);
4168 
4169 						//Raises an error if the operator class doesn't exists
4170 						if(!collation)
4171 						{
4172 							throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
4173 											.arg(tpattrib.getName())
4174 											.arg(tpattrib.getTypeName())
4175 											.arg(attribs[Attributes::Name])
4176 									.arg(BaseObject::getTypeName(ObjectType::Collation)),
4177 									ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
4178 						}
4179 
4180 						tpattrib.setCollation(collation);
4181 					}
4182 				}
4183 			}
4184 			while(xmlparser.accessElement(XmlParser::NextElement));
4185 		}
4186 
4187 		xmlparser.restorePosition();
4188 	}
4189 	catch(Exception &e)
4190 	{
4191 		QString extra_info=getErrorExtraInfo();
4192 		xmlparser.restorePosition();
4193 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, extra_info);
4194 	}
4195 
4196 	return tpattrib;
4197 }
4198 
createPgSQLType()4199 PgSqlType DatabaseModel::createPgSQLType()
4200 {
4201 	attribs_map attribs;
4202 	unsigned length=1, dimension=0, type_idx=0;
4203 	int precision=-1;
4204 	QString name;
4205 	void *ptype=nullptr;
4206 	bool with_timezone;
4207 	IntervalType interv_type;
4208 	SpatialType spatial_type;
4209 
4210 	xmlparser.getElementAttributes(attribs);
4211 
4212 	if(!attribs[Attributes::Length].isEmpty())
4213 		length=attribs[Attributes::Length].toUInt();
4214 
4215 	if(!attribs[Attributes::Dimension].isEmpty())
4216 		dimension=attribs[Attributes::Dimension].toUInt();
4217 
4218 	if(!attribs[Attributes::Precision].isEmpty())
4219 		precision=attribs[Attributes::Precision].toInt();
4220 
4221 	with_timezone=(attribs[Attributes::WithTimezone]==Attributes::True);
4222 	interv_type=attribs[Attributes::IntervalType];
4223 
4224 	if(!attribs[Attributes::SpatialType].isEmpty())
4225 		spatial_type=SpatialType(attribs[Attributes::SpatialType],
4226 				attribs[Attributes::Srid].toUInt(),
4227 				attribs[Attributes::Variation].toUInt());
4228 
4229 	name=attribs[Attributes::Name];
4230 
4231 	/* A small tweak to detect a timestamp/date type which name contains the time zone modifier.
4232 		 This situation can occur mainly on reverse engineering operation where the data type of objects
4233 		 in most of times came as string form and need to be parsed */
4234 	if(!with_timezone && attribs[Attributes::Name].contains(QString("with time zone"), Qt::CaseInsensitive))
4235 	{
4236 		with_timezone=true;
4237 		name.remove(QString(" with time zone"), Qt::CaseInsensitive);
4238 	}
4239 
4240 	type_idx=PgSqlType::getBaseTypeIndex(name);
4241 	if(type_idx!=PgSqlType::Null)
4242 	{
4243 		return PgSqlType(name, dimension, length, precision, with_timezone, interv_type, spatial_type);
4244 	}
4245 	else
4246 	{
4247 		//Raises an error if the referenced type name doesn't exists
4248 		if(PgSqlType::getUserTypeIndex(name,nullptr,this) == BaseType::Null)
4249 			throw Exception(ErrorCode::RefUserTypeInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
4250 
4251 		type_idx=PgSqlType::getUserTypeIndex(name, ptype);
4252 		return PgSqlType(type_idx, dimension, length, precision, with_timezone, interv_type, spatial_type);
4253 	}
4254 }
4255 
createType()4256 Type *DatabaseModel::createType()
4257 {
4258 	attribs_map attribs;
4259 	map<QString, unsigned> func_types;
4260 	Type *type=nullptr;
4261 	int count, i;
4262 	QStringList enums;
4263 	QString elem, str_aux;
4264 	BaseObject *func=nullptr, *collation=nullptr;
4265 	OperatorClass *op_class=nullptr;
4266 	PgSqlType aux_type;
4267 
4268 	try
4269 	{
4270 		type=new Type;
4271 		setBasicAttributes(type);
4272 		xmlparser.getElementAttributes(attribs);
4273 
4274 		if(attribs[Attributes::Configuration]==Attributes::BaseType)
4275 		{
4276 			type->setConfiguration(Type::BaseType);
4277 			type->setByValue(attribs[Attributes::ByValue]==Attributes::True);
4278 
4279 			if(!attribs[Attributes::InternalLength].isEmpty())
4280 				type->setInternalLength(attribs[Attributes::InternalLength].toUInt());
4281 
4282 			if(!attribs[Attributes::Alignment].isEmpty())
4283 				type->setAlignment(attribs[Attributes::Alignment]);
4284 
4285 			if(!attribs[Attributes::Storage].isEmpty())
4286 				type->setStorage(attribs[Attributes::Storage]);
4287 
4288 			if(!attribs[Attributes::Element].isEmpty())
4289 				type->setElement(attribs[Attributes::Element]);
4290 
4291 			if(!attribs[Attributes::Delimiter].isEmpty())
4292 				type->setDelimiter(attribs[Attributes::Delimiter][0].toLatin1());
4293 
4294 			if(!attribs[Attributes::DefaultValue].isEmpty())
4295 				type->setDefaultValue(attribs[Attributes::DefaultValue]);
4296 
4297 			if(!attribs[Attributes::Category].isEmpty())
4298 				type->setCategory(attribs[Attributes::Category]);
4299 
4300 			if(!attribs[Attributes::Preferred].isEmpty())
4301 				type->setPreferred(attribs[Attributes::Preferred]==Attributes::True);
4302 
4303 			//Configuring an auxiliary map used to reference the functions used by base type
4304 			func_types[Attributes::InputFunc]=Type::InputFunc;
4305 			func_types[Attributes::OutputFunc]=Type::OutputFunc;
4306 			func_types[Attributes::SendFunc]=Type::SendFunc;
4307 			func_types[Attributes::RecvFunc]=Type::RecvFunc;
4308 			func_types[Attributes::TpmodInFunc]=Type::TpmodInFunc;
4309 			func_types[Attributes::TpmodOutFunc]=Type::TpmodOutFunc;
4310 			func_types[Attributes::AnalyzeFunc]=Type::AnalyzeFunc;
4311 		}
4312 		else if(attribs[Attributes::Configuration]==Attributes::CompositeType)
4313 			type->setConfiguration(Type::CompositeType);
4314 		else if(attribs[Attributes::Configuration]==Attributes::EnumType)
4315 			type->setConfiguration(Type::EnumerationType);
4316 		else
4317 		{
4318 			type->setConfiguration(Type::RangeType);
4319 			func_types[Attributes::CanonicalFunc]=Type::CanonicalFunc;
4320 			func_types[Attributes::SubtypeDiffFunc]=Type::SubtypeDiffFunc;
4321 		}
4322 
4323 		if(xmlparser.accessElement(XmlParser::ChildElement))
4324 		{
4325 			do
4326 			{
4327 				if(xmlparser.getElementType()==XML_ELEMENT_NODE)
4328 				{
4329 					elem=xmlparser.getElementName();
4330 
4331 					//Specific operations for ENUM type
4332 					if(elem==Attributes::EnumType)
4333 					{
4334 						xmlparser.getElementAttributes(attribs);
4335 						enums=attribs[Attributes::Values].split(',');
4336 
4337 						count=enums.size();
4338 						for(i=0; i < count; i++)
4339 							type->addEnumeration(enums[i]);
4340 					}
4341 					//Specific operations for COMPOSITE types
4342 					else if(elem==Attributes::TypeAttribute)
4343 					{
4344 						type->addAttribute(createTypeAttribute());
4345 					}
4346 					//Specific operations for BASE / RANGE type
4347 					else if(elem==Attributes::Type)
4348 					{
4349 						aux_type=createPgSQLType();
4350 
4351 						if(type->getConfiguration()==Type::RangeType)
4352 							type->setSubtype(aux_type);
4353 						else
4354 							type->setLikeType(aux_type);
4355 					}
4356 					else if(elem==Attributes::Collation)
4357 					{
4358 						xmlparser.getElementAttributes(attribs);
4359 						collation=getObject(attribs[Attributes::Name], ObjectType::Collation);
4360 
4361 						//Raises an error if the operator class doesn't exists
4362 						if(!collation)
4363 						{
4364 							throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
4365 											.arg(type->getName())
4366 											.arg(type->getTypeName())
4367 											.arg(attribs[Attributes::Name])
4368 									.arg(BaseObject::getTypeName(ObjectType::Collation)),
4369 									ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
4370 						}
4371 
4372 						type->setCollation(collation);
4373 					}
4374 					if(elem==Attributes::OpClass)
4375 					{
4376 						xmlparser.getElementAttributes(attribs);
4377 						op_class=dynamic_cast<OperatorClass *>(getObject(attribs[Attributes::Name], ObjectType::OpClass));
4378 
4379 						//Raises an error if the operator class doesn't exists
4380 						if(!op_class)
4381 						{
4382 							throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
4383 											.arg(type->getName())
4384 											.arg(type->getTypeName())
4385 											.arg(attribs[Attributes::Name])
4386 									.arg(BaseObject::getTypeName(ObjectType::OpClass)),
4387 									ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
4388 						}
4389 
4390 						type->setSubtypeOpClass(op_class);
4391 					}
4392 					//Configuring the functions used by the type (only for BASE type)
4393 					else if(elem==Attributes::Function)
4394 					{
4395 						xmlparser.getElementAttributes(attribs);
4396 
4397 						//Tries to get the function from the model
4398 						func=getObject(attribs[Attributes::Signature], ObjectType::Function);
4399 
4400 						//Raises an error if the function doesn't exists
4401 						if(!func && !attribs[Attributes::Signature].isEmpty())
4402 							throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
4403 											.arg(type->getName())
4404 											.arg(type->getTypeName())
4405 											.arg(attribs[Attributes::Signature])
4406 								.arg(BaseObject::getTypeName(ObjectType::Function)),
4407 								ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
4408 						//Raises an error if the function type is invalid
4409 						else if(func_types.count(attribs[Attributes::RefType])==0)
4410 							throw Exception(ErrorCode::RefFunctionInvalidType,__PRETTY_FUNCTION__,__FILE__,__LINE__);
4411 
4412 						type->setFunction(func_types[attribs[Attributes::RefType]],	dynamic_cast<Function *>(func));
4413 					}
4414 				}
4415 			}
4416 			while(xmlparser.accessElement(XmlParser::NextElement));
4417 		}
4418 	}
4419 	catch(Exception &e)
4420 	{
4421 		if(type)
4422 		{
4423 			str_aux=type->getName(true);
4424 			delete type;
4425 		}
4426 
4427 		if(e.getErrorCode()==ErrorCode::RefUserTypeInexistsModel)
4428 			throw Exception(Exception::getErrorMessage(ErrorCode::AsgObjectInvalidDefinition)
4429 							.arg(str_aux)
4430 							.arg(type->getTypeName()),
4431 							ErrorCode::AsgObjectInvalidDefinition,__PRETTY_FUNCTION__,__FILE__,__LINE__,&e, getErrorExtraInfo());
4432 		else
4433 			throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, getErrorExtraInfo());
4434 	}
4435 
4436 	return type;
4437 }
4438 
createDomain()4439 Domain *DatabaseModel::createDomain()
4440 {
4441 	attribs_map attribs;
4442 	Domain *domain=nullptr;
4443 	QString elem;
4444 
4445 	try
4446 	{
4447 		domain=new Domain;
4448 		setBasicAttributes(domain);
4449 		xmlparser.getElementAttributes(attribs);
4450 
4451 		if(!attribs[Attributes::DefaultValue].isEmpty())
4452 			domain->setDefaultValue(attribs[Attributes::DefaultValue]);
4453 
4454 		domain->setNotNull(attribs[Attributes::NotNull]==Attributes::True);
4455 
4456 		if(xmlparser.accessElement(XmlParser::ChildElement))
4457 		{
4458 			do
4459 			{
4460 				if(xmlparser.getElementType()==XML_ELEMENT_NODE)
4461 				{
4462 					elem=xmlparser.getElementName();
4463 
4464 					//If a type element is found it'll be extracted an type which the domain is applied
4465 					if(elem==Attributes::Type)
4466 					{
4467 						domain->setType(createPgSQLType());
4468 					}
4469 					else if(elem==Attributes::Constraint)
4470 					{
4471 						xmlparser.savePosition();
4472 						xmlparser.getElementAttributes(attribs);
4473 						xmlparser.accessElement(XmlParser::ChildElement);
4474 						xmlparser.accessElement(XmlParser::ChildElement);
4475 						domain->addCheckConstraint(attribs[Attributes::Name], xmlparser.getElementContent());
4476 						xmlparser.restorePosition();
4477 					}
4478 				}
4479 			}
4480 			while(xmlparser.accessElement(xmlparser.NextElement));
4481 		}
4482 	}
4483 	catch(Exception &e)
4484 	{
4485 		if(domain) delete domain;
4486 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, getErrorExtraInfo());
4487 	}
4488 
4489 	return domain;
4490 }
4491 
createCast()4492 Cast *DatabaseModel::createCast()
4493 {
4494 	attribs_map attribs;
4495 	Cast *cast=nullptr;
4496 	QString elem;
4497 	unsigned type_idx=0;
4498 	PgSqlType type;
4499 	BaseObject *func=nullptr;
4500 
4501 	try
4502 	{
4503 		cast=new Cast;
4504 		setBasicAttributes(cast);
4505 		xmlparser.getElementAttributes(attribs);
4506 
4507 		if(attribs[Attributes::CastType]==Attributes::Implicit)
4508 			cast->setCastType(Cast::Implicit);
4509 		else if(attribs[Attributes::CastType]==Attributes::Assignment)
4510 			cast->setCastType(Cast::Assignment);
4511 		else
4512 			cast->setCastType(Cast::Explicit);
4513 
4514 		cast->setInOut(attribs[Attributes::IoCast]==Attributes::True);
4515 
4516 		if(xmlparser.accessElement(XmlParser::ChildElement))
4517 		{
4518 			do
4519 			{
4520 				if(xmlparser.getElementType()==XML_ELEMENT_NODE)
4521 				{
4522 					elem=xmlparser.getElementName();
4523 
4524 					//Extract one argument type from the XML
4525 					if(elem==Attributes::Type)
4526 					{
4527 						type=createPgSQLType();
4528 						if(type_idx==0)
4529 							cast->setDataType(Cast::SrcType, type);
4530 						else
4531 							cast->setDataType(Cast::DstType, type);
4532 						type_idx++;
4533 					}
4534 					//Extracts the conversion function
4535 					else if(elem==Attributes::Function)
4536 					{
4537 						xmlparser.getElementAttributes(attribs);
4538 						func=getObject(attribs[Attributes::Signature], ObjectType::Function);
4539 
4540 						//Raises an error if the function doesn't exists
4541 						if(!func && !attribs[Attributes::Signature].isEmpty())
4542 							throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
4543 											.arg(cast->getName())
4544 											.arg(cast->getTypeName())
4545 											.arg(attribs[Attributes::Signature])
4546 								.arg(BaseObject::getTypeName(ObjectType::Function)),
4547 								ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
4548 
4549 						cast->setCastFunction(dynamic_cast<Function *>(func));
4550 					}
4551 				}
4552 			}
4553 			while(xmlparser.accessElement(XmlParser::NextElement));
4554 		}
4555 	}
4556 	catch(Exception &e)
4557 	{
4558 		if(cast) delete cast;
4559 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, getErrorExtraInfo());
4560 	}
4561 
4562 	return cast;
4563 }
4564 
createConversion()4565 Conversion *DatabaseModel::createConversion()
4566 {
4567 	attribs_map attribs;
4568 	Conversion *conv=nullptr;
4569 	QString elem;
4570 	BaseObject *func=nullptr;
4571 
4572 	try
4573 	{
4574 		conv=new Conversion;
4575 		setBasicAttributes(conv);
4576 		xmlparser.getElementAttributes(attribs);
4577 
4578 		conv->setEncoding(Conversion::SrcEncoding,
4579 							EncodingType(attribs[Attributes::SrcEncoding]));
4580 
4581 		conv->setEncoding(Conversion::DstEncoding,
4582 							EncodingType(attribs[Attributes::DstEncoding]));
4583 
4584 		conv->setDefault(attribs[Attributes::Default]==Attributes::True);
4585 
4586 		if(xmlparser.accessElement(XmlParser::ChildElement))
4587 		{
4588 			do
4589 			{
4590 				if(xmlparser.getElementType()==XML_ELEMENT_NODE)
4591 				{
4592 					elem=xmlparser.getElementName();
4593 
4594 					if(elem==Attributes::Function)
4595 					{
4596 						xmlparser.getElementAttributes(attribs);
4597 						func=getObject(attribs[Attributes::Signature], ObjectType::Function);
4598 
4599 						//Raises an error if the function doesn't exists
4600 						if(!func && !attribs[Attributes::Signature].isEmpty())
4601 							throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
4602 											.arg(conv->getName())
4603 											.arg(conv->getTypeName())
4604 											.arg(attribs[Attributes::Signature])
4605 								.arg(BaseObject::getTypeName(ObjectType::Function)),
4606 								ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
4607 
4608 						conv->setConversionFunction(dynamic_cast<Function *>(func));
4609 					}
4610 				}
4611 			}
4612 			while(xmlparser.accessElement(XmlParser::NextElement));
4613 		}
4614 	}
4615 	catch(Exception &e)
4616 	{
4617 		if(conv) delete conv;
4618 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, getErrorExtraInfo());
4619 	}
4620 
4621 	return conv;
4622 }
4623 
createOperator()4624 Operator *DatabaseModel::createOperator()
4625 {
4626 	attribs_map attribs;
4627 	map<QString, unsigned> func_types;
4628 	map<QString, unsigned> oper_types;
4629 	Operator *oper=nullptr;
4630 	QString elem;
4631 	BaseObject *func=nullptr,*oper_aux=nullptr;
4632 	unsigned arg_type;
4633 	PgSqlType type;
4634 
4635 	try
4636 	{
4637 		oper=new Operator;
4638 		setBasicAttributes(oper);
4639 		xmlparser.getElementAttributes(attribs);
4640 
4641 		oper->setMerges(attribs[Attributes::Merges]==Attributes::True);
4642 		oper->setHashes(attribs[Attributes::Hashes]==Attributes::True);
4643 
4644 		func_types[Attributes::OperatorFunc]=Operator::FuncOperator;
4645 		func_types[Attributes::JoinFunc]=Operator::FuncJoin;
4646 		func_types[Attributes::RestrictionFunc]=Operator::FuncRestrict;
4647 
4648 		oper_types[Attributes::CommutatorOp]=Operator::OperCommutator;
4649 		oper_types[Attributes::NegatorOp]=Operator::OperNegator;
4650 
4651 		if(xmlparser.accessElement(XmlParser::ChildElement))
4652 		{
4653 			do
4654 			{
4655 				if(xmlparser.getElementType()==XML_ELEMENT_NODE)
4656 				{
4657 					elem=xmlparser.getElementName();
4658 
4659 					if(elem==objs_schemas[enum_cast(ObjectType::Operator)])
4660 					{
4661 						xmlparser.getElementAttributes(attribs);
4662 						oper_aux=getObject(attribs[Attributes::Signature], ObjectType::Operator);
4663 
4664 						//Raises an error if the auxiliary operator doesn't exists
4665 						if(!oper_aux && !attribs[Attributes::Signature].isEmpty())
4666 							throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
4667 											.arg(oper->getSignature(true))
4668 											.arg(oper->getTypeName())
4669 											.arg(attribs[Attributes::Signature])
4670 								.arg(BaseObject::getTypeName(ObjectType::Operator)),
4671 								ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
4672 
4673 						oper->setOperator(dynamic_cast<Operator *>(oper_aux),
4674 											oper_types[attribs[Attributes::RefType]]);
4675 					}
4676 					else if(elem==Attributes::Type)
4677 					{
4678 						xmlparser.getElementAttributes(attribs);
4679 
4680 						if(attribs[Attributes::RefType]!=Attributes::RightType)
4681 							arg_type=Operator::LeftArg;
4682 						else
4683 							arg_type=Operator::RightArg;
4684 
4685 						type=createPgSQLType();
4686 						oper->setArgumentType(type, arg_type);
4687 					}
4688 					else if(elem==Attributes::Function)
4689 					{
4690 						xmlparser.getElementAttributes(attribs);
4691 						func=getObject(attribs[Attributes::Signature], ObjectType::Function);
4692 
4693 						//Raises an error if the function doesn't exists on the model
4694 						if(!func && !attribs[Attributes::Signature].isEmpty())
4695 							throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
4696 											.arg(oper->getName())
4697 											.arg(oper->getTypeName())
4698 											.arg(attribs[Attributes::Signature])
4699 								.arg(BaseObject::getTypeName(ObjectType::Function)),
4700 								ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
4701 
4702 						oper->setFunction(dynamic_cast<Function *>(func),
4703 											func_types[attribs[Attributes::RefType]]);
4704 					}
4705 				}
4706 			}
4707 			while(xmlparser.accessElement(XmlParser::NextElement));
4708 		}
4709 	}
4710 	catch(Exception &e)
4711 	{
4712 		if(oper) delete oper;
4713 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, getErrorExtraInfo());
4714 	}
4715 
4716 	return oper;
4717 }
4718 
createOperatorClass()4719 OperatorClass *DatabaseModel::createOperatorClass()
4720 {
4721 	attribs_map attribs, attribs_aux;
4722 	map<QString, unsigned> elem_types;
4723 	BaseObject *object=nullptr;
4724 	QString elem;
4725 	PgSqlType type;
4726 	OperatorClass *op_class=nullptr;
4727 	OperatorClassElement class_elem;
4728 	unsigned stg_number, elem_type;
4729 
4730 	try
4731 	{
4732 		op_class=new OperatorClass;
4733 		setBasicAttributes(op_class);
4734 		xmlparser.getElementAttributes(attribs);
4735 
4736 		op_class->setIndexingType(IndexingType(attribs[Attributes::IndexType]));
4737 		op_class->setDefault(attribs[Attributes::Default]==Attributes::True);
4738 
4739 		elem_types[Attributes::Function]=OperatorClassElement::FunctionElem;
4740 		elem_types[Attributes::Operator]=OperatorClassElement::OperatorElem;
4741 		elem_types[Attributes::Storage]=OperatorClassElement::StorageElem;
4742 
4743 		if(xmlparser.accessElement(XmlParser::ChildElement))
4744 		{
4745 			do
4746 			{
4747 				if(xmlparser.getElementType()==XML_ELEMENT_NODE)
4748 				{
4749 					elem=xmlparser.getElementName();
4750 
4751 					if(elem==objs_schemas[enum_cast(ObjectType::OpFamily)])
4752 					{
4753 						xmlparser.getElementAttributes(attribs);
4754 						object=getObject(attribs[Attributes::Signature], ObjectType::OpFamily);
4755 
4756 						//Raises an error if the operator family doesn't exists
4757 						if(!object)
4758 							throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
4759 											.arg(op_class->getName())
4760 											.arg(op_class->getTypeName())
4761 											.arg(attribs[Attributes::Signature])
4762 								.arg(BaseObject::getTypeName(ObjectType::OpFamily)),
4763 								ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
4764 
4765 						op_class->setFamily(dynamic_cast<OperatorFamily *>(object));
4766 					}
4767 					else if(elem==Attributes::Type)
4768 					{
4769 						xmlparser.getElementAttributes(attribs);
4770 						type=createPgSQLType();
4771 						op_class->setDataType(type);
4772 					}
4773 					else if(elem==Attributes::Element)
4774 					{
4775 						xmlparser.getElementAttributes(attribs);
4776 
4777 						stg_number=attribs[Attributes::StrategyNum].toUInt();
4778 						elem_type=elem_types[attribs[Attributes::Type]];
4779 
4780 						xmlparser.savePosition();
4781 						xmlparser.accessElement(XmlParser::ChildElement);
4782 						xmlparser.getElementAttributes(attribs);
4783 
4784 						if(elem_type==OperatorClassElement::StorageElem)
4785 						{
4786 							type=createPgSQLType();
4787 							class_elem.setStorage(type);
4788 						}
4789 						else if(elem_type==OperatorClassElement::FunctionElem)
4790 						{
4791 							object=getObject(attribs[Attributes::Signature],ObjectType::Function);
4792 							class_elem.setFunction(dynamic_cast<Function *>(object),stg_number);
4793 						}
4794 						else if(elem_type==OperatorClassElement::OperatorElem)
4795 						{
4796 							object=getObject(attribs[Attributes::Signature],ObjectType::Operator);
4797 							class_elem.setOperator(dynamic_cast<Operator *>(object),stg_number);
4798 
4799 							if(xmlparser.hasElement(XmlParser::NextElement))
4800 							{
4801 								xmlparser.savePosition();
4802 								xmlparser.accessElement(XmlParser::NextElement);
4803 								xmlparser.getElementAttributes(attribs_aux);
4804 
4805 								object=getObject(attribs_aux[Attributes::Signature],ObjectType::OpFamily);
4806 
4807 								if(!object && !attribs_aux[Attributes::Signature].isEmpty())
4808 									throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
4809 													.arg(op_class->getName())
4810 													.arg(op_class->getTypeName())
4811 													.arg(attribs_aux[Attributes::Signature])
4812 										.arg(BaseObject::getTypeName(ObjectType::OpFamily)),
4813 										ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
4814 
4815 								class_elem.setOperatorFamily(dynamic_cast<OperatorFamily *>(object));
4816 								xmlparser.restorePosition();
4817 							}
4818 						}
4819 
4820 						op_class->addElement(class_elem);
4821 						xmlparser.restorePosition();
4822 					}
4823 				}
4824 			}
4825 			while(xmlparser.accessElement(XmlParser::NextElement));
4826 		}
4827 	}
4828 	catch(Exception &e)
4829 	{
4830 		if(op_class) delete op_class;
4831 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, getErrorExtraInfo());
4832 	}
4833 
4834 	return op_class;
4835 }
4836 
createOperatorFamily()4837 OperatorFamily *DatabaseModel::createOperatorFamily()
4838 {
4839 	attribs_map attribs;
4840 	OperatorFamily *op_family=nullptr;
4841 
4842 	try
4843 	{
4844 		op_family=new OperatorFamily;
4845 		setBasicAttributes(op_family);
4846 		xmlparser.getElementAttributes(attribs);
4847 		op_family->setIndexingType(IndexingType(attribs[Attributes::IndexType]));
4848 	}
4849 	catch(Exception &e)
4850 	{
4851 		if(op_family) delete op_family;
4852 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, getErrorExtraInfo());
4853 	}
4854 
4855 	return op_family;
4856 }
4857 
createAggregate()4858 Aggregate *DatabaseModel::createAggregate()
4859 {
4860 	attribs_map attribs;
4861 	BaseObject *func=nullptr;
4862 	QString elem;
4863 	PgSqlType type;
4864 	Aggregate *aggreg=nullptr;
4865 
4866 	try
4867 	{
4868 		aggreg=new Aggregate;
4869 		setBasicAttributes(aggreg);
4870 		xmlparser.getElementAttributes(attribs);
4871 
4872 		aggreg->setInitialCondition(attribs[Attributes::InitialCond]);
4873 
4874 		if(xmlparser.accessElement(XmlParser::ChildElement))
4875 		{
4876 			do
4877 			{
4878 				if(xmlparser.getElementType()==XML_ELEMENT_NODE)
4879 				{
4880 					elem=xmlparser.getElementName();
4881 
4882 					if(elem==Attributes::Type)
4883 					{
4884 						xmlparser.getElementAttributes(attribs);
4885 						type=createPgSQLType();
4886 
4887 						if(attribs[Attributes::RefType]==Attributes::StateType)
4888 							aggreg->setStateType(type);
4889 						else
4890 							aggreg->addDataType(type);
4891 					}
4892 					else if(elem==Attributes::Function)
4893 					{
4894 						xmlparser.getElementAttributes(attribs);
4895 						func=getObject(attribs[Attributes::Signature], ObjectType::Function);
4896 
4897 						//Raises an error if the function doesn't exists on the model
4898 						if(!func && !attribs[Attributes::Signature].isEmpty())
4899 							throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
4900 											.arg(aggreg->getName())
4901 											.arg(aggreg->getTypeName())
4902 											.arg(attribs[Attributes::Signature])
4903 								.arg(BaseObject::getTypeName(ObjectType::Function)),
4904 								ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
4905 
4906 						if(attribs[Attributes::RefType]==Attributes::TransitionFunc)
4907 							aggreg->setFunction(Aggregate::TransitionFunc,
4908 												dynamic_cast<Function *>(func));
4909 						else
4910 							aggreg->setFunction(Aggregate::FinalFunc,
4911 												dynamic_cast<Function *>(func));
4912 					}
4913 				}
4914 			}
4915 			while(xmlparser.accessElement(XmlParser::NextElement));
4916 		}
4917 	}
4918 	catch(Exception &e)
4919 	{
4920 		if(aggreg) delete aggreg;
4921 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, getErrorExtraInfo());
4922 	}
4923 
4924 	return aggreg;
4925 }
4926 
createTable()4927 Table *DatabaseModel::createTable()
4928 {
4929 	try
4930 	{
4931 		Table *table = nullptr;
4932 		attribs_map attribs;
4933 
4934 		xmlparser.getElementAttributes(attribs);
4935 		table = createPhysicalTable<Table>();
4936 		table->setUnlogged(attribs[Attributes::Unlogged]==Attributes::True);
4937 		table->setRLSEnabled(attribs[Attributes::RlsEnabled]==Attributes::True);
4938 		table->setRLSForced(attribs[Attributes::RlsForced]==Attributes::True);
4939 		table->setWithOIDs(attribs[Attributes::Oids]==Attributes::True);
4940 
4941 		return table;
4942 	}
4943 	catch(Exception &e)
4944 	{
4945 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
4946 	}
4947 }
4948 
createColumn()4949 Column *DatabaseModel::createColumn()
4950 {
4951 	attribs_map attribs;
4952 	Column *column=nullptr;
4953 	BaseObject *seq=nullptr;
4954 	QString elem;
4955 
4956 	try
4957 	{
4958 		column=new Column;
4959 		setBasicAttributes(column);
4960 
4961 		xmlparser.getElementAttributes(attribs);
4962 		column->setNotNull(attribs[Attributes::NotNull]==Attributes::True);
4963 		column->setGenerated(attribs[Attributes::Generated]==Attributes::True);
4964 		column->setDefaultValue(attribs[Attributes::DefaultValue]);
4965 		column->setIdSeqAttributes(attribs[Attributes::MinValue], attribs[Attributes::MaxValue], attribs[Attributes::Increment],
4966 																attribs[Attributes::Start], attribs[Attributes::Cache], attribs[Attributes::Cycle] == Attributes::True);
4967 
4968 		if(!attribs[Attributes::IdentityType].isEmpty())
4969 			column->setIdentityType(IdentityType(attribs[Attributes::IdentityType]));
4970 
4971 		if(!attribs[Attributes::Sequence].isEmpty())
4972 		{
4973 			seq=getObject(attribs[Attributes::Sequence], ObjectType::Sequence);
4974 
4975 			if(!seq)
4976 				throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
4977 								.arg(attribs[Attributes::Name])
4978 					.arg(BaseObject::getTypeName(ObjectType::Column))
4979 					.arg(attribs[Attributes::Sequence])
4980 					.arg(BaseObject::getTypeName(ObjectType::Sequence)),
4981 					ErrorCode::PermissionRefInexistObject,__PRETTY_FUNCTION__,__FILE__,__LINE__);
4982 
4983 
4984 			column->setSequence(seq);
4985 		}
4986 
4987 		if(xmlparser.accessElement(XmlParser::ChildElement))
4988 		{
4989 			do
4990 			{
4991 				if(xmlparser.getElementType()==XML_ELEMENT_NODE)
4992 				{
4993 					elem=xmlparser.getElementName();
4994 
4995 					if(elem==Attributes::Type)
4996 					{
4997 						column->setType(createPgSQLType());
4998 					}
4999 				}
5000 			}
5001 			while(xmlparser.accessElement(XmlParser::NextElement));
5002 		}
5003 	}
5004 	catch(Exception &e)
5005 	{
5006 		if(column) delete column;
5007 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, getErrorExtraInfo());
5008 	}
5009 
5010 	return column;
5011 }
5012 
createConstraint(BaseObject * parent_obj)5013 Constraint *DatabaseModel::createConstraint(BaseObject *parent_obj)
5014 {
5015 	attribs_map attribs;
5016 	Constraint *constr=nullptr;
5017 	BaseObject *ref_table=nullptr;
5018 	PhysicalTable *table=nullptr,*table_aux=nullptr;
5019 	Column *column=nullptr;
5020 	Relationship *rel=nullptr;
5021 	QString elem, str_aux;
5022 	bool deferrable, ins_constr_table=false;
5023 	ConstraintType constr_type;
5024 	QStringList col_list;
5025 	int count, i;
5026 	unsigned col_type;
5027 	ObjectType obj_type;
5028 	ExcludeElement exc_elem;
5029 
5030 	try
5031 	{
5032 		xmlparser.getElementAttributes(attribs);
5033 
5034 		//If the constraint parent is allocated
5035 		if(parent_obj)
5036 		{
5037 			obj_type=parent_obj->getObjectType();
5038 
5039 			//Identifies the correct parent type
5040 			if(PhysicalTable::isPhysicalTable(obj_type))
5041 				table=dynamic_cast<PhysicalTable *>(parent_obj);
5042 			else if(obj_type==ObjectType::Relationship)
5043 				rel=dynamic_cast<Relationship *>(parent_obj);
5044 			else
5045 				//Raises an error if the user tries to create a constraint in a invalid parent
5046 				throw Exception(ErrorCode::OprObjectInvalidType,__PRETTY_FUNCTION__,__FILE__,__LINE__);
5047 		}
5048 		else
5049 		{
5050 			obj_type = ObjectType::Table;
5051 			table = dynamic_cast<PhysicalTable *>(getObject(attribs[Attributes::Table], {ObjectType::Table, ObjectType::ForeignTable}));
5052 			parent_obj=table;
5053 			ins_constr_table=true;
5054 
5055 			//Raises an error if the parent table doesn't exists
5056 			if(!table)
5057 			{
5058 				str_aux=Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
5059 						.arg(attribs[Attributes::Name])
5060 						.arg(BaseObject::getTypeName(ObjectType::Constraint))
5061 						.arg(attribs[Attributes::Table])
5062 						.arg(BaseObject::getTypeName(obj_type));
5063 
5064 				throw Exception(str_aux,ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
5065 			}
5066 		}
5067 
5068 		constr=new Constraint;
5069 		constr->setParentTable(table);
5070 
5071 		//Configuring the constraint type
5072 		if(attribs[Attributes::Type]==Attributes::CkConstr)
5073 			constr_type=ConstraintType::Check;
5074 		else if(attribs[Attributes::Type]==Attributes::PkConstr)
5075 			constr_type=ConstraintType::PrimaryKey;
5076 		else if(attribs[Attributes::Type]==Attributes::FkConstr)
5077 			constr_type=ConstraintType::ForeignKey;
5078 		else if(attribs[Attributes::Type]==Attributes::UqConstr)
5079 			constr_type=ConstraintType::Unique;
5080 		else
5081 			constr_type=ConstraintType::Exclude;
5082 
5083 		constr->setConstraintType(constr_type);
5084 
5085 		if(!attribs[Attributes::Factor].isEmpty())
5086 			constr->setFillFactor(attribs[Attributes::Factor].toUInt());
5087 
5088 		setBasicAttributes(constr);
5089 
5090 		//Raises an error if the constraint is a primary key and no parent object is specified
5091 		if(!parent_obj && constr_type==ConstraintType::PrimaryKey)
5092 			throw Exception(Exception::getErrorMessage(ErrorCode::InvPrimaryKeyAllocation)
5093 							.arg(constr->getName()),
5094 							ErrorCode::InvPrimaryKeyAllocation,__PRETTY_FUNCTION__,__FILE__,__LINE__);
5095 
5096 		deferrable=(attribs[Attributes::Deferrable]==Attributes::True);
5097 		constr->setDeferrable(deferrable);
5098 
5099 		if(deferrable && !attribs[Attributes::DeferType].isEmpty())
5100 			constr->setDeferralType(attribs[Attributes::DeferType]);
5101 
5102 		if(constr_type==ConstraintType::ForeignKey)
5103 		{
5104 			if(!attribs[Attributes::ComparisonType].isEmpty())
5105 				constr->setMatchType(attribs[Attributes::ComparisonType]);
5106 
5107 			if(!attribs[Attributes::DelAction].isEmpty())
5108 				constr->setActionType(attribs[Attributes::DelAction], Constraint::DeleteAction);
5109 
5110 			if(!attribs[Attributes::UpdAction].isEmpty())
5111 				constr->setActionType(attribs[Attributes::UpdAction], Constraint::UpdateAction);
5112 
5113 			ref_table=getObject(attribs[Attributes::RefTable], ObjectType::Table);
5114 
5115 			if(!ref_table && table->getName(true)==attribs[Attributes::RefTable])
5116 				ref_table=table;
5117 
5118 			//Raises an error if the referenced table doesn't exists
5119 			if(!ref_table)
5120 			{
5121 				str_aux=Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
5122 						.arg(constr->getName())
5123 						.arg(constr->getTypeName())
5124 						.arg(attribs[Attributes::RefTable])
5125 						.arg(BaseObject::getTypeName(ObjectType::Table));
5126 
5127 				throw Exception(str_aux,ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
5128 			}
5129 
5130 			constr->setReferencedTable(dynamic_cast<BaseTable *>(ref_table));
5131 		}
5132 		else if(constr_type==ConstraintType::Check)
5133 		{
5134 			constr->setNoInherit(attribs[Attributes::NoInherit]==Attributes::True);
5135 		}
5136 		else if(constr_type==ConstraintType::Exclude &&	!attribs[Attributes::IndexType].isEmpty())
5137 		{
5138 			constr->setIndexType(attribs[Attributes::IndexType]);
5139 		}
5140 
5141 		if(xmlparser.accessElement(XmlParser::ChildElement))
5142 		{
5143 			do
5144 			{
5145 				if(xmlparser.getElementType()==XML_ELEMENT_NODE)
5146 				{
5147 					elem=xmlparser.getElementName();
5148 
5149 					if(elem==Attributes::ExcludeElement)
5150 					{
5151 						createElement(exc_elem, constr, parent_obj);
5152 						constr->addExcludeElement(exc_elem);
5153 					}
5154 					else if(elem==Attributes::Expression)
5155 					{
5156 						xmlparser.savePosition();
5157 						xmlparser.accessElement(XmlParser::ChildElement);
5158 
5159 						constr->setExpression(xmlparser.getElementContent());
5160 
5161 						xmlparser.restorePosition();
5162 					}
5163 					else if(elem==Attributes::Columns)
5164 					{
5165 						xmlparser.getElementAttributes(attribs);
5166 
5167 						col_list=attribs[Attributes::Names].split(',');
5168 						count=col_list.count();
5169 
5170 						if(attribs[Attributes::RefType]==Attributes::SrcColumns)
5171 							col_type=Constraint::SourceCols;
5172 						else
5173 							col_type=Constraint::ReferencedCols;
5174 
5175 						for(i=0; i < count; i++)
5176 						{
5177 							if(col_type==Constraint::SourceCols)
5178 							{
5179 								if(PhysicalTable::isPhysicalTable(obj_type))
5180 								{
5181 									column=table->getColumn(col_list[i]);
5182 
5183 									//If the column doesn't exists tries to get it searching by the old name
5184 									if(!column)
5185 										column=table->getColumn(col_list[i], true);
5186 								}
5187 								else
5188 									column=dynamic_cast<Column *>(rel->getObject(col_list[i], ObjectType::Column));
5189 							}
5190 							else
5191 							{
5192 								table_aux=dynamic_cast<PhysicalTable *>(ref_table);
5193 								column=table_aux->getColumn(col_list[i]);
5194 
5195 								//If the column doesn't exists tries to get it searching by the old name
5196 								if(!column)
5197 									column=table_aux->getColumn(col_list[i], true);
5198 							}
5199 
5200 							constr->addColumn(column, col_type);
5201 						}
5202 					}
5203 				}
5204 			}
5205 			while(xmlparser.accessElement(XmlParser::NextElement));
5206 		}
5207 
5208 		if(ins_constr_table)
5209 		{
5210 			if(constr->getConstraintType()!=ConstraintType::PrimaryKey)
5211 			{
5212 				table->addConstraint(constr);
5213 
5214 				if(this->getObjectIndex(table) >= 0)
5215 					table->setModified(!loading_model);
5216 			}
5217 		}
5218 	}
5219 	catch(Exception &e)
5220 	{
5221 		if(constr) delete constr;
5222 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, getErrorExtraInfo());
5223 	}
5224 
5225 	return constr;
5226 }
5227 
createElement(Element & elem,TableObject * tab_obj,BaseObject * parent_obj)5228 void DatabaseModel::createElement(Element &elem, TableObject *tab_obj, BaseObject *parent_obj)
5229 {
5230 	attribs_map attribs;
5231 	Column *column=nullptr;
5232 	OperatorClass *op_class=nullptr;
5233 	Operator *oper=nullptr;
5234 	Collation *collation=nullptr;
5235 	QString xml_elem;
5236 	bool is_part_key = false;
5237 
5238 	xml_elem=xmlparser.getElementName();
5239 	is_part_key = xml_elem == Attributes::PartitionKey;
5240 
5241 	if(xml_elem==Attributes::IndexElement || xml_elem==Attributes::ExcludeElement || is_part_key)
5242 	{
5243 		xmlparser.getElementAttributes(attribs);
5244 
5245 		elem.setColumn(nullptr);
5246 		elem.setCollation(nullptr);
5247 		elem.setOperator(nullptr);
5248 		elem.setOperatorClass(nullptr);
5249 
5250 		elem.setSortingAttribute(Element::AscOrder, attribs[Attributes::AscOrder]==Attributes::True);
5251 		elem.setSortingAttribute(Element::NullsFirst, attribs[Attributes::NullsFirst]==Attributes::True);
5252 		elem.setSortingEnabled(attribs[Attributes::UseSorting]!=Attributes::False);
5253 
5254 		xmlparser.savePosition();
5255 		xmlparser.accessElement(XmlParser::ChildElement);
5256 
5257 		do
5258 		{
5259 			xml_elem=xmlparser.getElementName();
5260 
5261 			if(xmlparser.getElementType()==XML_ELEMENT_NODE)
5262 			{
5263 				if(xml_elem==Attributes::OpClass)
5264 				{
5265 					xmlparser.getElementAttributes(attribs);
5266 					op_class=dynamic_cast<OperatorClass *>(getObject(attribs[Attributes::Signature], ObjectType::OpClass));
5267 
5268 					//Raises an error if the operator class doesn't exists
5269 					if(!op_class)
5270 					{
5271 						if(!is_part_key)
5272 						{
5273 							throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
5274 											.arg(tab_obj->getName())
5275 											.arg(tab_obj->getTypeName())
5276 											.arg(attribs[Attributes::Signature])
5277 									.arg(BaseObject::getTypeName(ObjectType::OpClass)),
5278 									ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
5279 						}
5280 						else
5281 						{
5282 							throw Exception(Exception::getErrorMessage(ErrorCode::PartKeyObjectInexistsModel)
5283 											.arg(parent_obj->getName())
5284 											.arg(attribs[Attributes::Signature])
5285 									.arg(BaseObject::getTypeName(ObjectType::OpClass)),
5286 									ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
5287 						}
5288 					}
5289 
5290 					elem.setOperatorClass(op_class);
5291 				}
5292 				//Checking if elem is a ExcludeElement to be able to assign an operator to it
5293 				else if(xml_elem==Attributes::Operator)
5294 				{
5295 					xmlparser.getElementAttributes(attribs);
5296 					oper=dynamic_cast<Operator *>(getObject(attribs[Attributes::Signature], ObjectType::Operator));
5297 
5298 					//Raises an error if the operator doesn't exists
5299 					if(!oper)
5300 					{
5301 						throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
5302 										.arg(tab_obj->getName())
5303 										.arg(tab_obj->getTypeName())
5304 										.arg(attribs[Attributes::Signature])
5305 								.arg(BaseObject::getTypeName(ObjectType::Operator)),
5306 								ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
5307 					}
5308 
5309 					elem.setOperator(oper);
5310 				}
5311 				else if(xml_elem==Attributes::Collation)
5312 				{
5313 					xmlparser.getElementAttributes(attribs);
5314 					collation=dynamic_cast<Collation *>(getObject(attribs[Attributes::Name], ObjectType::Collation));
5315 
5316 					//Raises an error if the operator class doesn't exists
5317 					if(!collation)
5318 					{
5319 						if(!is_part_key)
5320 						{
5321 							throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
5322 															.arg(tab_obj->getName())
5323 															.arg(tab_obj->getTypeName())
5324 															.arg(attribs[Attributes::Name])
5325 															.arg(BaseObject::getTypeName(ObjectType::Collation)),
5326 															ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
5327 						}
5328 						else
5329 						{
5330 							throw Exception(Exception::getErrorMessage(ErrorCode::PartKeyObjectInexistsModel)
5331 															.arg(parent_obj->getName())
5332 															.arg(attribs[Attributes::Name])
5333 															.arg(BaseObject::getTypeName(ObjectType::Collation)),
5334 															ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
5335 						}
5336 					}
5337 
5338 					elem.setCollation(collation);
5339 				}
5340 				else if(xml_elem==Attributes::Column)
5341 				{
5342 					xmlparser.getElementAttributes(attribs);
5343 
5344 					if(parent_obj->getObjectType()==ObjectType::Table)
5345 					{
5346 						column=dynamic_cast<Table *>(parent_obj)->getColumn(attribs[Attributes::Name]);
5347 
5348 						if(!column)
5349 							column=dynamic_cast<Table *>(parent_obj)->getColumn(attribs[Attributes::Name], true);
5350 					}
5351 					else
5352 					{
5353 						column=dynamic_cast<Column *>(dynamic_cast<Relationship *>(parent_obj)->getObject(attribs[Attributes::Name], ObjectType::Column));
5354 					}
5355 
5356 					//Raises an error if the column doesn't exists
5357 					if(!column)
5358 					{
5359 						if(!is_part_key)
5360 						{
5361 							throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
5362 											.arg(tab_obj->getName())
5363 											.arg(tab_obj->getTypeName())
5364 											.arg(attribs[Attributes::Name])
5365 									.arg(BaseObject::getTypeName(ObjectType::Column)),
5366 									ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
5367 						}
5368 						else
5369 						{
5370 							throw Exception(Exception::getErrorMessage(ErrorCode::PartKeyObjectInexistsModel)
5371 											.arg(parent_obj->getName())
5372 											.arg(attribs[Attributes::Name])
5373 									.arg(BaseObject::getTypeName(ObjectType::Column)),
5374 									ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
5375 						}
5376 					}
5377 
5378 					elem.setColumn(column);
5379 				}
5380 				else if(xml_elem==Attributes::Expression)
5381 				{
5382 					xmlparser.savePosition();
5383 					xmlparser.accessElement(XmlParser::ChildElement);
5384 					elem.setExpression(xmlparser.getElementContent());
5385 					xmlparser.restorePosition();
5386 				}
5387 			}
5388 		}
5389 		while(xmlparser.accessElement(XmlParser::NextElement));
5390 
5391 		xmlparser.restorePosition();
5392 	}
5393 }
5394 
getXMLParser()5395 XmlParser *DatabaseModel::getXMLParser()
5396 {
5397 	return &xmlparser;
5398 }
5399 
getAlterDefinition(BaseObject * object)5400 QString DatabaseModel::getAlterDefinition(BaseObject *object)
5401 {
5402 	DatabaseModel *db_aux=dynamic_cast<DatabaseModel *>(object);
5403 
5404 	if(!db_aux)
5405 		throw Exception(ErrorCode::OprNotAllocatedObject,__PRETTY_FUNCTION__,__FILE__,__LINE__);
5406 
5407 	try
5408 	{
5409 		QString alter_def;
5410 		attribs_map aux_attribs;
5411 
5412 		aux_attribs[Attributes::Signature] = this->getSignature();
5413 		aux_attribs[Attributes::SqlObject] = this->getSQLName();
5414 
5415 		if(this->conn_limit!=db_aux->conn_limit)
5416 			aux_attribs[Attributes::ConnLimit]=QString::number(db_aux->conn_limit);
5417 
5418 		if(this->is_template != db_aux->is_template)
5419 			aux_attribs[Attributes::IsTemplate] = (db_aux->is_template ? Attributes::True : Attributes::False);
5420 
5421 		if(this->allow_conns != db_aux->allow_conns)
5422 			aux_attribs[Attributes::AllowConns] = (db_aux->allow_conns ? Attributes::True : Attributes::False);
5423 
5424 		alter_def+=BaseObject::getAlterDefinition(this->getSchemaName(), aux_attribs, true, false);
5425 		alter_def+=BaseObject::getAlterDefinition(object);
5426 
5427 		return alter_def;
5428 	}
5429 	catch(Exception &e)
5430 	{
5431 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
5432 	}
5433 }
5434 
createIndex()5435 Index *DatabaseModel::createIndex()
5436 {
5437 	attribs_map attribs;
5438 	Index *index=nullptr;
5439 	QString elem, str_aux;
5440 	IndexElement idx_elem;
5441 	BaseTable *table=nullptr;
5442 
5443 	try
5444 	{
5445 		xmlparser.getElementAttributes(attribs);
5446 
5447 		table=dynamic_cast<BaseTable *>(getObject(attribs[Attributes::Table], ObjectType::Table));
5448 
5449 		if(!table)
5450 			table=dynamic_cast<BaseTable *>(getObject(attribs[Attributes::Table], ObjectType::View));
5451 
5452 		//Raises an error if the parent table doesn't exists
5453 		if(!table)
5454 		{
5455 			str_aux=Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
5456 					.arg(attribs[Attributes::Name])
5457 					.arg(BaseObject::getTypeName(ObjectType::Index))
5458 					.arg(attribs[Attributes::Table])
5459 					.arg(BaseObject::getTypeName(ObjectType::Table));
5460 
5461 			throw Exception(str_aux,ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
5462 		}
5463 
5464 		index=new Index;
5465 		setBasicAttributes(index);
5466 		index->setParentTable(table);
5467 		index->setIndexAttribute(Index::Concurrent, attribs[Attributes::Concurrent]==Attributes::True);
5468 		index->setIndexAttribute(Index::Unique, attribs[Attributes::Unique]==Attributes::True);
5469 		index->setIndexAttribute(Index::FastUpdate, attribs[Attributes::FastUpdate]==Attributes::True);
5470 		index->setIndexAttribute(Index::Buffering, attribs[Attributes::Buffering]==Attributes::True);
5471 		index->setIndexingType(attribs[Attributes::IndexType]);
5472 		index->setFillFactor(attribs[Attributes::Factor].toUInt());
5473 
5474 		if(xmlparser.accessElement(XmlParser::ChildElement))
5475 		{
5476 			do
5477 			{
5478 				if(xmlparser.getElementType()==XML_ELEMENT_NODE)
5479 				{
5480 					elem=xmlparser.getElementName();
5481 
5482 					if(elem==Attributes::IndexElement)
5483 					{
5484 						createElement(idx_elem, index, table);
5485 						index->addIndexElement(idx_elem);
5486 					}
5487 					else if(elem==Attributes::Predicate)
5488 					{
5489 						xmlparser.savePosition();
5490 						xmlparser.accessElement(XmlParser::ChildElement);
5491 						str_aux=xmlparser.getElementContent();
5492 						xmlparser.restorePosition();
5493 						index->setPredicate(str_aux);
5494 					}
5495 				}
5496 			}
5497 			while(xmlparser.accessElement(XmlParser::NextElement));
5498 		}
5499 
5500 		table->addObject(index);
5501 		table->setModified(!loading_model);
5502 	}
5503 	catch(Exception &e)
5504 	{
5505 		if(index) delete index;
5506 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, getErrorExtraInfo());
5507 	}
5508 
5509 	return index;
5510 }
5511 
createRule()5512 Rule *DatabaseModel::createRule()
5513 {
5514 	attribs_map attribs;
5515 	QStringList cmd_list;
5516 	Rule *rule=nullptr;
5517 	QString elem, str_aux;
5518 	int count, i;
5519 	BaseTable *table=nullptr;
5520 
5521 	try
5522 	{
5523 		rule=new Rule;
5524 		setBasicAttributes(rule);
5525 
5526 		xmlparser.getElementAttributes(attribs);
5527 
5528 		table=dynamic_cast<BaseTable *>(getObject(attribs[Attributes::Table], ObjectType::Table));
5529 
5530 		if(!table)
5531 			table=dynamic_cast<BaseTable *>(getObject(attribs[Attributes::Table], ObjectType::View));
5532 
5533 		if(!table)
5534 			throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
5535 							.arg(attribs[Attributes::Name])
5536 				.arg(BaseObject::getTypeName(ObjectType::Rule))
5537 				.arg(attribs[Attributes::Table])
5538 				.arg(BaseObject::getTypeName(ObjectType::Table)),
5539 				ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
5540 
5541 
5542 		rule->setExecutionType(attribs[Attributes::ExecType]);
5543 		rule->setEventType(attribs[Attributes::EventType]);
5544 
5545 		if(xmlparser.accessElement(XmlParser::ChildElement))
5546 		{
5547 			do
5548 			{
5549 				if(xmlparser.getElementType()==XML_ELEMENT_NODE)
5550 				{
5551 					elem=xmlparser.getElementName();
5552 
5553 					if(elem==Attributes::Commands ||
5554 							elem==Attributes::Condition)
5555 					{
5556 						xmlparser.savePosition();
5557 						xmlparser.accessElement(XmlParser::ChildElement);
5558 
5559 						str_aux=xmlparser.getElementContent();
5560 						xmlparser.restorePosition();
5561 
5562 						if(elem==Attributes::Commands)
5563 						{
5564 							cmd_list=str_aux.split(';');
5565 							count=cmd_list.count();
5566 							for(i=0; i < count; i++)
5567 							{
5568 								if(!cmd_list[i].isEmpty())
5569 									rule->addCommand(cmd_list[i]);
5570 							}
5571 						}
5572 						else
5573 							rule->setConditionalExpression(str_aux);
5574 					}
5575 				}
5576 			}
5577 			while(xmlparser.accessElement(XmlParser::NextElement));
5578 		}
5579 
5580 		table->addObject(rule);
5581 		table->setModified(!loading_model);
5582 	}
5583 	catch(Exception &e)
5584 	{
5585 		if(rule) delete rule;
5586 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, getErrorExtraInfo());
5587 	}
5588 
5589 	return rule;
5590 }
5591 
createTrigger()5592 Trigger *DatabaseModel::createTrigger()
5593 {
5594 	attribs_map attribs;
5595 	Trigger *trigger=nullptr;
5596 	QString elem, str_aux;
5597 	QStringList list_aux;
5598 	int count, i;
5599 	BaseObject *ref_table=nullptr, *func=nullptr;
5600 	Column *column=nullptr;
5601 	BaseTable *table=nullptr;
5602 	PhysicalTable *aux_table = nullptr;
5603 	vector<ObjectType> table_types = { ObjectType::Table, ObjectType::ForeignTable, ObjectType::View };
5604 
5605 	try
5606 	{
5607 		xmlparser.getElementAttributes(attribs);
5608 
5609 		for(auto &type : table_types)
5610 		{
5611 			table = dynamic_cast<BaseTable *>(getObject(attribs[Attributes::Table], type));
5612 			if(table) break;
5613 		}
5614 
5615 		if(!table)
5616 		{
5617 			throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
5618 							.arg(attribs[Attributes::Name])
5619 				.arg(BaseObject::getTypeName(ObjectType::Trigger))
5620 				.arg(attribs[Attributes::Table])
5621 				.arg(BaseObject::getTypeName(ObjectType::Table)),
5622 				ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
5623 		}
5624 
5625 		trigger=new Trigger;
5626 		trigger->setParentTable(table);
5627 
5628 		setBasicAttributes(trigger);
5629 
5630 		trigger->setConstraint(attribs[Attributes::Constraint]==Attributes::True);
5631 
5632 		trigger->setEvent(EventType::OnInsert,
5633 							(attribs[Attributes::InsEvent]==Attributes::True));
5634 
5635 		trigger->setEvent(EventType::OnDelete,
5636 							(attribs[Attributes::DelEvent]==Attributes::True));
5637 
5638 		trigger->setEvent(EventType::OnUpdate,
5639 							(attribs[Attributes::UpdEvent]==Attributes::True));
5640 
5641 		trigger->setEvent(EventType::OnTruncate,
5642 							(attribs[Attributes::TruncEvent]==Attributes::True));
5643 
5644 		trigger->setExecutePerRow(attribs[Attributes::PerRow]==Attributes::True);
5645 
5646 		trigger->setFiringType(FiringType(attribs[Attributes::FiringType]));
5647 
5648 		trigger->setTransitionTableName(Trigger::OldTableName, attribs[Attributes::OldTableName]);
5649 		trigger->setTransitionTableName(Trigger::NewTableName, attribs[Attributes::NewTableName]);
5650 
5651 		list_aux=attribs[Attributes::Arguments].split(',');
5652 		count=list_aux.count();
5653 		for(i=0; i < count; i++)
5654 		{
5655 			if(!list_aux[i].isEmpty())
5656 				trigger->addArgument(list_aux[i]);
5657 		}
5658 
5659 		trigger->setDeferrable(attribs[Attributes::Deferrable]==Attributes::True);
5660 
5661 		if(trigger->isDeferrable())
5662 			trigger->setDeferralType(attribs[Attributes::DeferType]);
5663 
5664 		if(!attribs[Attributes::RefTable].isEmpty())
5665 		{
5666 			ref_table=getObject(attribs[Attributes::RefTable], ObjectType::Table);
5667 
5668 			if(!ref_table)
5669 				ref_table=getObject(attribs[Attributes::RefTable], ObjectType::View);
5670 
5671 			//Raises an error if the trigger is referencing a inexistent table
5672 			if(!ref_table)
5673 			{
5674 				throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
5675 								.arg(trigger->getName())
5676 								.arg(trigger->getTypeName())
5677 								.arg(attribs[Attributes::RefTable])
5678 						.arg(BaseObject::getTypeName(ObjectType::Table)),
5679 						ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
5680 			}
5681 
5682 			trigger->setReferecendTable(dynamic_cast<BaseTable *>(ref_table));
5683 		}
5684 
5685 		if(xmlparser.accessElement(XmlParser::ChildElement))
5686 		{
5687 			do
5688 			{
5689 				if(xmlparser.getElementType()==XML_ELEMENT_NODE)
5690 				{
5691 					elem=xmlparser.getElementName();
5692 
5693 					if(elem==Attributes::Function)
5694 					{
5695 						xmlparser.getElementAttributes(attribs);
5696 						func=getObject(attribs[Attributes::Signature], ObjectType::Function);
5697 
5698 						//Raises an error if the function doesn't exists
5699 						if(!func && !attribs[Attributes::Signature].isEmpty())
5700 						{
5701 							str_aux=Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
5702 									.arg(trigger->getName())
5703 									.arg(trigger->getTypeName())
5704 									.arg(attribs[Attributes::Signature])
5705 									.arg(BaseObject::getTypeName(ObjectType::Function));
5706 
5707 							throw Exception(str_aux,ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
5708 						}
5709 
5710 						trigger->setFunction(dynamic_cast<Function *>(func));
5711 					}
5712 					else if(elem==Attributes::Condition)
5713 					{
5714 						xmlparser.savePosition();
5715 						xmlparser.accessElement(XmlParser::ChildElement);
5716 						str_aux=xmlparser.getElementContent();
5717 						xmlparser.restorePosition();
5718 						trigger->setCondition(str_aux);
5719 					}
5720 					else if(elem==Attributes::Columns)
5721 					{
5722 						xmlparser.getElementAttributes(attribs);
5723 
5724 						list_aux=attribs[Attributes::Names].split(',');
5725 						count=list_aux.count();
5726 
5727 						for(i=0; i < count; i++)
5728 						{
5729 							column=dynamic_cast<Column *>(table->getObject(list_aux[i].trimmed(), ObjectType::Column));
5730 							aux_table=dynamic_cast<PhysicalTable *>(table);
5731 
5732 							if(!column && aux_table)
5733 								column=aux_table->getColumn(list_aux[i].trimmed(), true);
5734 
5735 							trigger->addColumn(column);
5736 						}
5737 					}
5738 				}
5739 			}
5740 			while(xmlparser.accessElement(XmlParser::NextElement));
5741 		}
5742 
5743 		table->addObject(trigger);
5744 		table->setModified(!loading_model);
5745 	}
5746 	catch(Exception &e)
5747 	{
5748 		if(trigger) delete trigger;
5749 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, getErrorExtraInfo());
5750 	}
5751 
5752 	return trigger;
5753 }
5754 
createPolicy()5755 Policy *DatabaseModel::createPolicy()
5756 {
5757 	attribs_map attribs;
5758 	Policy *policy=nullptr;
5759 	QString elem;
5760 	BaseTable *table=nullptr;
5761 
5762 	try
5763 	{
5764 		policy=new Policy;
5765 		setBasicAttributes(policy);
5766 
5767 		xmlparser.getElementAttributes(attribs);
5768 
5769 		table=dynamic_cast<BaseTable *>(getObject(attribs[Attributes::Table], ObjectType::Table));
5770 
5771 		if(!table)
5772 			throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
5773 											.arg(attribs[Attributes::Name])
5774 											.arg(BaseObject::getTypeName(ObjectType::Policy))
5775 											.arg(attribs[Attributes::Table])
5776 											.arg(BaseObject::getTypeName(ObjectType::Table)),
5777 				ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
5778 
5779 		policy->setPermissive(attribs[Attributes::Permissive] == Attributes::True);
5780 		policy->setPolicyCommand(PolicyCmdType(attribs[Attributes::Command]));
5781 
5782 		if(xmlparser.accessElement(XmlParser::ChildElement))
5783 		{
5784 			do
5785 			{
5786 				if(xmlparser.getElementType()==XML_ELEMENT_NODE)
5787 				{
5788 					elem=xmlparser.getElementName();
5789 
5790 					if(elem==Attributes::Expression)
5791 					{
5792 						xmlparser.getElementAttributes(attribs);
5793 						xmlparser.savePosition();
5794 						xmlparser.accessElement(XmlParser::ChildElement);
5795 
5796 						if(attribs[Attributes::Type] == Attributes::UsingExp)
5797 							policy->setUsingExpression(xmlparser.getElementContent());
5798 						else if(attribs[Attributes::Type] == Attributes::CheckExp)
5799 							policy->setCheckExpression(xmlparser.getElementContent());
5800 
5801 						xmlparser.restorePosition();
5802 					}
5803 					else if(xmlparser.getElementName()==Attributes::Roles)
5804 					{
5805 						QStringList rol_names;
5806 						Role *role = nullptr;
5807 
5808 						xmlparser.getElementAttributes(attribs);
5809 
5810 						rol_names = attribs[Attributes::Names].split(',');
5811 
5812 						for(auto &name : rol_names)
5813 						{
5814 							role=dynamic_cast<Role *>(getObject(name.trimmed(), ObjectType::Role));
5815 
5816 							//Raises an error if the referenced role doesn't exists
5817 							if(!role)
5818 							{
5819 								throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
5820 																.arg(policy->getName())
5821 																.arg(policy->getTypeName())
5822 																.arg(name)
5823 																.arg(BaseObject::getTypeName(ObjectType::Role)),
5824 																ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
5825 							}
5826 
5827 							policy->addRole(role);
5828 						}
5829 					}
5830 				}
5831 			}
5832 			while(xmlparser.accessElement(XmlParser::NextElement));
5833 		}
5834 
5835 		table->addObject(policy);
5836 		table->setModified(!loading_model);
5837 	}
5838 	catch(Exception &e)
5839 	{
5840 		if(policy) delete policy;
5841 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, getErrorExtraInfo());
5842 	}
5843 
5844 	return policy;
5845 }
5846 
createEventTrigger()5847 EventTrigger *DatabaseModel::createEventTrigger()
5848 {
5849 	attribs_map attribs;
5850 	EventTrigger *event_trig=nullptr;
5851 	BaseObject *func=nullptr;
5852 	QString elem;
5853 
5854 	try
5855 	{
5856 		event_trig=new EventTrigger;
5857 		setBasicAttributes(event_trig);
5858 		xmlparser.getElementAttributes(attribs);
5859 		event_trig->setEvent(EventTriggerType(attribs[Attributes::Event]));
5860 
5861 		if(xmlparser.accessElement(XmlParser::ChildElement))
5862 		{
5863 			do
5864 			{
5865 				if(xmlparser.getElementType()==XML_ELEMENT_NODE)
5866 				{
5867 					elem=xmlparser.getElementName();
5868 
5869 					if(elem==Attributes::Function)
5870 					{
5871 						xmlparser.getElementAttributes(attribs);
5872 						func=getObject(attribs[Attributes::Signature], ObjectType::Function);
5873 
5874 						//Raises an error if the function doesn't exists
5875 						if(!func && !attribs[Attributes::Signature].isEmpty())
5876 						{
5877 							throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
5878 											.arg(event_trig->getName())
5879 											.arg(event_trig->getTypeName())
5880 											.arg(attribs[Attributes::Signature])
5881 									.arg(BaseObject::getTypeName(ObjectType::Function)),
5882 									ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
5883 						}
5884 
5885 						event_trig->setFunction(dynamic_cast<Function *>(func));
5886 					}
5887 					else if(elem==Attributes::Filter)
5888 					{
5889 						xmlparser.getElementAttributes(attribs);
5890 						event_trig->setFilter(attribs[Attributes::Variable], attribs[Attributes::Values].split(','));
5891 					}
5892 				}
5893 			}
5894 			while(xmlparser.accessElement(XmlParser::NextElement));
5895 		}
5896 
5897 	}
5898 	catch(Exception &e)
5899 	{
5900 		if(event_trig) delete event_trig;
5901 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, getErrorExtraInfo());
5902 	}
5903 
5904 	return event_trig;
5905 }
5906 
createGenericSQL()5907 GenericSQL *DatabaseModel::createGenericSQL()
5908 {
5909 	GenericSQL *genericsql=nullptr;
5910 	attribs_map attribs;
5911 	QString elem, parent_name, obj_name;
5912 	ObjectType obj_type;
5913 	PhysicalTable *parent_table = nullptr;
5914 	BaseObject *object = nullptr;
5915 
5916 	try
5917 	{
5918 		genericsql = new GenericSQL;
5919 		setBasicAttributes(genericsql);
5920 
5921 		if(xmlparser.accessElement(XmlParser::ChildElement))
5922 		{
5923 			do
5924 			{
5925 				if(xmlparser.getElementType()==XML_ELEMENT_NODE)
5926 				{
5927 					elem = xmlparser.getElementName();
5928 
5929 					if(elem == Attributes::Definition)
5930 					{
5931 						xmlparser.savePosition();
5932 						xmlparser.accessElement(XmlParser::ChildElement);
5933 						genericsql->setDefinition(xmlparser.getElementContent());
5934 						xmlparser.restorePosition();
5935 					}
5936 					else if(elem == Attributes::Object)
5937 					{
5938 						xmlparser.getElementAttributes(attribs);
5939 
5940 						obj_type = BaseObject::getObjectType(attribs[Attributes::Type]);
5941 						obj_name = attribs[Attributes::Name];
5942 
5943 						//If the object is a column its needed to get the parent table
5944 						if(obj_type == ObjectType::Column)
5945 						{
5946 							QStringList names = obj_name.split('.');
5947 
5948 							if(names.size() > 2)
5949 							{
5950 								parent_name = QString("%1.%2").arg(names[0]).arg(names[1]);
5951 								obj_name = names[2];
5952 							}
5953 
5954 							parent_table = dynamic_cast<PhysicalTable *>(getObject(parent_name, {ObjectType::Table, ObjectType::ForeignTable}));
5955 
5956 							if(parent_table)
5957 								object = parent_table->getColumn(obj_name);
5958 						}
5959 						else
5960 							object = getObject(obj_name, obj_type);
5961 
5962 						//Raises an error if the generic object references an object that does not exist
5963 						if(!object)
5964 							throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
5965 															.arg(genericsql->getName())
5966 															.arg(genericsql->getTypeName())
5967 															.arg(obj_name)
5968 															.arg(BaseObject::getTypeName(obj_type)),
5969 															ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
5970 
5971 						genericsql->addObjectReference(object, attribs[Attributes::RefName],
5972 																					 attribs[Attributes::UseSignature] == Attributes::True,
5973 																					 attribs[Attributes::FormatName] == Attributes::True);
5974 					}
5975 				}
5976 			}
5977 			while(xmlparser.accessElement(XmlParser::NextElement));
5978 		}
5979 	}
5980 	catch(Exception &e)
5981 	{
5982 		if(genericsql) delete genericsql;
5983 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, getErrorExtraInfo());
5984 	}
5985 
5986 	return genericsql;
5987 }
5988 
createForeignDataWrapper()5989 ForeignDataWrapper *DatabaseModel::createForeignDataWrapper()
5990 {
5991 	attribs_map attribs;
5992 	ForeignDataWrapper *fdw=nullptr;
5993 	BaseObject *func=nullptr;
5994 	QString signature, ref_type;
5995 	ObjectType obj_type;
5996 
5997 	try
5998 	{
5999 		fdw = new ForeignDataWrapper;
6000 
6001 		xmlparser.getElementAttributes(attribs);
6002 		setBasicAttributes(fdw);
6003 
6004 		if(xmlparser.accessElement(XmlParser::ChildElement))
6005 		{
6006 			do
6007 			{
6008 				if(xmlparser.getElementType() == XML_ELEMENT_NODE)
6009 				{
6010 					obj_type = BaseObject::getObjectType(xmlparser.getElementName());
6011 
6012 					if(obj_type == ObjectType::Function)
6013 					{
6014 						xmlparser.getElementAttributes(attribs);
6015 
6016 						//Gets the function reference type
6017 						ref_type = attribs[Attributes::RefType];
6018 
6019 						//Try to retrieve one the functions of the fdw
6020 						if(ref_type == Attributes::ValidatorFunc || ref_type == Attributes::HandlerFunc)
6021 						{
6022 							//Gets the function signature and tries to retrieve it from the model
6023 							signature = attribs[Attributes::Signature];
6024 							func = getObject(signature, ObjectType::Function);
6025 
6026 							//Raises an error if the function doesn't exists
6027 							if(!func)
6028 								throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
6029 												.arg(fdw->getName())
6030 												.arg(fdw->getTypeName())
6031 												.arg(signature)
6032 												.arg(BaseObject::getTypeName(ObjectType::Function)),
6033 												ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
6034 
6035 							if(ref_type == Attributes::ValidatorFunc)
6036 								fdw->setValidatorFunction(dynamic_cast<Function *>(func));
6037 							else if(ref_type == Attributes::HandlerFunc)
6038 								fdw->setHandlerFunction(dynamic_cast<Function *>(func));
6039 						}
6040 						else
6041 							//Raises an error if the function type is invalid
6042 							throw Exception(ErrorCode::RefFunctionInvalidType,__PRETTY_FUNCTION__,__FILE__,__LINE__);
6043 					}
6044 				}
6045 			}
6046 			while(xmlparser.accessElement(XmlParser::NextElement));
6047 		}
6048 	}
6049 	catch(Exception &e)
6050 	{
6051 		if(fdw)
6052 			delete fdw;
6053 
6054 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, getErrorExtraInfo());
6055 	}
6056 
6057 	return fdw;
6058 }
6059 
createForeignServer()6060 ForeignServer *DatabaseModel::createForeignServer()
6061 {
6062 	attribs_map attribs;
6063 	ForeignServer *server = nullptr;
6064 	BaseObject *fdw = nullptr;
6065 	ObjectType obj_type;
6066 
6067 	try
6068 	{
6069 		server = new ForeignServer;
6070 
6071 		xmlparser.getElementAttributes(attribs);
6072 		setBasicAttributes(server);
6073 		server->setType(attribs[Attributes::Type]);
6074 		server->setVersion(attribs[Attributes::Version]);
6075 
6076 		if(xmlparser.accessElement(XmlParser::ChildElement))
6077 		{
6078 			do
6079 			{
6080 				if(xmlparser.getElementType() == XML_ELEMENT_NODE)
6081 				{
6082 					obj_type = BaseObject::getObjectType(xmlparser.getElementName());
6083 
6084 					if(obj_type == ObjectType::ForeignDataWrapper)
6085 					{
6086 						xmlparser.getElementAttributes(attribs);
6087 						fdw = getObject(attribs[Attributes::Name], ObjectType::ForeignDataWrapper);
6088 
6089 						//Raises an error if the fdw doesn't exists
6090 						if(!fdw)
6091 							throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
6092 															.arg(server->getName())
6093 															.arg(server->getTypeName())
6094 															.arg(attribs[Attributes::Name])
6095 															.arg(BaseObject::getTypeName(ObjectType::ForeignDataWrapper)),
6096 															ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
6097 
6098 						server->setForeignDataWrapper(dynamic_cast<ForeignDataWrapper *>(fdw));
6099 					}
6100 				}
6101 			}
6102 			while(xmlparser.accessElement(XmlParser::NextElement));
6103 		}
6104 	}
6105 	catch(Exception &e)
6106 	{
6107 		if(server)
6108 			delete server;
6109 
6110 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, getErrorExtraInfo());
6111 	}
6112 
6113 	return server;
6114 }
6115 
createUserMapping()6116 UserMapping *DatabaseModel::createUserMapping()
6117 {
6118 	attribs_map attribs;
6119 	UserMapping *user_map = nullptr;
6120 	ForeignServer *server = nullptr;
6121 	ObjectType obj_type;
6122 
6123 	try
6124 	{
6125 		user_map = new UserMapping;
6126 
6127 		xmlparser.getElementAttributes(attribs);
6128 		setBasicAttributes(user_map);
6129 
6130 		if(xmlparser.accessElement(XmlParser::ChildElement))
6131 		{
6132 			do
6133 			{
6134 				if(xmlparser.getElementType() == XML_ELEMENT_NODE)
6135 				{
6136 					obj_type = BaseObject::getObjectType(xmlparser.getElementName());
6137 
6138 					if(obj_type == ObjectType::ForeignServer)
6139 					{
6140 						xmlparser.savePosition();
6141 						xmlparser.getElementAttributes(attribs);
6142 						server = dynamic_cast<ForeignServer *>(getObject(attribs[Attributes::Name], ObjectType::ForeignServer));
6143 
6144 						//Raises an error if the server doesn't exists
6145 						if(!server)
6146 							throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
6147 															.arg(user_map->getName())
6148 															.arg(user_map->getTypeName())
6149 															.arg(attribs[Attributes::Name])
6150 															.arg(BaseObject::getTypeName(ObjectType::ForeignServer)),
6151 															ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
6152 
6153 						user_map->setForeignServer(server);
6154 						xmlparser.restorePosition();
6155 					}
6156 				}
6157 			}
6158 			while(xmlparser.accessElement(XmlParser::NextElement));
6159 		}
6160 	}
6161 	catch(Exception &e)
6162 	{
6163 		if(user_map)
6164 			delete user_map;
6165 
6166 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, getErrorExtraInfo());
6167 	}
6168 
6169 	return user_map;
6170 }
6171 
createForeignTable()6172 ForeignTable *DatabaseModel::createForeignTable()
6173 {
6174 	ForeignTable *ftable = nullptr;
6175 
6176 	try
6177 	{
6178 		ForeignServer *fserver = nullptr;
6179 		attribs_map attribs;
6180 		ObjectType obj_type;
6181 
6182 		xmlparser.savePosition();
6183 		ftable = createPhysicalTable<ForeignTable>();
6184 		xmlparser.restorePosition();
6185 
6186 		if(xmlparser.accessElement(XmlParser::ChildElement))
6187 		{
6188 			do
6189 			{
6190 				if(xmlparser.getElementType() == XML_ELEMENT_NODE)
6191 				{
6192 					obj_type = BaseObject::getObjectType(xmlparser.getElementName());
6193 
6194 					if(obj_type == ObjectType::ForeignServer)
6195 					{
6196 						xmlparser.savePosition();
6197 						xmlparser.getElementAttributes(attribs);
6198 						fserver = dynamic_cast<ForeignServer *>(getObject(attribs[Attributes::Name], ObjectType::ForeignServer));
6199 
6200 						//Raises an error if the server doesn't exists
6201 						if(!fserver)
6202 							throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
6203 															.arg(ftable->getName())
6204 															.arg(ftable->getTypeName())
6205 															.arg(attribs[Attributes::Name])
6206 															.arg(BaseObject::getTypeName(ObjectType::ForeignServer)),
6207 															ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
6208 
6209 						ftable->setForeignServer(fserver);
6210 						xmlparser.restorePosition();
6211 						break;
6212 					}
6213 				}
6214 			}
6215 			while(xmlparser.accessElement(XmlParser::NextElement));
6216 		}
6217 
6218 		return ftable;
6219 	}
6220 	catch(Exception &e)
6221 	{
6222 		if(ftable) delete ftable;
6223 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
6224 	}
6225 }
6226 
updateViewsReferencingTable(PhysicalTable * table)6227 void DatabaseModel::updateViewsReferencingTable(PhysicalTable *table)
6228 {
6229 	BaseRelationship *rel = nullptr;
6230 	View *view = nullptr;
6231 	PhysicalTable *tab = nullptr;
6232 
6233 	if(!table) return;
6234 
6235 	for(auto obj : base_relationships)
6236 	{
6237 		rel = dynamic_cast<BaseRelationship *>(obj);
6238 
6239 		if(rel->getRelationshipType() != BaseRelationship::RelationshipDep)
6240 			continue;
6241 
6242 		view = dynamic_cast<View *>(rel->getTable(BaseRelationship::SrcTable));
6243 		tab = dynamic_cast<PhysicalTable *>(rel->getTable(BaseRelationship::DstTable));
6244 
6245 		if(view && tab == table)
6246 		{
6247 			view->generateColumns();
6248 			view->setCodeInvalidated(true);
6249 			view->setModified(true);
6250 			dynamic_cast<Schema *>(view->getSchema())->setModified(true);
6251 		}
6252 	}
6253 }
6254 
createSequence(bool ignore_onwer)6255 Sequence *DatabaseModel::createSequence(bool ignore_onwer)
6256 {
6257 	attribs_map attribs;
6258 	Sequence *sequence=nullptr;
6259 	BaseObject *table=nullptr;
6260 	Column *column=nullptr;
6261 	QString str_aux, tab_name, col_name;
6262 	QStringList elem_list;
6263 	int count;
6264 
6265 	try
6266 	{
6267 		sequence=new Sequence;
6268 		setBasicAttributes(sequence);
6269 		xmlparser.getElementAttributes(attribs);
6270 
6271 		sequence->setValues(attribs[Attributes::MinValue],
6272 				attribs[Attributes::MaxValue],
6273 				attribs[Attributes::Increment],
6274 				attribs[Attributes::Start],
6275 				attribs[Attributes::Cache]);
6276 
6277 		sequence->setCycle(attribs[Attributes::Cycle]==Attributes::True);
6278 
6279 		//Getting the sequence's owner column
6280 		if(!attribs[Attributes::OwnerColumn].isEmpty())
6281 		{
6282 			elem_list=attribs[Attributes::OwnerColumn].split('.');
6283 			count=elem_list.count();
6284 
6285 			if(count==3)
6286 			{
6287 				tab_name=elem_list[0] + QString(".") + elem_list[1];
6288 				col_name=elem_list[2];
6289 			}
6290 			else if(count==2)
6291 			{
6292 				tab_name=elem_list[0];
6293 				col_name=elem_list[1];
6294 			}
6295 
6296 			table=getObject(tab_name, {ObjectType::Table, ObjectType::ForeignTable});
6297 
6298 			//Raises an error if the column parent table doesn't exists
6299 			if(!table)
6300 			{
6301 				str_aux=Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
6302 						.arg(sequence->getName())
6303 						.arg(BaseObject::getTypeName(ObjectType::Sequence))
6304 						.arg(tab_name)
6305 						.arg(BaseObject::getTypeName(ObjectType::Table));
6306 
6307 				throw Exception(str_aux,ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
6308 			}
6309 
6310 			column=dynamic_cast<PhysicalTable *>(table)->getColumn(col_name);
6311 
6312 			if(!column)
6313 				column=dynamic_cast<PhysicalTable *>(table)->getColumn(col_name, true);
6314 
6315 			//Raises an error if the column doesn't exists
6316 			if(!column && !ignore_onwer)
6317 				throw Exception(Exception::getErrorMessage(ErrorCode::AsgInexistentSeqOwnerColumn)
6318 								.arg(sequence->getName(true)),
6319 								ErrorCode::AsgInexistentSeqOwnerColumn,__PRETTY_FUNCTION__,__FILE__,__LINE__);
6320 
6321 			sequence->setOwnerColumn(column);
6322 		}
6323 	}
6324 	catch(Exception &e)
6325 	{
6326 		if(sequence) delete sequence;
6327 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, getErrorExtraInfo());
6328 	}
6329 
6330 	return sequence;
6331 }
6332 
createView()6333 View *DatabaseModel::createView()
6334 {
6335 	attribs_map attribs, aux_attribs;
6336 	View *view=nullptr;
6337 	Column *column=nullptr;
6338 	PhysicalTable *table=nullptr;
6339 	QString elem, str_aux;
6340 	QStringList list_aux;
6341 	vector<Reference> refs;
6342 	BaseObject *tag=nullptr;
6343 	unsigned type;
6344 	int ref_idx, i, count;
6345 	bool refs_in_expr=false;
6346 	Reference reference;
6347 
6348 	try
6349 	{
6350 		view=new View;
6351 		setBasicAttributes(view);
6352 
6353 		xmlparser.getElementAttributes(attribs);
6354 		view->setObjectListsCapacity(attribs[Attributes::MaxObjCount].toUInt());
6355 		view->setMaterialized(attribs[Attributes::Materialized]==Attributes::True);
6356 		view->setRecursive(attribs[Attributes::Recursive]==Attributes::True);
6357 		view->setWithNoData(attribs[Attributes::WithNoData]==Attributes::True);
6358 		view->setCollapseMode(attribs[Attributes::CollapseMode].isEmpty() ? CollapseMode::NotCollapsed : static_cast<CollapseMode>(attribs[Attributes::CollapseMode].toUInt()));
6359 		view->setPaginationEnabled(attribs[Attributes::Pagination]==Attributes::True);
6360 		view->setCurrentPage(BaseTable::AttribsSection, attribs[Attributes::AttribsPage].toUInt());
6361 		view->setCurrentPage(BaseTable::ExtAttribsSection, attribs[Attributes::ExtAttribsPage].toUInt());
6362 		view->setFadedOut(attribs[Attributes::FadedOut]==Attributes::True);
6363 		view->setLayer(attribs[Attributes::Layer].toUInt());
6364 
6365 		if(xmlparser.accessElement(XmlParser::ChildElement))
6366 		{
6367 			do
6368 			{
6369 				if(xmlparser.getElementType()==XML_ELEMENT_NODE)
6370 				{
6371 					elem=xmlparser.getElementName();
6372 
6373 					if(elem==Attributes::Reference)
6374 					{
6375 						xmlparser.getElementAttributes(attribs);
6376 
6377 						//If the table name is specified tries to create a reference to a table/column
6378 						if(!attribs[Attributes::Table].isEmpty())
6379 						{
6380 							column=nullptr;
6381 							table=dynamic_cast<PhysicalTable *>(getObject(attribs[Attributes::Table], {ObjectType::Table, ObjectType::ForeignTable}));
6382 
6383 							//Raises an error if the table doesn't exists
6384 							if(!table)
6385 							{
6386 								str_aux=Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
6387 										.arg(view->getName())
6388 										.arg(BaseObject::getTypeName(ObjectType::View))
6389 										.arg(attribs[Attributes::Table])
6390 										.arg(BaseObject::getTypeName(ObjectType::Table));
6391 
6392 								throw Exception(str_aux,ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
6393 							}
6394 
6395 							if(!attribs[Attributes::Column].isEmpty())
6396 							{
6397 								column=table->getColumn(attribs[Attributes::Column]);
6398 
6399 								if(!column)
6400 									column=table->getColumn(attribs[Attributes::Column], true);
6401 
6402 								//Raises an error if the view references an inexistant column
6403 								if(!column)
6404 								{
6405 									str_aux=Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
6406 											.arg(view->getName())
6407 											.arg(BaseObject::getTypeName(ObjectType::View))
6408 											.arg(attribs[Attributes::Table] + QString(".") +
6409 											attribs[Attributes::Column])
6410 											.arg(BaseObject::getTypeName(ObjectType::Column));
6411 
6412 									throw Exception(str_aux,ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
6413 								}
6414 							}
6415 
6416 							//Adds the configured reference to a temporarily list
6417 							reference = Reference(table, column,
6418 																		attribs[Attributes::Alias],
6419 																		attribs[Attributes::ColumnAlias]);
6420 							reference.setReferenceAlias(attribs[Attributes::RefAlias]);
6421 							refs.push_back(reference);
6422 						}
6423 						else
6424 						{
6425 							xmlparser.savePosition();
6426 							str_aux=attribs[Attributes::Alias];
6427 
6428 							// Retrieving the reference expression
6429 							xmlparser.accessElement(XmlParser::ChildElement);
6430 							xmlparser.savePosition();
6431 							xmlparser.accessElement(XmlParser::ChildElement);
6432 							reference = Reference(xmlparser.getElementContent(), str_aux);
6433 							reference.setReferenceAlias(attribs[Attributes::RefAlias]);
6434 							xmlparser.restorePosition();
6435 
6436 							// Creating the columns related to the expression
6437 							if(xmlparser.accessElement(XmlParser::NextElement))
6438 							{
6439 								do
6440 								{
6441 									elem = xmlparser.getElementName();
6442 									xmlparser.savePosition();
6443 
6444 									if(elem == Attributes::Column)
6445 									{
6446 										column = createColumn();
6447 										reference.addColumn(column);
6448 										delete column;
6449 									}
6450 									else if(elem == Attributes::RefTableTag)
6451 									{
6452 										xmlparser.getElementAttributes(aux_attribs);
6453 										table = getTable(aux_attribs[Attributes::Name]);
6454 
6455 										if(!table)
6456 											table = getForeignTable(aux_attribs[Attributes::Name]);
6457 
6458 										reference.addReferencedTable(table);
6459 									}
6460 
6461 									xmlparser.restorePosition();
6462 								}
6463 								while(xmlparser.accessElement(XmlParser::NextElement));
6464 							}
6465 
6466 							refs.push_back(reference);
6467 							xmlparser.restorePosition();
6468 						}
6469 					}
6470 					else if(elem==Attributes::Expression)
6471 					{
6472 						xmlparser.savePosition();
6473 						xmlparser.getElementAttributes(attribs);
6474 						xmlparser.accessElement(XmlParser::ChildElement);
6475 
6476 						if(attribs[Attributes::Type]==Attributes::CteExpression)
6477 							view->setCommomTableExpression(xmlparser.getElementContent());
6478 						else
6479 						{
6480 							if(attribs[Attributes::Type]==Attributes::SelectExp)
6481 								type=Reference::SqlReferSelect;
6482 							else if(attribs[Attributes::Type]==Attributes::FromExp)
6483 								type=Reference::SqlReferFrom;
6484 							else if(attribs[Attributes::Type]==Attributes::SimpleExp)
6485 								type=Reference::SqlReferWhere;
6486 							else
6487 								type=Reference::SqlReferEndExpr;
6488 
6489 							list_aux=xmlparser.getElementContent().split(',');
6490 							count=list_aux.size();
6491 
6492 							//Indicates that some of the references were used in the expressions
6493 							if(count > 0 && !refs_in_expr)
6494 								refs_in_expr=true;
6495 
6496 							for(i=0; i < count; i++)
6497 							{
6498 								ref_idx=list_aux[i].toInt();
6499 								view->addReference(refs[ref_idx],type);
6500 							}
6501 						}
6502 
6503 						xmlparser.restorePosition();
6504 					}
6505 					else if(elem==BaseObject::getSchemaName(ObjectType::Tag))
6506 					{
6507 						xmlparser.getElementAttributes(aux_attribs);
6508 						tag=getObject(aux_attribs[Attributes::Name] ,ObjectType::Tag);
6509 
6510 						if(!tag)
6511 						{
6512 							throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
6513 											.arg(attribs[Attributes::Name])
6514 									.arg(BaseObject::getTypeName(ObjectType::Table))
6515 									.arg(aux_attribs[Attributes::Table])
6516 									.arg(BaseObject::getTypeName(ObjectType::Tag))
6517 									, ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
6518 						}
6519 
6520 						view->setTag(dynamic_cast<Tag *>(tag));
6521 					}
6522 				}
6523 			}
6524 			while(xmlparser.accessElement(XmlParser::NextElement));
6525 		}
6526 
6527 		/** Special case for refereces used as view definition **
6528 
6529 			If the flag 'refs_in_expr' isn't set indicates that the user defined a reference
6530 	  but has no used to define the view declaration, this way pgModeler will consider these
6531 	  references as View definition expressions and will force the insertion of them as
6532 			Reference::SQL_VIEW_DEFINITION.
6533 
6534 		This process can raise errors because if the user defined more than one reference the view
6535 		cannot accept the two as it's SQL definition, also the defined references MUST be expressions in
6536 		order to be used as view definition */
6537 		if(!refs.empty() && !refs_in_expr)
6538 		{
6539 			vector<Reference>::iterator itr;
6540 
6541 			itr=refs.begin();
6542 			while(itr!=refs.end())
6543 			{
6544 				view->addReference(*itr, Reference::SqlViewDefinition);
6545 				itr++;
6546 			}
6547 		}
6548 	}
6549 	catch(Exception &e)
6550 	{
6551 		if(view) delete view;
6552 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, getErrorExtraInfo());
6553 	}
6554 
6555 	return view;
6556 }
6557 
createCollation()6558 Collation *DatabaseModel::createCollation()
6559 {
6560 	Collation *collation=nullptr;
6561 	BaseObject *copy_coll=nullptr;
6562 	EncodingType encoding;
6563 	attribs_map attribs;
6564 
6565 	try
6566 	{
6567 		collation=new Collation;
6568 		setBasicAttributes(collation);
6569 
6570 		xmlparser.getElementAttributes(attribs);
6571 
6572 		encoding=EncodingType(attribs[Attributes::Encoding]);
6573 		collation->setEncoding(encoding);
6574 
6575 		//Creating a collation from a base locale
6576 		if(!attribs[Attributes::Locale].isEmpty())
6577 			collation->setLocale(attribs[Attributes::Locale]);
6578 		//Creating a collation from another collation
6579 		else if(!attribs[Attributes::Collation].isEmpty())
6580 		{
6581 			copy_coll=this->getObject(attribs[Attributes::Collation], ObjectType::Collation);
6582 
6583 			//Raises an error if the copy collation doesn't exists
6584 			if(!copy_coll)
6585 			{
6586 				throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
6587 								.arg(collation->getName())
6588 								.arg(BaseObject::getTypeName(ObjectType::Collation))
6589 								.arg(attribs[Attributes::Collation])
6590 						.arg(BaseObject::getTypeName(ObjectType::Collation)),
6591 						ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
6592 			}
6593 
6594 			collation->setCollation(dynamic_cast<Collation *>(copy_coll));
6595 		}
6596 		//Creating a collation using LC_COLLATE and LC_CTYPE params
6597 		else
6598 		{
6599 			collation->setLocalization(Collation::LcCollate, attribs[Attributes::LcCollate]);
6600 			collation->setLocalization(Collation::LcCtype, attribs[Attributes::LcCtype]);
6601 		}
6602 	}
6603 	catch(Exception &e)
6604 	{
6605 		if(collation) delete collation;
6606 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, getErrorExtraInfo());
6607 	}
6608 
6609 	return collation;
6610 }
6611 
createExtension()6612 Extension *DatabaseModel::createExtension()
6613 {
6614 	Extension *extension=nullptr;
6615 	attribs_map attribs;
6616 
6617 	try
6618 	{
6619 		extension=new Extension;
6620 		xmlparser.getElementAttributes(attribs);
6621 		setBasicAttributes(extension);
6622 
6623 		extension->setHandlesType(attribs[Attributes::HandlesType]==Attributes::True);
6624 		extension->setVersion(Extension::CurVersion, attribs[Attributes::CurVersion]);
6625 		extension->setVersion(Extension::OldVersion, attribs[Attributes::OldVersion]);
6626 	}
6627 	catch(Exception &e)
6628 	{
6629 		if(extension) delete extension;
6630 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, getErrorExtraInfo());
6631 	}
6632 
6633 	return extension;
6634 }
6635 
createTag()6636 Tag *DatabaseModel::createTag()
6637 {
6638 	Tag *tag=nullptr;
6639 	attribs_map attribs;
6640 	QString elem;
6641 
6642 	try
6643 	{
6644 		tag=new Tag;
6645 		setBasicAttributes(tag);
6646 
6647 		if(xmlparser.accessElement(XmlParser::ChildElement))
6648 		{
6649 			do
6650 			{
6651 				if(xmlparser.getElementType()==XML_ELEMENT_NODE)
6652 				{
6653 					elem=xmlparser.getElementName();
6654 
6655 					if(elem==Attributes::Style)
6656 					{
6657 						xmlparser.getElementAttributes(attribs);
6658 						tag->setElementColors(attribs[Attributes::Id],attribs[Attributes::Colors]);
6659 					}
6660 				}
6661 			}
6662 			while(xmlparser.accessElement(XmlParser::NextElement));
6663 		}
6664 
6665 		return tag;
6666 	}
6667 	catch(Exception &e)
6668 	{
6669 		if(tag) delete tag;
6670 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, getErrorExtraInfo());
6671 	}
6672 }
6673 
createTextbox()6674 Textbox *DatabaseModel::createTextbox()
6675 {
6676 	Textbox *txtbox=nullptr;
6677 	attribs_map attribs;
6678 
6679 	try
6680 	{
6681 		txtbox=new Textbox;
6682 		setBasicAttributes(txtbox);
6683 
6684 		xmlparser.getElementAttributes(attribs);
6685 
6686 		txtbox->setFadedOut(attribs[Attributes::FadedOut]==Attributes::True);
6687 		txtbox->setLayer(attribs[Attributes::Layer].toUInt());
6688 		txtbox->setTextAttribute(Textbox::ItalicText, attribs[Attributes::Italic]==Attributes::True);
6689 		txtbox->setTextAttribute(Textbox::BoldText, attribs[Attributes::Bold]==Attributes::True);
6690 		txtbox->setTextAttribute(Textbox::UnderlineText, attribs[Attributes::Underline]==Attributes::True);
6691 
6692 		if(!attribs[Attributes::Color].isEmpty())
6693 			txtbox->setTextColor(QColor(attribs[Attributes::Color]));
6694 
6695 		if(!attribs[Attributes::FontSize].isEmpty())
6696 			txtbox->setFontSize(attribs[Attributes::FontSize].toDouble());
6697 	}
6698 	catch(Exception &e)
6699 	{
6700 		if(txtbox) delete txtbox;
6701 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, getErrorExtraInfo());
6702 	}
6703 
6704 	return txtbox;
6705 }
6706 
createRelationship()6707 BaseRelationship *DatabaseModel::createRelationship()
6708 {
6709 	vector<unsigned> cols_special_pk;
6710 	attribs_map attribs, constr_attribs;
6711 	map<QString, unsigned> labels_id;
6712 	BaseRelationship *base_rel=nullptr;
6713 	Relationship *rel=nullptr;
6714 	BaseTable *tables[2]={nullptr, nullptr};
6715 	bool src_mand, dst_mand, identifier, protect, deferrable, sql_disabled, single_pk_col, faded_out;
6716 	DeferralType defer_type;
6717 	ActionType del_action, upd_action;
6718 	unsigned rel_type=0, i = 0, layer = 0;
6719 	ObjectType table_types[2]={ ObjectType::View, ObjectType::Table }, obj_rel_type;
6720 	QString str_aux, elem, tab_attribs[2]={ Attributes::SrcTable, Attributes::DstTable };
6721 	QColor custom_color=Qt::transparent;
6722 	Table *table = nullptr;
6723 
6724 	try
6725 	{
6726 		labels_id[Attributes::NameLabel]=BaseRelationship::RelNameLabel;
6727 		labels_id[Attributes::SrcLabel]=BaseRelationship::SrcCardLabel;
6728 		labels_id[Attributes::DstLabel]=BaseRelationship::DstCardLabel;
6729 
6730 		xmlparser.getElementAttributes(attribs);
6731 
6732 		src_mand=attribs[Attributes::SrcRequired]==Attributes::True;
6733 		dst_mand=attribs[Attributes::DstRequired]==Attributes::True;
6734 		protect=(attribs[Attributes::Protected]==Attributes::True);
6735 		faded_out=(attribs[Attributes::FadedOut]==Attributes::True);
6736 		layer = attribs[Attributes::Layer].toUInt();
6737 
6738 		if(!attribs[Attributes::CustomColor].isEmpty())
6739 			custom_color=QColor(attribs[Attributes::CustomColor]);
6740 
6741 		if(attribs[Attributes::Type]!=Attributes::RelationshipTabView &&
6742 				attribs[Attributes::Type]!=Attributes::RelationshipFk)
6743 		{
6744 			table_types[0]=ObjectType::Table;
6745 			obj_rel_type=ObjectType::Relationship;
6746 		}
6747 		else
6748 		{
6749 			if(attribs[Attributes::Type]==Attributes::RelationshipFk)
6750 				table_types[0]=ObjectType::Table;
6751 
6752 			obj_rel_type=ObjectType::BaseRelationship;
6753 		}
6754 
6755 		//Gets the participant tables
6756 		for(i=0; i < 2; i++)
6757 		{
6758 			tables[i]=dynamic_cast<BaseTable *>(getObject(attribs[tab_attribs[i]], table_types[i]));
6759 
6760 			/* If the relationship is between a view and a table and the table is not found
6761 			 * we try to find a foreign table instead */
6762 			if(table_types[i] == ObjectType::Table && !tables[i])
6763 				tables[i]=dynamic_cast<BaseTable *>(getObject(attribs[tab_attribs[i]], ObjectType::ForeignTable));
6764 
6765 			//Raises an error if some table doesn't exists
6766 			if(!tables[i])
6767 			{
6768 				str_aux=Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
6769 						.arg(attribs[Attributes::Name])
6770 						.arg(BaseObject::getTypeName(obj_rel_type))
6771 						.arg(attribs[tab_attribs[i]])
6772 						.arg(BaseObject::getTypeName(table_types[i]));
6773 
6774 				throw Exception(str_aux,ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
6775 			}
6776 		}
6777 
6778 		if(obj_rel_type==ObjectType::BaseRelationship)
6779 		{
6780 			base_rel=getRelationship(tables[0], tables[1]);
6781 
6782 			/* Creates the fk relationship if it not exists. This generally happens when a foreign key is
6783 			added to the table after its creation. */
6784 			if(attribs[Attributes::Type]==Attributes::RelationshipFk)
6785 			{
6786 				base_rel=new BaseRelationship(BaseRelationship::RelationshipFk, tables[0], tables[1], src_mand, dst_mand);
6787 				base_rel->setName(attribs[Attributes::Name]);
6788 				base_rel->setAlias(attribs[Attributes::Alias]);
6789 				addRelationship(base_rel);
6790 
6791 				/* If the source table doesn't have any fk that references the destination table indicates that the relationship
6792 				is being created before the fk that represents it or the fk is invalid (inconsistence!). In this case an error is raised. */
6793 				if(base_rel->getRelationshipType() == BaseRelationship::RelationshipFk &&
6794 				   !base_rel->getReferenceForeignKey())
6795 				{
6796 					Table *src_tab = dynamic_cast<Table *>(base_rel->getTable(BaseRelationship::SrcTable)),
6797 							*dst_tab = dynamic_cast<Table *>(base_rel->getTable(BaseRelationship::DstTable));
6798 					vector<Constraint *> fks;
6799 
6800 					src_tab->getForeignKeys(fks, false, dst_tab);
6801 
6802 					for(auto fk : fks)
6803 					{
6804 						if(!getRelationship(src_tab, dst_tab, fk))
6805 						{
6806 							base_rel->setReferenceForeignKey(fk);
6807 							break;
6808 						}
6809 					}
6810 
6811 					//Throws an error if the relationship was created without a valid foreign key attached to it
6812 					if(!base_rel->getReferenceForeignKey())
6813 					{
6814 						throw Exception(Exception::getErrorMessage(ErrorCode::InvAllocationFKRelationship)
6815 										.arg(attribs[Attributes::Name])
6816 									  .arg(src_tab->getName(true)),
6817 										ErrorCode::InvAllocationFKRelationship,__PRETTY_FUNCTION__,__FILE__,__LINE__);
6818 					}
6819 				}
6820 			}
6821 			else if(base_rel)
6822 				base_rel->setName(attribs[Attributes::Name]);
6823 
6824 			if(!base_rel)
6825 				throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
6826 								.arg(this->getName())
6827 								.arg(this->getTypeName())
6828 								.arg(attribs[Attributes::Name])
6829 					.arg(BaseObject::getTypeName(ObjectType::BaseRelationship)),
6830 					ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
6831 
6832 			base_rel->blockSignals(loading_model);
6833 			base_rel->disconnectRelationship();
6834 			base_rel->blockSignals(false);
6835 		}
6836 		else
6837 		{
6838 			QString pat_attrib[]= { Attributes::SrcColPattern, Attributes::DstColPattern,
6839 									Attributes::SrcFkPattern, Attributes::DstFkPattern,
6840 									Attributes::PkPattern, Attributes::UqPattern,
6841 									Attributes::PkColPattern };
6842 
6843 			unsigned 	pattern_id[]= { Relationship::SrcColPattern, Relationship::DstColPattern,
6844 										Relationship::SrcFkPattern, Relationship::DstFkPattern,
6845 										Relationship::PkPattern, Relationship::UqPattern,
6846 										Relationship::PkColPattern },
6847 					pat_count=sizeof(pattern_id)/sizeof(unsigned);
6848 
6849 			sql_disabled=attribs[Attributes::SqlDisabled]==Attributes::True;
6850 			identifier=attribs[Attributes::Identifier]==Attributes::True;
6851 			deferrable=attribs[Attributes::Deferrable]==Attributes::True;
6852 			defer_type=DeferralType(attribs[Attributes::DeferType]);
6853 			del_action=ActionType(attribs[Attributes::DelAction]);
6854 			upd_action=ActionType(attribs[Attributes::UpdAction]);
6855 			single_pk_col=(attribs[Attributes::SinglePkColumn]==Attributes::True);
6856 
6857 			if(attribs[Attributes::Type]==Attributes::Relationship11)
6858 				rel_type=BaseRelationship::Relationship11;
6859 			else if(attribs[Attributes::Type]==Attributes::Relationship1n)
6860 				rel_type=BaseRelationship::Relationship1n;
6861 			else if(attribs[Attributes::Type]==Attributes::RelationshipNn)
6862 				rel_type=BaseRelationship::RelationshipNn;
6863 			else if(attribs[Attributes::Type]==Attributes::RelationshipGen)
6864 				rel_type=BaseRelationship::RelationshipGen;
6865 			else if(attribs[Attributes::Type]==Attributes::RelationshipDep)
6866 				rel_type=BaseRelationship::RelationshipDep;
6867 			else if(attribs[Attributes::Type]==Attributes::RelationshipPart)
6868 				rel_type=BaseRelationship::RelationshipPart;
6869 
6870 			rel=new Relationship(rel_type,
6871 					dynamic_cast<PhysicalTable *>(tables[0]),
6872 					dynamic_cast<PhysicalTable *>(tables[1]),
6873 					src_mand, dst_mand,
6874 					identifier, deferrable, defer_type, del_action, upd_action,
6875 					CopyOptions(attribs[Attributes::CopyMode].toUInt(),
6876 					attribs[Attributes::CopyOptions].toUInt()));
6877 
6878 			rel->setSQLDisabled(sql_disabled);
6879 			rel->setSiglePKColumn(single_pk_col);
6880 
6881 			if(!attribs[Attributes::TableName].isEmpty())
6882 				rel->setTableNameRelNN(attribs[Attributes::TableName]);
6883 
6884 			rel->setName(attribs[Attributes::Name]);
6885 			rel->setAlias(attribs[Attributes::Alias]);
6886 			base_rel=rel;
6887 
6888 			//Configuring the name patterns
6889 			for(i=0; i < pat_count; i++)
6890 				rel->setNamePattern(pattern_id[i], attribs[pat_attrib[i]]);
6891 		}
6892 
6893 		if(xmlparser.accessElement(XmlParser::ChildElement))
6894 		{
6895 			do
6896 			{
6897 				if(xmlparser.getElementType()==XML_ELEMENT_NODE)
6898 				{
6899 					elem=xmlparser.getElementName();
6900 
6901 					if(elem == Attributes::Expression && rel)
6902 					{
6903 						xmlparser.savePosition();
6904 						xmlparser.accessElement(XmlParser::ChildElement);
6905 						rel->setPartitionBoundingExpr(xmlparser.getElementContent());
6906 						xmlparser.restorePosition();
6907 					}
6908 					else if(elem==Attributes::Column && rel)
6909 					{
6910 						xmlparser.savePosition();
6911 						rel->addObject(createColumn());
6912 						xmlparser.restorePosition();
6913 					}
6914 					else if(elem==Attributes::Constraint && rel)
6915 					{
6916 						xmlparser.savePosition();
6917 						xmlparser.getElementAttributes(constr_attribs);
6918 
6919 						/* If we find a primary key constraint at this point means that we're handling the original primary key stored by the relationship.
6920 						 * Since relationships can't have primary keys created manually by the users we assume that
6921 						 * the relationship contains a special primary key (created during relationship connection)
6922 						 * and the current constraint is the original one owned by one of the tables prior the connection
6923 						 * of the relationship. */
6924 						if(constr_attribs[Attributes::Type] == Attributes::PkConstr)
6925 						{
6926 							table = getTable(constr_attribs[Attributes::Table]);
6927 							rel->setOriginalPrimaryKey(createConstraint(table));
6928 						}
6929 						else
6930 							rel->addObject(createConstraint(rel));
6931 
6932 						xmlparser.restorePosition();
6933 					}
6934 					else if(elem==Attributes::Line)
6935 					{
6936 						vector<QPointF> points;
6937 						xmlparser.savePosition();
6938 						xmlparser.accessElement(XmlParser::ChildElement);
6939 
6940 						do
6941 						{
6942 							xmlparser.getElementAttributes(attribs);
6943 							points.push_back(QPointF(attribs[Attributes::XPos].toDouble(),
6944 											 attribs[Attributes::YPos].toDouble()));
6945 						}
6946 						while(xmlparser.accessElement(XmlParser::NextElement));
6947 
6948 						base_rel->setPoints(points);
6949 						xmlparser.restorePosition();
6950 					}
6951 					else if(elem==Attributes::Label)
6952 					{
6953 						xmlparser.getElementAttributes(attribs);
6954 						str_aux=attribs[Attributes::RefType];
6955 
6956 						xmlparser.savePosition();
6957 						xmlparser.accessElement(XmlParser::ChildElement);
6958 						xmlparser.getElementAttributes(attribs);
6959 						xmlparser.restorePosition();
6960 
6961 						base_rel->setLabelDistance(labels_id[str_aux],
6962 													 QPointF(attribs[Attributes::XPos].toDouble(),
6963 													 attribs[Attributes::YPos].toDouble()));
6964 					}
6965 					else if(elem==Attributes::SpecialPkCols && rel)
6966 					{
6967 						QList<QString> col_list;
6968 
6969 						xmlparser.getElementAttributes(attribs);
6970 						col_list=attribs[Attributes::Indexes].split(',');
6971 
6972 						while(!col_list.isEmpty())
6973 						{
6974 							cols_special_pk.push_back(col_list.front().toUInt());
6975 							col_list.pop_front();
6976 						}
6977 
6978 						rel->setSpecialPrimaryKeyCols(cols_special_pk);
6979 					}
6980 				}
6981 			}
6982 			while(xmlparser.accessElement(XmlParser::NextElement));
6983 		}
6984 	}
6985 	catch(Exception &e)
6986 	{
6987 		if(base_rel && base_rel->getObjectType()==ObjectType::Relationship)
6988 			delete base_rel;
6989 
6990 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, getErrorExtraInfo());
6991 	}
6992 
6993 	if(rel)
6994 	{
6995 		storeSpecialObjectsXML();
6996 		addRelationship(rel);
6997 	}
6998 
6999 	base_rel->setFadedOut(faded_out);
7000 	base_rel->setProtected(protect);
7001 	base_rel->setCustomColor(custom_color);
7002 	base_rel->setLayer(layer);
7003 
7004 	/* If the FK relationship does not reference a foreign key (models generated in older versions)
7005 	 * we need to assign them to the respective relationships */
7006 	if(base_rel && base_rel->getObjectType()==ObjectType::BaseRelationship)
7007 	{
7008 		base_rel->blockSignals(loading_model);
7009 		base_rel->connectRelationship();
7010 		base_rel->blockSignals(false);
7011 	}
7012 
7013 	return base_rel;
7014 }
7015 
createPermission()7016 Permission *DatabaseModel::createPermission()
7017 {
7018 	Permission *perm=nullptr;
7019 	BaseObject *object=nullptr;
7020 	PhysicalTable *parent_table=nullptr;
7021 	Role *role=nullptr;
7022 	attribs_map priv_attribs, attribs;
7023 	attribs_map::iterator itr, itr_end;
7024 	ObjectType obj_type;
7025 	QString parent_name, obj_name;
7026 	QStringList list;
7027 	unsigned priv_type=Permission::PrivSelect;
7028 	bool priv_value, grant_op, revoke, cascade;
7029 
7030 	try
7031 	{
7032 		xmlparser.getElementAttributes(priv_attribs);
7033 		revoke=priv_attribs[Attributes::Revoke]==Attributes::True;
7034 		cascade=priv_attribs[Attributes::Cascade]==Attributes::True;
7035 
7036 		xmlparser.savePosition();
7037 		xmlparser.accessElement(XmlParser::ChildElement);
7038 		xmlparser.getElementAttributes(attribs);
7039 
7040 		obj_type=BaseObject::getObjectType(attribs[Attributes::Type]);
7041 		obj_name=attribs[Attributes::Name];
7042 		parent_name=attribs[Attributes::Parent];
7043 
7044 		//If the object is a column its needed to get the parent table
7045 		if(obj_type==ObjectType::Column)
7046 		{
7047 			parent_table=dynamic_cast<PhysicalTable *>(getObject(parent_name, {ObjectType::Table, ObjectType::ForeignTable}));
7048 
7049 			if(parent_table)
7050 				object=parent_table->getColumn(obj_name);
7051 		}
7052 		else if(obj_type==ObjectType::Database)
7053 		{
7054 			object=this;
7055 		}
7056 		else
7057 			object=getObject(obj_name, obj_type);
7058 
7059 		//Raises an error if the permission references an object that does not exists
7060 		if(!object)
7061 			throw Exception(Exception::getErrorMessage(ErrorCode::PermissionRefInexistObject)
7062 							.arg(obj_name)
7063 							.arg(BaseObject::getTypeName(obj_type)),
7064 							ErrorCode::PermissionRefInexistObject,__PRETTY_FUNCTION__,__FILE__,__LINE__);
7065 
7066 		perm=new Permission(object);
7067 		perm->setRevoke(revoke);
7068 		perm->setCascade(cascade);
7069 
7070 		do
7071 		{
7072 			if(xmlparser.getElementName()==Attributes::Roles)
7073 			{
7074 				xmlparser.getElementAttributes(attribs);
7075 				list = attribs[Attributes::Names].split(',');
7076 
7077 				for(auto &name : list)
7078 				{
7079 					role=dynamic_cast<Role *>(getObject(name.trimmed(), ObjectType::Role));
7080 
7081 					//Raises an error if the referenced role doesn't exists
7082 					if(!role)
7083 					{
7084 						throw Exception(Exception::getErrorMessage(ErrorCode::PermissionRefInexistObject)
7085 										.arg(name)
7086 										.arg(BaseObject::getTypeName(ObjectType::Role)),
7087 										ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
7088 
7089 					}
7090 
7091 					perm->addRole(role);
7092 				}
7093 			}
7094 			else if(xmlparser.getElementName()==Attributes::Privileges)
7095 			{
7096 				xmlparser.getElementAttributes(priv_attribs);
7097 
7098 				itr=priv_attribs.begin();
7099 				itr_end=priv_attribs.end();
7100 
7101 				while(itr!=itr_end)
7102 				{
7103 					if(itr->first!=Attributes::GrantOp)
7104 					{
7105 						priv_value=(itr->second==Attributes::True);
7106 						grant_op=(itr->second==Attributes::GrantOp);
7107 
7108 						if(itr->first==Attributes::ConnectPriv)
7109 							priv_type=Permission::PrivConnect;
7110 						else if(itr->first==Attributes::CreatePriv)
7111 							priv_type=Permission::PrivCreate;
7112 						else if(itr->first==Attributes::DeletePriv)
7113 							priv_type=Permission::PrivDelete;
7114 						else if(itr->first==Attributes::ExecutPriv)
7115 							priv_type=Permission::PrivExecute;
7116 						else if(itr->first==Attributes::InsertPriv)
7117 							priv_type=Permission::PrivInsert;
7118 						else if(itr->first==Attributes::ReferencesPriv)
7119 							priv_type=Permission::PrivReferences;
7120 						else if(itr->first==Attributes::SelectPriv)
7121 							priv_type=Permission::PrivSelect;
7122 						else if(itr->first==Attributes::TemporaryPriv)
7123 							priv_type=Permission::PrivTemporary;
7124 						else if(itr->first==Attributes::TriggerPriv)
7125 							priv_type=Permission::PrivTrigger;
7126 						else if(itr->first==Attributes::TruncatePriv)
7127 							priv_type=Permission::PrivTruncate;
7128 						else if(itr->first==Attributes::UpdatePriv)
7129 							priv_type=Permission::PrivUpdate;
7130 						else if(itr->first==Attributes::UsagePriv)
7131 							priv_type=Permission::PrivUsage;
7132 
7133 						perm->setPrivilege(priv_type, (priv_value || grant_op), grant_op);
7134 					}
7135 					itr++;
7136 				}
7137 			}
7138 		}
7139 		while(xmlparser.accessElement(XmlParser::NextElement));
7140 
7141 		xmlparser.restorePosition();
7142 	}
7143 	catch(Exception &e)
7144 	{
7145 		if(perm) delete perm;
7146 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, getErrorExtraInfo());
7147 	}
7148 
7149 	return perm;
7150 }
7151 
validateColumnRemoval(Column * column)7152 void DatabaseModel::validateColumnRemoval(Column *column)
7153 {
7154 	if(column && column->getParentTable())
7155 	{
7156 		vector<BaseObject *> refs;
7157 		getObjectReferences(column, refs);
7158 
7159 		//Raises an error if there are objects referencing the column
7160 		if(!refs.empty())
7161 			throw Exception(Exception::getErrorMessage(ErrorCode::RemDirectReference)
7162 							.arg(column->getParentTable()->getName(true) + QString(".") + column->getName(true))
7163 							.arg(column->getTypeName())
7164 							.arg(refs[0]->getName(true))
7165 				.arg(refs[0]->getTypeName()),
7166 				ErrorCode::RemDirectReference,__PRETTY_FUNCTION__,__FILE__,__LINE__);
7167 	}
7168 }
7169 
validateRelationships(TableObject * object,Table * parent_tab)7170 void DatabaseModel::validateRelationships(TableObject *object, Table *parent_tab)
7171 {
7172 	try
7173 	{
7174 		bool revalidate_rels=false, ref_tab_inheritance=false;
7175 		Relationship *rel=nullptr;
7176 		vector<BaseObject *>::iterator itr, itr_end;
7177 		ObjectType obj_type;
7178 
7179 		if(object && parent_tab)
7180 		{
7181 			obj_type=object->getObjectType();
7182 
7183 			/* Relationship validation condition:
7184 			> Case the object is a column and its reference by the parent table primary key
7185 			> Case the parent table is a partition and a column is being removed
7186 			> Case the object is a constraint and its a table primary key */
7187 			revalidate_rels=((obj_type==ObjectType::Column &&
7188 												(parent_tab->isConstraintRefColumn(dynamic_cast<Column *>(object), ConstraintType::PrimaryKey) ||
7189 												 parent_tab->isPartition() || parent_tab->isPartitioned())) ||
7190 											 (obj_type==ObjectType::Constraint &&
7191 												dynamic_cast<Constraint *>(object)->getConstraintType()==ConstraintType::PrimaryKey));
7192 
7193 			/* Additional validation for columns: checks if the parent table participates on a
7194 			generalization/copy as destination table */
7195 			if(obj_type==ObjectType::Column)
7196 			{
7197 				itr=relationships.begin();
7198 				itr_end=relationships.end();
7199 
7200 				while(itr!=itr_end && !ref_tab_inheritance)
7201 				{
7202 					rel=dynamic_cast<Relationship *>(*itr);
7203 					itr++;
7204 					ref_tab_inheritance=(rel->getRelationshipType()==Relationship::RelationshipGen &&
7205 															 rel->getReferenceTable()==parent_tab);
7206 				}
7207 			}
7208 
7209 			if(revalidate_rels || ref_tab_inheritance)
7210 			{
7211 				storeSpecialObjectsXML();
7212 				disconnectRelationships();
7213 				validateRelationships();
7214 			}
7215 		}
7216 	}
7217 	catch(Exception &e)
7218 	{
7219 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
7220 	}
7221 }
7222 
__getCodeDefinition(unsigned def_type)7223 QString DatabaseModel::__getCodeDefinition(unsigned def_type)
7224 {
7225 	QString def, bkp_appended_sql, bkp_prepended_sql;
7226 
7227 	//Forcing the name/signature cleanup due to the validation temp. names feature
7228 	attributes[Attributes::Name]="";
7229 	attributes[Attributes::Signature]="";
7230 
7231 	if(conn_limit >= 0)
7232 		attributes[Attributes::ConnLimit]=QString("%1").arg(conn_limit);
7233 
7234 	if(def_type==SchemaParser::SqlDefinition)
7235 	{
7236 		QString loc_attribs[]={ Attributes::LcCtype,  Attributes::LcCollate };
7237 
7238 		if(encoding!=BaseType::Null)
7239 			attributes[Attributes::Encoding]=QString("'%1'").arg(~encoding);
7240 
7241 		for(unsigned i=0; i < 2; i++)
7242 		{
7243 			if(!localizations[i].isEmpty())
7244 			{
7245 				attributes[loc_attribs[i]]=QString("'%1'").arg(localizations[i]);
7246 			}
7247 		}
7248 	}
7249 	else
7250 	{
7251 		attributes[Attributes::Encoding]=(~encoding);
7252 		attributes[Attributes::LcCollate]=localizations[1];
7253 		attributes[Attributes::LcCtype]=localizations[0];
7254 		attributes[Attributes::AppendAtEod]=(append_at_eod ? Attributes::True : "");
7255 		attributes[Attributes::PrependAtBod]=(prepend_at_bod ? Attributes::True : "");
7256 	}
7257 
7258 	attributes[Attributes::IsTemplate]=(is_template ? Attributes::True : Attributes::False);
7259 	attributes[Attributes::AllowConns]=(allow_conns ? Attributes::True : Attributes::False);
7260 	attributes[Attributes::TemplateDb]=template_db;
7261 
7262 	if(def_type==SchemaParser::SqlDefinition && append_at_eod)
7263 	{
7264 		bkp_appended_sql=this->appended_sql;
7265 		this->appended_sql.clear();
7266 	}
7267 
7268 	if(def_type==SchemaParser::SqlDefinition && prepend_at_bod)
7269 	{
7270 		bkp_prepended_sql=this->prepended_sql;
7271 		this->prepended_sql.clear();
7272 	}
7273 
7274 	try
7275 	{
7276 		def=this->BaseObject::__getCodeDefinition(def_type);
7277 
7278 		if(def_type==SchemaParser::SqlDefinition && append_at_eod)
7279 			this->appended_sql=bkp_appended_sql;
7280 
7281 		if(def_type==SchemaParser::SqlDefinition && prepend_at_bod)
7282 			this->prepended_sql=bkp_prepended_sql;
7283 
7284 		return def;
7285 	}
7286 	catch(Exception &e)
7287 	{
7288 		this->appended_sql=bkp_appended_sql;
7289 		this->prepended_sql=bkp_prepended_sql;
7290 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
7291 	}
7292 }
7293 
getCodeDefinition(unsigned def_type)7294 QString DatabaseModel::getCodeDefinition(unsigned def_type)
7295 {
7296 	return this->getCodeDefinition(def_type, true);
7297 }
7298 
getCodeDefinition(unsigned def_type,bool export_file)7299 QString DatabaseModel::getCodeDefinition(unsigned def_type, bool export_file)
7300 {
7301 	attribs_map attribs_aux;
7302 	unsigned general_obj_cnt, gen_defs_count;
7303 	bool sql_disabled=false;
7304 	BaseObject *object=nullptr;
7305 	QString def, search_path=QString("pg_catalog,public"),
7306 			msg=tr("Generating %1 code: `%2' (%3)"),
7307 			attrib=Attributes::Objects, attrib_aux,
7308 			def_type_str=(def_type==SchemaParser::SqlDefinition ? QString("SQL") : QString("XML"));
7309 	Type *usr_type=nullptr;
7310 	map<unsigned, BaseObject *> objects_map;
7311 	ObjectType obj_type;
7312 
7313 	try
7314 	{
7315 		objects_map=getCreationOrder(def_type);
7316 		general_obj_cnt=objects_map.size();
7317 		gen_defs_count=0;
7318 
7319 		attribs_aux[Attributes::ShellTypes]="";
7320 		attribs_aux[Attributes::Permission]="";
7321 		attribs_aux[Attributes::Schema]="";
7322 		attribs_aux[Attributes::Tablespace]="";
7323 		attribs_aux[Attributes::Role]="";
7324 
7325 		if(def_type==SchemaParser::SqlDefinition)
7326 		{
7327 			attribs_aux[Attributes::Function]=(!functions.empty() ? Attributes::True : "");
7328 
7329 			for(auto &type : types)
7330 			{
7331 				usr_type=dynamic_cast<Type *>(type);
7332 
7333 				if(usr_type->getConfiguration()==Type::BaseType)
7334 				{
7335 					usr_type->convertFunctionParameters();
7336 
7337 					//Generating the shell type declaration (only for base types)
7338 					attribs_aux[Attributes::ShellTypes] += usr_type->getCodeDefinition(def_type, true);
7339 
7340 					/* Forcing the code invalidation for the type so the complete definition can be
7341 					 * generated in the below iteration */
7342 					usr_type->setCodeInvalidated(true);
7343 				}
7344 			}
7345 		}
7346 		else
7347 		{
7348 			//Configuring the changelog attributes when generating XML code
7349 			attribs_aux[Attributes::UseChangelog] = persist_changelog ? Attributes::True : Attributes::False;
7350 			attribs_aux[Attributes::Changelog] = getChangelogDefinition();
7351 		}
7352 
7353 		for(auto &obj_itr : objects_map)
7354 		{
7355 			object=obj_itr.second;
7356 			obj_type=object->getObjectType();
7357 
7358 			if(obj_type==ObjectType::Type && def_type==SchemaParser::SqlDefinition)
7359 			{
7360 				usr_type=dynamic_cast<Type *>(object);
7361 				attribs_aux[attrib]+=usr_type->getCodeDefinition(def_type);
7362 			}
7363 			else if(obj_type==ObjectType::Database)
7364 			{
7365 				if(def_type==SchemaParser::SqlDefinition)
7366 				{
7367 					/* The Database has the SQL code definition disabled when generating the
7368 		  code of the entire model because this object cannot be created from a multiline sql command */
7369 
7370 					//Saving the sql disabled state
7371 					sql_disabled=this->isSQLDisabled();
7372 
7373 					//Disables the sql to generate a commented code
7374 					this->setSQLDisabled(true);
7375 					attribs_aux[this->getSchemaName()]+=this->__getCodeDefinition(def_type);
7376 
7377 					//Restore the original sql disabled state
7378 					this->setSQLDisabled(sql_disabled);
7379 				}
7380 				else
7381 					attribs_aux[attrib]+=this->__getCodeDefinition(def_type);
7382 			}
7383 			else if(obj_type==ObjectType::Permission)
7384 			{
7385 				attribs_aux[Attributes::Permission]+=dynamic_cast<Permission *>(object)->getCodeDefinition(def_type);
7386 			}
7387 			else if(obj_type==ObjectType::Constraint)
7388 			{
7389 				attribs_aux[attrib]+=dynamic_cast<Constraint *>(object)->getCodeDefinition(def_type, true);
7390 			}
7391 			else if(obj_type==ObjectType::Role || obj_type==ObjectType::Tablespace ||  obj_type==ObjectType::Schema)
7392 			{
7393 				//The "public" schema does not have the SQL code definition generated
7394 				if(def_type==SchemaParser::SqlDefinition)
7395 					attrib_aux=BaseObject::getSchemaName(obj_type);
7396 				else
7397 					attrib_aux=attrib;
7398 
7399 				/* The Tablespace has the SQL code definition disabled when generating the
7400 		  code of the entire model because this object cannot be created from a multiline sql command */
7401 				if(obj_type==ObjectType::Tablespace && !object->isSystemObject() && def_type==SchemaParser::SqlDefinition)
7402 				{
7403 					//Saving the sql disabled state
7404 					sql_disabled=object->isSQLDisabled();
7405 
7406 					//Disables the sql to generate a commented code
7407 					object->setSQLDisabled(true);
7408 					attribs_aux[attrib_aux]+=object->getCodeDefinition(def_type);
7409 
7410 					//Restore the original sql disabled state
7411 					object->setSQLDisabled(sql_disabled);
7412 				}
7413 				//System object doesn't has the XML generated (the only exception is for public schema)
7414 				else if((obj_type!=ObjectType::Schema && !object->isSystemObject()) ||
7415 						(obj_type==ObjectType::Schema &&
7416 						 ((object->getName()==QString("public") && def_type==SchemaParser::XmlDefinition) ||
7417 						  (object->getName()!=QString("public") && object->getName()!=QString("pg_catalog")))))
7418 				{
7419 					if(object->getObjectType()==ObjectType::Schema)
7420 						search_path+=QString(",") + object->getName(true);
7421 
7422 					//Generates the code definition and concatenates to the others
7423 					attribs_aux[attrib_aux]+=object->getCodeDefinition(def_type);
7424 				}
7425 			}
7426 			else
7427 			{
7428 				if(object->isSystemObject())
7429 					attribs_aux[attrib]+="";
7430 				else
7431 					attribs_aux[attrib]+=object->getCodeDefinition(def_type);
7432 			}
7433 
7434 			gen_defs_count++;
7435 
7436 			if((def_type==SchemaParser::SqlDefinition && !object->isSQLDisabled()) ||
7437 					(def_type==SchemaParser::XmlDefinition && !object->isSystemObject()))
7438 			{
7439 				emit s_objectLoaded((gen_defs_count/static_cast<double>(general_obj_cnt)) * 100,
7440 									msg.arg(def_type_str)
7441 									.arg(object->getName())
7442 									.arg(object->getTypeName()),
7443 									enum_cast(object->getObjectType()));
7444 			}
7445 		}
7446 
7447 		attribs_aux[Attributes::SearchPath]=search_path;
7448 		attribs_aux[Attributes::ModelAuthor]=author;
7449 		attribs_aux[Attributes::PgModelerVersion]=GlobalAttributes::PgModelerVersion;
7450 
7451 		if(def_type==SchemaParser::XmlDefinition)
7452 		{
7453 			QStringList act_layers;
7454 
7455 			for(auto &layer_id : active_layers)
7456 				act_layers.push_back(QString::number(layer_id));
7457 
7458 			attribs_aux[Attributes::Layers]=layers.join(';');
7459 			attribs_aux[Attributes::ActiveLayers]=act_layers.join(';');
7460 			attribs_aux[Attributes::MaxObjCount]=QString::number(static_cast<unsigned>(getMaxObjectCount() * 1.20));
7461 			attribs_aux[Attributes::Protected]=(this->is_protected ? Attributes::True : "");
7462 			attribs_aux[Attributes::LastPosition]=QString("%1,%2").arg(last_pos.x()).arg(last_pos.y());
7463 			attribs_aux[Attributes::LastZoom]=QString::number(last_zoom);
7464 			attribs_aux[Attributes::DefaultSchema]=(default_objs[ObjectType::Schema] ? default_objs[ObjectType::Schema]->getName(true) : "");
7465 			attribs_aux[Attributes::DefaultOwner]=(default_objs[ObjectType::Role] ? default_objs[ObjectType::Role]->getName(true) : "");
7466 			attribs_aux[Attributes::DefaultTablespace]=(default_objs[ObjectType::Tablespace] ? default_objs[ObjectType::Tablespace]->getName(true) : "");
7467 			attribs_aux[Attributes::DefaultCollation]=(default_objs[ObjectType::Collation] ? default_objs[ObjectType::Collation]->getName(true) : "");
7468 		}
7469 		else
7470 		{
7471 			for(auto &type : types)
7472 			{
7473 				usr_type=dynamic_cast<Type *>(type);
7474 				if(usr_type->getConfiguration()==Type::BaseType)
7475 				{
7476 					attribs_aux[attrib]+=usr_type->getCodeDefinition(def_type);
7477 					usr_type->convertFunctionParameters(true);
7478 				}
7479 			}
7480 		}
7481 	}
7482 	catch(Exception &e)
7483 	{
7484 		if(def_type==SchemaParser::SqlDefinition)
7485 		{
7486 			for(auto &type : types)
7487 			{
7488 				usr_type=dynamic_cast<Type *>(type);
7489 				if(usr_type->getConfiguration()==Type::BaseType)
7490 				{
7491 					attribs_aux[attrib]+=usr_type->getCodeDefinition(def_type);
7492 					usr_type->convertFunctionParameters(true);
7493 				}
7494 			}
7495 		}
7496 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
7497 	}
7498 
7499 	attribs_aux[Attributes::ExportToFile]=(export_file ? Attributes::True : "");
7500 	def=schparser.getCodeDefinition(Attributes::DbModel, attribs_aux, def_type);
7501 
7502 	if(prepend_at_bod && def_type==SchemaParser::SqlDefinition)
7503 		def=QString("-- Prepended SQL commands --\n") +	this->prepended_sql + Attributes::DdlEndToken + def;
7504 
7505 	if(append_at_eod && def_type==SchemaParser::SqlDefinition)
7506 		def+=QString("-- Appended SQL commands --\n") +	this->appended_sql + QChar('\n') + Attributes::DdlEndToken;
7507 
7508 	return def;
7509 }
7510 
getCreationOrder(unsigned def_type,bool incl_relnn_objs,bool incl_rel1n_constrs)7511 map<unsigned, BaseObject *> DatabaseModel::getCreationOrder(unsigned def_type, bool incl_relnn_objs, bool incl_rel1n_constrs)
7512 {
7513 	BaseObject *object=nullptr;
7514 	vector<BaseObject *> fkeys, fk_rels, aux_tables;
7515 	vector<BaseObject *> *obj_list=nullptr;
7516 	vector<BaseObject *>::iterator itr, itr_end;
7517 	map<unsigned, BaseObject *> objects_map;
7518 	PhysicalTable *table=nullptr;
7519 	Constraint *constr=nullptr;
7520 	View *view=nullptr;
7521 	Relationship *rel=nullptr;
7522 	ObjectType aux_obj_types[]={ ObjectType::Role, ObjectType::Tablespace, ObjectType::Schema, ObjectType::Tag };
7523 
7524 	vector<ObjectType> obj_types_vect = getObjectTypes(false, { ObjectType::Role, ObjectType::Tablespace, ObjectType::Schema,
7525 																															ObjectType::Tag, ObjectType::Database, ObjectType::Permission });
7526 
7527 	unsigned i=0, aux_obj_cnt=sizeof(aux_obj_types)/sizeof(ObjectType);
7528 
7529 	//The first objects on the map will be roles, tablespaces, schemas and tags
7530 	for(i=0; i < aux_obj_cnt; i++)
7531 	{
7532 		if(aux_obj_types[i]!=ObjectType::Tag || def_type==SchemaParser::XmlDefinition)
7533 		{
7534 			obj_list=getObjectList(aux_obj_types[i]);
7535 
7536 			for(auto &object : (*obj_list))
7537 				objects_map[object->getObjectId()]=object;
7538 		}
7539 	}
7540 
7541 	//Includes the database model on the objects map permitting to create the code in a correct order
7542 	objects_map[this->getObjectId()]=this;
7543 
7544 	for(auto &obj_type : obj_types_vect)
7545 	{
7546 		//For SQL definition, only the textbox and base relationship does not enters to the code generation list
7547 		if(def_type==SchemaParser::SqlDefinition &&
7548 			 (obj_type==ObjectType::Textbox || obj_type==ObjectType::BaseRelationship))
7549 			obj_list=nullptr;
7550 		else
7551 			obj_list=getObjectList(obj_type);
7552 
7553 		if(obj_list)
7554 		{
7555 			for(auto &object : (*obj_list))
7556 			{
7557 				/* If the object is a FK relationship it's stored in a separeted list in order to have the
7558 			 code generated at end of whole definition (after foreign keys definition) */
7559 				if(object->getObjectType()==ObjectType::BaseRelationship &&
7560 						dynamic_cast<BaseRelationship *>(object)->getRelationshipType()==BaseRelationship::RelationshipFk)
7561 				{
7562 					fk_rels.push_back(object);
7563 				}
7564 				else
7565 				{
7566 					if(def_type==SchemaParser::XmlDefinition || !incl_relnn_objs)
7567 						objects_map[object->getObjectId()]=object;
7568 					else
7569 					{
7570 						rel=dynamic_cast<Relationship *>(object);
7571 
7572 						/* Avoiding many-to-many relationships to be included in the map.
7573 			 They are treated in a separated way below, because on the diff process (ModelsDiffHelper) the generated table
7574 			 need to be compared to other tables not the relationship itself */
7575 						if(!incl_relnn_objs || !rel || (rel && rel->getRelationshipType()!=BaseRelationship::RelationshipNn))
7576 							objects_map[object->getObjectId()]=object;
7577 					}
7578 				}
7579 			}
7580 		}
7581 	}
7582 
7583 	/* Getting and storing the special objects (which reference columns of tables added for relationships)
7584 	  on the map of objects. */
7585 	aux_tables = tables;
7586 	aux_tables.insert(aux_tables.end(), foreign_tables.begin(), foreign_tables.end());
7587 
7588 	for(auto &obj : aux_tables)
7589 	{
7590 		table = dynamic_cast<PhysicalTable *>(obj);
7591 
7592 		for(auto &obj : *table->getObjectList(ObjectType::Constraint))
7593 		{
7594 			//table->getConstraint(i);
7595 			constr = dynamic_cast<Constraint *>(obj);
7596 
7597 			/* Case the constraint is a special object stores it on the objects map. Independently to the
7598 		configuration, foreign keys are discarded in this iteration because on the end of the method
7599 		they have the definition generated */
7600 			if(constr->getConstraintType()!=ConstraintType::ForeignKey &&  !constr->isAddedByLinking() &&
7601 					((constr->getConstraintType()!=ConstraintType::PrimaryKey && constr->isReferRelationshipAddedColumn())))
7602 				objects_map[constr->getObjectId()]=constr;
7603 			else if(constr->getConstraintType()==ConstraintType::ForeignKey && !constr->isAddedByLinking())
7604 				fkeys.push_back(constr);
7605 		}
7606 
7607 		for(auto obj : table->getObjects({ ObjectType::Column, ObjectType::Constraint }))
7608 			objects_map[obj->getObjectId()]=obj;
7609 	}
7610 
7611 	/* Getting and storing the special objects (which reference columns of tables added for relationships)
7612 			on the map of objects. */
7613 	for(auto &obj : views)
7614 	{
7615 		view=dynamic_cast<View *>(obj);
7616 
7617 		for(auto obj : view->getObjects())
7618 			objects_map[obj->getObjectId()]=obj;
7619 	}
7620 
7621 	/* SPECIAL CASE: Generating the correct order for tables, views, relationships and sequences
7622 
7623 	 This generation is made in the following way:
7624 	 1) Based on the relationship list, participant tables comes before the relationship itself.
7625 	 2) Other tables came after the objects on the step 1.
7626 	 3) The sequences must have their code generated after the tables
7627 	 4) View are the last objects in the list avoiding table/column reference breaking */
7628 	if(def_type==SchemaParser::SqlDefinition)
7629 	{
7630 		BaseObject *objs[3]={nullptr, nullptr, nullptr};
7631 		vector<BaseObject *> vet_aux, rel_constrs;
7632 
7633 		vet_aux=relationships;
7634 		vet_aux.insert(vet_aux.end(), tables.begin(),tables.end());
7635 		vet_aux.insert(vet_aux.end(), foreign_tables.begin(),foreign_tables.end());
7636 		vet_aux.insert(vet_aux.end(), sequences.begin(),sequences.end());
7637 		vet_aux.insert(vet_aux.end(), views.begin(),views.end());;
7638 		itr=vet_aux.begin();
7639 		itr_end=vet_aux.end();
7640 
7641 		while(itr!=itr_end)
7642 		{
7643 			object=(*itr);
7644 			itr++;
7645 
7646 			if(object->getObjectType()==ObjectType::Relationship)
7647 			{
7648 				rel=dynamic_cast<Relationship *>(object);
7649 				objs[0]=rel->getTable(Relationship::SrcTable);
7650 				objs[1]=rel->getTable(Relationship::DstTable);
7651 
7652 				/* For many-to-many relationship, the generated table and the foreign keys that represents
7653 		   the link are included on the creation order map instead of the relationship itself. This is
7654 		   done to permit the table to be accessed and compared on the diff process */
7655 				if(incl_relnn_objs &&
7656 						rel->getRelationshipType()==BaseRelationship::RelationshipNn &&
7657 						rel->getGeneratedTable())
7658 				{
7659 					table=rel->getGeneratedTable();
7660 					objs[2]=table;
7661 
7662 					for(BaseObject *tab_obj : *table->getObjectList(ObjectType::Constraint))
7663 					{
7664 						constr=dynamic_cast<Constraint *>(tab_obj);
7665 
7666 						if(constr->getConstraintType()==ConstraintType::ForeignKey)
7667 							fkeys.push_back(constr);
7668 					}
7669 				}
7670 				else if(incl_rel1n_constrs)
7671 				{
7672 					vector<Constraint *> constrs=rel->getGeneratedConstraints();
7673 
7674 					for(auto &constr : constrs)
7675 					{
7676 						if(constr->getConstraintType()!=ConstraintType::PrimaryKey)
7677 							rel_constrs.push_back(constr);
7678 					}
7679 				}
7680 				else
7681 					objs[2]=rel;
7682 
7683 				for(i=0; i < 3; i++)
7684 				{
7685 					if(objs[i] && objects_map.count(objs[i]->getObjectId())==0)
7686 						objects_map[objs[i]->getObjectId()]=objs[i];
7687 				}
7688 			}
7689 			else
7690 			{
7691 				if(objects_map.count(object->getObjectId())==0)
7692 					objects_map[object->getObjectId()]=object;
7693 			}
7694 		}
7695 
7696 		fkeys.insert(fkeys.end(), rel_constrs.begin(), rel_constrs.end());
7697 	}
7698 
7699 	//Adding fk relationships and foreign keys at end of objects map
7700 	i=BaseObject::getGlobalId() + 1;
7701 	fkeys.insert(fkeys.end(), fk_rels.begin(), fk_rels.end());
7702 
7703 	for(auto &obj : fkeys)
7704 	{
7705 		objects_map[i]=obj;
7706 		i++;
7707 	}
7708 
7709 	//Adding permissions at the very end of object map
7710 	i=BaseObject::getGlobalId() + fkeys.size() + 1;
7711 
7712 	for(auto &obj : permissions)
7713 	{
7714 		objects_map[i]=obj;
7715 		i++;
7716 	}
7717 
7718 	return objects_map;
7719 }
7720 
7721 
__getObjectDependencies(BaseObject * object,vector<BaseObject * > & objs)7722 void DatabaseModel::__getObjectDependencies(BaseObject *object, vector<BaseObject *> &objs)
7723 {
7724 	vector<BaseObject *> dep_objs, chld_objs;
7725 	PhysicalTable *table=dynamic_cast<PhysicalTable *>(object);
7726 	ObjectType obj_type=ObjectType::BaseObject;
7727 
7728 	if(!object) return;
7729 
7730 	getObjectDependecies(object, objs, true);
7731 	obj_type=object->getObjectType();
7732 
7733 	//If the object is a table include as dependency the copy table as well any ancestor table
7734 	if(table)
7735 	{
7736 		//Including copy table and its dependencies
7737 		if(table->getCopyTable())
7738 		{
7739 			__getObjectDependencies(table->getCopyTable(), dep_objs);
7740 			objs.insert(objs.end(), dep_objs.begin(), dep_objs.end());
7741 		}
7742 
7743 		//Including ancestor tables and their dependencies
7744 		dep_objs.clear();
7745 		for(unsigned i=0; i < table->getAncestorTableCount(); i++)
7746 		{
7747 			__getObjectDependencies(table->getAncestorTable(i), dep_objs);
7748 			objs.insert(objs.end(), dep_objs.begin(), dep_objs.end());
7749 		}
7750 	}
7751 
7752 	//If there is the need to include the children objects
7753 	if(BaseTable::isBaseTable(obj_type) || obj_type==ObjectType::Schema)
7754 	{
7755 		vector<BaseObject *>::iterator end;
7756 
7757 		if(obj_type==ObjectType::Schema)
7758 		{
7759 			//Retrieve all objects that belongs to the schema
7760 			chld_objs=getObjects(object);
7761 			objs.insert(objs.end(), chld_objs.begin(), chld_objs.end());
7762 
7763 			for(BaseObject *aux_obj : chld_objs)
7764 			{
7765 				__getObjectDependencies(aux_obj, dep_objs);
7766 				objs.insert(objs.end(), dep_objs.begin(), dep_objs.end());
7767 			}
7768 		}
7769 		else
7770 		{
7771 			BaseTable *tab=dynamic_cast<BaseTable *>(object);
7772 			Constraint *constr=nullptr;
7773 
7774 			chld_objs=tab->getObjects();
7775 
7776 			for(BaseObject *child : chld_objs)
7777 			{
7778 				constr=dynamic_cast<Constraint *>(child);
7779 
7780 				/* Columns are discarded but constraint included only if they are included by relationship
7781 		   or foreign keys in which referenced table resides in the same schema as their parent tables */
7782 				if((!constr && child->getObjectType()!=ObjectType::Column) ||
7783 						(constr &&
7784 						 ((constr->getConstraintType()==ConstraintType::ForeignKey) ||
7785 							(constr->getConstraintType()!=ConstraintType::ForeignKey &&
7786 							 constr->getConstraintType()!=ConstraintType::PrimaryKey &&
7787 						   constr->isReferRelationshipAddedColumn()))))
7788 				{
7789 					__getObjectDependencies(child, objs);
7790 
7791 					if(constr && constr->getReferencedTable() && std::find(objs.begin(), objs.end(), constr->getReferencedTable())==objs.end())
7792 						__getObjectDependencies(constr->getReferencedTable(), objs);
7793 				}
7794 			}
7795 		}
7796 
7797 		//Cleaning up the resulting list removing duplicate elements
7798 		std::sort(objs.begin(), objs.end());
7799 		end=std::unique(objs.begin(), objs.end());
7800 		objs.erase(end, objs.end());
7801 	}
7802 }
7803 
getCreationOrder(BaseObject * object,bool only_children)7804 vector<BaseObject *> DatabaseModel::getCreationOrder(BaseObject *object, bool only_children)
7805 {
7806 	if(!object)
7807 		return vector<BaseObject *>();
7808 
7809 	map<unsigned, BaseObject *> objs_map;
7810 	vector<BaseObject *> objs, children;
7811 	vector<Permission *> perms_aux, perms;
7812 	vector<Role *> roles;
7813 	PhysicalTable *table=nullptr;
7814 	Relationship *rel=nullptr;
7815 	ObjectType obj_type=object->getObjectType();
7816 
7817 	if(only_children)
7818 		objs.push_back(object);
7819 	else
7820 		__getObjectDependencies(object, objs);
7821 
7822 	/* Include tables generated by many-to-many relationships if their schemas are the same
7823 	 as the 'object' when this one is a schema too */
7824 	if(obj_type==ObjectType::Schema)
7825 	{
7826 		if(only_children)
7827 		{
7828 			children=getObjects(object);
7829 			objs.insert(objs.end(), children.begin(), children.end());
7830 		}
7831 
7832 		for(BaseObject *obj : relationships)
7833 		{
7834 			rel=dynamic_cast<Relationship *>(obj);
7835 
7836 			if(rel->getRelationshipType()==Relationship::RelationshipNn &&
7837 					rel->getGeneratedTable() &&
7838 					rel->getGeneratedTable()->getSchema()==object)
7839 			{
7840 				if(only_children)
7841 					objs.push_back(rel->getGeneratedTable());
7842 				else
7843 					__getObjectDependencies(rel->getGeneratedTable(), objs);
7844 			}
7845 		}
7846 	}
7847 
7848 	if(only_children)
7849 	{
7850 		BaseTable *table=nullptr;
7851 		Constraint *constr=nullptr;
7852 		vector<BaseObject *> objs_aux;
7853 
7854 		for(BaseObject *obj : objs)
7855 		{
7856 			table=dynamic_cast<BaseTable *>(obj);
7857 
7858 			if(table)
7859 			{
7860 				children=table->getObjects();
7861 
7862 				for(BaseObject *child : children)
7863 				{
7864 					constr=dynamic_cast<Constraint *>(child);
7865 
7866 					if((!constr && child->getObjectType()!=ObjectType::Column) ||
7867 							(constr &&
7868 							 ((constr->getConstraintType()==ConstraintType::ForeignKey) ||
7869 								(constr->getConstraintType()!=ConstraintType::ForeignKey &&
7870 								 constr->getConstraintType()!=ConstraintType::PrimaryKey &&
7871 							   constr->isReferRelationshipAddedColumn()))))
7872 					{
7873 						objs_aux.push_back(child);
7874 					}
7875 				}
7876 			}
7877 		}
7878 
7879 		objs.insert(objs.end(), objs_aux.begin(), objs_aux.end());
7880 	}
7881 	else
7882 	{
7883 		//Retrieving all permission related to the gathered objects
7884 		for(BaseObject *obj : objs)
7885 		{
7886 			getPermissions(obj, perms_aux);
7887 			perms.insert(perms.end(), perms_aux.begin(), perms_aux.end());
7888 			perms_aux.clear();
7889 
7890 			table=dynamic_cast<PhysicalTable *>(obj);
7891 
7892 			if(table)
7893 			{
7894 				for(BaseObject *col : *table->getObjectList(ObjectType::Column))
7895 				{
7896 					getPermissions(col, perms_aux);
7897 					perms.insert(perms.end(), perms_aux.begin(), perms_aux.end());
7898 				}
7899 			}
7900 		}
7901 
7902 		/* Retrieving all additional roles (reference by permissions) that are not in the
7903 	 main object list (used as creation order) */
7904 		for(Permission *perm : perms)
7905 		{
7906 			roles=perm->getRoles();
7907 
7908 			for(Role *role : roles)
7909 			{
7910 				if(std::find(objs.begin(), objs.end(), role)==objs.end())
7911 					getObjectDependecies(role, objs, true);
7912 			}
7913 		}
7914 	}
7915 
7916 	if(objs.size() > 1 || !perms.empty())
7917 	{
7918 		//Putting all objects in a map ordering them by ID
7919 		for(BaseObject *obj : objs)
7920 			objs_map[obj->getObjectId()]=obj;
7921 
7922 		//Recreationg the object list now with objects ordered properly
7923 		objs.clear();
7924 		for(auto &itr : objs_map)
7925 			objs.push_back(itr.second);
7926 
7927 		//Appending permissions at the end of the creation order list
7928 		objs.insert(objs.end(), perms.begin(), perms.end());
7929 	}
7930 
7931 	return objs;
7932 }
7933 
saveModel(const QString & filename,unsigned def_type)7934 void DatabaseModel::saveModel(const QString &filename, unsigned def_type)
7935 {
7936 	QFile output(filename);
7937 	QByteArray buf;
7938 
7939 	output.open(QFile::WriteOnly);
7940 
7941 	if(!output.isOpen())
7942 		throw Exception(Exception::getErrorMessage(ErrorCode::FileDirectoryNotWritten).arg(filename),
7943 										ErrorCode::FileDirectoryNotWritten,__PRETTY_FUNCTION__,__FILE__,__LINE__);
7944 
7945 	try
7946 	{
7947 		buf.append(this->getCodeDefinition(def_type));
7948 		output.write(buf.data(),buf.size());
7949 		output.close();
7950 	}
7951 	catch(Exception &e)
7952 	{
7953 		if(output.isOpen()) output.close();
7954 		throw Exception(Exception::getErrorMessage(ErrorCode::FileNotWrittenInvalidDefinition).arg(filename),
7955 										ErrorCode::FileNotWrittenInvalidDefinition,__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
7956 	}
7957 }
7958 
getOpClassDependencies(BaseObject * object,vector<BaseObject * > & deps,bool inc_indirect_deps)7959 void DatabaseModel::getOpClassDependencies(BaseObject *object, vector<BaseObject *> &deps, bool inc_indirect_deps)
7960 {
7961 	OperatorClass *opclass=dynamic_cast<OperatorClass *>(object);
7962 	BaseObject *usr_type=getObjectPgSQLType(opclass->getDataType());
7963 	unsigned i, cnt;
7964 	OperatorClassElement elem;
7965 
7966 	if(usr_type)
7967 		getObjectDependecies(usr_type, deps, inc_indirect_deps);
7968 
7969 	if(opclass->getFamily())
7970 		getObjectDependecies(opclass->getFamily(), deps, inc_indirect_deps);
7971 
7972 	cnt=opclass->getElementCount();
7973 
7974 	for(i=0; i < cnt; i++)
7975 	{
7976 		elem=opclass->getElement(i);
7977 
7978 		if(elem.getFunction())
7979 			getObjectDependecies(elem.getFunction(), deps, inc_indirect_deps);
7980 
7981 		if(elem.getOperator())
7982 			getObjectDependecies(elem.getOperator(), deps, inc_indirect_deps);
7983 
7984 		if(elem.getOperatorFamily())
7985 			getObjectDependecies(elem.getOperatorFamily(), deps, inc_indirect_deps);
7986 
7987 		if(elem.getStorage().isUserType())
7988 		{
7989 			usr_type=getObjectPgSQLType(elem.getStorage());
7990 			getObjectDependecies(usr_type, deps, inc_indirect_deps);
7991 		}
7992 	}
7993 }
7994 
getDomainDependencies(BaseObject * object,vector<BaseObject * > & deps,bool inc_indirect_deps)7995 void DatabaseModel::getDomainDependencies(BaseObject *object, vector<BaseObject *> &deps, bool inc_indirect_deps)
7996 {
7997 	BaseObject *usr_type=getObjectPgSQLType(dynamic_cast<Domain *>(object)->getType());
7998 
7999 	if(usr_type)
8000 		getObjectDependecies(usr_type, deps, inc_indirect_deps);
8001 }
8002 
getCastDependencies(BaseObject * object,vector<BaseObject * > & deps,bool inc_indirect_deps)8003 void DatabaseModel::getCastDependencies(BaseObject *object, vector<BaseObject *> &deps, bool inc_indirect_deps)
8004 {
8005 	Cast *cast=dynamic_cast<Cast *>(object);
8006 	BaseObject *usr_type=nullptr;
8007 
8008 	for(unsigned i=Cast::SrcType; i <= Cast::DstType; i++)
8009 	{
8010 		usr_type=getObjectPgSQLType(cast->getDataType(i));
8011 
8012 		if(usr_type)
8013 			getObjectDependecies(usr_type, deps, inc_indirect_deps);
8014 	}
8015 
8016 	getObjectDependecies(cast->getCastFunction(), deps, inc_indirect_deps);
8017 }
8018 
getFunctionDependencies(BaseObject * object,vector<BaseObject * > & deps,bool inc_indirect_deps)8019 void DatabaseModel::getFunctionDependencies(BaseObject *object, vector<BaseObject *> &deps, bool inc_indirect_deps)
8020 {
8021 	Function *func=dynamic_cast<Function *>(object);
8022 	BaseObject *usr_type=getObjectPgSQLType(func->getReturnType());
8023 	unsigned count, i;
8024 
8025 	if(!func->isSystemObject())
8026 		getObjectDependecies(func->getLanguage(), deps, inc_indirect_deps);
8027 
8028 	if(usr_type)
8029 		getObjectDependecies(usr_type, deps, inc_indirect_deps);
8030 
8031 	count=func->getParameterCount();
8032 	for(i=0; i < count; i++)
8033 	{
8034 		usr_type=getObjectPgSQLType(func->getParameter(i).getType());
8035 
8036 		if(usr_type)
8037 			getObjectDependecies(usr_type, deps, inc_indirect_deps);
8038 	}
8039 
8040 	count=func->getReturnedTableColumnCount();
8041 	for(i=0; i < count; i++)
8042 	{
8043 		usr_type=getObjectPgSQLType(func->getReturnedTableColumn(i).getType());
8044 
8045 		if(usr_type)
8046 			getObjectDependecies(usr_type, deps, inc_indirect_deps);
8047 	}
8048 }
8049 
getAggregateDependencies(BaseObject * object,vector<BaseObject * > & deps,bool inc_indirect_deps)8050 void DatabaseModel::getAggregateDependencies(BaseObject *object, vector<BaseObject *> &deps, bool inc_indirect_deps)
8051 {
8052 	Aggregate *aggreg=dynamic_cast<Aggregate *>(object);
8053 	BaseObject *usr_type=nullptr;
8054 	unsigned count, i;
8055 
8056 	for(i=Aggregate::FinalFunc; i <= Aggregate::TransitionFunc; i++)
8057 		getObjectDependecies(aggreg->getFunction(i), deps, inc_indirect_deps);
8058 
8059 	usr_type=getObjectPgSQLType(aggreg->getStateType());
8060 
8061 	if(usr_type)
8062 		getObjectDependecies(usr_type, deps, inc_indirect_deps);
8063 
8064 	if(aggreg->getSortOperator())
8065 		getObjectDependecies(aggreg->getSortOperator(), deps, inc_indirect_deps);
8066 
8067 	count=aggreg->getDataTypeCount();
8068 	for(i=0; i < count; i++)
8069 	{
8070 		usr_type=getObjectPgSQLType(aggreg->getDataType(i));
8071 
8072 		if(usr_type)
8073 			getObjectDependecies(usr_type, deps, inc_indirect_deps);
8074 	}
8075 }
8076 
getLanguageDependencies(BaseObject * object,vector<BaseObject * > & deps,bool inc_indirect_deps)8077 void DatabaseModel::getLanguageDependencies(BaseObject *object, vector<BaseObject *> &deps, bool inc_indirect_deps)
8078 {
8079 	Language *lang=dynamic_cast<Language *>(object);
8080 
8081 	for(unsigned i=Language::ValidatorFunc; i <= Language::InlineFunc; i++)
8082 	{
8083 		if(lang->getFunction(i))
8084 			getObjectDependecies(lang->getFunction(i), deps, inc_indirect_deps);
8085 	}
8086 }
8087 
getOperatorDependencies(BaseObject * object,vector<BaseObject * > & deps,bool inc_indirect_deps)8088 void DatabaseModel::getOperatorDependencies(BaseObject *object, vector<BaseObject *> &deps, bool inc_indirect_deps)
8089 {
8090 	Operator *oper=dynamic_cast<Operator *>(object);
8091 	BaseObject *usr_type=nullptr;
8092 	unsigned i;
8093 
8094 	for(i=Operator::FuncOperator; i <= Operator::FuncRestrict; i++)
8095 	{
8096 		if(oper->getFunction(i))
8097 			getObjectDependecies(oper->getFunction(i), deps, inc_indirect_deps);
8098 	}
8099 
8100 	for(i=Operator::LeftArg; i <= Operator::RightArg; i++)
8101 	{
8102 		usr_type=getObjectPgSQLType(oper->getArgumentType(i));
8103 
8104 		if(usr_type)
8105 			getObjectDependecies(usr_type, deps, inc_indirect_deps);
8106 	}
8107 
8108 	for(i=Operator::OperCommutator; i <= Operator::OperNegator; i++)
8109 	{
8110 		if(oper->getOperator(i))
8111 			getObjectDependecies(oper->getOperator(i), deps, inc_indirect_deps);
8112 	}
8113 }
8114 
getRoleDependencies(BaseObject * object,vector<BaseObject * > & deps,bool inc_indirect_deps)8115 void DatabaseModel::getRoleDependencies(BaseObject *object, vector<BaseObject *> &deps, bool inc_indirect_deps)
8116 {
8117 	Role *role=dynamic_cast<Role *>(object);
8118 	unsigned i, i1, count,
8119 			role_types[3]={ Role::RefRole, Role::MemberRole, Role::AdminRole };
8120 
8121 	for(i=0; i < 3; i++)
8122 	{
8123 		count=role->getRoleCount(role_types[i]);
8124 		for(i1=0; i1 < count; i1++)
8125 			getObjectDependecies(role->getRole(role_types[i], i1), deps, inc_indirect_deps);
8126 	}
8127 }
8128 
getRelationshipDependencies(BaseObject * object,vector<BaseObject * > & deps,bool inc_indirect_deps)8129 void DatabaseModel::getRelationshipDependencies(BaseObject *object, vector<BaseObject *> &deps, bool inc_indirect_deps)
8130 {
8131 	Relationship *rel=dynamic_cast<Relationship *>(object);
8132 	BaseObject *usr_type=nullptr;
8133 	Constraint *constr=nullptr;
8134 	unsigned i, count;
8135 
8136 	getObjectDependecies(rel->getTable(Relationship::SrcTable), deps, inc_indirect_deps);
8137 	getObjectDependecies(rel->getTable(Relationship::DstTable), deps, inc_indirect_deps);
8138 
8139 	count=rel->getAttributeCount();
8140 	for(i=0; i < count; i++)
8141 	{
8142 		usr_type=getObjectPgSQLType(rel->getAttribute(i)->getType());
8143 
8144 		if(usr_type)
8145 			getObjectDependecies(usr_type, deps, inc_indirect_deps);
8146 	}
8147 
8148 	count=rel->getConstraintCount();
8149 	for(i=0; i < count; i++)
8150 	{
8151 		constr=dynamic_cast<Constraint *>(rel->getConstraint(i));
8152 
8153 		if(constr->getTablespace())
8154 			getObjectDependecies(constr->getTablespace(), deps, inc_indirect_deps);
8155 	}
8156 }
8157 
getSequenceDependencies(BaseObject * object,vector<BaseObject * > & deps,bool inc_indirect_deps)8158 void DatabaseModel::getSequenceDependencies(BaseObject *object, vector<BaseObject *> &deps, bool inc_indirect_deps)
8159 {
8160 	Sequence *seq=dynamic_cast<Sequence *>(object);
8161 	if(seq->getOwnerColumn())
8162 		getObjectDependecies(seq->getOwnerColumn()->getParentTable(), deps, inc_indirect_deps);
8163 }
8164 
getColumnDependencies(BaseObject * object,vector<BaseObject * > & deps,bool inc_indirect_deps)8165 void DatabaseModel::getColumnDependencies(BaseObject *object, vector<BaseObject *> &deps, bool inc_indirect_deps)
8166 {
8167 	Column *col=dynamic_cast<Column *>(object);
8168 	BaseObject *usr_type=getObjectPgSQLType(col->getType()),
8169 			*sequence=col->getSequence();
8170 
8171 	if(usr_type)
8172 		getObjectDependecies(usr_type, deps, inc_indirect_deps);
8173 
8174 	if(sequence)
8175 		getObjectDependecies(sequence, deps, inc_indirect_deps);
8176 }
8177 
getTriggerDependencies(BaseObject * object,vector<BaseObject * > & deps,bool inc_indirect_deps)8178 void DatabaseModel::getTriggerDependencies(BaseObject *object, vector<BaseObject *> &deps, bool inc_indirect_deps)
8179 {
8180 	Trigger *trig=dynamic_cast<Trigger *>(object);
8181 
8182 	if(trig->getReferencedTable())
8183 		getObjectDependecies(trig->getReferencedTable(), deps, inc_indirect_deps);
8184 
8185 	if(trig->getFunction())
8186 		getObjectDependecies(trig->getFunction(), deps, inc_indirect_deps);
8187 }
8188 
getIndexDependencies(BaseObject * object,vector<BaseObject * > & deps,bool inc_indirect_deps)8189 void DatabaseModel::getIndexDependencies(BaseObject *object, vector<BaseObject *> &deps, bool inc_indirect_deps)
8190 {
8191 	Index *index=dynamic_cast<Index *>(object);
8192 	BaseObject *usr_type=nullptr;
8193 	unsigned i, count=index->getIndexElementCount();
8194 
8195 	for(i=0; i < count; i++)
8196 	{
8197 		if(index->getIndexElement(i).getOperatorClass())
8198 			getObjectDependecies(index->getIndexElement(i).getOperatorClass(), deps, inc_indirect_deps);
8199 
8200 		if(index->getIndexElement(i).getColumn())
8201 		{
8202 			usr_type=getObjectPgSQLType(index->getIndexElement(i).getColumn()->getType());
8203 
8204 			if(usr_type)
8205 				getObjectDependecies(usr_type, deps, inc_indirect_deps);
8206 		}
8207 
8208 		if(index->getIndexElement(i).getCollation())
8209 			getObjectDependecies(index->getIndexElement(i).getCollation(), deps, inc_indirect_deps);
8210 	}
8211 }
8212 
getPolicyDependencies(BaseObject * object,vector<BaseObject * > & deps,bool inc_indirect_deps)8213 void DatabaseModel::getPolicyDependencies(BaseObject *object, vector<BaseObject *> &deps, bool inc_indirect_deps)
8214 {
8215 	Policy *pol=dynamic_cast<Policy *>(object);
8216 
8217 	for(auto role : pol->getRoles())
8218 		getObjectDependecies(role, deps, inc_indirect_deps);
8219 }
8220 
getPhysicalTableDependencies(BaseObject * object,vector<BaseObject * > & deps,bool inc_indirect_deps)8221 void DatabaseModel::getPhysicalTableDependencies(BaseObject *object, vector<BaseObject *> &deps, bool inc_indirect_deps)
8222 {
8223 	PhysicalTable *tab=dynamic_cast<PhysicalTable *>(object);
8224 	Table *aux_tab = dynamic_cast<Table *>(object);
8225 	ForeignTable *ftable = dynamic_cast<ForeignTable *>(tab);
8226 	BaseObject *usr_type=nullptr,  *seq=nullptr;
8227 	Constraint *constr=nullptr;
8228 	Trigger *trig=nullptr;
8229 	Index *index=nullptr;
8230 	Column *col=nullptr;
8231 	Policy *pol=nullptr;
8232 	unsigned count, i, count1, i1;
8233 
8234 	count=tab->getColumnCount();
8235 	for(i=0; i < count; i++)
8236 	{
8237 		col=tab->getColumn(i);
8238 		usr_type=getObjectPgSQLType(col->getType());
8239 		seq=col->getSequence();
8240 
8241 		if(!col->isAddedByLinking())
8242 		{
8243 			if(usr_type)
8244 				getObjectDependecies(usr_type, deps, inc_indirect_deps);
8245 
8246 			if(seq)
8247 				getObjectDependecies(seq, deps, inc_indirect_deps);
8248 		}
8249 	}
8250 
8251 	count=tab->getConstraintCount();
8252 	for(i=0; i < count; i++)
8253 	{
8254 		constr=dynamic_cast<Constraint *>(tab->getConstraint(i));
8255 		count1=constr->getExcludeElementCount();
8256 
8257 		for(i1=0; i1 < count1; i1++)
8258 		{
8259 			if(constr->getExcludeElement(i1).getOperator())
8260 				getObjectDependecies(constr->getExcludeElement(i1).getOperator(), deps, inc_indirect_deps);
8261 
8262 			if(constr->getExcludeElement(i1).getOperatorClass())
8263 				getObjectDependecies(constr->getExcludeElement(i1).getOperatorClass(), deps, inc_indirect_deps);
8264 		}
8265 
8266 		if(inc_indirect_deps &&
8267 				!constr->isAddedByLinking() &&
8268 				constr->getConstraintType()==ConstraintType::ForeignKey)
8269 			getObjectDependecies(constr->getReferencedTable(), deps, inc_indirect_deps);
8270 
8271 		if(!constr->isAddedByLinking() && constr->getTablespace())
8272 			getObjectDependecies(constr->getTablespace(), deps, inc_indirect_deps);
8273 	}
8274 
8275 	count=tab->getTriggerCount();
8276 	for(i=0; i < count; i++)
8277 	{
8278 		trig=dynamic_cast<Trigger *>(tab->getTrigger(i));
8279 		if(trig->getReferencedTable())
8280 			getObjectDependecies(trig->getReferencedTable(), deps, inc_indirect_deps);
8281 
8282 		if(trig->getFunction())
8283 			getObjectDependecies(trig->getFunction(), deps, inc_indirect_deps);
8284 	}
8285 
8286 	if(ftable)
8287 	{
8288 		getObjectDependecies(ftable->getForeignServer(), deps, inc_indirect_deps);
8289 	}
8290 
8291 	if(aux_tab)
8292 	{
8293 		count=aux_tab->getIndexCount();
8294 		for(i=0; i < count; i++)
8295 		{
8296 			index=dynamic_cast<Index *>(aux_tab->getIndex(i));
8297 			count1=index->getIndexElementCount();
8298 
8299 			for(i1=0; i1 < count1; i1++)
8300 			{
8301 				if(index->getIndexElement(i1).getOperatorClass())
8302 					getObjectDependecies(index->getIndexElement(i1).getOperatorClass(), deps, inc_indirect_deps);
8303 
8304 				if(index->getIndexElement(i1).getColumn())
8305 				{
8306 					usr_type=getObjectPgSQLType(index->getIndexElement(i1).getColumn()->getType());
8307 
8308 					if(usr_type)
8309 						getObjectDependecies(usr_type, deps, inc_indirect_deps);
8310 				}
8311 
8312 				if(index->getIndexElement(i1).getCollation())
8313 					getObjectDependecies(index->getIndexElement(i1).getCollation(), deps, inc_indirect_deps);
8314 			}
8315 		}
8316 
8317 		count=aux_tab->getPolicyCount();
8318 		for(i=0; i < count; i++)
8319 		{
8320 			pol=dynamic_cast<Policy *>(aux_tab->getPolicy(i));
8321 
8322 			for(auto role : pol->getRoles())
8323 				getObjectDependecies(role, deps, inc_indirect_deps);
8324 		}
8325 	}
8326 }
8327 
getTypeDependencies(BaseObject * object,vector<BaseObject * > & deps,bool inc_indirect_deps)8328 void DatabaseModel::getTypeDependencies(BaseObject *object, vector<BaseObject *> &deps, bool inc_indirect_deps)
8329 {
8330 	Type *usr_type=dynamic_cast<Type *>(object);
8331 	BaseObject *aux_type=nullptr;
8332 	unsigned count, i;
8333 
8334 	if(usr_type->getConfiguration()==Type::BaseType)
8335 	{
8336 		aux_type=getObjectPgSQLType(usr_type->getLikeType());
8337 
8338 		if(aux_type)
8339 			getObjectDependecies(aux_type, deps, inc_indirect_deps);
8340 
8341 		for(i=Type::InputFunc; i <= Type::AnalyzeFunc; i++)
8342 			getObjectDependecies(usr_type->getFunction(i), deps, inc_indirect_deps);
8343 	}
8344 	else if(usr_type->getConfiguration()==Type::CompositeType)
8345 	{
8346 		count=usr_type->getAttributeCount();
8347 		for(i=0; i < count; i++)
8348 		{
8349 			aux_type=getObjectPgSQLType(usr_type->getAttribute(i).getType());
8350 
8351 			if(aux_type)
8352 				getObjectDependecies(aux_type, deps, inc_indirect_deps);
8353 		}
8354 	}
8355 }
8356 
getViewDependencies(BaseObject * object,vector<BaseObject * > & deps,bool inc_indirect_deps)8357 void DatabaseModel::getViewDependencies(BaseObject *object, vector<BaseObject *> &deps, bool inc_indirect_deps)
8358 {
8359 	View *view=dynamic_cast<View *>(object);
8360 	unsigned i, count;
8361 
8362 	count=view->getReferenceCount();
8363 	for(i=0; i < count; i++)
8364 	{
8365 		if(view->getReference(i).getTable())
8366 			getObjectDependecies(view->getReference(i).getTable(), deps, inc_indirect_deps);
8367 	}
8368 
8369 	for(i=0; i < view->getTriggerCount(); i++)
8370 		getObjectDependecies(view->getTrigger(i), deps, inc_indirect_deps);
8371 
8372 	for(i=0; i < view->getTriggerCount(); i++)
8373 	{
8374 		if(view->getTrigger(i)->getReferencedTable())
8375 			getObjectDependecies(view->getTrigger(i)->getReferencedTable(), deps, inc_indirect_deps);
8376 	}
8377 }
8378 
getGenericSQLDependencies(BaseObject * object,vector<BaseObject * > & deps,bool inc_indirect_deps)8379 void DatabaseModel::getGenericSQLDependencies(BaseObject *object, vector<BaseObject *> &deps, bool inc_indirect_deps)
8380 {
8381 	GenericSQL *generic_sql = dynamic_cast<GenericSQL *>(object);
8382 	vector<BaseObject *> ref_objs = generic_sql->getReferencedObjects();
8383 	for(auto &obj : ref_objs)
8384 		getObjectDependecies(obj, deps, inc_indirect_deps);
8385 }
8386 
getObjectDependecies(BaseObject * object,vector<BaseObject * > & deps,bool inc_indirect_deps)8387 void DatabaseModel::getObjectDependecies(BaseObject *object, vector<BaseObject *> &deps, bool inc_indirect_deps)
8388 {
8389 	//Case the object is allocated and is not included in the dependecies list
8390 	if(object && std::find(deps.begin(), deps.end(), object)==deps.end())
8391 	{
8392 		deps.push_back(object);
8393 
8394 		if((deps.size()==1 && !inc_indirect_deps) || inc_indirect_deps)
8395 		{
8396 			ObjectType obj_type=object->getObjectType();
8397 
8398 			if(object->getSchema())
8399 				getObjectDependecies(object->getSchema(), deps, inc_indirect_deps);
8400 
8401 			if(object->getTablespace())
8402 				getObjectDependecies(object->getTablespace(), deps, inc_indirect_deps);
8403 
8404 			if(object->getOwner())
8405 				getObjectDependecies(object->getOwner(), deps, inc_indirect_deps);
8406 
8407 			if(object->getCollation())
8408 				getObjectDependecies(object->getCollation(), deps, inc_indirect_deps);
8409 
8410 			if(obj_type==ObjectType::OpClass)
8411 				getOpClassDependencies(object, deps, inc_indirect_deps);
8412 
8413 			if(obj_type==ObjectType::Domain)
8414 				getDomainDependencies(object, deps, inc_indirect_deps);
8415 
8416 			if(obj_type==ObjectType::Conversion)
8417 				getObjectDependecies(dynamic_cast<Conversion *>(object)->getConversionFunction(), deps, inc_indirect_deps);
8418 
8419 			if(obj_type==ObjectType::Cast)
8420 				getCastDependencies(object, deps, inc_indirect_deps);
8421 
8422 			if(obj_type==ObjectType::EventTrigger)
8423 				getObjectDependecies(dynamic_cast<EventTrigger *>(object)->getFunction(), deps, inc_indirect_deps);
8424 
8425 			if(obj_type==ObjectType::Function)
8426 				getFunctionDependencies(object, deps, inc_indirect_deps);
8427 
8428 			if(obj_type==ObjectType::Aggregate)
8429 				getAggregateDependencies(object, deps, inc_indirect_deps);
8430 
8431 			if(obj_type==ObjectType::Language)
8432 				getLanguageDependencies(object, deps, inc_indirect_deps);
8433 
8434 			if(obj_type==ObjectType::Operator)
8435 				getOperatorDependencies(object, deps, inc_indirect_deps);
8436 
8437 			if(obj_type==ObjectType::Role)
8438 				getRoleDependencies(object, deps, inc_indirect_deps);
8439 
8440 			if(obj_type==ObjectType::Relationship)
8441 				getRelationshipDependencies(object, deps, inc_indirect_deps);
8442 
8443 			if(obj_type==ObjectType::Sequence)
8444 				getSequenceDependencies(object, deps, inc_indirect_deps);
8445 
8446 			if(obj_type==ObjectType::Column)
8447 				getColumnDependencies(object, deps, inc_indirect_deps);
8448 
8449 			if(obj_type==ObjectType::Trigger)
8450 				getTriggerDependencies(object, deps, inc_indirect_deps);
8451 
8452 			if(obj_type==ObjectType::Index)
8453 				getIndexDependencies(object, deps, inc_indirect_deps);
8454 
8455 			if(obj_type==ObjectType::Policy)
8456 				getPolicyDependencies(object, deps, inc_indirect_deps);
8457 
8458 			if(PhysicalTable::isPhysicalTable(obj_type))
8459 				getPhysicalTableDependencies(object, deps, inc_indirect_deps);
8460 
8461 			if(obj_type==ObjectType::Type)
8462 				getTypeDependencies(object, deps, inc_indirect_deps);
8463 
8464 			if(obj_type==ObjectType::View)
8465 			 getViewDependencies(object, deps, inc_indirect_deps);
8466 
8467 			if(obj_type == ObjectType::ForeignDataWrapper)
8468 			{
8469 				ForeignDataWrapper *fdw = dynamic_cast<ForeignDataWrapper *>(object);
8470 				getObjectDependecies(fdw->getHandlerFunction(), deps, inc_indirect_deps);
8471 				getObjectDependecies(fdw->getValidatorFunction(), deps, inc_indirect_deps);
8472 			}
8473 
8474 			if(obj_type == ObjectType::ForeignServer)
8475 				getObjectDependecies(dynamic_cast<ForeignServer *>(object)->getForeignDataWrapper(), deps, inc_indirect_deps);
8476 
8477 			if(obj_type==ObjectType::GenericSql)
8478 				getGenericSQLDependencies(object, deps, inc_indirect_deps);
8479 
8480 			if(obj_type==ObjectType::UserMapping)
8481 				getObjectDependecies(dynamic_cast<UserMapping *>(object)->getForeignServer(), deps, inc_indirect_deps);
8482 
8483 			if(BaseTable::isBaseTable(obj_type))
8484 			{
8485 				BaseTable *tab = dynamic_cast<BaseTable *>(object);
8486 
8487 				if(tab->getTag())
8488 					deps.push_back(tab->getTag());
8489 			}
8490 		}
8491 	}
8492 }
8493 
getViewReferences(BaseObject * object,vector<BaseObject * > & refs,bool exclusion_mode)8494 void DatabaseModel::getViewReferences(BaseObject *object, vector<BaseObject *> &refs, bool exclusion_mode)
8495 {
8496 	View *view=dynamic_cast<View *>(object);
8497 	vector<BaseObject *> tab_objs=view->getObjects();
8498 	refs.insert(refs.end(), tab_objs.begin(), tab_objs.end());
8499 
8500 	if(!exclusion_mode)
8501 	{
8502 		vector<BaseRelationship *> base_rels=getRelationships(view);
8503 		while(!base_rels.empty())
8504 		{
8505 			refs.push_back(base_rels.back());
8506 			base_rels.pop_back();
8507 		}
8508 	}
8509 }
8510 
getPhysicalTableReferences(BaseObject * object,vector<BaseObject * > & refs,bool & refer,bool exclusion_mode)8511 void DatabaseModel::getPhysicalTableReferences(BaseObject *object, vector<BaseObject *> &refs, bool &refer, bool exclusion_mode)
8512 {
8513 	PhysicalTable *table=dynamic_cast<PhysicalTable *>(object);
8514 	ObjectType obj_type = object->getObjectType();
8515 	Sequence *seq=nullptr;
8516 	Constraint *constr=nullptr;
8517 	PhysicalTable *tab=nullptr;
8518 	Trigger *gat=nullptr;
8519 	BaseRelationship *base_rel=nullptr;
8520 	View *view=nullptr;
8521 	vector<BaseObject *>::iterator itr, itr_end;
8522 	vector<TableObject *> *tab_objs;
8523 	unsigned i, count;
8524 	vector<ObjectType> tab_obj_types={ ObjectType::Trigger, ObjectType::Rule, ObjectType::Index, ObjectType::Policy };
8525 	vector<BaseObject *> tabs;
8526 
8527 	for(auto &type : tab_obj_types)
8528 	{
8529 		if(obj_type == ObjectType::ForeignTable && type != ObjectType::Trigger)
8530 			continue;
8531 
8532 		tab_objs=table->getObjectList(type);
8533 		refs.insert(refs.end(), tab_objs->begin(), tab_objs->end());
8534 	}
8535 
8536 	itr=relationships.begin();
8537 	itr_end=relationships.end();
8538 
8539 	while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
8540 	{
8541 		base_rel=dynamic_cast<BaseRelationship *>(*itr);
8542 		if(base_rel->getTable(BaseRelationship::SrcTable)==table ||
8543 				base_rel->getTable(BaseRelationship::DstTable)==table)
8544 		{
8545 			refer=true;
8546 			refs.push_back(base_rel);
8547 		}
8548 		itr++;
8549 	}
8550 
8551 	itr=base_relationships.begin();
8552 	itr_end=base_relationships.end();
8553 
8554 	while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
8555 	{
8556 		base_rel=dynamic_cast<BaseRelationship *>(*itr);
8557 		if(base_rel->getRelationshipType()==BaseRelationship::RelationshipFk &&
8558 				(base_rel->getTable(BaseRelationship::SrcTable)==table ||
8559 				 base_rel->getTable(BaseRelationship::DstTable)==table))
8560 		{
8561 			refer=true;
8562 			refs.push_back(base_rel);
8563 		}
8564 		itr++;
8565 	}
8566 
8567 	itr=sequences.begin();
8568 	itr_end=sequences.end();
8569 
8570 	while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
8571 	{
8572 		seq=dynamic_cast<Sequence *>(*itr);
8573 		if(seq->getOwnerColumn() &&
8574 				seq->getOwnerColumn()->getParentTable()==table)
8575 		{
8576 			refer=true;
8577 			refs.push_back(seq);
8578 		}
8579 
8580 		itr++;
8581 	}
8582 
8583 	tabs = tables;
8584 	tabs.insert(tabs.end(), foreign_tables.begin(), foreign_tables.end());
8585 	itr= tabs.begin();
8586 	itr_end = tabs.end();
8587 
8588 	while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
8589 	{
8590 		tab = dynamic_cast<PhysicalTable *>(*itr);
8591 
8592 		count=tab->getConstraintCount();
8593 		for(i=0; i < count&& (!exclusion_mode || (exclusion_mode && !refer)); i++)
8594 		{
8595 			constr=tab->getConstraint(i);
8596 			//If a constraint references its own parent table it'll not be included on the references list
8597 			if(constr->getConstraintType()==ConstraintType::ForeignKey &&
8598 					constr->getParentTable()!=constr->getReferencedTable() &&
8599 					constr->getReferencedTable()==table)
8600 			{
8601 				refer=true;
8602 				refs.push_back(constr);
8603 			}
8604 		}
8605 
8606 		count=tab->getTriggerCount();
8607 		for(i=0; i < count && (!exclusion_mode || (exclusion_mode && !refer)); i++)
8608 		{
8609 			gat=tab->getTrigger(i);
8610 			if(gat->getReferencedTable()==table)
8611 			{
8612 				refer=true;
8613 				refs.push_back(gat);
8614 			}
8615 		}
8616 
8617 		itr++;
8618 	}
8619 
8620 	itr=views.begin();
8621 	itr_end=views.end();
8622 
8623 	while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
8624 	{
8625 		view=dynamic_cast<View *>(*itr);
8626 
8627 		if(view->isReferencingTable(table))
8628 		{
8629 			refer=true;
8630 			refs.push_back(view);
8631 		}
8632 
8633 		itr++;
8634 	}
8635 
8636 	/* As base relationship are created automatically by the model they aren't considered
8637 	as a reference to the table in exclusion mode */
8638 	itr=base_relationships.begin();
8639 	itr_end=base_relationships.end();
8640 
8641 	while(itr!=itr_end && !exclusion_mode)// || (exclusion_mode && !refer)))
8642 	{
8643 		base_rel=dynamic_cast<BaseRelationship *>(*itr);
8644 
8645 		if(base_rel->getTable(BaseRelationship::SrcTable)==table ||
8646 				base_rel->getTable(BaseRelationship::DstTable)==table)
8647 		{
8648 			refer=true;
8649 			refs.push_back(base_rel);
8650 		}
8651 		itr++;
8652 	}
8653 }
8654 
getFunctionReferences(BaseObject * object,vector<BaseObject * > & refs,bool & refer,bool exclusion_mode)8655 void DatabaseModel::getFunctionReferences(BaseObject *object, vector<BaseObject *> &refs, bool &refer, bool exclusion_mode)
8656 {
8657 	Function *func=dynamic_cast<Function *>(object);
8658 	vector<BaseObject *> *obj_list=nullptr;
8659 	vector<BaseObject *>::iterator itr, itr_end;
8660 	ObjectType obj_types[]={ObjectType::Cast, ObjectType::EventTrigger, ObjectType::Conversion,
8661 													ObjectType::Aggregate, ObjectType::Operator, ObjectType::OpClass,
8662 													ObjectType::Table, ObjectType::Type, ObjectType::Language,
8663 													ObjectType::ForeignDataWrapper, ObjectType::ForeignTable };
8664 	unsigned i, i1, count, cnt=sizeof(obj_types)/sizeof(ObjectType);
8665 	PhysicalTable *tab=nullptr;
8666 	Aggregate *aggreg=nullptr;
8667 	Operator *oper=nullptr;
8668 	Trigger *trig=nullptr;
8669 	Type *type=nullptr;
8670 	Language *lang=nullptr;
8671 	OperatorClass *opclass=nullptr;
8672 	ForeignDataWrapper *fdw=nullptr;
8673 
8674 	for(i=0; i < cnt && (!exclusion_mode || (exclusion_mode && !refer)); i++)
8675 	{
8676 		obj_list=getObjectList(obj_types[i]);
8677 		itr=obj_list->begin();
8678 		itr_end=obj_list->end();
8679 
8680 		if(obj_types[i]==ObjectType::Cast)
8681 		{
8682 			while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
8683 			{
8684 				if(dynamic_cast<Cast *>(*itr)->getCastFunction()==func)
8685 				{
8686 					refer=true;
8687 					refs.push_back(*itr);
8688 				}
8689 				itr++;
8690 			}
8691 		}
8692 		else if(obj_types[i]==ObjectType::EventTrigger)
8693 		{
8694 			while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
8695 			{
8696 				if(dynamic_cast<EventTrigger *>(*itr)->getFunction()==func)
8697 				{
8698 					refer=true;
8699 					refs.push_back(*itr);
8700 				}
8701 				itr++;
8702 			}
8703 		}
8704 		else if(obj_types[i]==ObjectType::Conversion)
8705 		{
8706 			while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
8707 			{
8708 				if(dynamic_cast<Conversion *>(*itr)->getConversionFunction()==func)
8709 				{
8710 					refer=true;
8711 					refs.push_back(*itr);
8712 				}
8713 				itr++;
8714 			}
8715 		}
8716 		else if(obj_types[i]==ObjectType::Aggregate)
8717 		{
8718 			while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
8719 			{
8720 				aggreg=dynamic_cast<Aggregate *>(*itr);
8721 
8722 				if(aggreg->getFunction(Aggregate::FinalFunc)==func ||
8723 						aggreg->getFunction(Aggregate::TransitionFunc)==func)
8724 				{
8725 					refer=true;
8726 					refs.push_back(aggreg);
8727 				}
8728 				itr++;
8729 			}
8730 		}
8731 		else if(obj_types[i]==ObjectType::Operator)
8732 		{
8733 			while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
8734 			{
8735 				oper=dynamic_cast<Operator *>(*itr);
8736 
8737 				if(oper->getFunction(Operator::FuncOperator)==func ||
8738 						oper->getFunction(Operator::FuncJoin)==func  ||
8739 						oper->getFunction(Operator::FuncRestrict)==func)
8740 				{
8741 					refer=true;
8742 					refs.push_back(oper);
8743 				}
8744 				itr++;
8745 			}
8746 		}
8747 		else if(obj_types[i]==ObjectType::OpClass)
8748 		{
8749 			while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
8750 			{
8751 				opclass=dynamic_cast<OperatorClass *>(*itr);
8752 				count=opclass->getElementCount();
8753 
8754 				for(i1=0; i1 < count && (!exclusion_mode || (exclusion_mode && !refer)); i1++)
8755 				{
8756 					if(opclass->getElement(i1).getFunction()==func)
8757 					{
8758 						refer=true;
8759 						refs.push_back(opclass);
8760 					}
8761 				}
8762 				itr++;
8763 			}
8764 		}
8765 		else if(obj_types[i]==ObjectType::Table ||
8766 						obj_types[i]==ObjectType::ForeignTable)
8767 		{
8768 			while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
8769 			{
8770 				tab=dynamic_cast<PhysicalTable *>(*itr);
8771 				itr++;
8772 				count=tab->getTriggerCount();
8773 
8774 				for(i1=0; i1 < count && (!exclusion_mode || (exclusion_mode && !refer)); i1++)
8775 				{
8776 					trig=tab->getTrigger(i1);
8777 
8778 					if(trig->getFunction()==func)
8779 					{
8780 						refer=true;
8781 						refs.push_back(trig);
8782 					}
8783 				}
8784 			}
8785 		}
8786 		else if(obj_types[i]==ObjectType::Type)
8787 		{
8788 			while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
8789 			{
8790 				type=dynamic_cast<Type *>(*itr);
8791 				itr++;
8792 
8793 				for(i1=Type::InputFunc; i1 <= Type::AnalyzeFunc && (!exclusion_mode || (exclusion_mode && !refer)); i1++)
8794 				{
8795 					if(type->getFunction(i1)==func)
8796 					{
8797 						refer=true;
8798 						refs.push_back(type);
8799 					}
8800 				}
8801 			}
8802 		}
8803 		else if(obj_types[i]==ObjectType::Language)
8804 		{
8805 			while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
8806 			{
8807 				lang=dynamic_cast<Language *>(*itr);
8808 				itr++;
8809 
8810 				if(lang->getFunction(Language::HandlerFunc)==func ||
8811 						lang->getFunction(Language::ValidatorFunc)==func ||
8812 						lang->getFunction(Language::InlineFunc)==func)
8813 				{
8814 					refer=true;
8815 					refs.push_back(lang);
8816 				}
8817 			}
8818 		}
8819 		else if(obj_types[i]==ObjectType::ForeignDataWrapper)
8820 		{
8821 			while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
8822 			{
8823 				fdw=dynamic_cast<ForeignDataWrapper *>(*itr);
8824 				itr++;
8825 
8826 				if(fdw->getHandlerFunction() == func || fdw->getValidatorFunction() == func)
8827 				{
8828 					refer=true;
8829 					refs.push_back(fdw);
8830 				}
8831 			}
8832 		}
8833 	}
8834 }
8835 
getSchemaReferences(BaseObject * object,vector<BaseObject * > & refs,bool & refer,bool exclusion_mode)8836 void DatabaseModel::getSchemaReferences(BaseObject *object, vector<BaseObject *> &refs, bool &refer, bool exclusion_mode)
8837 {
8838 	vector<BaseObject *> *obj_list=nullptr;
8839 	vector<BaseObject *>::iterator itr, itr_end;
8840 	ObjectType obj_types[12]={ObjectType::Function, ObjectType::Table, ObjectType::ForeignTable, ObjectType::View,
8841 														ObjectType::Domain, ObjectType::Aggregate, ObjectType::Operator,
8842 														ObjectType::Sequence, ObjectType::Conversion,
8843 														ObjectType::Type, ObjectType::OpFamily, ObjectType::OpClass};
8844 	unsigned i;
8845 
8846 	for(i=0; i < 12 && (!exclusion_mode || (exclusion_mode && !refer)); i++)
8847 	{
8848 		obj_list=getObjectList(obj_types[i]);
8849 		itr=obj_list->begin();
8850 		itr_end=obj_list->end();
8851 
8852 		while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
8853 		{
8854 			if((*itr)->getSchema()==object)
8855 			{
8856 				refer=true;
8857 				refs.push_back(*itr);
8858 			}
8859 			itr++;
8860 		}
8861 	}
8862 }
8863 
getUserDefTypesReferences(BaseObject * object,vector<BaseObject * > & refs,bool & refer,bool exclusion_mode)8864 void DatabaseModel::getUserDefTypesReferences(BaseObject *object, vector<BaseObject *> &refs, bool &refer, bool exclusion_mode)
8865 {
8866 	vector<BaseObject *> *obj_list=nullptr;
8867 	vector<BaseObject *>::iterator itr, itr_end;
8868 	ObjectType obj_types[]={ObjectType::Table, ObjectType::ForeignTable, ObjectType::OpClass,
8869 													ObjectType::Cast,	ObjectType::Domain, ObjectType::Function, ObjectType::Aggregate,
8870 													ObjectType::Operator, ObjectType::Type, ObjectType::Relationship };
8871 	unsigned i, i1, count, tp_count = sizeof(obj_types)/sizeof(ObjectType);
8872 	OperatorClass *op_class=nullptr;
8873 	OperatorClassElement elem;
8874 	PhysicalTable *tab=nullptr;
8875 	Column *col=nullptr;
8876 	Cast *cast=nullptr;
8877 	Domain *dom=nullptr;
8878 	Function *func=nullptr;
8879 	Aggregate *aggreg=nullptr;
8880 	Operator *oper=nullptr;
8881 	Type *type=nullptr;
8882 	Relationship *rel=nullptr;
8883 	void *ptr_pgsqltype=nullptr;
8884 	ObjectType obj_type = object->getObjectType();
8885 
8886 	switch(obj_type)
8887 	{
8888 		case ObjectType::Type:
8889 			ptr_pgsqltype=dynamic_cast<Type*>(object);
8890 		break;
8891 		case ObjectType::Domain:
8892 			ptr_pgsqltype=dynamic_cast<Domain*>(object);
8893 		break;
8894 		case ObjectType::Sequence:
8895 			ptr_pgsqltype=dynamic_cast<Sequence*>(object);
8896 		break;
8897 		case ObjectType::Extension:
8898 			ptr_pgsqltype=dynamic_cast<Extension*>(object);
8899 		break;
8900 		case ObjectType::View:
8901 			ptr_pgsqltype=dynamic_cast<View*>(object);
8902 		break;
8903 		case ObjectType::ForeignTable:
8904 			ptr_pgsqltype=dynamic_cast<ForeignTable*>(object);
8905 		break;
8906 		default:
8907 			ptr_pgsqltype=dynamic_cast<Table*>(object);
8908 		break;
8909 	}
8910 
8911 	for(i=0; i < tp_count && (!exclusion_mode || (exclusion_mode && !refer)); i++)
8912 	{
8913 		obj_list=getObjectList(obj_types[i]);
8914 		itr=obj_list->begin();
8915 		itr_end=obj_list->end();
8916 
8917 		if(obj_types[i]==ObjectType::Relationship)
8918 		{
8919 			bool added;
8920 
8921 			while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
8922 			{
8923 				added=false;
8924 				rel=dynamic_cast<Relationship *>(*itr);
8925 				itr++;
8926 
8927 				count=rel->getAttributeCount();
8928 				for(i1=0; i1 < count && !added; i1++)
8929 				{
8930 					col=rel->getAttribute(i1);
8931 
8932 					if(col->getType()==ptr_pgsqltype)
8933 					{
8934 						added=refer=true;
8935 						refs.push_back(rel);
8936 					}
8937 				}
8938 			}
8939 		}
8940 		else if(PhysicalTable::isPhysicalTable(obj_types[i]))
8941 		{
8942 			while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
8943 			{
8944 				tab=dynamic_cast<PhysicalTable *>(*itr);
8945 				itr++;
8946 
8947 				count=tab->getColumnCount();
8948 				for(i1=0; i1 < count && (!exclusion_mode || (exclusion_mode && !refer)); i1++)
8949 				{
8950 					col=tab->getColumn(i1);
8951 
8952 					if(!col->isAddedByRelationship() &&
8953 						 (col->getType()==ptr_pgsqltype ||
8954 							//Special case for postgis extension
8955 							(obj_type == ObjectType::Extension && object->getName() == QString("postgis") && col->getType().isGiSType())))
8956 					{
8957 						refer=true;
8958 						refs.push_back(col);
8959 					}
8960 				}
8961 			}
8962 		}
8963 		else if(obj_types[i]==ObjectType::OpClass)
8964 		{
8965 			while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
8966 			{
8967 				op_class=dynamic_cast<OperatorClass *>(*itr);
8968 				itr++;
8969 
8970 				if(op_class->getDataType()==ptr_pgsqltype)
8971 				{
8972 					refer=true;
8973 					refs.push_back(op_class);
8974 				}
8975 
8976 				for(i1=0; i1 < op_class->getElementCount() && (!exclusion_mode || (exclusion_mode && !refer)); i1++)
8977 				{
8978 					elem=op_class->getElement(i1);
8979 					if(elem.getStorage()==ptr_pgsqltype)
8980 					{
8981 						refer=true;
8982 						refs.push_back(op_class);
8983 					}
8984 				}
8985 			}
8986 		}
8987 		else if(obj_types[i]==ObjectType::Domain)
8988 		{
8989 			while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
8990 			{
8991 				dom=dynamic_cast<Domain *>(*itr);
8992 				itr++;
8993 
8994 				if(dom->getType()==ptr_pgsqltype)
8995 				{
8996 					refer=true;
8997 					refs.push_back(dom);
8998 				}
8999 			}
9000 		}
9001 		else if(obj_types[i]==ObjectType::Type)
9002 		{
9003 			while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
9004 			{
9005 				type=dynamic_cast<Type *>(*itr);
9006 				itr++;
9007 
9008 				if(type->getAlignment()==ptr_pgsqltype ||
9009 						type->getElement()==ptr_pgsqltype ||
9010 						type->getLikeType()==ptr_pgsqltype ||
9011 						type->getSubtype()==ptr_pgsqltype)
9012 				{
9013 					refer=true;
9014 					refs.push_back(type);
9015 				}
9016 			}
9017 		}
9018 		else if(obj_types[i]==ObjectType::Aggregate)
9019 		{
9020 			while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
9021 			{
9022 				aggreg=dynamic_cast<Aggregate *>(*itr);
9023 				itr++;
9024 
9025 				count=aggreg->getDataTypeCount();
9026 				for(i1=0; i1 < count  && (!exclusion_mode || (exclusion_mode && !refer)); i1++)
9027 				{
9028 					if(aggreg->getDataType(i1)==ptr_pgsqltype)
9029 					{
9030 						refer=true;
9031 						refs.push_back(aggreg);
9032 					}
9033 				}
9034 			}
9035 		}
9036 		else if(obj_types[i]==ObjectType::Function)
9037 		{
9038 			while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
9039 			{
9040 				func=dynamic_cast<Function *>(*itr);
9041 				itr++;
9042 
9043 				if(func->getReturnType()==ptr_pgsqltype)
9044 				{
9045 					refer=true;
9046 					refs.push_back(func);
9047 				}
9048 				else
9049 				{
9050 					count=func->getParameterCount();
9051 					for(i1=0; i1 < count && (!exclusion_mode || (exclusion_mode && !refer)); i1++)
9052 					{
9053 						if(func->getParameter(i1).getType()==ptr_pgsqltype)
9054 						{
9055 							refer=true;
9056 							refs.push_back(func);
9057 						}
9058 					}
9059 				}
9060 			}
9061 		}
9062 		else if(obj_types[i]==ObjectType::Operator)
9063 		{
9064 			while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
9065 			{
9066 				oper=dynamic_cast<Operator *>(*itr);
9067 				itr++;
9068 
9069 				if(oper->getArgumentType(Operator::LeftArg)==ptr_pgsqltype ||
9070 						oper->getArgumentType(Operator::RightArg)==ptr_pgsqltype)
9071 				{
9072 					refer=true;
9073 					refs.push_back(oper);
9074 				}
9075 			}
9076 		}
9077 		else if(obj_types[i]==ObjectType::Cast)
9078 		{
9079 			while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
9080 			{
9081 				cast=dynamic_cast<Cast *>(*itr);
9082 				itr++;
9083 
9084 				if(cast->getDataType(Cast::SrcType)==ptr_pgsqltype ||
9085 						cast->getDataType(Cast::DstType)==ptr_pgsqltype)
9086 				{
9087 					refer=true;
9088 					refs.push_back(cast);
9089 				}
9090 			}
9091 		}
9092 	}
9093 }
9094 
getRoleReferences(BaseObject * object,vector<BaseObject * > & refs,bool & refer,bool exclusion_mode)9095 void DatabaseModel::getRoleReferences(BaseObject *object, vector<BaseObject *> &refs, bool &refer, bool exclusion_mode)
9096 {
9097 	vector<BaseObject *> *obj_list=nullptr;
9098 	vector<BaseObject *>::iterator itr, itr_end;
9099 	vector<ObjectType> obj_types = {
9100 								ObjectType::Function, ObjectType::Table, ObjectType::ForeignTable, ObjectType::Domain,
9101 								ObjectType::Aggregate, ObjectType::Schema, ObjectType::Operator,
9102 								ObjectType::Sequence, ObjectType::Conversion,
9103 								ObjectType::Language, ObjectType::Tablespace,
9104 								ObjectType::Type, ObjectType::OpFamily, ObjectType::OpClass,
9105 								ObjectType::UserMapping };
9106 	vector<ObjectType>::iterator itr_tp, itr_tp_end;
9107 	unsigned i,i1, count;
9108 	Role *role_aux=nullptr;
9109 	Role *role=dynamic_cast<Role *>(object);
9110 	unsigned role_types[3]={Role::RefRole, Role::MemberRole, Role::AdminRole};
9111 	Permission *perm=nullptr;
9112 
9113 	//Check if the role is being referencend by permissions
9114 	itr=permissions.begin();
9115 	itr_end=permissions.end();
9116 	while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
9117 	{
9118 		perm=dynamic_cast<Permission *>(*itr);
9119 		itr++;
9120 
9121 		if(perm->isRoleExists(role))
9122 		{
9123 			refer=true;
9124 			refs.push_back(perm);
9125 		}
9126 	}
9127 
9128 	//Check if the role is being referenced in other roles
9129 	itr=roles.begin();
9130 	itr_end=roles.end();
9131 	while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
9132 	{
9133 		role_aux=dynamic_cast<Role *>(*itr);
9134 		itr++;
9135 
9136 		for(i1=0; i1 < 3 && (!exclusion_mode || (exclusion_mode && !refer)); i1++)
9137 		{
9138 			count=role_aux->getRoleCount(role_types[i1]);
9139 			for(i=0; i < count && !refer; i++)
9140 			{
9141 				if(role_aux->getRole(role_types[i1], i)==role)
9142 				{
9143 					refer=true;
9144 					refs.push_back(role_aux);
9145 				}
9146 			}
9147 		}
9148 	}
9149 
9150 	itr_tp = obj_types.begin();
9151 	itr_tp_end = obj_types.end();
9152 
9153 	while(itr_tp != itr_tp_end && (!exclusion_mode || (exclusion_mode && !refer)))
9154 	{
9155 		obj_list=getObjectList(*itr_tp);
9156 		itr_tp++;
9157 
9158 		itr=obj_list->begin();
9159 		itr_end=obj_list->end();
9160 
9161 		while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
9162 		{
9163 			if((*itr)->getOwner()==role)
9164 			{
9165 				refer=true;
9166 				refs.push_back(*itr);
9167 			}
9168 
9169 			if((*itr)->getObjectType() == ObjectType::Table)
9170 			{
9171 				for(auto obj : *(dynamic_cast<Table *>(*itr))->getObjectList(ObjectType::Policy))
9172 				{
9173 					if(dynamic_cast<Policy *>(obj)->isRoleExists(role))
9174 					{
9175 						refer=true;
9176 						refs.push_back(obj);
9177 					}
9178 				}
9179 			}
9180 
9181 			itr++;
9182 		}
9183 	}
9184 
9185 	//Special case: check if the role to be removed is the owner of the database
9186 	if((!exclusion_mode || (exclusion_mode && !refer)) && this->getOwner()==role)
9187 	{
9188 		refer=true;
9189 		refs.push_back(this);
9190 	}
9191 }
9192 
getTablespaceReferences(BaseObject * object,vector<BaseObject * > & refs,bool & refer,bool exclusion_mode)9193 void DatabaseModel::getTablespaceReferences(BaseObject *object, vector<BaseObject *> &refs, bool &refer, bool exclusion_mode)
9194 {
9195 	vector<BaseObject *>::iterator itr, itr_end;
9196 	unsigned i, count;
9197 	Table *tab=nullptr;
9198 	Index *ind=nullptr;
9199 	Constraint *rest=nullptr;
9200 
9201 	itr=tables.begin();
9202 	itr_end=tables.end();
9203 
9204 	while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
9205 	{
9206 		tab=dynamic_cast<Table *>(*itr);
9207 
9208 		if(tab->getTablespace()==object)
9209 		{
9210 			refer=true;
9211 			refs.push_back(tab);
9212 		}
9213 
9214 		count=tab->getIndexCount();
9215 		for(i=0; i < count && (!exclusion_mode || (exclusion_mode && !refer)); i++)
9216 		{
9217 			ind=tab->getIndex(i);
9218 			if(ind->getTablespace()==object)
9219 			{
9220 				refer=true;
9221 				refs.push_back(ind);
9222 			}
9223 		}
9224 
9225 		count=tab->getConstraintCount();
9226 		for(i=0; i < count && (!exclusion_mode || (exclusion_mode && !refer)); i++)
9227 		{
9228 			rest=tab->getConstraint(i);
9229 			if(rest->getTablespace()==object)
9230 			{
9231 				refer=true;
9232 				refs.push_back(rest);
9233 			}
9234 		}
9235 
9236 		itr++;
9237 	}
9238 
9239 	if((!exclusion_mode || (exclusion_mode && !refer)) && this->BaseObject::getTablespace()==object)
9240 	{
9241 		refer=true;
9242 		refs.push_back(this);
9243 	}
9244 }
9245 
getLanguageReferences(BaseObject * object,vector<BaseObject * > & refs,bool & refer,bool exclusion_mode)9246 void DatabaseModel::getLanguageReferences(BaseObject *object, vector<BaseObject *> &refs, bool &refer, bool exclusion_mode)
9247 {
9248 	vector<BaseObject *>::iterator itr, itr_end;
9249 	Function *func=nullptr;
9250 
9251 	itr=functions.begin();
9252 	itr_end=functions.end();
9253 
9254 	while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
9255 	{
9256 		func=dynamic_cast<Function *>(*itr);
9257 		if(func->getLanguage()==object)
9258 		{
9259 			refer=true;
9260 			refs.push_back(func);
9261 		}
9262 		itr++;
9263 	}
9264 }
9265 
getOpClassReferences(BaseObject * object,vector<BaseObject * > & refs,bool & refer,bool exclusion_mode)9266 void DatabaseModel::getOpClassReferences(BaseObject *object, vector<BaseObject *> &refs, bool &refer, bool exclusion_mode)
9267 {
9268 	vector<BaseObject *>::iterator itr, itr_end;
9269 	Type *usertype=nullptr;
9270 	Index *ind=nullptr;
9271 	Constraint *constr=nullptr;
9272 	Table *table=nullptr;
9273 	ForeignTable *ftable=nullptr;
9274 
9275 	itr=types.begin();
9276 	itr_end=types.end();
9277 
9278 	while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
9279 	{
9280 		usertype=dynamic_cast<Type *>(*itr);
9281 
9282 		if(usertype->getSubtypeOpClass()==object)
9283 		{
9284 			refer=true;
9285 			refs.push_back(usertype);
9286 		}
9287 		itr++;
9288 	}
9289 
9290 	itr=tables.begin();
9291 	itr_end=tables.end();
9292 	while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
9293 	{
9294 		table=dynamic_cast<Table *>(*itr);
9295 
9296 		//Checking if the indexes are referencing the operator class
9297 		for(unsigned idx=0; idx < table->getIndexCount() &&
9298 			(!exclusion_mode || (exclusion_mode && !refer)); idx++)
9299 		{
9300 			ind=table->getIndex(idx);
9301 
9302 			for(unsigned id_elem=0; id_elem < ind->getIndexElementCount() &&
9303 				(!exclusion_mode || (exclusion_mode && !refer)); id_elem++)
9304 			{
9305 				if(ind->getIndexElement(id_elem).getOperatorClass()==object)
9306 				{
9307 					refer=true;
9308 					refs.push_back(ind);
9309 				}
9310 			}
9311 		}
9312 
9313 		//Checking if the constraints are referencing the operator class
9314 		for(unsigned idx=0; idx < table->getConstraintCount() &&
9315 			(!exclusion_mode || (exclusion_mode && !refer)); idx++)
9316 		{
9317 			constr=table->getConstraint(idx);
9318 
9319 			for(unsigned id_elem=0; id_elem < constr->getExcludeElementCount() &&
9320 				(!exclusion_mode || (exclusion_mode && !refer)); id_elem++)
9321 			{
9322 				if(constr->getExcludeElement(id_elem).getOperatorClass()==object)
9323 				{
9324 					refer=true;
9325 					refs.push_back(constr);
9326 				}
9327 			}
9328 		}
9329 
9330 		//Checking if the partition keys are referencing the operator class
9331 		for(auto &part_key : table->getPartitionKeys())
9332 		{
9333 			if(part_key.getOperatorClass() == object)
9334 			{
9335 				refer = true;
9336 				refs.push_back(table);
9337 				break;
9338 			}
9339 		}
9340 
9341 		itr++;
9342 	}
9343 
9344 
9345 	itr=foreign_tables.begin();
9346 	itr_end=foreign_tables.end();
9347 	while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
9348 	{
9349 		ftable=dynamic_cast<ForeignTable *>(*itr);
9350 
9351 		//Checking if the partition keys are referencing the operator class
9352 		for(auto &part_key : ftable->getPartitionKeys())
9353 		{
9354 			if(part_key.getOperatorClass() == object)
9355 			{
9356 				refer = true;
9357 				refs.push_back(ftable);
9358 				break;
9359 			}
9360 		}
9361 
9362 		itr++;
9363 	}
9364 }
9365 
getOperatorReferences(BaseObject * object,vector<BaseObject * > & refs,bool & refer,bool exclusion_mode)9366 void DatabaseModel::getOperatorReferences(BaseObject *object, vector<BaseObject *> &refs, bool &refer, bool exclusion_mode)
9367 {
9368 	vector<BaseObject *> *obj_list=nullptr;
9369 	vector<BaseObject *>::iterator itr, itr_end;
9370 	ObjectType obj_types[]={ObjectType::OpClass,
9371 													ObjectType::Aggregate,
9372 													ObjectType::Operator,
9373 													ObjectType::Table };
9374 	unsigned i, i1, count;
9375 	OperatorClass *op_class=nullptr;
9376 	Operator *oper_aux=nullptr, *oper=dynamic_cast<Operator *>(object);
9377 	Table *table=nullptr;
9378 	Constraint *constr=nullptr;
9379 
9380 	for(i=0; i < 4 && (!exclusion_mode || (exclusion_mode && !refer)); i++)
9381 	{
9382 		obj_list=getObjectList(obj_types[i]);
9383 		itr=obj_list->begin();
9384 		itr_end=obj_list->end();
9385 
9386 		if(obj_types[i]==ObjectType::OpClass)
9387 		{
9388 			while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
9389 			{
9390 				op_class=dynamic_cast<OperatorClass *>(*itr);
9391 				itr++;
9392 
9393 				count=op_class->getElementCount();
9394 				for(i1=0; i1 < count && (!exclusion_mode || (exclusion_mode && !refer)); i1++)
9395 				{
9396 					if(op_class->getElement(i1).getOperator()==oper)
9397 					{
9398 						refer=true;
9399 						refs.push_back(op_class);
9400 					}
9401 				}
9402 			}
9403 		}
9404 		else if(obj_types[i]==ObjectType::Aggregate)
9405 		{
9406 			while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
9407 			{
9408 				if(dynamic_cast<Aggregate *>(*itr)->getSortOperator()==oper)
9409 				{
9410 					refer=true;
9411 					refs.push_back(*itr);
9412 				}
9413 				itr++;
9414 			}
9415 		}
9416 		else if(obj_types[i]==ObjectType::Operator)
9417 		{
9418 			while(itr!=itr_end && !refer)
9419 			{
9420 				oper_aux=dynamic_cast<Operator *>(*itr);
9421 				itr++;
9422 
9423 				for(i1=Operator::OperCommutator; i1 <= Operator::OperNegator &&
9424 					(!exclusion_mode || (exclusion_mode && !refer)); i1++)
9425 				{
9426 					if(oper_aux->getOperator(i1)==oper)
9427 					{
9428 						refer=true;
9429 						refs.push_back(oper_aux);
9430 					}
9431 				}
9432 			}
9433 		}
9434 		else
9435 		{
9436 			while(itr!=itr_end && !refer)
9437 			{
9438 				table=dynamic_cast<Table *>(*itr);
9439 				itr++;
9440 
9441 				count=table->getConstraintCount();
9442 				for(i1=0; i1 < count && (!exclusion_mode || (exclusion_mode && !refer)); i1++)
9443 				{
9444 					constr=table->getConstraint(i1);
9445 
9446 					if(constr->getConstraintType()==ConstraintType::Exclude)
9447 					{
9448 						for(auto &elem : constr->getExcludeElements())
9449 						{
9450 							if(elem.getOperator()==oper)
9451 							{
9452 								refer=true;
9453 								refs.push_back(constr);
9454 								if(exclusion_mode) break;
9455 							}
9456 						}
9457 					}
9458 				}
9459 			}
9460 		}
9461 	}
9462 }
9463 
getCollationReferences(BaseObject * object,vector<BaseObject * > & refs,bool & refer,bool exclusion_mode)9464 void DatabaseModel::getCollationReferences(BaseObject *object, vector<BaseObject *> &refs, bool &refer, bool exclusion_mode)
9465 {
9466 	ObjectType  obj_types[]={ ObjectType::Domain, ObjectType::Collation, ObjectType::Type },
9467 			tab_obj_types[]={ ObjectType::Column, ObjectType::Index };
9468 	unsigned i, count;
9469 	vector<BaseObject *> *obj_list=nullptr;
9470 	vector<BaseObject *>::iterator itr, itr_end;
9471 	vector<TableObject *> *tab_obj_list=nullptr;
9472 	vector<TableObject *>::iterator tab_itr, tab_itr_end;
9473 	TableObject *tab_obj=nullptr;
9474 	PhysicalTable *table = nullptr;
9475 
9476 	count=sizeof(obj_types)/sizeof(ObjectType);
9477 	for(i=0; i < count && (!exclusion_mode || (exclusion_mode && !refer)); i++)
9478 	{
9479 		obj_list=getObjectList(obj_types[i]);
9480 		itr=obj_list->begin();
9481 		itr_end=obj_list->end();
9482 
9483 		while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
9484 		{
9485 			if((*itr)->getCollation()==object)
9486 			{
9487 				refer=true;
9488 				refs.push_back(*itr);
9489 			}
9490 
9491 			itr++;
9492 		}
9493 	}
9494 
9495 	count=sizeof(tab_obj_types)/sizeof(ObjectType);
9496 	vector<BaseObject *> tabs;
9497 
9498 	tabs.insert(tabs.end(), tables.begin(), tables.end());
9499 	tabs.insert(tabs.end(), foreign_tables.begin(), foreign_tables.end());
9500 	itr=tabs.begin();
9501 	itr_end=tabs.end();
9502 
9503 	while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
9504 	{
9505 		table = dynamic_cast<PhysicalTable *>(*itr);
9506 
9507 		for(i=0; i < count && (!exclusion_mode || (exclusion_mode && !refer)); i++)
9508 		{
9509 			tab_obj_list = table->getObjectList(tab_obj_types[i]);
9510 			if(!tab_obj_list) continue;
9511 
9512 			tab_itr=tab_obj_list->begin();
9513 			tab_itr_end=tab_obj_list->end();
9514 
9515 			while(tab_itr!=tab_itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
9516 			{
9517 				tab_obj=(*tab_itr);
9518 				if((tab_obj->getObjectType()==ObjectType::Column && tab_obj->getCollation()==object) ||
9519 						(tab_obj->getObjectType()==ObjectType::Index &&
9520 						 dynamic_cast<Index *>(tab_obj)->isReferCollation(dynamic_cast<Collation *>(object))))
9521 				{
9522 					refer=true;
9523 					refs.push_back(*tab_itr);
9524 				}
9525 				tab_itr++;
9526 			}
9527 		}
9528 
9529 		//Checking if the partition keys are referencing the operator class
9530 		for(auto &part_key : table->getPartitionKeys())
9531 		{
9532 			if(part_key.getCollation() == object)
9533 			{
9534 				refer = true;
9535 				refs.push_back(table);
9536 				break;
9537 			}
9538 		}
9539 
9540 		itr++;
9541 	}
9542 }
9543 
getOpFamilyReferences(BaseObject * object,vector<BaseObject * > & refs,bool & refer,bool exclusion_mode)9544 void DatabaseModel::getOpFamilyReferences(BaseObject *object, vector<BaseObject *> &refs, bool &refer, bool exclusion_mode)
9545 {
9546 	vector<BaseObject *>::iterator itr, itr_end;
9547 	OperatorFamily *op_family=dynamic_cast<OperatorFamily *>(object);
9548 
9549 	itr=op_classes.begin();
9550 	itr_end=op_classes.end();
9551 
9552 	while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
9553 	{
9554 		if(dynamic_cast<OperatorClass *>(*itr)->getFamily()==op_family)
9555 		{
9556 			refer=true;
9557 			refs.push_back(*itr);
9558 		}
9559 		itr++;
9560 	}
9561 }
9562 
getColumnReferences(BaseObject * object,vector<BaseObject * > & refs,bool & refer,bool exclusion_mode)9563 void DatabaseModel::getColumnReferences(BaseObject *object, vector<BaseObject *> &refs, bool &refer, bool exclusion_mode)
9564 {
9565 	Column *column=dynamic_cast<Column *>(object);
9566 	vector<BaseObject *> *obj_list=nullptr;
9567 	vector<BaseObject *>::iterator itr, itr_end;
9568 	ObjectType  obj_types[]={ ObjectType::Sequence, ObjectType::View, ObjectType::Table,
9569 														ObjectType::ForeignTable, ObjectType::Relationship };
9570 	unsigned i, count=sizeof(obj_types)/sizeof(ObjectType);
9571 
9572 	for(i=0; i < count && (!exclusion_mode || (exclusion_mode && !refer)); i++)
9573 	{
9574 		obj_list=getObjectList(obj_types[i]);
9575 		itr=obj_list->begin();
9576 		itr_end=obj_list->end();
9577 
9578 		while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
9579 		{
9580 			if((obj_types[i]==ObjectType::Sequence && dynamic_cast<Sequence *>(*itr)->getOwnerColumn()==column) ||
9581 					(obj_types[i]==ObjectType::View && dynamic_cast<View *>(*itr)->isReferencingColumn(column)))
9582 			{
9583 				refer=true;
9584 				refs.push_back(*itr);
9585 			}
9586 			else if(obj_types[i]==ObjectType::Table || obj_types[i]==ObjectType::ForeignTable)
9587 			{
9588 				PhysicalTable *tab=dynamic_cast<PhysicalTable *>(*itr);
9589 				Table *aux_tab = dynamic_cast<Table *>(tab);
9590 				unsigned count, idx, count1, i1;
9591 				Trigger *trig=nullptr;
9592 				Index *index=nullptr;
9593 				Constraint *constr=nullptr;
9594 				vector<PartitionKey> part_keys;
9595 
9596 				count=tab->getConstraintCount();
9597 				for(idx=0; idx < count && (!exclusion_mode || (exclusion_mode && !refer)); idx++)
9598 				{
9599 					constr=tab->getConstraint(idx);
9600 					if(constr->isColumnReferenced(column))
9601 					{
9602 						refer=true;
9603 						refs.push_back(constr);
9604 					}
9605 				}
9606 
9607 				if(aux_tab)
9608 				{
9609 					count=aux_tab->getIndexCount();
9610 					for(idx=0; idx < count && (!exclusion_mode || (exclusion_mode && !refer)); idx++)
9611 					{
9612 						index=aux_tab->getIndex(idx);
9613 						if(index->isReferColumn(column))
9614 						{
9615 							refer=true;
9616 							refs.push_back(index);
9617 						}
9618 					}
9619 				}
9620 
9621 				count=tab->getTriggerCount();
9622 				for(idx=0; idx < count && (!exclusion_mode || (exclusion_mode && !refer)); idx++)
9623 				{
9624 					trig=tab->getTrigger(idx);
9625 					count1=trig->getColumnCount();
9626 
9627 					for(i1=0; i1 < count1 && (!exclusion_mode || (exclusion_mode && !refer)); i1++)
9628 					{
9629 						if(trig->getColumn(i1)==column)
9630 						{
9631 							refer=true;
9632 							refs.push_back(trig);
9633 						}
9634 					}
9635 				}
9636 
9637 				part_keys = tab->getPartitionKeys();
9638 				for(auto &part_key : part_keys)
9639 				{
9640 					if(part_key.getColumn() == column)
9641 					{
9642 						refer = true;
9643 						refs.push_back(tab);
9644 						break;
9645 					}
9646 				}
9647 			}
9648 			else if(obj_types[i]==ObjectType::Relationship)
9649 			{
9650 				Relationship *rel=dynamic_cast<Relationship *>(*itr);
9651 				unsigned constr_cnt, idx;
9652 
9653 				constr_cnt=rel->getConstraintCount();
9654 				for(idx=0; idx < constr_cnt && (!exclusion_mode || (exclusion_mode && !refer)); idx++)
9655 				{
9656 					if(rel->getConstraint(idx)->isColumnReferenced(column))
9657 					{
9658 						refer=true;
9659 						refs.push_back(rel);
9660 					}
9661 				}
9662 			}
9663 
9664 			itr++;
9665 		}
9666 	}
9667 }
9668 
getTagReferences(BaseObject * object,vector<BaseObject * > & refs,bool & refer,bool exclusion_mode)9669 void DatabaseModel::getTagReferences(BaseObject *object, vector<BaseObject *> &refs, bool &refer, bool exclusion_mode)
9670 {
9671 	vector<BaseObject *>::iterator itr, itr_end;
9672 	vector<BaseObject *> list;
9673 	Tag *tag=dynamic_cast<Tag *>(object);
9674 
9675 	list.assign(tables.begin(), tables.end());
9676 	list.insert(list.end(), foreign_tables.begin(), foreign_tables.end());
9677 	list.insert(list.end(), views.begin(), views.end());
9678 
9679 	itr=list.begin();
9680 	itr_end=list.end();
9681 
9682 	while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
9683 	{
9684 		if(dynamic_cast<BaseTable *>(*itr)->getTag()==tag)
9685 		{
9686 			refer=true;
9687 			refs.push_back(*itr);
9688 		}
9689 		itr++;
9690 	}
9691 }
9692 
getSequenceReferences(BaseObject * object,vector<BaseObject * > & refs,bool & refer,bool exclusion_mode)9693 void DatabaseModel::getSequenceReferences(BaseObject *object, vector<BaseObject *> &refs, bool &refer, bool exclusion_mode)
9694 {
9695 	PhysicalTable *table=nullptr;
9696 	vector<TableObject *> *cols=nullptr;
9697 	vector<TableObject *>::iterator itr, itr_end;
9698 	vector<BaseObject *> tabs;
9699 	unsigned i = 0, cnt = 0;
9700 
9701 	tabs = tables;
9702 	tabs.insert(tabs.end(), foreign_tables.begin(), foreign_tables.end());
9703 	cnt = tabs.size();
9704 
9705 	for(i=0; i < cnt && (!exclusion_mode || (exclusion_mode && !refer)); i++)
9706 	{
9707 		table=dynamic_cast<PhysicalTable *>(tabs[i]);
9708 		cols=table->getObjectList(ObjectType::Column);
9709 		itr=cols->begin();
9710 		itr_end=cols->end();
9711 
9712 		while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
9713 		{
9714 			if(dynamic_cast<Column *>(*itr)->getSequence()==object)
9715 			{
9716 				refer=true;
9717 				refs.push_back(*itr);
9718 			}
9719 			itr++;
9720 		}
9721 	}
9722 }
9723 
getFdwReferences(BaseObject * object,vector<BaseObject * > & refs,bool & refer,bool exclusion_mode)9724 void DatabaseModel::getFdwReferences(BaseObject *object, vector<BaseObject *> &refs, bool &refer, bool exclusion_mode)
9725 {
9726 	vector<BaseObject *>::iterator itr, itr_end;
9727 	vector<BaseObject *> list;
9728 	ForeignDataWrapper *fdw=dynamic_cast<ForeignDataWrapper *>(object);
9729 
9730 	itr=foreign_servers.begin();
9731 	itr_end=foreign_servers.end();
9732 
9733 	while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
9734 	{
9735 		if(dynamic_cast<ForeignServer *>(*itr)->getForeignDataWrapper() == fdw)
9736 		{
9737 			refer=true;
9738 			refs.push_back(*itr);
9739 		}
9740 		itr++;
9741 	}
9742 }
9743 
getServerReferences(BaseObject * object,vector<BaseObject * > & refs,bool & refer,bool exclusion_mode)9744 void DatabaseModel::getServerReferences(BaseObject *object, vector<BaseObject *> &refs, bool &refer, bool exclusion_mode)
9745 {
9746 	vector<BaseObject *>::iterator itr, itr_end;
9747 	vector<BaseObject *> list;
9748 	ForeignServer *srv=dynamic_cast<ForeignServer *>(object);
9749 
9750 	itr=usermappings.begin();
9751 	itr_end=usermappings.end();
9752 
9753 	while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
9754 	{
9755 		if(dynamic_cast<UserMapping *>(*itr)->getForeignServer() == srv)
9756 		{
9757 			refer=true;
9758 			refs.push_back(*itr);
9759 		}
9760 		itr++;
9761 	}
9762 
9763 	itr=foreign_tables.begin();
9764 	itr_end=foreign_tables.end();
9765 
9766 	while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
9767 	{
9768 		if(dynamic_cast<ForeignTable *>(*itr)->getForeignServer() == srv)
9769 		{
9770 			refer=true;
9771 			refs.push_back(*itr);
9772 		}
9773 		itr++;
9774 	}
9775 }
9776 
getObjectReferences(BaseObject * object,vector<BaseObject * > & refs,bool exclusion_mode,bool exclude_perms)9777 void DatabaseModel::getObjectReferences(BaseObject *object, vector<BaseObject *> &refs, bool exclusion_mode, bool exclude_perms)
9778 {
9779 	refs.clear();
9780 
9781 	if(!object)
9782 		return;
9783 
9784 	vector<BaseObject *>::iterator itr_perm, itr_perm_end;
9785 	ObjectType obj_type=object->getObjectType();
9786 	bool refer=false;
9787 	Permission *perm=nullptr;
9788 
9789 	if(!exclude_perms)
9790 	{
9791 		//Get the permissions thata references the object
9792 		itr_perm=permissions.begin();
9793 		itr_perm_end=permissions.end();
9794 
9795 		while(itr_perm!=itr_perm_end && (!exclusion_mode || (exclusion_mode && !refer)))
9796 		{
9797 			perm=dynamic_cast<Permission *>(*itr_perm);
9798 			if(perm->getObject()==object)
9799 			{
9800 				refer=true;
9801 				refs.push_back(perm);
9802 			}
9803 			itr_perm++;
9804 		}
9805 	}
9806 
9807 	if(exclusion_mode && !refer && default_objs.count(obj_type) && default_objs[obj_type]==object)
9808 	{
9809 		refer=true;
9810 		refs.push_back(this);
9811 	}
9812 
9813 	if(obj_type==ObjectType::View && (!exclusion_mode || (exclusion_mode && !refer)))
9814 		getViewReferences(object, refs, exclusion_mode);
9815 
9816 	if(PhysicalTable::isPhysicalTable(obj_type) && (!exclusion_mode || (exclusion_mode && !refer)))
9817 		getPhysicalTableReferences(object, refs, refer, exclusion_mode);
9818 
9819 	if(obj_type==ObjectType::Function && (!exclusion_mode || (exclusion_mode && !refer)))
9820 		getFunctionReferences(object, refs, refer, exclusion_mode);
9821 
9822 	if(obj_type==ObjectType::Schema && (!exclusion_mode || (exclusion_mode && !refer)))
9823 		getSchemaReferences(object, refs, refer, exclusion_mode);
9824 
9825 	if((obj_type==ObjectType::Type || obj_type==ObjectType::Domain || obj_type==ObjectType::Sequence ||
9826 			obj_type==ObjectType::Extension || BaseTable::isBaseTable(obj_type))
9827 			&& (!exclusion_mode || (exclusion_mode && !refer)))
9828 		getUserDefTypesReferences(object, refs, refer, exclusion_mode);
9829 
9830 	if(obj_type==ObjectType::Role && (!exclusion_mode || (exclusion_mode && !refer)))
9831 		getRoleReferences(object, refs, refer, exclusion_mode);
9832 
9833 	if(obj_type==ObjectType::Tablespace && (!exclusion_mode || (exclusion_mode && !refer)))
9834 		getTablespaceReferences(object, refs, refer, exclusion_mode);
9835 
9836 	if(obj_type==ObjectType::Language && (!exclusion_mode || (exclusion_mode && !refer)))
9837 		getLanguageReferences(object, refs, refer, exclusion_mode);
9838 
9839 	if(obj_type==ObjectType::OpClass && (!exclusion_mode || (exclusion_mode && !refer)))
9840 		getOpClassReferences(object, refs, refer, exclusion_mode);
9841 
9842 	if(obj_type==ObjectType::Operator && (!exclusion_mode || (exclusion_mode && !refer)))
9843 		getOperatorReferences(object, refs, refer, exclusion_mode);
9844 
9845 	if(obj_type==ObjectType::OpFamily && (!exclusion_mode || (exclusion_mode && !refer)))
9846 		getOpFamilyReferences(object, refs, refer, exclusion_mode);
9847 
9848 	if(obj_type==ObjectType::Collation && (!exclusion_mode || (exclusion_mode && !refer)))
9849 		getCollationReferences(object, refs, refer, exclusion_mode);
9850 
9851 	if(obj_type==ObjectType::Column && (!exclusion_mode || (exclusion_mode && !refer)))
9852 		getColumnReferences(object, refs, refer, exclusion_mode);
9853 
9854 	if(obj_type==ObjectType::Tag && (!exclusion_mode || (exclusion_mode && !refer)))
9855 		getTagReferences(object, refs, refer, exclusion_mode);
9856 
9857 	if(obj_type==ObjectType::Sequence && (!exclusion_mode || (exclusion_mode && !refer)))
9858 		getSequenceReferences(object, refs, refer, exclusion_mode);
9859 
9860 	if(obj_type==ObjectType::ForeignDataWrapper && (!exclusion_mode || (exclusion_mode && !refer)))
9861 		getFdwReferences(object, refs, refer, exclusion_mode);
9862 
9863 	if(obj_type==ObjectType::ForeignServer && (!exclusion_mode || (exclusion_mode && !refer)))
9864 		getServerReferences(object, refs, refer, exclusion_mode);
9865 
9866 	// Checking if any generic SQL object is referencing the object passed
9867 	vector<BaseObject *>::iterator itr = genericsqls.begin(),
9868 			itr_end = genericsqls.end();
9869 
9870 	while(itr != itr_end && (!exclusion_mode || (exclusion_mode && !refer)))
9871 	{
9872 		if(dynamic_cast<GenericSQL *>(*itr)->isObjectReferenced(object))
9873 		{
9874 			refer = true;
9875 			refs.push_back(*itr);
9876 		}
9877 
9878 		itr++;
9879 	}
9880 }
9881 
__getObjectReferences(BaseObject * object,vector<BaseObject * > & refs,bool exclude_perms)9882 void DatabaseModel::__getObjectReferences(BaseObject *object, vector<BaseObject *> &refs, bool exclude_perms)
9883 {
9884 	vector<BaseObject *> refs_aux;
9885 	vector<BaseObject *>::iterator end;
9886 
9887 	getObjectReferences(object, refs_aux, exclude_perms);
9888 
9889 	if(!refs_aux.empty())
9890 	{
9891 		refs.insert(refs.end(), refs_aux.begin(), refs_aux.end());
9892 		std::sort(refs.begin(), refs.end());
9893 		end=std::unique(refs.begin(), refs.end());
9894 		refs.erase(end, refs.end());
9895 
9896 		for(BaseObject *obj : refs_aux)
9897 			__getObjectReferences(obj, refs, exclude_perms);
9898 	}
9899 }
9900 
setObjectsModified(vector<BaseObject * > & objects)9901 void DatabaseModel::setObjectsModified(vector<BaseObject *> &objects)
9902 {
9903 	for(auto &obj : objects)
9904 	{
9905 		if(BaseGraphicObject::isGraphicObject(obj->getObjectType()))
9906 			dynamic_cast<BaseGraphicObject *>(obj)->setModified(true);
9907 	}
9908 }
9909 
setObjectsModified(vector<ObjectType> types)9910 void DatabaseModel::setObjectsModified(vector<ObjectType> types)
9911 {
9912 	ObjectType obj_types[]={ObjectType::Table, ObjectType::View, ObjectType::ForeignTable,
9913 							ObjectType::Relationship, ObjectType::BaseRelationship,
9914 							ObjectType::Textbox, ObjectType::Schema };
9915 	vector<BaseObject *>::iterator itr, itr_end;
9916 	vector<BaseObject *> *obj_list=nullptr;
9917 	Textbox *label=nullptr;
9918 	BaseRelationship *rel=nullptr;
9919 	unsigned i, i1, count=sizeof(obj_types)/sizeof(ObjectType);
9920 
9921 	for(i=0; i < count; i++)
9922 	{
9923 		if(types.empty() || find(types.begin(), types.end(), obj_types[i])!=types.end())
9924 		{
9925 			obj_list=getObjectList(obj_types[i]);
9926 			itr=obj_list->begin();
9927 			itr_end=obj_list->end();
9928 
9929 			while(itr!=itr_end)
9930 			{
9931 				dynamic_cast<BaseGraphicObject *>(*itr)->setModified(true);
9932 
9933 				//For relationships is needed to set the labels as modified too
9934 				if(obj_types[i]==ObjectType::Relationship || obj_types[i]==ObjectType::BaseRelationship)
9935 				{
9936 					rel=dynamic_cast<BaseRelationship *>(*itr);
9937 					for(i1=0; i1 < 3; i1++)
9938 					{
9939 						label=rel->getLabel(i1);
9940 						if(label) label->setModified(true);
9941 					}
9942 				}
9943 
9944 				itr++;
9945 			}
9946 		}
9947 	}
9948 }
9949 
setCodesInvalidated(vector<ObjectType> types)9950 void DatabaseModel::setCodesInvalidated(vector<ObjectType> types)
9951 {
9952 	vector<ObjectType> sel_types;
9953 	vector<BaseObject *> *list=nullptr;
9954 
9955 	if(types.empty())
9956 		sel_types=BaseObject::getObjectTypes(false);
9957 	else
9958 	{
9959 		ObjectType tab_obj_types[]={ObjectType::Column, ObjectType::Constraint,
9960 									ObjectType::Trigger, ObjectType::Rule, ObjectType::Index, ObjectType::Policy};
9961 		for(unsigned i=0; i < 6; i++)
9962 			sel_types.erase(std::find(sel_types.begin(), sel_types.end(), tab_obj_types[i]));
9963 
9964 		sel_types=types;
9965 	}
9966 
9967 	while(!sel_types.empty())
9968 	{
9969 		list=getObjectList(sel_types.back());
9970 		sel_types.pop_back();
9971 
9972 		if(list)
9973 		{
9974 			for(auto &obj : *list)
9975 				obj->setCodeInvalidated(true);
9976 		}
9977 	}
9978 }
9979 
getObjectPgSQLType(PgSqlType type)9980 BaseObject *DatabaseModel::getObjectPgSQLType(PgSqlType type)
9981 {
9982 	switch(type.getUserTypeConfig())
9983 	{
9984 		case UserTypeConfig::BaseType:
9985 		return this->getObject(*type, ObjectType::Type);
9986 
9987 		case UserTypeConfig::DomainType:
9988 		return this->getObject(*type, ObjectType::Domain);
9989 
9990 		case UserTypeConfig::TableType:
9991 		return this->getObject(*type, ObjectType::Table);
9992 
9993 		case UserTypeConfig::ViewType:
9994 		return this->getObject(*type, ObjectType::View);
9995 
9996 		case UserTypeConfig::SequenceType:
9997 		return this->getObject(*type, ObjectType::Sequence);
9998 
9999 		case UserTypeConfig::ExtensionType:
10000 		return this->getObject(*type, ObjectType::Extension);
10001 
10002 		default:
10003 		return nullptr;
10004 	}
10005 }
10006 
validateSchemaRenaming(Schema * schema,const QString & prev_sch_name)10007 void DatabaseModel::validateSchemaRenaming(Schema *schema, const QString &prev_sch_name)
10008 {
10009 	vector<ObjectType> types = { ObjectType::Table, ObjectType::ForeignTable, ObjectType::View,
10010 															 ObjectType::Domain, ObjectType::Type, ObjectType::Sequence };
10011 	vector<BaseObject *> list, sch_objs, refs;
10012 	QString prev_name;
10013 
10014 	//Raise an error if the schema is not allocated
10015 	if(!schema)
10016 		throw Exception(ErrorCode::OprNotAllocatedObject,__PRETTY_FUNCTION__,__FILE__,__LINE__);
10017 
10018 	//Get all the objects on the informed schema
10019 	for(auto &type : types)
10020 	{
10021 		list = getObjects(type, schema);
10022 		sch_objs.insert(sch_objs.end(), list.begin(), list.end());
10023 	}
10024 
10025 	for(auto &obj : sch_objs)
10026 	{
10027 		//Configures the previous type name
10028 		prev_name=BaseObject::formatName(prev_sch_name) + QString(".") +
10029 							BaseObject::formatName(obj->getName(), false);
10030 
10031 		/* Special case for tables. Need to make a dynamic_cast before the reinterpret_cast to get
10032 		the correct reference to table */
10033 		if(obj->getObjectType() == ObjectType::Table)
10034 			PgSqlType::renameUserType(prev_name, reinterpret_cast<void *>(dynamic_cast<Table *>(obj)), obj->getName(true));
10035 		else if(obj->getObjectType() == ObjectType::View)
10036 			PgSqlType::renameUserType(prev_name, reinterpret_cast<void *>(dynamic_cast<View *>(obj)), obj->getName(true));
10037 		else if(obj->getObjectType() == ObjectType::ForeignTable)
10038 			PgSqlType::renameUserType(prev_name, reinterpret_cast<void *>(dynamic_cast<ForeignTable *>(obj)), obj->getName(true));
10039 		else
10040 			PgSqlType::renameUserType(prev_name, reinterpret_cast<void *>(obj), obj->getName(true));
10041 
10042 		getObjectReferences(obj, refs);
10043 
10044 		//For graphical objects set them as modified to redraw them
10045 		if(BaseTable::isBaseTable(obj->getObjectType()))
10046 			dynamic_cast<BaseGraphicObject *>(obj)->setModified(true);
10047 
10048 		for(auto &ref_obj : refs)
10049 		{
10050 			if(BaseTable::isBaseTable(ref_obj->getObjectType()))
10051 				dynamic_cast<BaseGraphicObject *>(ref_obj)->setModified(true);
10052 			else if(TableObject::isTableObject(ref_obj->getObjectType()))
10053 			{
10054 				BaseTable *tab = dynamic_cast<TableObject *>(ref_obj)->getParentTable();
10055 				tab->setModified(true);
10056 				tab->setCodeInvalidated(true);
10057 			}
10058 
10059 			ref_obj->setCodeInvalidated(true);
10060 		}
10061 
10062 		refs.clear();
10063 	}
10064 }
10065 
createSystemObjects(bool create_public)10066 void DatabaseModel::createSystemObjects(bool create_public)
10067 {
10068 	Schema *public_sch=nullptr, *pg_catalog=nullptr;
10069 	Language *lang=nullptr;
10070 	Tablespace *tbspace=nullptr;
10071 	QStringList langs={ DefaultLanguages::C, DefaultLanguages::Sql,
10072 											DefaultLanguages::PlPgsql, DefaultLanguages::Internal };
10073 	Role *postgres=nullptr;
10074 	Collation *collation=nullptr;
10075 	QString collnames[]={ "default", "C", "POSIX" };
10076 
10077 	/* The particular case is for public schema that is created only when the flag
10078 	is set. This because the public schema is written on model file even being
10079 	a system object. This strategy permits the user controls the schema rectangle behavior */
10080 	if(create_public && getObjectIndex(QString("public"), ObjectType::Schema) < 0)
10081 	{
10082 		public_sch=new Schema;
10083 		public_sch->setName(QString("public"));
10084 		public_sch->setSystemObject(true);
10085 		addSchema(public_sch);
10086 	}
10087 
10088 	//Create the pg_catalog schema in order to insert default collations in
10089 	pg_catalog=new Schema;
10090 	pg_catalog->BaseObject::setName(QString("pg_catalog"));
10091 	pg_catalog->setSystemObject(true);
10092 	addSchema(pg_catalog);
10093 
10094 	//Creating default collations
10095 	for(unsigned i=0; i < 3; i++)
10096 	{
10097 		collation=new Collation;
10098 		collation->setName(collnames[i]);
10099 		collation->setSchema(pg_catalog);
10100 		collation->setEncoding(EncodingType(QString("UTF8")));
10101 		collation->setLocale(QString("C"));
10102 		collation->setSystemObject(true);
10103 		addCollation(collation);
10104 	}
10105 
10106 	for(auto &lang_name : langs)
10107 	{
10108 		if(getObjectIndex(lang_name, ObjectType::Language) < 0)
10109 		{
10110 			lang = new Language;
10111 			lang->BaseObject::setName(lang_name);
10112 			lang->setSystemObject(true);
10113 			addLanguage(lang);
10114 		}
10115 	}
10116 
10117 	tbspace=new Tablespace;
10118 	tbspace->BaseObject::setName(QString("pg_global"));
10119 	tbspace->setDirectory(QString("_pg_global_dir_"));
10120 	tbspace->setSystemObject(true);
10121 	addTablespace(tbspace);
10122 
10123 	tbspace=new Tablespace;
10124 	tbspace->BaseObject::setName(QString("pg_default"));
10125 	tbspace->setDirectory(QString("_pg_default_dir_"));
10126 	tbspace->setSystemObject(true);
10127 	addTablespace(tbspace);
10128 
10129 	postgres=new Role;
10130 	postgres->setName(QString("postgres"));
10131 	postgres->setOption(Role::OpSuperuser, true);
10132 	postgres->setSystemObject(true);
10133 	addRole(postgres);
10134 
10135 	setDefaultObject(postgres);
10136 	setDefaultObject(getObject(QString("public"), ObjectType::Schema), ObjectType::Schema);
10137 }
10138 
findObjects(const QStringList & filters,const QString & search_attr)10139 vector<BaseObject *> DatabaseModel::findObjects(const QStringList &filters, const QString &search_attr)
10140 {
10141 	vector<BaseObject *> objects, aux_objs;
10142 	QString pattern, mode;
10143 	QStringList values, modes = { PgModelerNs::FilterWildcard, PgModelerNs::FilterRegExp };
10144 	ObjectType obj_type;
10145 	bool exact_match = false;
10146 
10147 	for(auto &filter : filters)
10148 	{
10149 		values = filter.split(PgModelerNs::FilterSeparator);
10150 
10151 		// Raises an error if the filter has an invalid field count
10152 		if(values.size() != 3)
10153 		{
10154 			throw Exception(Exception::getErrorMessage(ErrorCode::InvalidObjectFilter).arg(filter).arg(modes.join('|')),
10155 											ErrorCode::InvalidObjectFilter,__PRETTY_FUNCTION__,__FILE__,__LINE__);
10156 		}
10157 
10158 		obj_type = BaseObject::getObjectType(values[0]);
10159 		pattern = values[1];
10160 		mode = values[2];
10161 		exact_match = (mode == PgModelerNs::FilterWildcard && !pattern.contains(PgModelerNs::WildcardChar));
10162 
10163 		// Raises an error if the filter has an invalid object type, pattern or mode
10164 		if(obj_type == ObjectType::BaseObject || pattern.isEmpty() || !modes.contains(mode))
10165 		{
10166 			throw Exception(Exception::getErrorMessage(ErrorCode::InvalidObjectFilter).arg(filter).arg(modes.join('|')),
10167 											ErrorCode::InvalidObjectFilter,__PRETTY_FUNCTION__,__FILE__,__LINE__);
10168 		}
10169 
10170 		aux_objs = findObjects(pattern, { obj_type }, false, mode == PgModelerNs::FilterRegExp, exact_match, search_attr);
10171 		objects.insert(objects.end(), aux_objs.begin(), aux_objs.end());
10172 	}
10173 
10174 	std::sort(objects.begin(), objects.end());
10175 	vector<BaseObject *>::iterator end = std::unique(objects.begin(), objects.end());
10176 	objects.erase(end, objects.end());
10177 
10178 	return objects;
10179 }
10180 
findObjects(const QString & pattern,vector<ObjectType> types,bool case_sensitive,bool is_regexp,bool exact_match,const QString & search_attr)10181 vector<BaseObject *> DatabaseModel::findObjects(const QString &pattern, vector<ObjectType> types, bool case_sensitive, bool is_regexp, bool exact_match, const QString &search_attr)
10182 {
10183 	vector<BaseObject *> list, objs;
10184 	vector<BaseObject *>::iterator end;
10185 	vector<ObjectType>::iterator itr_tp=types.begin();
10186 	vector<BaseObject *> tables;
10187 	bool inc_tabs=false, inc_views=false;
10188 	ObjectType obj_type;
10189 	QRegExp regexp;
10190 	BaseObject *object = nullptr;
10191 	attribs_map srch_attribs;
10192 
10193 	//Configuring the regex style
10194 	regexp.setPattern(pattern);
10195 	regexp.setCaseSensitivity(case_sensitive ?  Qt::CaseSensitive :  Qt::CaseInsensitive);
10196 
10197 	if(is_regexp)
10198 		regexp.setPatternSyntax(QRegExp::RegExp2);
10199 	else if(exact_match)
10200 		regexp.setPatternSyntax(QRegExp::FixedString);
10201 	else
10202 		regexp.setPatternSyntax(QRegExp::Wildcard);
10203 
10204 	//If there is some table object types on the type list, gather tables and views
10205 	while(itr_tp!=types.end() && (!inc_views || !inc_tabs))
10206 	{
10207 		if(!inc_tabs && TableObject::isTableObject(*itr_tp))
10208 		{
10209 			tables.insert(tables.end(), getObjectList(ObjectType::Table)->begin(), getObjectList(ObjectType::Table)->end());
10210 			tables.insert(tables.end(), getObjectList(ObjectType::ForeignTable)->begin(), getObjectList(ObjectType::ForeignTable)->end());
10211 			inc_tabs=true;
10212 		}
10213 
10214 		if(!inc_views && ((*itr_tp)==ObjectType::Rule || (*itr_tp)==ObjectType::Trigger))
10215 		{
10216 			tables.insert(tables.end(), getObjectList(ObjectType::View)->begin(), getObjectList(ObjectType::View)->end());
10217 			inc_views=true;
10218 		}
10219 
10220 		itr_tp++;
10221 	}
10222 
10223 	//Gathering all other objects
10224 	itr_tp=types.begin();
10225 	while(itr_tp!=types.end())
10226 	{
10227 		obj_type=(*itr_tp);
10228 		itr_tp++;
10229 
10230 		if(obj_type==ObjectType::Database)
10231 			objs.push_back(this);
10232 		else if(!TableObject::isTableObject(obj_type))
10233 			objs.insert(objs.end(), getObjectList(obj_type)->begin(), getObjectList(obj_type)->end());
10234 		else
10235 		{
10236 			//Including table object on the object list
10237 			vector<TableObject *> *tab_objs=nullptr;
10238 			vector<BaseObject *>::iterator itr=tables.begin();
10239 			BaseObject *tab=nullptr;
10240 
10241 			while(itr!=tables.end())
10242 			{
10243 				tab=(*itr);
10244 				itr++;
10245 
10246 				if(PhysicalTable::isPhysicalTable(tab->getObjectType()))
10247 					tab_objs=dynamic_cast<PhysicalTable *>(tab)->getObjectList(obj_type);
10248 				else if(tab->getObjectType()==ObjectType::View &&	(obj_type==ObjectType::Trigger || obj_type==ObjectType::Rule))
10249 					tab_objs=dynamic_cast<View *>(tab)->getObjectList(obj_type);
10250 
10251 				if(tab_objs)
10252 					objs.insert(objs.end(), tab_objs->begin(), tab_objs->end());
10253 			}
10254 		}
10255 	}
10256 
10257 	//Try to find  the objects on the configured list
10258 	while(!objs.empty())
10259 	{
10260 		object = objs.back();
10261 		object->configureSearchAttributes();
10262 		srch_attribs = object->getSearchAttributes();
10263 
10264 		if((exact_match && pattern == srch_attribs[search_attr]) ||
10265 			 (exact_match && regexp.exactMatch(srch_attribs[search_attr])) ||
10266 			 (!exact_match && regexp.indexIn(srch_attribs[search_attr]) >= 0))
10267 			list.push_back(object);
10268 
10269 		objs.pop_back();
10270 	}
10271 
10272 	//Removing the duplicate items on the list
10273 	std::sort(list.begin(), list.end());
10274 	end=std::unique(list.begin(), list.end());
10275 	list.erase(end, list.end());
10276 
10277 	return list;
10278 }
10279 
setInvalidated(bool value)10280 void DatabaseModel::setInvalidated(bool value)
10281 {
10282 	this->invalidated=value;
10283 }
10284 
isInvalidated()10285 bool DatabaseModel::isInvalidated()
10286 {
10287 	return invalidated;
10288 }
10289 
setAppendAtEOD(bool value)10290 void  DatabaseModel::setAppendAtEOD(bool value)
10291 {
10292 	append_at_eod=value;
10293 }
10294 
setPrependAtBOD(bool value)10295 void DatabaseModel::setPrependAtBOD(bool value)
10296 {
10297 	prepend_at_bod=value;
10298 }
10299 
setDefaultObject(BaseObject * object,ObjectType obj_type)10300 void DatabaseModel::setDefaultObject(BaseObject *object, ObjectType obj_type)
10301 {
10302 	if((!object && default_objs.count(obj_type)==0) ||
10303 			(object && default_objs.count(object->getObjectType())==0))
10304 		throw Exception(ErrorCode::RefObjectInvalidType, __PRETTY_FUNCTION__,__FILE__,__LINE__);
10305 
10306 	if(!object)
10307 		default_objs[obj_type]=nullptr;
10308 	else
10309 		default_objs[object->getObjectType()]=object;
10310 }
10311 
setIsTemplate(bool value)10312 void DatabaseModel::setIsTemplate(bool value)
10313 {
10314 	is_template = value;
10315 }
10316 
setAllowConnections(bool value)10317 void DatabaseModel::setAllowConnections(bool value)
10318 {
10319 	allow_conns = value;
10320 }
10321 
isAppendAtEOD()10322 bool  DatabaseModel::isAppendAtEOD()
10323 {
10324 	return append_at_eod;
10325 }
10326 
isPrependedAtBOD()10327 bool DatabaseModel::isPrependedAtBOD()
10328 {
10329 	return prepend_at_bod;
10330 }
10331 
isTemplate()10332 bool DatabaseModel::isTemplate()
10333 {
10334 	return is_template;
10335 }
10336 
isAllowConnections()10337 bool DatabaseModel::isAllowConnections()
10338 {
10339 	return allow_conns;
10340 }
10341 
saveObjectsMetadata(const QString & filename,unsigned options)10342 void DatabaseModel::saveObjectsMetadata(const QString &filename, unsigned options)
10343 {
10344 	QFile output(filename);
10345 	QByteArray buf;
10346 	QString objs_def;
10347 	vector<BaseObject *> objects, tab_objs;
10348 	attribs_map attribs;
10349 	BaseGraphicObject *graph_obj=nullptr;
10350 	Relationship *rel=nullptr;
10351 	PhysicalTable *tab_nn=nullptr;
10352 	BaseTable *src_tab=nullptr, *dst_tab=nullptr, *base_tab=nullptr;
10353 	Schema *schema=nullptr;
10354 	QPointF pnt;
10355 	ObjectType obj_type;
10356 	int idx=0;
10357 	bool save_db_attribs=false, save_objs_pos=false, save_objs_prot=false,
10358 			save_objs_sqldis=false, save_textboxes=false, save_tags=false,
10359 			save_custom_sql=false, save_custom_colors=false, save_fadeout=false,
10360 			save_collapsemode=false, save_genericsqls=false, save_objs_aliases=false,
10361 			save_objs_z_value=false;
10362 	QStringList labels_attrs={ Attributes::SrcLabel,
10363 														 Attributes::DstLabel,
10364 														 Attributes::NameLabel };
10365 
10366 	save_db_attribs=(MetaDbAttributes & options) == MetaDbAttributes;
10367 	save_objs_pos=(MetaObjsPositioning & options) == MetaObjsPositioning;
10368 	save_objs_prot=(MetaObjsProtection & options) == MetaObjsProtection;
10369 	save_objs_sqldis=(MetaObjsSqlDisabled & options) == MetaObjsSqlDisabled;
10370 	save_textboxes=(MetaTextboxObjs & options) == MetaTextboxObjs;
10371 	save_tags=(MetaTagObjs & options) == MetaTagObjs;
10372 	save_custom_sql=(MetaObjsCustomSql & options) == MetaObjsCustomSql;
10373 	save_custom_colors=(MetaObjsCustomColors & options) == MetaObjsCustomColors;
10374 	save_fadeout=(MetaObjsFadeOut & options) == MetaObjsFadeOut;
10375 	save_collapsemode=(MetaObjsCollapseMode & options) == MetaObjsCollapseMode;
10376 	save_genericsqls=(MetaGenericSqlObjs & options) == MetaGenericSqlObjs;
10377 	save_objs_aliases=(MetaObjsAliases & options) == MetaObjsAliases;
10378 	save_objs_z_value=(MetaObjsZStackValue & options) == MetaObjsZStackValue;
10379 
10380 	output.open(QFile::WriteOnly);
10381 
10382 	if(!output.isOpen())
10383 		throw Exception(Exception::getErrorMessage(ErrorCode::FileDirectoryNotWritten).arg(filename),
10384 										ErrorCode::FileDirectoryNotWritten,__PRETTY_FUNCTION__,__FILE__,__LINE__);
10385 
10386 	try
10387 	{
10388 		if(save_textboxes || save_tags || save_genericsqls)
10389 		{
10390 			if(save_textboxes)
10391 				objects.insert(objects.end(), textboxes.begin(), textboxes.end());
10392 
10393 			if(save_tags)
10394 				objects.insert(objects.end(), tags.begin(), tags.end());
10395 
10396 			if(save_genericsqls)
10397 				objects.insert(objects.end(), genericsqls.begin(), genericsqls.end());
10398 		}
10399 
10400 		if(save_db_attribs)
10401 			objects.push_back(this);
10402 
10403 		if(save_objs_pos || save_objs_aliases)
10404 		{
10405 			objects.insert(objects.end(), schemas.begin(), schemas.end());
10406 			objects.insert(objects.end(), tables.begin(), tables.end());
10407 			objects.insert(objects.end(), views.begin(), views.end());
10408 			objects.insert(objects.end(), relationships.begin(), relationships.end());
10409 			objects.insert(objects.end(), base_relationships.begin(), base_relationships.end());
10410 
10411 			//Adding rel. n-n generated tables to the list of tables too
10412 			for(BaseObject *object : relationships)
10413 			{
10414 				rel=dynamic_cast<Relationship *>(object);
10415 
10416 				if(save_objs_pos && rel->getRelationshipType()==BaseRelationship::RelationshipNn && rel->getReceiverTable())
10417 				{
10418 					tab_nn=rel->getReceiverTable();
10419 					src_tab=rel->getTable(BaseRelationship::SrcTable);
10420 					dst_tab=rel->getTable(BaseRelationship::DstTable);
10421 
10422 					//Since the generated table does not have a position we create one based upon the source tables  positions
10423 					pnt.setX((src_tab->getPosition().x() + dst_tab->getPosition().x())/2.0);
10424 					pnt.setY((src_tab->getPosition().y() + dst_tab->getPosition().y())/2.0);
10425 					tab_nn->setPosition(pnt);
10426 
10427 					objects.push_back(tab_nn);
10428 				}
10429 			}
10430 
10431 			//Saving aliases the children of tables and views
10432 			if(save_objs_aliases)
10433 			{
10434 				for(auto &tab : tables)
10435 				{
10436 					tab_objs = dynamic_cast<Table *>(tab)->getObjects();
10437 					objects.insert(objects.end(), tab_objs.begin(), tab_objs.end());
10438 				}
10439 
10440 				for(auto &tab : foreign_tables)
10441 				{
10442 					tab_objs = dynamic_cast<ForeignTable *>(tab)->getObjects();
10443 					objects.insert(objects.end(), tab_objs.begin(), tab_objs.end());
10444 				}
10445 
10446 				for(auto &vw : views)
10447 				{
10448 					tab_objs = dynamic_cast<View *>(vw)->getObjects();
10449 					objects.insert(objects.end(), tab_objs.begin(), tab_objs.end());
10450 				}
10451 			}
10452 		}
10453 
10454 		if(save_objs_prot || save_objs_sqldis)
10455 		{
10456 			vector<ObjectType> types=getChildObjectTypes(ObjectType::Database), sch_types=getChildObjectTypes(ObjectType::Schema);
10457 			types.insert(types.end(), sch_types.begin(), sch_types.end());
10458 
10459 			//Removing the types for schema, table and view to avoid retrieving the objects twice
10460 			if(save_objs_pos)
10461 			{
10462 				types.erase(std::find(types.begin(), types.end(), ObjectType::Schema));
10463 				types.erase(std::find(types.begin(), types.end(), ObjectType::Table));
10464 				types.erase(std::find(types.begin(), types.end(), ObjectType::View));
10465 			}
10466 
10467 			//Append the other objects to the list of selected entities
10468 			for(ObjectType type : types)
10469 				objects.insert(objects.end(), getObjectList(type)->begin(), getObjectList(type)->end());
10470 		}
10471 
10472 		for(BaseObject *object : objects)
10473 		{
10474 			obj_type=object->getObjectType();
10475 
10476 			//When handling a tag , textbox or generic sql we just extract their XML code
10477 			if(obj_type==ObjectType::Textbox || obj_type==ObjectType::Tag || obj_type == ObjectType::GenericSql)
10478 			{
10479 				emit s_objectLoaded(((idx++)/static_cast<double>(objects.size()))*100,
10480 														tr("Saving object `%1' (%2)")
10481 														.arg(object->getName()).arg(object->getTypeName()), enum_cast(obj_type));
10482 
10483 				objs_def+=object->getCodeDefinition(SchemaParser::XmlDefinition);
10484 				continue;
10485 			}
10486 			//Discarding the relationship added table objects (when extracting aliases)
10487 			else if(TableObject::isTableObject(obj_type) && dynamic_cast<TableObject *>(object)->isAddedByRelationship())
10488 				continue;
10489 
10490 			graph_obj=dynamic_cast<BaseGraphicObject *>(object);
10491 			base_tab=dynamic_cast<BaseTable *>(object);
10492 
10493 			attribs[Attributes::Table]="";
10494 			attribs[Attributes::Name]=(TableObject::isTableObject(obj_type) ? object->getName() : object->getSignature());
10495 			attribs[Attributes::Alias]=(save_objs_aliases ? object->getAlias() : "");
10496 			attribs[Attributes::Type]=object->getSchemaName();
10497 			attribs[Attributes::Protected]=(save_objs_prot && object->isProtected() && !object->isSystemObject() ? Attributes::True : "");
10498 			attribs[Attributes::SqlDisabled]=(save_objs_sqldis && object->isSQLDisabled() && !object->isSystemObject()  ? Attributes::True : "");
10499 			attribs[Attributes::Tag]=(save_tags && base_tab && base_tab->getTag() ? base_tab->getTag()->getName() : "");
10500 			attribs[Attributes::AppendedSql]=object->getAppendedSQL();
10501 			attribs[Attributes::PrependedSql]=object->getPrependedSQL();
10502 			attribs[Attributes::FadedOut]=(save_fadeout && graph_obj && graph_obj->isFadedOut() ? Attributes::True : "");
10503 			attribs[Attributes::CollapseMode]=(save_collapsemode && base_tab ? QString::number(enum_cast(base_tab->getCollapseMode())) : "");
10504 
10505 			if(TableObject::isTableObject(obj_type))
10506 			{
10507 				base_tab = dynamic_cast<TableObject *>(object)->getParentTable();
10508 				attribs[Attributes::Table]=base_tab->getSignature();
10509 			}
10510 
10511 			if(save_custom_sql && obj_type==ObjectType::Database)
10512 			{
10513 				attribs[Attributes::AppendAtEod]=(this->isAppendAtEOD() ? Attributes::True : Attributes::False);
10514 				attribs[Attributes::PrependAtBod]=(this->isPrependedAtBOD() ? Attributes::True : Attributes::False);
10515 			}
10516 
10517 			//Configuring database model attributes
10518 			if(save_db_attribs && object==this)
10519 			{
10520 				attribs[Attributes::ModelAuthor]=this->getAuthor();
10521 				attribs[Attributes::LastPosition]=QString("%1,%2").arg(last_pos.x()).arg(last_pos.y());
10522 				attribs[Attributes::LastZoom]=QString::number(last_zoom);
10523 				attribs[Attributes::DefaultCollation]=(default_objs[ObjectType::Collation] ? default_objs[ObjectType::Collation]->getSignature() : "");
10524 				attribs[Attributes::DefaultSchema]=(default_objs[ObjectType::Schema] ? default_objs[ObjectType::Schema]->getSignature() : "");
10525 				attribs[Attributes::DefaultTablespace]=(default_objs[ObjectType::Tablespace] ? default_objs[ObjectType::Tablespace]->getSignature() : "");
10526 				attribs[Attributes::DefaultOwner]=(default_objs[ObjectType::Role] ? default_objs[ObjectType::Role]->getSignature() : "");
10527 			}
10528 
10529 			/* If the object is a graphic one and has Z stack value (currently only for tables/view/foreign tables,
10530 			 * textboxes are already save completely in the metadata, so there's no need to separate their z values) */
10531 			if(save_objs_z_value && graph_obj && BaseTable::isBaseTable(graph_obj->getObjectType()))
10532 			{
10533 				attribs[Attributes::ZValue]=QString::number(graph_obj->getZValue());
10534 			}
10535 
10536 			//If the object is a graphic one and we need to save positions and colors
10537 			if((save_objs_pos || save_custom_colors) && graph_obj)
10538 			{
10539 				if(obj_type!=ObjectType::BaseRelationship && obj_type!=ObjectType::Relationship)
10540 				{
10541 					pnt=graph_obj->getPosition();
10542 
10543 					if(obj_type==ObjectType::Schema)
10544 					{
10545 						schema=dynamic_cast<Schema *>(object);
10546 
10547 						attribs[Attributes::CustomColor]=(save_custom_colors ? schema->getFillColor().name() : "");
10548 						attribs[Attributes::RectVisible]=(schema->isRectVisible() ? Attributes::True : Attributes::False);
10549 
10550 						if(schema->isRectVisible())
10551 						{
10552 							attribs[Attributes::XPos]=QString::number(pnt.x());
10553 							attribs[Attributes::YPos]=QString::number(pnt.y());
10554 						}
10555 					}
10556 					else
10557 					{
10558 						attribs[Attributes::XPos]=QString::number(pnt.x());
10559 						attribs[Attributes::YPos]=QString::number(pnt.y());
10560 					}
10561 
10562 					if(obj_type!=ObjectType::Schema || !attribs[Attributes::XPos].isEmpty())
10563 					{
10564 						schparser.ignoreUnkownAttributes(true);
10565 						attribs[Attributes::Position]=
10566 								schparser.getCodeDefinition(GlobalAttributes::getSchemaFilePath(GlobalAttributes::XMLSchemaDir, Attributes::Position),
10567 																						attribs);
10568 					}
10569 				}
10570 				else
10571 				{
10572 					BaseRelationship *rel=dynamic_cast<BaseRelationship *>(object);
10573 					vector<QPointF> points=rel->getPoints();
10574 
10575 					attribs_map aux_attribs;
10576 
10577 					attribs[Attributes::CustomColor]=(save_custom_colors && rel->getCustomColor()!=Qt::transparent ? rel->getCustomColor().name() : Attributes::None);
10578 
10579 					attribs[Attributes::SrcTable]=rel->getTable(BaseRelationship::SrcTable)->getSignature();
10580 					attribs[Attributes::SrcType]=rel->getTable(BaseRelationship::SrcTable)->getSchemaName();
10581 
10582 					attribs[Attributes::DstTable]=rel->getTable(BaseRelationship::DstTable)->getSignature();
10583 					attribs[Attributes::DstType]=rel->getTable(BaseRelationship::DstTable)->getSchemaName();
10584 
10585 					for(QPointF pnt : points)
10586 					{
10587 						attribs[Attributes::XPos]=QString::number(pnt.x());
10588 						attribs[Attributes::YPos]=QString::number(pnt.y());
10589 
10590 						schparser.ignoreUnkownAttributes(true);
10591 						attribs[Attributes::Position]+=
10592 								schparser.getCodeDefinition(GlobalAttributes::getSchemaFilePath(GlobalAttributes::XMLSchemaDir, Attributes::Position),
10593 																						attribs);
10594 					}
10595 
10596 					//Saving the labels' custom positions
10597 					for(unsigned id=BaseRelationship::SrcCardLabel; id <= BaseRelationship::RelNameLabel; id++)
10598 					{
10599 						pnt=rel->getLabelDistance(id);
10600 						if(!std::isnan(pnt.x()) && !std::isnan(pnt.y()))
10601 						{
10602 							aux_attribs[Attributes::XPos]=QString::number(pnt.x());
10603 							aux_attribs[Attributes::YPos]=QString::number(pnt.y());
10604 							aux_attribs[Attributes::RefType]=labels_attrs[id];
10605 
10606 							aux_attribs[Attributes::Position]=schparser.getCodeDefinition(GlobalAttributes::getSchemaFilePath(GlobalAttributes::XMLSchemaDir, Attributes::Position),
10607 																																						aux_attribs);
10608 
10609 							attribs[Attributes::Position]+=schparser.getCodeDefinition(GlobalAttributes::getSchemaFilePath( GlobalAttributes::XMLSchemaDir, Attributes::Label),
10610 																																				 aux_attribs);
10611 
10612 						}
10613 					}
10614 				}
10615 			}
10616 
10617 			//Storing the custom SQLs if the object has them configured
10618 			if(save_custom_sql)
10619 			{
10620 				if(!object->getAppendedSQL().isEmpty())
10621 					attribs[Attributes::AppendedSql]=schparser.getCodeDefinition(GlobalAttributes::getSchemaFilePath(GlobalAttributes::XMLSchemaDir, QString(Attributes::AppendedSql).remove(QChar('-'))),
10622 																																			 attribs);
10623 
10624 
10625 				if(!object->getPrependedSQL().isEmpty())
10626 					attribs[Attributes::PrependedSql]=schparser.getCodeDefinition(GlobalAttributes::getSchemaFilePath(GlobalAttributes::XMLSchemaDir,	QString(Attributes::PrependedSql).remove(QChar('-'))),
10627 																																				attribs);
10628 
10629 			}
10630 
10631 			/* The object's metadata code will be generated only if one of the key attributes
10632 			 for each option were filled previously. */
10633 			if((save_db_attribs && obj_type==ObjectType::Database) ||
10634 				 (save_custom_colors &&
10635 					((obj_type==ObjectType::Relationship || obj_type==ObjectType::BaseRelationship) ||
10636 					 (!attribs[Attributes::CustomColor].isEmpty()))) ||
10637 				 (save_objs_pos &&
10638 					(!attribs[Attributes::Position].isEmpty() ||
10639 					 !attribs[Attributes::RectVisible].isEmpty())) ||
10640 				 (save_tags && !attribs[Attributes::Tag].isEmpty()) ||
10641 				 (save_objs_prot && !attribs[Attributes::Protected].isEmpty()) ||
10642 				 (save_objs_sqldis && !attribs[Attributes::SqlDisabled].isEmpty()) ||
10643 				 (save_custom_sql && (!attribs[Attributes::AppendedSql].isEmpty() ||
10644 															!attribs[Attributes::PrependedSql].isEmpty())) ||
10645 				 (save_fadeout && !attribs[Attributes::FadedOut].isEmpty()) ||
10646 				 (save_collapsemode && !attribs[Attributes::CollapseMode].isEmpty()) ||
10647 				 (save_objs_aliases && !attribs[Attributes::Alias].isEmpty()) ||
10648 				 (save_objs_z_value && !attribs[Attributes::ZValue].isEmpty()))
10649 			{
10650 				emit s_objectLoaded(((idx++)/static_cast<double>(objects.size()))*100,
10651 														tr("Saving metadata of the object `%1' (%2)")
10652 														.arg(object->getSignature()).arg(object->getTypeName()), enum_cast(obj_type));
10653 
10654 				schparser.ignoreUnkownAttributes(true);
10655 				objs_def+=XmlParser::convertCharsToXMLEntities(
10656 										schparser.getCodeDefinition(GlobalAttributes::getSchemaFilePath(GlobalAttributes::XMLSchemaDir, Attributes::Info),
10657 																								attribs));
10658 			}
10659 			else
10660 				idx++;
10661 
10662 			attribs.clear();
10663 		}
10664 
10665 		if(!objs_def.isEmpty())
10666 		{
10667 			//Generates the metadata XML buffer
10668 			attribs[Attributes::Info]=objs_def;
10669 			buf.append(schparser.getCodeDefinition(GlobalAttributes::getSchemaFilePath(GlobalAttributes::XMLSchemaDir, Attributes::Metadata),
10670 																						 attribs));
10671 
10672 			output.write(buf.data(),buf.size());
10673 
10674 			emit s_objectLoaded(100, tr("Metadata file successfully saved!"), enum_cast(ObjectType::BaseObject));
10675 		}
10676 		else
10677 			emit s_objectLoaded(100, tr("Process successfully ended but no metadata was saved!"), enum_cast(ObjectType::BaseObject));
10678 
10679 		output.close();
10680 	}
10681 	catch(Exception &e)
10682 	{
10683 		if(output.isOpen()) output.close();
10684 		throw Exception(Exception::getErrorMessage(ErrorCode::FileNotWrittenInvalidDefinition).arg(filename),
10685 										ErrorCode::FileNotWrittenInvalidDefinition,__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
10686 	}
10687 }
10688 
loadObjectsMetadata(const QString & filename,unsigned options)10689 void DatabaseModel::loadObjectsMetadata(const QString &filename, unsigned options)
10690 {
10691 	QString elem_name, aux_elem, obj_name, ref_type,
10692 			dtd_file=GlobalAttributes::getSchemasRootDir() +
10693 							 GlobalAttributes::DirSeparator +
10694 							 GlobalAttributes::XMLSchemaDir +
10695 							 GlobalAttributes::DirSeparator +
10696 							 GlobalAttributes::ObjectDTDDir +
10697 							 GlobalAttributes::DirSeparator;
10698 	attribs_map attribs, aux_attrib;
10699 	ObjectType obj_type;
10700 	BaseObject *object=nullptr, *new_object=nullptr;
10701 	BaseTable *src_tab=nullptr, *dst_tab=nullptr, *base_tab=nullptr;
10702 	vector<QPointF> points;
10703 	map<QString, unsigned> labels_attrs;
10704 	vector<QPointF> labels_pos={ QPointF(DNaN,DNaN), QPointF(DNaN,DNaN), QPointF(DNaN,DNaN) };
10705 	BaseRelationship *rel=nullptr;
10706 	Schema *schema=nullptr;
10707 	Tag *tag=nullptr;
10708 	int progress=0;
10709 	bool load_db_attribs=false, load_objs_pos=false, load_objs_prot=false,
10710 			load_objs_sqldis=false, load_textboxes=false, load_tags=false,
10711 			load_custom_sql=false, load_custom_colors=false, load_fadeout=false,
10712 			load_collapse_mode=false, load_genericsqls=false, load_objs_aliases=false,
10713 			load_objs_z_value=false;
10714 
10715 	load_db_attribs=(MetaDbAttributes & options) == MetaDbAttributes;
10716 	load_objs_pos=(MetaObjsPositioning & options) == MetaObjsPositioning;
10717 	load_objs_prot=(MetaObjsProtection & options) == MetaObjsProtection;
10718 	load_objs_sqldis=(MetaObjsSqlDisabled & options) == MetaObjsSqlDisabled;
10719 	load_textboxes=(MetaTextboxObjs & options) == MetaTextboxObjs;
10720 	load_tags=(MetaTagObjs & options) == MetaTagObjs;
10721 	load_custom_sql=(MetaObjsCustomSql & options) == MetaObjsCustomSql;
10722 	load_custom_colors=(MetaObjsCustomColors & options) == MetaObjsCustomColors;
10723 	load_fadeout=(MetaObjsFadeOut & options) == MetaObjsFadeOut;
10724 	load_collapse_mode=(MetaObjsCollapseMode & options) == MetaObjsCollapseMode;
10725 	load_genericsqls=(MetaGenericSqlObjs & options) == MetaGenericSqlObjs;
10726 	load_objs_aliases=(MetaObjsAliases & options) == MetaObjsAliases;
10727 	load_objs_z_value=(MetaObjsZStackValue & options) == MetaObjsZStackValue;
10728 
10729 	try
10730 	{
10731 		labels_attrs[Attributes::SrcLabel]=BaseRelationship::SrcCardLabel;
10732 		labels_attrs[Attributes::DstLabel]=BaseRelationship::DstCardLabel;
10733 		labels_attrs[Attributes::NameLabel]=BaseRelationship::RelNameLabel;
10734 
10735 		xmlparser.restartParser();
10736 
10737 		xmlparser.setDTDFile(dtd_file + GlobalAttributes::MetadataDTD +
10738 												 GlobalAttributes::ObjectDTDExt,
10739 												 GlobalAttributes::MetadataDTD);
10740 
10741 		xmlparser.loadXMLFile(filename);
10742 
10743 		if(xmlparser.accessElement(XmlParser::ChildElement))
10744 		{
10745 			do
10746 			{
10747 				if(xmlparser.getElementType()==XML_ELEMENT_NODE)
10748 				{
10749 					elem_name=xmlparser.getElementName();
10750 
10751 					if((elem_name==BaseObject::getSchemaName(ObjectType::Tag) && load_tags) ||
10752 						 (elem_name==BaseObject::getSchemaName(ObjectType::Textbox) && load_textboxes) ||
10753 						 (elem_name==BaseObject::getSchemaName(ObjectType::GenericSql) && load_genericsqls))
10754 					{
10755 						xmlparser.savePosition();
10756 						obj_type=BaseObject::getObjectType(elem_name);
10757 						new_object=createObject(obj_type);
10758 
10759 						if(getObjectIndex(new_object->getName(), obj_type) < 0)
10760 						{
10761 							emit s_objectLoaded(progress, tr("Creating object `%1' (%2)")
10762 																	.arg(new_object->getName()).arg(new_object->getTypeName()), enum_cast(obj_type));
10763 							addObject(new_object);
10764 						}
10765 						else
10766 						{
10767 							emit s_objectLoaded(progress, tr("Object `%1' (%2) already exists. Ignoring.")
10768 																	.arg(new_object->getName()).arg(new_object->getTypeName()), enum_cast(ObjectType::BaseObject));
10769 							delete new_object;
10770 						}
10771 
10772 						new_object=nullptr;
10773 						xmlparser.restorePosition();
10774 					}
10775 					else if(elem_name==Attributes::Info)
10776 					{
10777 						xmlparser.getElementAttributes(attribs);
10778 						obj_name=attribs[Attributes::Object];
10779 						xmlparser.savePosition();
10780 
10781 						obj_type=BaseObject::getObjectType(attribs[Attributes::Type]);
10782 						progress=xmlparser.getCurrentBufferLine()/static_cast<double>(xmlparser.getBufferLineCount()) * 100;
10783 
10784 						if(obj_type==ObjectType::Database)
10785 						{
10786 							if(load_db_attribs)
10787 							{
10788 								QStringList pos=attribs[Attributes::LastPosition].split(',');
10789 
10790 								default_objs[ObjectType::Schema]=getSchema(attribs[Attributes::DefaultSchema]);
10791 								default_objs[ObjectType::Role]=getRole(attribs[Attributes::DefaultOwner]);
10792 								default_objs[ObjectType::Collation]=getCollation(attribs[Attributes::DefaultCollation]);
10793 								default_objs[ObjectType::Tablespace]=getTablespace(attribs[Attributes::DefaultTablespace]);
10794 								author=attribs[Attributes::ModelAuthor];
10795 								last_zoom=attribs[Attributes::LastZoom].toDouble();
10796 
10797 								if(pos.size()>=2)
10798 									last_pos=QPoint(pos[0].toInt(), pos[1].toInt());
10799 							}
10800 
10801 							object=this;
10802 						}
10803 						else if(TableObject::isTableObject(obj_type))
10804 						{
10805 							base_tab = getTable(attribs[Attributes::Table]);
10806 
10807 							if(!base_tab && (obj_type == ObjectType::Rule || obj_type == ObjectType::Index || obj_type == ObjectType::Trigger))
10808 								base_tab = getView(attribs[Attributes::Table]);
10809 
10810 							if(base_tab)
10811 								object = base_tab->getObject(attribs[Attributes::Object], obj_type);
10812 
10813 							//Discarding the object if it was added by relationship
10814 							if(object && dynamic_cast<TableObject *>(object)->isAddedByRelationship())
10815 								object = nullptr;
10816 						}
10817 						else
10818 							object=getObject(obj_name, obj_type);
10819 
10820 						/* If the object does not exists but it is a relationship, we try to get the relationship
10821 						 involving the tables in paramenters src-table and dst-table */
10822 						if(!object && obj_type==ObjectType::Relationship)
10823 						{
10824 							src_tab=dynamic_cast<BaseTable *>(getObject(attribs[Attributes::SrcTable],
10825 																								BaseObject::getObjectType(attribs[Attributes::SrcType])));
10826 							dst_tab=dynamic_cast<BaseTable *>(getObject(attribs[Attributes::DstTable],
10827 																								BaseObject::getObjectType(attribs[Attributes::DstType])));
10828 							object=getRelationship(src_tab, dst_tab);
10829 						}
10830 
10831 						if(object)
10832 						{
10833 							emit s_objectLoaded(progress, tr("Loading metadata for object `%1' (%2)")
10834 																	.arg(object->getName()).arg(object->getTypeName()), enum_cast(obj_type));
10835 
10836 							if(!object->isSystemObject() &&
10837 								 ((!attribs[Attributes::Protected].isEmpty() && load_objs_prot) ||
10838 									(!attribs[Attributes::SqlDisabled].isEmpty() && load_objs_sqldis)))
10839 							{
10840 								if(!attribs[Attributes::Protected].isEmpty())
10841 									object->setProtected(attribs[Attributes::Protected]==Attributes::True);
10842 
10843 								if(!attribs[Attributes::SqlDisabled].isEmpty())
10844 									object->setSQLDisabled(attribs[Attributes::SqlDisabled]==Attributes::True);
10845 							}
10846 							else if(BaseTable::isBaseTable(obj_type) && load_tags && !attribs[Attributes::Tag].isEmpty())
10847 							{
10848 								tag=getTag(attribs[Attributes::Tag]);
10849 
10850 								if(tag)
10851 									dynamic_cast<BaseTable *>(object)->setTag(tag);
10852 							}
10853 							else if(BaseTable::isBaseTable(obj_type) && load_objs_z_value && !attribs[Attributes::ZValue].isEmpty())
10854 							{
10855 								dynamic_cast<BaseTable *>(object)->setZValue(attribs[Attributes::ZValue].toInt());
10856 							}
10857 							else if(obj_type==ObjectType::Database && load_custom_sql)
10858 							{
10859 								if(!attribs[Attributes::AppendAtEod].isEmpty())
10860 									this->setAppendAtEOD(attribs[Attributes::AppendAtEod]==Attributes::True);
10861 
10862 								if(!attribs[Attributes::PrependAtBod].isEmpty())
10863 									this->setPrependAtBOD(attribs[Attributes::PrependAtBod]==Attributes::True);
10864 							}
10865 
10866 							if(load_objs_aliases && !attribs[Attributes::Alias].isEmpty())
10867 								object->setAlias(attribs[Attributes::Alias]);
10868 
10869 							if(xmlparser.accessElement(XmlParser::ChildElement))
10870 							{
10871 								do
10872 								{
10873 									aux_elem=xmlparser.getElementName();
10874 									xmlparser.getElementAttributes(aux_attrib);
10875 
10876 									//Retrieving and storing the points
10877 									if(aux_elem==Attributes::Position)
10878 									{
10879 										points.push_back(QPointF(aux_attrib[Attributes::XPos].toDouble(),
10880 																						 aux_attrib[Attributes::YPos].toDouble()));
10881 									}
10882 									//Retrieving and storing the labels' custom positions
10883 									else if(aux_elem==Attributes::Label)
10884 									{
10885 										ref_type=aux_attrib[Attributes::RefType];
10886 										xmlparser.savePosition();
10887 
10888 										if(xmlparser.accessElement(XmlParser::ChildElement))
10889 										{
10890 											xmlparser.getElementAttributes(aux_attrib);
10891 											labels_pos[labels_attrs[ref_type]]=QPointF(aux_attrib[Attributes::XPos].toDouble(),
10892 																																 aux_attrib[Attributes::YPos].toDouble());
10893 										}
10894 
10895 										xmlparser.restorePosition();
10896 									}
10897 									else if(load_custom_sql && aux_elem==Attributes::AppendedSql &&
10898 													attribs[Attributes::AppendedSql].isEmpty())
10899 									{
10900 										xmlparser.savePosition();
10901 										xmlparser.accessElement(XmlParser::ChildElement);
10902 										object->setAppendedSQL(xmlparser.getElementContent());
10903 										xmlparser.restorePosition();
10904 									}
10905 									else if(load_custom_sql && aux_elem==Attributes::PrependedSql &&
10906 													attribs[Attributes::PrependedSql].isEmpty())
10907 									{
10908 										xmlparser.savePosition();
10909 										xmlparser.accessElement(XmlParser::ChildElement);
10910 										object->setPrependedSQL(xmlparser.getElementContent());
10911 										xmlparser.restorePosition();
10912 									}
10913 								}
10914 								while(xmlparser.accessElement(XmlParser::NextElement));
10915 							}
10916 
10917 							if(BaseGraphicObject::isGraphicObject(obj_type))
10918 							{
10919 								base_tab=dynamic_cast<BaseTable *>(object);
10920 								rel=dynamic_cast<BaseRelationship *>(object);
10921 								schema=dynamic_cast<Schema *>(object);
10922 
10923 								if(!rel && !schema && !points.empty() && load_objs_pos)
10924 									dynamic_cast<BaseGraphicObject *>(object)->setPosition(points[0]);
10925 								else if(rel)
10926 								{
10927 									if(load_custom_colors)
10928 									{
10929 										if(attribs[Attributes::CustomColor]==Attributes::None)
10930 											rel->setCustomColor(Qt::transparent);
10931 										else
10932 											rel->setCustomColor(QColor(attribs[Attributes::CustomColor]));
10933 									}
10934 
10935 									if(load_objs_pos)
10936 									{
10937 										rel->setPoints(points);
10938 
10939 										for(unsigned id=BaseRelationship::SrcCardLabel; id <= BaseRelationship::RelNameLabel; id++)
10940 										{
10941 											rel->setLabelDistance(id, labels_pos[id]);
10942 											labels_pos[id]=QPointF(DNaN, DNaN);
10943 										}
10944 									}
10945 								}
10946 								else if(schema)
10947 								{
10948 									if(load_custom_colors)
10949 										schema->setFillColor(QColor(attribs[Attributes::CustomColor]));
10950 
10951 									schema->setRectVisible(attribs[Attributes::RectVisible]==Attributes::True);
10952 								}
10953 
10954 								if(load_fadeout)
10955 									dynamic_cast<BaseGraphicObject *>(object)->setFadedOut(attribs[Attributes::FadedOut]==Attributes::True);
10956 
10957 								if(load_collapse_mode && base_tab)
10958 									base_tab->setCollapseMode(static_cast<CollapseMode>(attribs[Attributes::CollapseMode].toUInt()));
10959 							}
10960 
10961 							points.clear();
10962 
10963 						}
10964 						else if(!object)
10965 						{
10966 							emit s_objectLoaded(progress, tr("Object `%1' (%2) not found. Ignoring metadata.")
10967 																	.arg(obj_name).arg(BaseObject::getTypeName(obj_type)), enum_cast(ObjectType::BaseObject));
10968 						}
10969 
10970 						xmlparser.restorePosition();
10971 
10972 					}
10973 				}
10974 			}
10975 			while(xmlparser.accessElement(XmlParser::NextElement));
10976 		}
10977 
10978 		emit s_objectLoaded(100, tr("Metadata file successfully loaded!"), enum_cast(ObjectType::BaseObject));
10979 		setObjectsModified();
10980 	}
10981 	catch(Exception &e)
10982 	{
10983 		QString extra_info;
10984 
10985 		if(xmlparser.getCurrentElement())
10986 			extra_info=QString(QObject::tr("%1 (line: %2)")).arg(xmlparser.getLoadedFilename()).arg(xmlparser.getCurrentElement()->line);
10987 
10988 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, extra_info);
10989 	}
10990 }
10991 
setLayers(const QStringList & layers)10992 void DatabaseModel::setLayers(const QStringList &layers)
10993 {
10994 	this->layers = layers;
10995 }
10996 
getLayers()10997 QStringList DatabaseModel::getLayers()
10998 {
10999 	return layers;
11000 }
11001 
setActiveLayers(const QList<unsigned> & layers)11002 void DatabaseModel::setActiveLayers(const QList<unsigned> &layers)
11003 {
11004 	active_layers = layers;
11005 }
11006 
getActiveLayers()11007 QList<unsigned> DatabaseModel::getActiveLayers()
11008 {
11009 	return active_layers;
11010 }
11011 
addChangelogEntry(BaseObject * object,unsigned op_type,BaseObject * parent_obj)11012 void DatabaseModel::addChangelogEntry(BaseObject *object, unsigned op_type, BaseObject *parent_obj)
11013 {
11014 	if(op_type == Operation::NoOperation || op_type == Operation::ObjectMoved)
11015 		return;
11016 
11017 	if(!object || (object && TableObject::isTableObject(object->getObjectType()) && !parent_obj))
11018 		throw Exception(ErrorCode::InvChangelogEntryValues, __PRETTY_FUNCTION__, __FILE__, __LINE__);
11019 
11020 	QString action;
11021 	BaseObject *aux_obj = nullptr;
11022 	QDateTime date_time = QDateTime::currentDateTime();
11023 
11024 	if(TableObject::isTableObject(object->getObjectType()))
11025 	{
11026 		aux_obj = parent_obj;
11027 		action = Attributes::UpdatePriv;
11028 	}
11029 	else
11030 	{
11031 		aux_obj = object;
11032 
11033 		if(op_type == Operation::ObjectCreated)
11034 			action = Attributes::CreatePriv;
11035 		else if(op_type == Operation::ObjectRemoved)
11036 			action = Attributes::DeletePriv;
11037 		else
11038 			action = Attributes::UpdatePriv;
11039 	}
11040 
11041 	changelog.push_back(std::make_tuple(date_time,aux_obj->getSignature(), aux_obj->getObjectType(), action));
11042 }
11043 
addChangelogEntry(const QString & signature,const QString & type,const QString & action,const QString & date)11044 void DatabaseModel::addChangelogEntry(const QString &signature, const QString &type, const QString &action, const QString &date)
11045 {
11046 	QDateTime date_time = QDateTime::fromString(date, Qt::ISODate);
11047 	ObjectType obj_type = BaseObject::getObjectType(type);
11048 	QStringList actions = { Attributes::CreatePriv, Attributes::DeletePriv, Attributes::UpdatePriv };
11049 
11050 	if(!BaseObject::isValidName(signature) || obj_type == ObjectType::BaseObject ||
11051 		 TableObject::isTableObject(obj_type) || !date_time.isValid() || !actions.contains(action))
11052 		throw Exception(ErrorCode::InvChangelogEntryValues, __PRETTY_FUNCTION__, __FILE__, __LINE__);
11053 
11054 	changelog.push_back(std::make_tuple(date_time, signature, obj_type, action));
11055 }
11056 
getFiltersFromChangeLog(QDateTime start,QDateTime end)11057 QStringList DatabaseModel::getFiltersFromChangeLog(QDateTime start, QDateTime end)
11058 {
11059 	QStringList filters;
11060 	QString signature, action;
11061 	ObjectType type;
11062 	QDateTime date;
11063 
11064 	// Inverting the date range if the start is greater than the end
11065 	if(start.isValid() && end.isValid() && end < start)
11066 	{
11067 		QDateTime aux = start;
11068 		start = end;
11069 		end = aux;
11070 	}
11071 
11072 	for(auto &entry : changelog)
11073 	{
11074 		date = std::get<LogDate>(entry);
11075 		signature = std::get<LogSinature>(entry);
11076 		type = std::get<LogObjectType>(entry);
11077 		action = std::get<LogAction>(entry);
11078 
11079 		if((start.isValid() && end.isValid() && date >= start && date <= end) ||
11080 			 (start.isValid() && !end.isValid() && date >= start) ||
11081 			 (!start.isValid() && end.isValid() && date <= end))
11082 		{
11083 			filters.append(BaseObject::getSchemaName(type) +
11084 										 PgModelerNs::FilterSeparator +
11085 										 signature +
11086 										 PgModelerNs::FilterSeparator +
11087 										 PgModelerNs::FilterWildcard);
11088 		}
11089 	}
11090 
11091 	filters.removeDuplicates();
11092 	return filters;
11093 }
11094 
setPersistedChangelog(bool persist)11095 void DatabaseModel::setPersistedChangelog(bool persist)
11096 {
11097 	persist_changelog = persist;
11098 }
11099 
isPersistedChangelog()11100 bool DatabaseModel::isPersistedChangelog()
11101 {
11102 	return persist_changelog;
11103 }
11104 
clearChangelog()11105 void DatabaseModel::clearChangelog()
11106 {
11107 	changelog.clear();
11108 }
11109 
getLastChangelogDate()11110 QDateTime DatabaseModel::getLastChangelogDate()
11111 {
11112 	return changelog.empty() ?
11113 				 QDateTime() : std::get<LogDate>(changelog.back());
11114 }
11115 
getChangelogLength()11116 unsigned DatabaseModel::getChangelogLength()
11117 {
11118 	return changelog.size();
11119 }
11120 
11121 template<class TableClass>
createPhysicalTable()11122 TableClass *DatabaseModel::createPhysicalTable()
11123 {
11124 	attribs_map attribs, aux_attribs;
11125 	QString elem;
11126 	TableClass *table=nullptr;
11127 	TableObject *object=nullptr;
11128 	BaseObject *tag=nullptr;
11129 	ObjectType obj_type;
11130 	vector<unsigned> idxs;
11131 	vector<QString> names;
11132 	PartitionKey part_key;
11133 	vector<PartitionKey> partition_keys;
11134 
11135 	try
11136 	{
11137 		table = new TableClass;
11138 		setBasicAttributes(table);
11139 		xmlparser.getElementAttributes(attribs);
11140 
11141 		table->setObjectListsCapacity(attribs[Attributes::MaxObjCount].toUInt());
11142 		table->setGenerateAlterCmds(attribs[Attributes::GenAlterCmds]==Attributes::True);
11143 		table->setCollapseMode(attribs[Attributes::CollapseMode].isEmpty() ? CollapseMode::NotCollapsed : static_cast<CollapseMode>(attribs[Attributes::CollapseMode].toUInt()));
11144 		table->setPaginationEnabled(attribs[Attributes::Pagination]==Attributes::True);
11145 		table->setCurrentPage(BaseTable::AttribsSection, attribs[Attributes::AttribsPage].toUInt());
11146 		table->setCurrentPage(BaseTable::ExtAttribsSection, attribs[Attributes::ExtAttribsPage].toUInt());
11147 		table->setFadedOut(attribs[Attributes::FadedOut]==Attributes::True);
11148 		table->setLayer(attribs[Attributes::Layer].toUInt());
11149 
11150 		if(xmlparser.accessElement(XmlParser::ChildElement))
11151 		{
11152 			do
11153 			{
11154 				if(xmlparser.getElementType()==XML_ELEMENT_NODE)
11155 				{
11156 					elem=xmlparser.getElementName();
11157 					xmlparser.savePosition();
11158 					object=nullptr;
11159 
11160 					if(elem==BaseObject::objs_schemas[enum_cast(ObjectType::Column)])
11161 						object=createColumn();
11162 					else if(elem==BaseObject::objs_schemas[enum_cast(ObjectType::Constraint)])
11163 						object=createConstraint(table);
11164 					else if(elem==BaseObject::objs_schemas[enum_cast(ObjectType::Tag)])
11165 					{
11166 						xmlparser.getElementAttributes(aux_attribs);
11167 						tag=getObject(aux_attribs[Attributes::Name], ObjectType::Tag);
11168 
11169 						if(!tag)
11170 						{
11171 							throw Exception(Exception::getErrorMessage(ErrorCode::RefObjectInexistsModel)
11172 															.arg(attribs[Attributes::Name])
11173 									.arg(BaseObject::getTypeName(ObjectType::Table))
11174 									.arg(aux_attribs[Attributes::Table])
11175 									.arg(BaseObject::getTypeName(ObjectType::Tag))
11176 									, ErrorCode::RefObjectInexistsModel,__PRETTY_FUNCTION__,__FILE__,__LINE__);
11177 						}
11178 
11179 						table->setTag(dynamic_cast<Tag *>(tag));
11180 					}
11181 					//Retrieving custom columns / constraint indexes
11182 					else if(elem==Attributes::CustomIdxs)
11183 					{
11184 						xmlparser.getElementAttributes(aux_attribs);
11185 						obj_type=BaseObject::getObjectType(aux_attribs[Attributes::ObjectType]);
11186 
11187 						xmlparser.savePosition();
11188 
11189 						if(xmlparser.accessElement(XmlParser::ChildElement))
11190 						{
11191 							do
11192 							{
11193 								if(xmlparser.getElementType()==XML_ELEMENT_NODE)
11194 								{
11195 									elem=xmlparser.getElementName();
11196 
11197 									//The element <object> stores the index for each object in the current group
11198 									if(elem==Attributes::Object)
11199 									{
11200 										xmlparser.getElementAttributes(aux_attribs);
11201 										names.push_back(aux_attribs[Attributes::Name]);
11202 										idxs.push_back(aux_attribs[Attributes::Index].toUInt());
11203 									}
11204 								}
11205 							}
11206 							while(xmlparser.accessElement(XmlParser::NextElement));
11207 
11208 							table->setRelObjectsIndexes(names, idxs, obj_type);
11209 							names.clear();
11210 							idxs.clear();
11211 						}
11212 
11213 						xmlparser.restorePosition();
11214 					}
11215 					else if(elem==Attributes::Partitioning)
11216 					{
11217 						xmlparser.getElementAttributes(aux_attribs);
11218 						table->setPartitioningType(aux_attribs[Attributes::Type]);
11219 						xmlparser.savePosition();
11220 
11221 						if(xmlparser.accessElement(XmlParser::ChildElement))
11222 						{
11223 							do
11224 							{
11225 								if(xmlparser.getElementType()==XML_ELEMENT_NODE &&
11226 									 xmlparser.getElementName()==Attributes::PartitionKey)
11227 								{
11228 									createElement(part_key, nullptr, table);
11229 									partition_keys.push_back(part_key);
11230 								}
11231 							}
11232 							while(xmlparser.accessElement(XmlParser::NextElement));
11233 
11234 							table->addPartitionKeys(partition_keys);
11235 						}
11236 
11237 						xmlparser.restorePosition();
11238 					}
11239 					//Retrieving initial data
11240 					else if(elem==Attributes::InitialData)
11241 					{
11242 						xmlparser.savePosition();
11243 						xmlparser.accessElement(XmlParser::ChildElement);
11244 						table->setInitialData(xmlparser.getElementContent());
11245 						xmlparser.restorePosition();
11246 					}
11247 
11248 					if(object)
11249 						table->addObject(object);
11250 
11251 					xmlparser.restorePosition();
11252 				}
11253 			}
11254 			while(xmlparser.accessElement(XmlParser::NextElement));
11255 		}
11256 
11257 		table->setProtected(table->isProtected());
11258 	}
11259 	catch(Exception &e)
11260 	{
11261 		QString extra_info=getErrorExtraInfo();
11262 		xmlparser.restorePosition();
11263 
11264 		if(table) delete table;
11265 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, extra_info);
11266 	}
11267 
11268 	return table;
11269 }
11270 
getDataDictionary(attribs_map & datadict,bool browsable,bool splitted)11271 void DatabaseModel::getDataDictionary(attribs_map &datadict, bool browsable, bool splitted)
11272 {
11273 	int idx = 0;
11274 	BaseObject *object = nullptr;
11275 	vector<BaseObject *> objects;
11276 	map<QString, BaseObject *> objs_map;
11277 	QString styles, id, index, items, buffer;
11278 	attribs_map attribs, aux_attribs;
11279 	QStringList index_list;
11280 	QString dict_sch_file = GlobalAttributes::getSchemaFilePath(GlobalAttributes::DataDictSchemaDir, GlobalAttributes::DataDictSchemaDir),
11281 			style_sch_file = GlobalAttributes::getSchemaFilePath(GlobalAttributes::DataDictSchemaDir, Attributes::Styles),
11282 			item_sch_file = GlobalAttributes::getSchemaFilePath(GlobalAttributes::DataDictSchemaDir, Attributes::Item),
11283 			index_sch_file = GlobalAttributes::getSchemaFilePath(GlobalAttributes::DataDictSchemaDir, Attributes::Index);
11284 
11285 	objects.assign(tables.begin(), tables.end());
11286 	objects.insert(objects.end(), foreign_tables.begin(), foreign_tables.end());
11287 	objects.insert(objects.end(), views.begin(), views.end());
11288 	objects.insert(objects.end(), relationships.begin(), relationships.end());
11289 
11290 	// Placing the objects in alphabectical order
11291 	for(auto &obj : objects)
11292 	{
11293 		// Retrieving the generated table if the current object is a relationship (n-n)
11294 		if(obj->getObjectType() == ObjectType::Relationship)
11295 		{
11296 			Relationship *rel = dynamic_cast<Relationship *>(obj);
11297 
11298 			if(!rel->getGeneratedTable())
11299 				continue;
11300 
11301 			obj = rel->getGeneratedTable();
11302 		}
11303 
11304 		id = obj->getSignature().remove(QChar('"'));
11305 		objs_map[id] = obj;
11306 		index_list.push_back(id);
11307 	}
11308 
11309 	index_list.sort();
11310 	datadict.clear();
11311 
11312 	// Generates the the stylesheet
11313 	styles = schparser.getCodeDefinition(style_sch_file, attribs);
11314 	attribs[Attributes::Styles] = "";
11315 	attribs[Attributes::Index] = "";
11316 	attribs[Attributes::Splitted] = splitted ? Attributes::True : "";
11317 
11318 	// If the generation is a standalone HTML the css is embedded
11319 	if(!splitted)
11320 		attribs[Attributes::Styles] = styles;
11321 	else
11322 		// Otherwise we create a separated stylesheet file
11323 		datadict[Attributes::Styles + QString(".css")] = styles;
11324 
11325 	// Generating individual data dictionaries
11326 	for(auto &itr : objs_map)
11327 	{
11328 		object = itr.second;
11329 
11330 		// Generate the individual data dictionaries
11331 		aux_attribs[Attributes::Index] = browsable ? Attributes::True : "";
11332 		aux_attribs[Attributes::Previous] = idx - 1 >= 0 ? index_list.at(idx - 1) : "";
11333 		aux_attribs[Attributes::Next] = (++idx <= index_list.size() - 1) ? index_list.at(idx) : "";
11334 		attribs[Attributes::Objects] += dynamic_cast<BaseTable *>(object)->getDataDictionary(splitted, aux_attribs);
11335 
11336 		// If the generation is configured to be splitted we generate a complete HTML file for the current table
11337 		if(splitted && !attribs[Attributes::Objects].isEmpty())
11338 		{
11339 			id = itr.first + QString(".html");
11340 			schparser.ignoreEmptyAttributes(true);
11341 			datadict[id] = schparser.getCodeDefinition(dict_sch_file, attribs);
11342 			attribs[Attributes::Objects].clear();
11343 		}
11344 	}
11345 
11346 	// If the data dictionary is browsable we proceed with the index generation
11347 	if(browsable)
11348 	{
11349 		attribs_map idx_attribs;
11350 
11351 		idx_attribs[BaseObject::getSchemaName(ObjectType::Table)] = "";
11352 		idx_attribs[BaseObject::getSchemaName(ObjectType::View)] = "";
11353 		idx_attribs[BaseObject::getSchemaName(ObjectType::ForeignTable)] = "";
11354 
11355 		// Generating the index items
11356 		for(auto &item : index_list)
11357 		{
11358 			aux_attribs[Attributes::Splitted] = attribs[Attributes::Splitted];
11359 			aux_attribs[Attributes::Item] = item;
11360 			idx_attribs[objs_map[item]->getSchemaName()] += schparser.getCodeDefinition(item_sch_file, aux_attribs);
11361 		}
11362 
11363 		idx_attribs[Attributes::Name] = this->obj_name;
11364 		idx_attribs[Attributes::Splitted] = attribs[Attributes::Splitted];
11365 
11366 		schparser.ignoreEmptyAttributes(true);
11367 		index = schparser.getCodeDefinition(index_sch_file, idx_attribs);
11368 	}
11369 
11370 	// If the data dictionary is browsable and splitted the index goes into a separated file
11371 	if(splitted && browsable)
11372 		datadict[Attributes::Index + QString(".html")] = index;
11373 	else if(!splitted)
11374 	{
11375 		attribs[Attributes::Index] = index;
11376 		schparser.ignoreEmptyAttributes(true);
11377 		datadict[Attributes::Database] = schparser.getCodeDefinition(dict_sch_file, attribs);
11378 	}
11379 }
11380 
saveDataDictionary(const QString & path,bool browsable,bool splitted)11381 void DatabaseModel::saveDataDictionary(const QString &path, bool browsable, bool splitted)
11382 {
11383 	try
11384 	{
11385 		attribs_map datadict;
11386 		QFile output;
11387 		QByteArray buffer;
11388 		QFileInfo finfo(path);
11389 		QDir dir;
11390 
11391 		if(splitted)
11392 		{
11393 			if(finfo.exists() && !finfo.isDir())
11394 				throw Exception(Exception::getErrorMessage(ErrorCode::InvDataDictDirectory).arg(path),
11395 												ErrorCode::InvDataDictDirectory,__PRETTY_FUNCTION__,__FILE__,__LINE__);
11396 			else if(!finfo.exists())
11397 				dir.mkpath(path);
11398 		}
11399 
11400 		getDataDictionary(datadict, browsable, splitted);
11401 		output.setFileName(path);
11402 
11403 		for(auto &itr : datadict)
11404 		{
11405 			if(splitted)
11406 				output.setFileName(path + GlobalAttributes::DirSeparator + itr.first);
11407 
11408 			output.open(QFile::WriteOnly);
11409 
11410 			if(!output.isOpen())
11411 			{
11412 				throw Exception(Exception::getErrorMessage(ErrorCode::FileDirectoryNotWritten).arg(output.fileName()),
11413 												ErrorCode::FileDirectoryNotWritten,__PRETTY_FUNCTION__,__FILE__,__LINE__);
11414 			}
11415 
11416 			buffer.append(itr.second);
11417 			output.write(buffer);
11418 			output.close();
11419 			buffer.clear();
11420 		}
11421 	}
11422 	catch(Exception &e)
11423 	{
11424 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
11425 	}
11426 }
11427 
getChangelogDefinition()11428 QString DatabaseModel::getChangelogDefinition()
11429 {
11430 	if(!persist_changelog)
11431 		return "";
11432 
11433 	try
11434 	{
11435 		QDateTime date;
11436 		QString signature, action, xml_code;
11437 		ObjectType type;
11438 		attribs_map attribs;
11439 
11440 		for(auto &entry : changelog)
11441 		{
11442 			date = std::get<LogDate>(entry);
11443 			signature = std::get<LogSinature>(entry);
11444 			type = std::get<LogObjectType>(entry);
11445 			action = std::get<LogAction>(entry);
11446 
11447 			attribs[Attributes::Date] = date.toString(Qt::ISODate);
11448 			attribs[Attributes::Signature] = signature;
11449 			attribs[Attributes::Type] = BaseObject::getSchemaName(type);
11450 			attribs[Attributes::Action] = action;
11451 
11452 			xml_code += schparser.getCodeDefinition(Attributes::Entry, attribs, SchemaParser::XmlDefinition);
11453 		}
11454 
11455 		attribs.clear();
11456 		attribs[Attributes::Entry] = xml_code;
11457 		schparser.ignoreEmptyAttributes(true);
11458 		return schparser.getCodeDefinition(Attributes::Changelog, attribs, SchemaParser::XmlDefinition);
11459 	}
11460 	catch(Exception &e)
11461 	{
11462 		throw Exception(e.getErrorMessage(), e.getErrorCode(), __PRETTY_FUNCTION__, __FILE__, __LINE__, &e);
11463 	}
11464 }
11465