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