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 "constraint.h"
20 
Constraint()21 Constraint::Constraint()
22 {
23 	ref_table=nullptr;
24 	obj_type=ObjectType::Constraint;
25 	deferrable=false;
26 	no_inherit=false;
27 	fill_factor=0;
28 	index_type=BaseType::Null;
29 
30 	attributes[Attributes::PkConstr]="";
31 	attributes[Attributes::FkConstr]="";
32 	attributes[Attributes::CkConstr]="";
33 	attributes[Attributes::UqConstr]="";
34 	attributes[Attributes::ExConstr]="";
35 	attributes[Attributes::RefTable]="";
36 	attributes[Attributes::SrcColumns]="";
37 	attributes[Attributes::DstColumns]="";
38 	attributes[Attributes::DelAction]="";
39 	attributes[Attributes::UpdAction]="";
40 	attributes[Attributes::Expression]="";
41 	attributes[Attributes::Type]="";
42 	attributes[Attributes::ComparisonType]="";
43 	attributes[Attributes::DeferType]="";
44 	attributes[Attributes::IndexType]="";
45 	attributes[Attributes::Deferrable]="";
46 	attributes[Attributes::Table]="";
47 	attributes[Attributes::DeclInTable]="";
48 	attributes[Attributes::Factor]="";
49 	attributes[Attributes::NoInherit]="";
50 	attributes[Attributes::Elements]="";
51 }
52 
~Constraint()53 Constraint::~Constraint()
54 {
55 	columns.clear();
56 	ref_columns.clear();
57 }
58 
setConstraintType(ConstraintType constr_type)59 void Constraint::setConstraintType(ConstraintType constr_type)
60 {
61 	this->constr_type=constr_type;
62 }
63 
setActionType(ActionType action_type,unsigned act_id)64 void Constraint::setActionType(ActionType action_type, unsigned act_id)
65 {
66 	if(act_id==DeleteAction)
67 	{
68 		setCodeInvalidated(this->del_action != action_type);
69 		this->del_action=action_type;
70 	}
71 	else
72 	{
73 		setCodeInvalidated(this->upd_action != action_type);
74 		this->upd_action=action_type;
75 	}
76 }
77 
setExpression(const QString & expr)78 void Constraint::setExpression(const QString &expr)
79 {
80 	setCodeInvalidated(expression != expr);
81 	expression=expr;
82 }
83 
isColumnExists(Column * column,unsigned col_type)84 bool Constraint::isColumnExists(Column *column, unsigned col_type)
85 {
86 	vector<Column *>::iterator itr, itr_end;
87 	bool found=false;
88 
89 	//Raises an error if the column is not allocated
90 	if(!column)
91 		throw Exception(ErrorCode::OprNotAllocatedObject,__PRETTY_FUNCTION__,__FILE__,__LINE__);
92 
93 	//Gets the iterators from the specified internal list
94 	if(col_type==SourceCols)
95 	{
96 		itr=columns.begin();
97 		itr_end=columns.end();
98 	}
99 	else
100 	{
101 		itr=ref_columns.begin();
102 		itr_end=ref_columns.end();
103 	}
104 
105 	//Tries to find the column  on the internal list
106 	while(itr!=itr_end && !found)
107 	{
108 		found=((*itr)==column);
109 		itr++;
110 	}
111 
112 	return found;
113 }
114 
isColumnsExist(vector<Column * > columns,unsigned col_type)115 bool Constraint::isColumnsExist(vector<Column *> columns, unsigned col_type)
116 {
117 	bool is_ref = false;
118 
119 	for(auto &col : columns)
120 	{
121 		is_ref = isColumnExists(col, col_type);
122 		if(!is_ref) break;
123 	}
124 
125 	return is_ref;
126 }
127 
isColumnReferenced(Column * column,bool search_only_ref_cols)128 bool Constraint::isColumnReferenced(Column *column, bool search_only_ref_cols)
129 {
130 	bool found=false;
131 	vector<ExcludeElement>::iterator itr, itr_end;
132 
133 	if(constr_type == ConstraintType::PrimaryKey ||
134 			constr_type == ConstraintType::Unique ||
135 			constr_type == ConstraintType::ForeignKey)
136 	{
137 		if(!search_only_ref_cols)
138 			found=isColumnExists(column, SourceCols);
139 
140 		if(!found && constr_type==ConstraintType::ForeignKey)
141 			found=isColumnExists(column, ReferencedCols);
142 	}
143 	else if(constr_type==ConstraintType::Exclude)
144 	{
145 		//Iterates over the exclude elements
146 		itr=excl_elements.begin();
147 		itr_end=excl_elements.end();
148 
149 		while(itr!=itr_end && !found)
150 		{
151 			found=((*itr).getColumn() == column);
152 			itr++;
153 		}
154 	}
155 
156 	return found;
157 }
158 
addColumn(Column * column,unsigned col_type)159 void Constraint::addColumn(Column *column, unsigned col_type)
160 {
161 	//Raises an error if the column is not allocated
162 	if(!column)
163 		throw Exception(Exception::getErrorMessage(ErrorCode::AsgNotAllocatedColumn)
164 						.arg(this->getName())
165 						.arg(BaseObject::getTypeName(ObjectType::Constraint)),
166 						ErrorCode::AsgNotAllocatedColumn,__PRETTY_FUNCTION__,__FILE__,__LINE__);
167 	else if(constr_type!=ConstraintType::Check)
168 	{
169 		//Adds the column only if the column doesn't exists on the internal list
170 		if(!isColumnExists(column,col_type))
171 		{
172 			if(col_type==ReferencedCols)
173 				ref_columns.push_back(column);
174 			else
175 			{
176 				columns.push_back(column);
177 				setColumnsNotNull(true);
178 			}
179 
180 			setCodeInvalidated(true);
181 		}
182 	}
183 }
184 
setTablespace(BaseObject * tabspc)185 void Constraint::setTablespace(BaseObject *tabspc)
186 {
187 	try
188 	{
189 		if(tabspc &&
190 				constr_type!=ConstraintType::PrimaryKey &&
191 				constr_type!=ConstraintType::Unique)
192 			throw Exception(ErrorCode::AsgTablespaceInvalidConstraintType,__PRETTY_FUNCTION__,__FILE__,__LINE__);
193 
194 		BaseObject::setTablespace(tabspc);
195 	}
196 	catch(Exception &e)
197 	{
198 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
199 	}
200 }
201 
setColumnsAttribute(unsigned col_type,unsigned def_type,bool inc_addedbyrel)202 void Constraint::setColumnsAttribute(unsigned col_type, unsigned def_type, bool inc_addedbyrel)
203 {
204 	vector<Column *> *col_vector=nullptr;
205 	Column *col=nullptr;
206 	QString str_cols, attrib;
207 	unsigned i, count;
208 	bool format=(def_type==SchemaParser::SqlDefinition);
209 
210 	if(col_type==ReferencedCols)
211 	{
212 		col_vector=&ref_columns;
213 		attrib=Attributes::DstColumns;
214 	}
215 	else
216 	{
217 		col_vector=&columns;
218 		attrib=Attributes::SrcColumns;
219 	}
220 
221 	count=col_vector->size();
222 	for(i=0; i < count; i++)
223 	{
224 		col=col_vector->at(i);
225 
226 		/* For XML definition the columns added to the constraint
227 		 through relationship can not be included because they are inserted
228 		 to the restriction on the time of creation of the relationship from its XML
229 		 so the parameter 'inc_addedbyrel' can be used to solve this case. */
230 		if((def_type==SchemaParser::SqlDefinition) ||
231 				((def_type==SchemaParser::XmlDefinition) &&
232 				 ((inc_addedbyrel && col->isAddedByRelationship()) ||
233 				  (inc_addedbyrel && !col->isAddedByRelationship()) ||
234 				  (!inc_addedbyrel && !col->isAddedByRelationship()))))
235 		{
236 			str_cols+=col->getName(format);
237 			str_cols+=',';
238 		}
239 	}
240 
241 	str_cols.remove(str_cols.size()-1,1);
242 	attributes[attrib]=str_cols;
243 }
244 
setReferencedTable(BaseTable * tab_ref)245 void Constraint::setReferencedTable(BaseTable *tab_ref)
246 {
247 	this->ref_table=tab_ref;
248 }
249 
setDeferralType(DeferralType deferral_type)250 void Constraint::setDeferralType(DeferralType deferral_type)
251 {
252 	this->deferral_type=deferral_type;
253 }
254 
setDeferrable(bool value)255 void Constraint::setDeferrable(bool value)
256 {
257 	deferrable=value;
258 }
259 
setMatchType(MatchType match_type)260 void Constraint::setMatchType(MatchType match_type)
261 {
262 	this->match_type=match_type;
263 }
264 
setFillFactor(unsigned factor)265 void Constraint::setFillFactor(unsigned factor)
266 {
267 	if(factor!=0 && factor < 10) factor=10;
268 	else if(factor > 100) factor=100;
269 	fill_factor=factor;
270 }
271 
setNoInherit(bool value)272 void Constraint::setNoInherit(bool value)
273 {
274 	no_inherit=value;
275 }
276 
getFillFactor()277 unsigned Constraint::getFillFactor()
278 {
279 	return fill_factor;
280 }
281 
getConstraintType()282 ConstraintType Constraint::getConstraintType()
283 {
284 	return constr_type;
285 }
286 
getActionType(unsigned act_id)287 ActionType Constraint::getActionType(unsigned act_id)
288 {
289 	if(act_id==DeleteAction)
290 		return del_action;
291 	else
292 		return upd_action;
293 }
294 
getColumns(unsigned col_type)295 vector<Column *> Constraint::getColumns(unsigned col_type)
296 {
297   return (col_type==SourceCols ? columns : ref_columns);
298 }
299 
getExpression()300 QString Constraint::getExpression()
301 {
302 	return expression;
303 }
304 
getColumn(unsigned col_idx,unsigned col_type)305 Column *Constraint::getColumn(unsigned col_idx, unsigned col_type)
306 {
307 	vector<Column *> *col_list=nullptr;
308 
309 	col_list=(col_type==SourceCols ? &columns : &ref_columns);
310 
311 	//Raises an error if the column index is invalid (out of bound)
312 	if(col_idx>=col_list->size())
313 		throw Exception(ErrorCode::RefColumnInvalidIndex,__PRETTY_FUNCTION__,__FILE__,__LINE__);
314 
315 	return col_list->at(col_idx);
316 }
317 
getColumn(const QString & name,unsigned col_type)318 Column *Constraint::getColumn(const QString &name, unsigned col_type)
319 {
320 	bool found=false;
321 	vector<Column *> *col_list=nullptr;
322 	vector<Column *>::iterator itr_col, itr_end_col;
323 
324 	col_list=(col_type==SourceCols? &columns : &ref_columns);
325 
326 	itr_col=col_list->begin();
327 	itr_end_col=col_list->end();
328 
329 	while(itr_col!=itr_end_col)
330 	{
331 		found=((*itr_col)->getName()==name);
332 		if(!found) itr_col++;
333 		else break;
334 	}
335 
336 	if(found) return *itr_col;
337 	else return nullptr;
338 }
339 
getReferencedTable()340 BaseTable *Constraint::getReferencedTable()
341 {
342 	return ref_table;
343 }
344 
getColumnCount(unsigned col_type)345 unsigned Constraint::getColumnCount(unsigned col_type)
346 {
347 	if(col_type==ReferencedCols)
348 		return ref_columns.size();
349 	else
350 		return columns.size();
351 }
352 
removeColumns()353 void Constraint::removeColumns()
354 {
355 	setColumnsNotNull(false);
356 	columns.clear();
357 	ref_columns.clear();
358 	setCodeInvalidated(true);
359 }
360 
removeColumn(const QString & name,unsigned col_type)361 void Constraint::removeColumn(const QString &name, unsigned col_type)
362 {
363 	vector<Column *>::iterator itr, itr_end;
364 	vector<Column *> *cols=nullptr;
365 	Column *col=nullptr;
366 
367 	//Gets the column list using the specified internal list type
368 	if(col_type==ReferencedCols)
369 		cols=&ref_columns;
370 	else
371 		cols=&columns;
372 
373 	itr=cols->begin();
374 	itr_end=cols->end();
375 
376 	while(itr!=itr_end)
377 	{
378 		col=(*itr);
379 
380 		//Case the column is found
381 		if(col->getName()==name)
382 		{
383 			if(constr_type==ConstraintType::PrimaryKey)
384 				col->setNotNull(false);
385 
386 			//Remove its iterator from the list
387 			cols->erase(itr);
388 			setCodeInvalidated(true);
389 			break;
390 		}
391 		else itr++;
392 	}
393 }
394 
getDeferralType()395 DeferralType Constraint::getDeferralType()
396 {
397 	return deferral_type;
398 }
399 
isDeferrable()400 bool Constraint::isDeferrable()
401 {
402 	return deferrable;
403 }
404 
isNoInherit()405 bool Constraint::isNoInherit()
406 {
407 	return no_inherit;
408 }
409 
isReferRelationshipAddedColumn()410 bool Constraint::isReferRelationshipAddedColumn()
411 {
412 	vector<Column *>::iterator itr, itr_end;
413 	vector<ExcludeElement>::iterator itr1, itr1_end;
414 	Column *col=nullptr;
415 	bool found=false;
416 
417 	//First iterates over the source columns list
418 	itr=columns.begin();
419 	itr_end=columns.end();
420 
421 	while(itr!=itr_end && !found)
422 	{
423 		col=(*itr);
424 		//Check if the current column were added by relationship
425 		found=col->isAddedByRelationship();
426 		itr++;
427 
428 		/* Case the source column list is completely iterated steps to
429 		 the referenced columns list iteration */
430 		if(itr==itr_end && itr_end!=ref_columns.end() && !found)
431 		{
432 			itr=ref_columns.begin();
433 			itr_end=ref_columns.end();
434 		}
435 	}
436 
437 	//Iterates over the exclude elements
438 	itr1=excl_elements.begin();
439 	itr1_end=excl_elements.end();
440 
441 	while(itr1!=itr1_end && !found)
442 	{
443 		col=(*itr1).getColumn();
444 		found=(col && col->isAddedByRelationship());
445 		itr1++;
446 	}
447 
448 	return found;
449 }
450 
getRelationshipAddedColumns()451 vector<Column *> Constraint::getRelationshipAddedColumns()
452 {
453 	Column *column=nullptr;
454 	vector<Column *> cols;
455 	vector<vector<Column *> *> lists = { &columns, &ref_columns };
456 
457 	for(auto &p_lst : lists)
458 	{
459 		for(auto &col : (*p_lst))
460 		{
461 			if(col->isAddedByRelationship())
462 				cols.push_back(col);
463 		}
464 	}
465 
466 	for(auto &excl_elem : excl_elements)
467 	{
468 		column=excl_elem.getColumn();
469 		if(column && column->isAddedByRelationship())
470 			cols.push_back(column);
471 	}
472 
473 	return cols;
474 }
475 
getMatchType()476 MatchType Constraint::getMatchType()
477 {
478 	return match_type;
479 }
480 
481 
getExcludeElementIndex(ExcludeElement elem)482 int Constraint::getExcludeElementIndex(ExcludeElement elem)
483 {
484 	int idx=0;
485 	bool found=false;
486 
487 	while(idx < static_cast<int>(excl_elements.size()) && !found)
488 	{
489 		found=(excl_elements[idx]==elem);
490 		if(!found) idx++;
491 	}
492 
493 	return (found ? idx : -1);
494 }
495 
getExcludeElements()496 vector<ExcludeElement> Constraint::getExcludeElements()
497 {
498 	return excl_elements;
499 }
500 
addExcludeElements(vector<ExcludeElement> & elems)501 void Constraint::addExcludeElements(vector<ExcludeElement> &elems)
502 {
503 	vector<ExcludeElement> elems_bkp=excl_elements;
504 
505 	try
506 	{
507 		excl_elements.clear();
508 
509 		for(unsigned i=0; i < elems.size(); i++)
510 			addExcludeElement(elems[i]);
511 	}
512 	catch(Exception &e)
513 	{
514 		excl_elements = elems_bkp;
515 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
516 	}
517 }
518 
addExcludeElement(ExcludeElement elem)519 void Constraint::addExcludeElement(ExcludeElement elem)
520 {
521 	if(getExcludeElementIndex(elem) >= 0)
522 		throw Exception(ErrorCode::InsDuplicatedElement,__PRETTY_FUNCTION__,__FILE__,__LINE__);
523 
524 	if(elem.getExpression().isEmpty() && !elem.getColumn())
525 		throw Exception(ErrorCode::AsgInvalidExpressionObject,__PRETTY_FUNCTION__,__FILE__,__LINE__);
526 
527 	excl_elements.push_back(elem);
528 	setCodeInvalidated(true);
529 }
530 
addExcludeElement(const QString & expr,Operator * oper,OperatorClass * op_class,bool use_sorting,bool asc_order,bool nulls_first)531 void Constraint::addExcludeElement(const QString &expr, Operator *oper, OperatorClass *op_class, bool use_sorting, bool asc_order, bool nulls_first)
532 {
533 	try
534 	{
535 		ExcludeElement elem;
536 
537 		//Raises an error if the expression is empty
538 		if(expr.isEmpty())
539 			throw Exception(ErrorCode::AsgInvalidExpressionObject,__PRETTY_FUNCTION__,__FILE__,__LINE__);
540 
541 		//Configures the element
542 		elem.setExpression(expr);
543 		elem.setOperatorClass(op_class);
544 		elem.setOperator(oper);
545 		elem.setSortingEnabled(use_sorting);
546 		elem.setSortingAttribute(ExcludeElement::NullsFirst, nulls_first);
547 		elem.setSortingAttribute(ExcludeElement::AscOrder, asc_order);
548 
549 		if(getExcludeElementIndex(elem) >= 0)
550 			throw Exception(ErrorCode::InsDuplicatedElement,__PRETTY_FUNCTION__,__FILE__,__LINE__);
551 
552 		excl_elements.push_back(elem);
553 		setCodeInvalidated(true);
554 	}
555 	catch(Exception &e)
556 	{
557 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
558 	}
559 }
560 
addExcludeElement(Column * column,Operator * oper,OperatorClass * op_class,bool use_sorting,bool asc_order,bool nulls_first)561 void Constraint::addExcludeElement(Column *column, Operator *oper, OperatorClass *op_class, bool use_sorting, bool asc_order, bool nulls_first)
562 {
563 	try
564 	{
565 		ExcludeElement elem;
566 
567 		//Case the column is not allocated raises an error
568 		if(!column)
569 			throw Exception(Exception::getErrorMessage(ErrorCode::AsgNotAllocatedColumn)
570 							.arg(this->getName())
571 							.arg(this->getTypeName()),
572 							ErrorCode::AsgNotAllocatedColumn,__PRETTY_FUNCTION__,__FILE__,__LINE__);
573 
574 		//Configures the element
575 		elem.setColumn(column);
576 		elem.setOperatorClass(op_class);
577 		elem.setOperator(oper);
578 		elem.setSortingEnabled(use_sorting);
579 		elem.setSortingAttribute(ExcludeElement::NullsFirst, nulls_first);
580 		elem.setSortingAttribute(ExcludeElement::AscOrder, asc_order);
581 
582 		if(getExcludeElementIndex(elem) >= 0)
583 			throw Exception(ErrorCode::InsDuplicatedElement,__PRETTY_FUNCTION__,__FILE__,__LINE__);
584 
585 		excl_elements.push_back(elem);
586 		setCodeInvalidated(true);
587 	}
588 	catch(Exception &e)
589 	{
590 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
591 	}
592 }
593 
removeExcludeElement(unsigned elem_idx)594 void Constraint::removeExcludeElement(unsigned elem_idx)
595 {
596 	if(elem_idx >= excl_elements.size())
597 		throw Exception(ErrorCode::RefElementInvalidIndex,__PRETTY_FUNCTION__,__FILE__,__LINE__);
598 
599 	excl_elements.erase(excl_elements.begin() + elem_idx);
600 	setCodeInvalidated(true);
601 }
602 
removeExcludeElements()603 void Constraint::removeExcludeElements()
604 {
605 	excl_elements.clear();
606 	setCodeInvalidated(true);
607 }
608 
setColumnsNotNull(bool value)609 void Constraint::setColumnsNotNull(bool value)
610 {
611 	if(constr_type==ConstraintType::PrimaryKey)
612 	{
613 		for(auto &col : columns)
614 		{
615 			//if(!col->isAddedByRelationship())
616 			col->setNotNull(value);
617 		}
618 	}
619 }
620 
getExcludeElement(unsigned elem_idx)621 ExcludeElement Constraint::getExcludeElement(unsigned elem_idx)
622 {
623 	if(elem_idx >= excl_elements.size())
624 		throw Exception(ErrorCode::RefElementInvalidIndex,__PRETTY_FUNCTION__,__FILE__,__LINE__);
625 
626 	return excl_elements[elem_idx];
627 }
628 
getExcludeElementCount()629 unsigned Constraint::getExcludeElementCount()
630 {
631 	return excl_elements.size();
632 }
633 
setExcludeElementsAttribute(unsigned def_type)634 void Constraint::setExcludeElementsAttribute(unsigned def_type)
635 {
636 	QString str_elem;
637 	unsigned i, count;
638 
639 	count=excl_elements.size();
640 	for(i=0; i < count; i++)
641 	{
642 		str_elem+=excl_elements[i].getCodeDefinition(def_type);
643 		if(i < (count-1) && def_type==SchemaParser::SqlDefinition) str_elem+=',';
644 	}
645 
646 	attributes[Attributes::Elements]=str_elem;
647 }
648 
setIndexType(IndexingType index_type)649 void Constraint::setIndexType(IndexingType index_type)
650 {
651 	this->index_type=index_type;
652 }
653 
getIndexType()654 IndexingType Constraint::getIndexType()
655 {
656 	return index_type;
657 }
658 
getCodeDefinition(unsigned def_type)659 QString Constraint::getCodeDefinition(unsigned def_type)
660 {
661 	return getCodeDefinition(def_type, false);
662 }
663 
setDeclInTableAttribute()664 void Constraint::setDeclInTableAttribute()
665 {
666 	if(!isDeclaredInTable() || (constr_type==ConstraintType::ForeignKey && !isAddedByLinking()))
667 		attributes[Attributes::DeclInTable]="";
668 	else if(!isReferRelationshipAddedColumn() || constr_type==ConstraintType::PrimaryKey)
669 		attributes[Attributes::DeclInTable]=Attributes::True;
670 }
671 
getCodeDefinition(unsigned def_type,bool inc_addedbyrel)672 QString Constraint::getCodeDefinition(unsigned def_type, bool inc_addedbyrel)
673 {
674 	QString code_def=getCachedCode(def_type, false);
675 	if(!inc_addedbyrel && !code_def.isEmpty()) return code_def;
676 
677 	QString attrib;
678 
679 	attributes[Attributes::PkConstr]="";
680 	attributes[Attributes::FkConstr]="";
681 	attributes[Attributes::CkConstr]="";
682 	attributes[Attributes::UqConstr]="";
683 	attributes[Attributes::ExConstr]="";
684 
685 	switch(!constr_type)
686 	{
687 		case ConstraintType::Check:
688 			attrib=Attributes::CkConstr;
689 		break;
690 		case ConstraintType::PrimaryKey:
691 			attrib=Attributes::PkConstr;
692 		break;
693 		case ConstraintType::ForeignKey:
694 			attrib=Attributes::FkConstr;
695 		break;
696 		case ConstraintType::Unique:
697 			attrib=Attributes::UqConstr;
698 		break;
699 		default:
700 			attrib=Attributes::ExConstr;
701 		break;
702 	}
703 	attributes[attrib]=Attributes::True;
704 
705 	attributes[Attributes::Type]=attrib;
706 	attributes[Attributes::UpdAction]=(~upd_action);
707 	attributes[Attributes::DelAction]=(~del_action);
708 	attributes[Attributes::Expression]=expression;
709 
710 	if(constr_type!=ConstraintType::Check)
711 	{
712 		if(constr_type!=ConstraintType::Exclude)
713 			setColumnsAttribute(SourceCols, def_type, inc_addedbyrel);
714 		else
715 			setExcludeElementsAttribute(def_type);
716 
717 		/* Only generates the definition of the foreign key referenced columns
718 		 if the number of columns of the source and referenced cols list are equal,
719 		 this means the constraint is configured correctly, otherwise don't generates
720 		 the attribute forcing the schema parser to return an error because the foreign key is
721 		 misconfigured. */
722 		if(constr_type==ConstraintType::ForeignKey && columns.size() == ref_columns.size())
723 			setColumnsAttribute(ReferencedCols, def_type, inc_addedbyrel);
724 	}
725 
726 	attributes[Attributes::RefTable]=(ref_table ? ref_table->getName(true) : "");
727 	attributes[Attributes::Deferrable]=(deferrable ? Attributes::True : "");
728 	attributes[Attributes::NoInherit]=(no_inherit ? Attributes::True : "");
729 	attributes[Attributes::ComparisonType]=(~match_type);
730 	attributes[Attributes::DeferType]=(~deferral_type);
731 	attributes[Attributes::IndexType]=(~ index_type);
732 
733 	if(getParentTable())
734 		attributes[Attributes::Table]=getParentTable()->getName(true);
735 
736 	setDeclInTableAttribute();
737 
738 	if(fill_factor!=0 && (constr_type==ConstraintType::PrimaryKey || constr_type==ConstraintType::Unique))
739 		attributes[Attributes::Factor]=QString("%1").arg(fill_factor);
740 	else
741 		attributes[Attributes::Factor]="";
742 
743 	return BaseObject::__getCodeDefinition(def_type);
744 }
745 
getDropDefinition(bool cascade)746 QString Constraint::getDropDefinition(bool cascade)
747 {
748 	setDeclInTableAttribute();
749 	return TableObject::getDropDefinition(cascade);
750 }
751 
getSignature(bool format)752 QString Constraint::getSignature(bool format)
753 {
754 	if(!getParentTable())
755 		return BaseObject::getSignature(format);
756 
757 	return QString("%1 ON %2 ").arg(this->getName(format)).arg(getParentTable()->getSignature(true));
758 }
759 
isCodeDiffersFrom(BaseObject * object,const vector<QString> & ignored_attribs,const vector<QString> & ignored_tags)760 bool Constraint::isCodeDiffersFrom(BaseObject *object, const vector<QString> &ignored_attribs, const vector<QString> &ignored_tags)
761 {
762 	if(!object)
763 		throw Exception(ErrorCode::OprNotAllocatedObject,__PRETTY_FUNCTION__,__FILE__,__LINE__);
764 	else if(object->getObjectType()!=this->getObjectType())
765 		throw Exception(ErrorCode::OprObjectInvalidType,__PRETTY_FUNCTION__,__FILE__,__LINE__);
766 
767 	try
768 	{
769 		return BaseObject::isCodeDiffersFrom(this->getCodeDefinition(SchemaParser::XmlDefinition, true),
770 											 object->getCodeDefinition(SchemaParser::XmlDefinition, true),
771 											 ignored_attribs, ignored_tags);
772 	}
773 	catch(Exception &e)
774 	{
775 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
776 	}
777 }
778