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 /**
20 \ingroup libpgmodeler
21 \class Constraint
22 \brief Implements the operations to manipulate table constraints (primary keys, foreign key, unique and check).
23 \note <strong>Creation date:</strong> 17/09/2006
24 */
25 
26 #ifndef CONSTRAINT_H
27 #define CONSTRAINT_H
28 
29 #include "tableobject.h"
30 #include "tablespace.h"
31 #include "column.h"
32 #include "excludeelement.h"
33 #include "pgsqltypes/constrainttype.h"
34 #include "pgsqltypes/deferraltype.h"
35 #include "pgsqltypes/matchtype.h"
36 #include "pgsqltypes/actiontype.h"
37 
38 class Constraint: public TableObject{
39 	private:
40 		//! \brief Type of the constraint (primary key, foreign key, unique or check)
41 		ConstraintType constr_type;
42 
43 		//! \brief Indicates if the constraint is deferrable (except for check contraints)
44 		bool deferrable,
45 
46 		//! \brief Indicates if the constraint will be copied or not to the child tables of the contraint's table (only for check constraint)
47 		no_inherit;
48 
49 		//! \brief Deferral type for the constraint (except for check contraints)
50 		DeferralType deferral_type;
51 
52 		//! \brief Matching method used by the constraint (only for foreign key)
53 		MatchType match_type;
54 
55 		//! \brief Indexing type used by the constraint (only for exclude constraints)
56 		IndexingType index_type;
57 
58 		/*! \brief This factor is used to indicate the space usage for the index generated by the constraint.
59 		 Generally there is no need do fill this attribute but for more refined tuning this can be set.
60 		 This is applicable only on primary keys and unique. */
61 		unsigned fill_factor;
62 
63 		/*! \brief Actions taken when delete and update event occurs. This is applicable
64 		 only for foreign keys */
65 		ActionType del_action, upd_action;
66 
67 		//! \brief Stores the columns that is referenced by the constraint (except for check constraints)
68 		vector<Column *> columns;
69 
70 		//! \brief Stores the referenced columns from the referenced table primary key
71 		vector<Column *> ref_columns;
72 
73 		//! \brief Stores the exclude elements of the exclude constraint
74 		vector<ExcludeElement> excl_elements;
75 
76 		//! \brief Stores the check expression or the exclude predicate (only for check and exclude constraints)
77 		QString expression;
78 
79 		//! \brief Stores the referenced table (only for foreign keys)
80 		BaseTable *ref_table;
81 
82 		//! \brief Formats the string for constraint columns to be used by the SchemaParser
83 		void setColumnsAttribute(unsigned col_type, unsigned def_type, bool inc_addedbyrel=false);
84 
85 		//! \brief Formats the exclude elements string used by the SchemaParser
86 		void setExcludeElementsAttribute(unsigned def_type);
87 
88 		void setDeclInTableAttribute();
89 
90 	public:
91 		/*! \brief Access the source columns that means the columns that constrais
92 		is applied (from the constraint's parent table) */
93 		static constexpr unsigned SourceCols=0,
94 
95 		/*! \brief Access the referenced columns that means the columns from the
96 														 referenced table primary key (only for foreign keys) */
97 		ReferencedCols=1;
98 
99 		static constexpr unsigned DeleteAction=0,
100 		UpdateAction=1;
101 
102 		Constraint();
103 		virtual ~Constraint();
104 
105 		/*! \brief Adds one column to the internal column list referenced by the
106 		 constants SOURCE_COLS or REFERENCED_COLS */
107 		void addColumn(Column *column, unsigned col_type);
108 
109 		//! \brief Adds several elements to the constraint using a defined vector
110 		void addExcludeElements(vector<ExcludeElement> &elems);
111 
112 		//! \brief Defines the constraint type
113 		void setConstraintType(ConstraintType constr_type);
114 
115 		//! \brief Defines the type of action on foreign keys (ON DELETE and ON UPDATE). (only for foreign key)
116 		void setActionType(ActionType action_type, unsigned act_id);
117 
118 		//! \brief Defines the deferral type for the constraint (except for check contraints)
119 		void setDeferralType(DeferralType deferral_type);
120 
121 		//! \brief Defines whether the constraint is deferrable (except for check contraints)
122 		void setDeferrable(bool value);
123 
124 		//! \brief Defines the matching type used by the constraint (only for foreign key)
125 		void setMatchType(MatchType constr_type);
126 
127 		//! \brief Defines the indexing type used by the constraint (only for exclude)
128 		void setIndexType(IndexingType index_type);
129 
130 		//! \brief Defines the expresion used by the constraint (only for check and exclude constraint)
131 		void setExpression(const QString &expr);
132 
133 		//! \brief Defines the referenced table (only for foreign key)
134 		void setReferencedTable(BaseTable *tab_ref);
135 
136 		//! \brief Defines the tablespace used by the constraint (only for primary keys and unique)
137 		void setTablespace(BaseObject *tabspc);
138 
139 		/*! \brief Defines the constraint fill factor (only for primary keys and unique).
140 				Values less than 10 (except 0) or above 100 will be adjusted to accepted values. To use the default
141 				settings specify 0 as fill factor */
142 		void setFillFactor(unsigned factor);
143 
144 		//! \brief Defines if the constraints is propagated to child tables (only for exclude constraints)
145 		void setNoInherit(bool value);
146 
147 		//! \brief Returns the constraint fill factor
148 		unsigned getFillFactor();
149 
150 		//! \brief Retuns the action type (ON DELETE or ON UPDATE) of a foreign key
151 		ActionType getActionType(unsigned act_id);
152 
153 		//! \brief Returns the list of columns of the specified type SOURCE_COLS or REFERENCED_COLS
154 		vector<Column *> getColumns(unsigned col_type);
155 
156 		/*! \brief Returns one column (using its index) from the internal constraint column lists.
157 		 Use the constants SOURCE_COLS or REFERENCED_COLS to access the lists */
158 		Column *getColumn(unsigned col_idx, unsigned col_type);
159 
160 		/*! \brief Returns one column (using its name) from the internal constraint column lists.
161 		 Use the constants SOURCE_COLS or REFERENCED_COLS to access the lists */
162 		Column *getColumn(const QString &name, unsigned col_type);
163 
164 		/*! \brief Returns the column count for one internal list.
165 		 Use the constants SOURCE_COLS or REFERENCED_COLS to access the lists */
166 		unsigned getColumnCount(unsigned col_type);
167 
168 		//! \brief Returns the exclude constraint element count
169 		unsigned getExcludeElementCount();
170 
171 		//! \brief Returns a list of exclude elements
172 		vector<ExcludeElement> getExcludeElements();
173 
174 		/*! \brief Removes one column from internal list using its name.
175 		 Use the constants SOURCE_COLS or REFERENCED_COLS to access the lists */
176 		void removeColumn(const QString &name, unsigned col_type);
177 
178 		//! \brief Remove all columns from the internal lists
179 		void removeColumns();
180 
181 		//! \brief Returns the constraint type
182 		ConstraintType getConstraintType();
183 
184 		//! \brief Returns the check expression
185 		QString getExpression();
186 
187 		//! \brief Returns the referenced table
188 		BaseTable *getReferencedTable();
189 
190 		//! \brief Returns the constraint's deferral type
191 		DeferralType getDeferralType();
192 
193 		//! \brief Indicates whether the constraint is deferrable
194 		bool isDeferrable();
195 
196 		//! \brief Returns if the constraints will propagated to child tables
197 		bool isNoInherit();
198 
199 		/*! \brief Returns whether the constraint references columns added
200 		 by relationship. This method is used as auxiliary
201 		 to control which constraints reference columns added by the
202 		 relationship in order to avoid referece breaking due constants
203 		 connections and disconnections of relationships */
204 		bool isReferRelationshipAddedColumn();
205 
206 		/*! \brief Returns the list of all columns that is created by relationships.
207 	This method is slower than isReferRelationshipAddedColumn() so it's not
208 	recommended to use it only check if the object is referencing columns
209 	added by relationship */
210 		vector<Column *> getRelationshipAddedColumns();
211 
212 		//! \brief Returns the matching type adopted by the constraint
213 		MatchType getMatchType();
214 
215 		//! \brief Returns the indexing type adopted by the constraint
216 		IndexingType getIndexType();
217 
218 		/*! \brief Returns the SQL / XML definition for the constraint.
219 		 This method calls getCodeDefintion(unsigned, bool) with the
220 		 second parameter as false */
221 		virtual QString getCodeDefinition(unsigned def_type) final;
222 
223 		/*! \brief Returns the SQL / XML definition for the constraint. The boolean parameter indicates
224 		 whether the columns added by relationship must appear on the code definition */
225 		virtual QString getCodeDefinition(unsigned def_type, bool inc_addedbyrel) final;
226 
227 		virtual QString getDropDefinition(bool cascade) final;
228 
229 		//! \brief Indicates whether the column exists on the specified internal column list
230 		bool isColumnExists(Column *column, unsigned col_type);
231 
232 		/*! \brief Indicates whether the column is referenced in internal column list or exclude element list.
233 		The second parameter is useful to permit or not the search of column only on referenced columns list. */
234 		bool isColumnReferenced(Column *column, bool search_only_ref_cols = false);
235 
236 		//! \brief Indicates whether the columns are referenced in internal column list
237 		bool isColumnsExist(vector<Column *> columns, unsigned col_type);
238 
239 		//! \brief Adds an exclude element to the constraint using an column (only exclude constraint)
240 		void addExcludeElement(Column *column, Operator *oper, OperatorClass *op_class, bool use_sorting, bool asc_order, bool nulls_first);
241 
242 		//! \brief Adds an exclude element to the constraint using an expression (only exclude constraint)
243 		void addExcludeElement(const QString &expr, Operator *oper, OperatorClass *op_class, bool use_sorting, bool asc_order, bool nulls_first);
244 
245 		//! \brief Adds an exclude element to the constraint using other pre-configured element (only exclude constraint)
246 		void addExcludeElement(ExcludeElement elem);
247 
248 		//! \brief Returns one exclude element using its index
249 		ExcludeElement getExcludeElement(unsigned elem_idx);
250 
251 		//! \brief Returns the exclude element index
252 		int getExcludeElementIndex(ExcludeElement elem);
253 
254 		//! \brief Remove an exclude element using its index
255 		void removeExcludeElement(unsigned idx_elem);
256 
257 		//! \brief Remove all exclude elements from the constraint
258 		void removeExcludeElements();
259 
260 		//! \brief Toggles the not-null flag from source columns on primary key constraints. This methods has no effect in other constraint types
261 		void setColumnsNotNull(bool value);
262 
263 		virtual QString getSignature(bool format) final;
264 
265 		/*! \brief Compares two constratins XML definition and returns if they differs. This methods varies a little from
266 		BaseObject::isCodeDiffersFrom() because here we need to generate xml code including relationship added columns */
267 		virtual bool isCodeDiffersFrom(BaseObject *object, const vector<QString> &ignored_attribs={}, const vector<QString> &ignored_tags={});
268 };
269 
270 #endif
271