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 "table.h"
20 #include "pgmodelerns.h"
21
Table()22 Table::Table() : PhysicalTable()
23 {
24 obj_type = ObjectType::Table;
25 with_oid=unlogged=rls_enabled=rls_forced=false;
26 attributes[Attributes::Unlogged]="";
27 attributes[Attributes::RlsEnabled]="";
28 attributes[Attributes::RlsForced]="";
29 attributes[Attributes::Oids]="";
30 setName(tr("new_table"));
31 }
32
~Table()33 Table::~Table()
34 {
35 destroyObjects();
36 }
37
setUnlogged(bool value)38 void Table::setUnlogged(bool value)
39 {
40 setCodeInvalidated(unlogged != value);
41 unlogged=value;
42 }
43
setRLSEnabled(bool value)44 void Table::setRLSEnabled(bool value)
45 {
46 setCodeInvalidated(rls_enabled != value);
47 rls_enabled = value;
48 }
49
setRLSForced(bool value)50 void Table::setRLSForced(bool value)
51 {
52 setCodeInvalidated(rls_forced != value);
53 rls_forced = value;
54 }
55
addObject(BaseObject * object,int obj_idx)56 void Table::addObject(BaseObject *object, int obj_idx)
57 {
58 try
59 {
60 PhysicalTable::addObject(object, obj_idx);
61
62 if(object->getObjectType() == ObjectType::Table)
63 {
64 /* Updating the storage parameter WITH OIDS depending on the ancestors.
65 * According to the docs, the child table will inherit WITH OID status from the parents */
66 with_oid=(with_oid || dynamic_cast<Table *>(object)->isWithOIDs());
67 }
68 }
69 catch(Exception &e)
70 {
71 throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
72 }
73 }
74
removeObject(unsigned obj_idx,ObjectType obj_type)75 void Table::removeObject(unsigned obj_idx, ObjectType obj_type)
76 {
77 try
78 {
79 Table *tab = nullptr;
80 PhysicalTable::removeObject(obj_idx, obj_type);
81 with_oid=false;
82
83 for(auto &obj : ancestor_tables)
84 {
85 tab = dynamic_cast<Table *>(obj);
86 if(!with_oid && tab->isWithOIDs())
87 {
88 with_oid=true;
89 break;
90 }
91 }
92 }
93 catch(Exception &e)
94 {
95 throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
96 }
97 }
98
removeObject(const QString & name,ObjectType obj_type)99 void Table::removeObject(const QString &name, ObjectType obj_type)
100 {
101 try
102 {
103 PhysicalTable::removeObject(name, obj_type);
104 }
105 catch(Exception &e)
106 {
107 throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
108 }
109 }
110
removeObject(BaseObject * obj)111 void Table::removeObject(BaseObject *obj)
112 {
113 try
114 {
115 PhysicalTable::removeObject(obj);
116 }
117 catch(Exception &e)
118 {
119 throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
120 }
121 }
122
getObjectList(ObjectType obj_type)123 vector<TableObject *> *Table::getObjectList(ObjectType obj_type)
124 {
125 if(obj_type==ObjectType::Rule)
126 return &rules;
127
128 if(obj_type==ObjectType::Index)
129 return &indexes;
130
131 if(obj_type==ObjectType::Policy)
132 return &policies;
133
134 return PhysicalTable::getObjectList(obj_type);
135 }
136
addIndex(Index * ind,int idx)137 void Table::addIndex(Index *ind, int idx)
138 {
139 try
140 {
141 addObject(ind, idx);
142 }
143 catch(Exception &e)
144 {
145 throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
146 }
147 }
148
addRule(Rule * reg,int idx_reg)149 void Table::addRule(Rule *reg, int idx_reg)
150 {
151 try
152 {
153 addObject(reg, idx_reg);
154 }
155 catch(Exception &e)
156 {
157 throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
158 }
159 }
160
addPolicy(Policy * pol,int idx_pol)161 void Table::addPolicy(Policy *pol, int idx_pol)
162 {
163 try
164 {
165 addObject(pol, idx_pol);
166 }
167 catch(Exception &e)
168 {
169 throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
170 }
171 }
172
removeIndex(const QString & name)173 void Table::removeIndex(const QString &name)
174 {
175 try
176 {
177 removeObject(name,ObjectType::Index);
178 }
179 catch(Exception &e)
180 {
181 throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
182 }
183 }
184
removeIndex(unsigned idx)185 void Table::removeIndex(unsigned idx)
186 {
187 try
188 {
189 removeObject(idx,ObjectType::Index);
190 }
191 catch(Exception &e)
192 {
193 throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
194 }
195 }
196
removeRule(const QString & name)197 void Table::removeRule(const QString &name)
198 {
199 try
200 {
201 removeObject(name,ObjectType::Rule);
202 }
203 catch(Exception &e)
204 {
205 throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
206 }
207 }
208
removeRule(unsigned idx)209 void Table::removeRule(unsigned idx)
210 {
211 try
212 {
213 removeObject(idx,ObjectType::Rule);
214 }
215 catch(Exception &e)
216 {
217 throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
218 }
219 }
220
removePolicy(const QString & name)221 void Table::removePolicy(const QString &name)
222 {
223 try
224 {
225 removeObject(name, ObjectType::Policy);
226 }
227 catch(Exception &e)
228 {
229 throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
230 }
231 }
232
removePolicy(unsigned idx)233 void Table::removePolicy(unsigned idx)
234 {
235 try
236 {
237 removeObject(idx, ObjectType::Policy);
238 }
239 catch(Exception &e)
240 {
241 throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
242 }
243 }
244
getIndex(const QString & name)245 Index *Table::getIndex(const QString &name)
246 {
247 int idx;
248 return dynamic_cast<Index *>(getObject(name,ObjectType::Index,idx));
249 }
250
getIndex(unsigned idx)251 Index *Table::getIndex(unsigned idx)
252 {
253 return dynamic_cast<Index *>(getObject(idx,ObjectType::Index));
254 }
255
getRule(const QString & name)256 Rule *Table::getRule(const QString &name)
257 {
258 int idx;
259 return dynamic_cast<Rule *>(getObject(name,ObjectType::Rule,idx));
260 }
261
getRule(unsigned idx)262 Rule *Table::getRule(unsigned idx)
263 {
264 return dynamic_cast<Rule *>(getObject(idx,ObjectType::Rule));
265 }
266
getPolicy(const QString & name)267 Policy *Table::getPolicy(const QString &name)
268 {
269 int idx;
270 return dynamic_cast<Policy *>(getObject(name, ObjectType::Policy,idx));
271 }
272
getPolicy(unsigned idx)273 Policy *Table::getPolicy(unsigned idx)
274 {
275 return dynamic_cast<Policy *>(getObject(idx, ObjectType::Policy));
276 }
277
getIndexCount()278 unsigned Table::getIndexCount()
279 {
280 return indexes.size();
281 }
282
getRuleCount()283 unsigned Table::getRuleCount()
284 {
285 return rules.size();
286 }
287
getPolicyCount()288 unsigned Table::getPolicyCount()
289 {
290 return policies.size();
291 }
292
getForeignKeys(vector<Constraint * > & fks,bool inc_added_by_rel,Table * ref_table)293 void Table::getForeignKeys(vector<Constraint *> &fks, bool inc_added_by_rel, Table *ref_table)
294 {
295 unsigned count,i;
296 Constraint *constr=nullptr;
297
298 count=constraints.size();
299 for(i=0; i < count; i++)
300 {
301 constr=dynamic_cast<Constraint *>(constraints[i]);
302
303 if(constr->getConstraintType()==ConstraintType::ForeignKey &&
304 (!ref_table || (ref_table && constr->getReferencedTable()==ref_table)) &&
305 (!constr->isAddedByLinking() ||
306 (constr->isAddedByLinking() && inc_added_by_rel)))
307 fks.push_back(constr);
308 }
309 }
310
isUnlogged()311 bool Table::isUnlogged()
312 {
313 return unlogged;
314 }
315
isRLSEnabled()316 bool Table::isRLSEnabled()
317 {
318 return rls_enabled;
319 }
320
isRLSForced()321 bool Table::isRLSForced()
322 {
323 return rls_forced;
324 }
325
setWithOIDs(bool value)326 void Table::setWithOIDs(bool value)
327 {
328 setCodeInvalidated(with_oid != value);
329 with_oid=value;
330 }
331
isWithOIDs()332 bool Table::isWithOIDs()
333 {
334 return with_oid;
335 }
336
isReferTableOnForeignKey(Table * ref_tab)337 bool Table::isReferTableOnForeignKey(Table *ref_tab)
338 {
339 unsigned count,i;
340 Constraint *constr=nullptr;
341 bool found=false;
342
343 count=constraints.size();
344 for(i=0; i < count && !found; i++)
345 {
346 constr=dynamic_cast<Constraint *>(constraints[i]);
347 found=(constr->getConstraintType()==ConstraintType::ForeignKey &&
348 !constr->isAddedByLinking() &&
349 constr->getReferencedTable() == ref_tab);
350 }
351
352 return found;
353 }
354
__getCodeDefinition(unsigned def_type,bool incl_rel_added_objs)355 QString Table::__getCodeDefinition(unsigned def_type, bool incl_rel_added_objs)
356 {
357 setTableAttributes(def_type, incl_rel_added_objs);
358
359 attributes[Attributes::Oids]=(with_oid ? Attributes::True : "");
360 attributes[Attributes::Unlogged]=(unlogged ? Attributes::True : "");
361 attributes[Attributes::RlsEnabled]=(rls_enabled ? Attributes::True : "");
362 attributes[Attributes::RlsForced]=(rls_forced ? Attributes::True : "");
363 attributes[Attributes::CopyTable]="";
364
365 if(def_type==SchemaParser::SqlDefinition && copy_table)
366 attributes[Attributes::CopyTable]=copy_table->getName(true) + copy_op.getSQLDefinition();
367
368 return BaseObject::__getCodeDefinition(def_type);
369 }
370
getCodeDefinition(unsigned def_type)371 QString Table::getCodeDefinition(unsigned def_type)
372 {
373 QString code_def=getCachedCode(def_type, false);
374 if(!code_def.isEmpty()) return code_def;
375
376 return __getCodeDefinition(def_type, false);
377 }
378
operator =(Table & tab)379 void Table::operator = (Table &tab)
380 {
381 (*dynamic_cast<PhysicalTable *>(this))=dynamic_cast<PhysicalTable &>(tab);
382
383 this->copy_op=tab.copy_op;
384 this->unlogged=tab.unlogged;
385 this->with_oid=tab.with_oid;
386 this->rls_forced=tab.rls_forced;
387 this->rls_enabled=tab.rls_enabled;
388 }
389
getColumnReferences(Column * column,vector<TableObject * > & refs,bool exclusion_mode)390 void Table::getColumnReferences(Column *column, vector<TableObject *> &refs, bool exclusion_mode)
391 {
392 if(column && !column->isAddedByRelationship())
393 {
394 unsigned count, i;
395 IndexElement elem;
396 Column *col=nullptr;
397 vector<TableObject *>::iterator itr, itr_end;
398 bool found=false;
399 Index *ind=nullptr;
400
401 itr=indexes.begin();
402 itr_end=indexes.end();
403
404 while(itr!=itr_end && (!exclusion_mode || (exclusion_mode && !found)))
405 {
406 ind=dynamic_cast<Index *>(*itr);
407 itr++;
408
409 count=ind->getIndexElementCount();
410 for(i=0; i < count && (!exclusion_mode || (exclusion_mode && !found)); i++)
411 {
412 elem=ind->getIndexElement(i);
413 col=elem.getColumn();
414 if(col && col==column)
415 {
416 found=true;
417 refs.push_back(ind);
418 }
419 }
420 }
421
422 PhysicalTable::getColumnReferences(column, refs, exclusion_mode);
423 }
424 }
425
getTruncateDefinition(bool cascade)426 QString Table::getTruncateDefinition(bool cascade)
427 {
428 try
429 {
430 BaseObject::setBasicAttributes(true);
431 attributes[Attributes::Cascade]=(cascade ? Attributes::True : "");
432 return BaseObject::getAlterDefinition(Attributes::TruncatePriv, attributes, false, false);
433 }
434 catch(Exception &e)
435 {
436 throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
437 }
438 }
439
getAlterDefinition(BaseObject * object)440 QString Table::getAlterDefinition(BaseObject *object)
441 {
442 Table *tab=dynamic_cast<Table *>(object);
443
444 if(!tab)
445 throw Exception(ErrorCode::OprNotAllocatedObject,__PRETTY_FUNCTION__,__FILE__,__LINE__);
446
447 try
448 {
449 QString alter_def;
450 attribs_map attribs;
451
452 attribs[Attributes::Oids]="";
453 attribs[Attributes::AlterCmds]=BaseObject::getAlterDefinition(object, true);
454
455 if(this->getName()==tab->getName())
456 {
457 attribs[Attributes::HasChanges]=Attributes::True;
458
459 if(this->with_oid!=tab->with_oid)
460 attribs[Attributes::Oids]=(tab->with_oid ? Attributes::True : Attributes::Unset);
461
462 if(this->unlogged!=tab->unlogged)
463 attribs[Attributes::Unlogged]=(tab->unlogged ? Attributes::True : Attributes::Unset);
464
465 if(this->rls_enabled!=tab->rls_enabled)
466 attribs[Attributes::RlsEnabled]=(tab->rls_enabled ? Attributes::True : Attributes::Unset);
467
468 if(this->rls_forced!=tab->rls_forced)
469 attribs[Attributes::RlsForced]=(tab->rls_forced ? Attributes::True : Attributes::Unset);
470 }
471
472 copyAttributes(attribs);
473 alter_def=BaseObject::getAlterDefinition(this->getSchemaName(), attributes, false, true);
474
475 return alter_def;
476 }
477 catch(Exception &e)
478 {
479 throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
480 }
481 }
482