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