1 //////////////////////////////////////////////////////////////////////////
2 //
3 // pgAdmin III - PostgreSQL Tools
4 //
5 // Copyright (C) 2002 - 2016, The pgAdmin Development Team
6 // This software is released under the PostgreSQL Licence
7 //
8 // pgCheck.cpp - Check class
9 //
10 //////////////////////////////////////////////////////////////////////////
11
12 // wxWindows headers
13 #include <wx/wx.h>
14
15 // App headers
16 #include "pgAdmin3.h"
17 #include "frm/frmMain.h"
18 #include "utils/misc.h"
19 #include "schema/pgCheck.h"
20
21
pgCheck(pgSchema * newSchema,const wxString & newName)22 pgCheck::pgCheck(pgSchema *newSchema, const wxString &newName)
23 : pgSchemaObject(newSchema, checkFactory, newName)
24 {
25 }
26
~pgCheck()27 pgCheck::~pgCheck()
28 {
29 }
30
31
GetTranslatedMessage(int kindOfMessage) const32 wxString pgCheck::GetTranslatedMessage(int kindOfMessage) const
33 {
34 wxString message = wxEmptyString;
35
36 switch (kindOfMessage)
37 {
38 case RETRIEVINGDETAILS:
39 message = _("Retrieving details on check constraint");
40 message += wxT(" ") + GetName();
41 break;
42 case REFRESHINGDETAILS:
43 message = _("Refreshing check constraint");
44 message += wxT(" ") + GetName();
45 break;
46 case GRANTWIZARDTITLE:
47 message = _("Privileges for check constraint");
48 message += wxT(" ") + GetName();
49 break;
50 case DROPINCLUDINGDEPS:
51 message = wxString::Format(_("Are you sure you wish to drop check constraint \"%s\" including all objects that depend on it?"),
52 GetFullIdentifier().c_str());
53 break;
54 case DROPEXCLUDINGDEPS:
55 message = wxString::Format(_("Are you sure you wish to drop check constraint \"%s\"?"),
56 GetFullIdentifier().c_str());
57 break;
58 case DROPCASCADETITLE:
59 message = _("Drop check constraint cascaded?");
60 break;
61 case DROPTITLE:
62 message = _("Drop check constraint?");
63 break;
64 case PROPERTIESREPORT:
65 message = _("Check constraint properties report");
66 message += wxT(" - ") + GetName();
67 break;
68 case PROPERTIES:
69 message = _("Check constraint properties");
70 break;
71 case DDLREPORT:
72 message = _("Check constraint DDL report");
73 message += wxT(" - ") + GetName();
74 break;
75 case DDL:
76 message = _("Check constraint DDL");
77 break;
78 case DEPENDENCIESREPORT:
79 message = _("Check constraint dependencies report");
80 message += wxT(" - ") + GetName();
81 break;
82 case DEPENDENCIES:
83 message = _("Check constraint dependencies");
84 break;
85 case DEPENDENTSREPORT:
86 message = _("Check constraint dependents report");
87 message += wxT(" - ") + GetName();
88 break;
89 case DEPENDENTS:
90 message = _("Check constraint dependents");
91 break;
92 }
93
94 return message;
95 }
96
97
GetIconId()98 int pgCheck::GetIconId()
99 {
100 if (!GetDatabase()->BackendMinimumVersion(9, 2) || GetValid())
101 return checkFactory.GetIconId();
102 else
103 return checkFactory.GetClosedIconId();
104 }
105
106
DropObject(wxFrame * frame,ctlTree * browser,bool cascaded)107 bool pgCheck::DropObject(wxFrame *frame, ctlTree *browser, bool cascaded)
108 {
109 wxString sql = wxT("ALTER ") + objectKind + wxT(" ") + qtIdent(objectSchema) + wxT(".") + qtIdent(objectName)
110 + wxT(" DROP CONSTRAINT ") + GetQuotedIdentifier();
111 if (cascaded)
112 sql += wxT(" CASCADE");
113 return GetDatabase()->ExecuteVoid(sql);
114 }
115
116
GetConstraint()117 wxString pgCheck::GetConstraint()
118 {
119 sql = GetQuotedIdentifier() + wxT(" CHECK ");
120
121 sql += wxT("(") + GetDefinition() + wxT(")");
122
123 if (GetDatabase()->BackendMinimumVersion(9, 2) && GetNoInherit())
124 sql += wxT(" NO INHERIT");
125
126 if (GetDatabase()->BackendMinimumVersion(9, 2) && !GetValid())
127 sql += wxT(" NOT VALID");
128
129 return sql;
130 }
131
132
GetSql(ctlTree * browser)133 wxString pgCheck::GetSql(ctlTree *browser)
134 {
135 if (sql.IsNull())
136 {
137 sql = wxT("-- Check: ") + GetQuotedFullIdentifier() + wxT("\n\n")
138 + wxT("-- ALTER ") + objectKind + wxT(" ") + GetQuotedSchemaPrefix(objectSchema) + qtIdent(objectName)
139 + wxT(" DROP CONSTRAINT ") + GetQuotedIdentifier()
140 + wxT(";\n\nALTER ") + objectKind + wxT(" ") + GetQuotedSchemaPrefix(objectSchema) + qtIdent(objectName)
141 + wxT("\n ADD CONSTRAINT ") + GetConstraint()
142 + wxT(";\n");
143
144 if (!GetComment().IsNull())
145 {
146 sql += wxT("COMMENT ON CONSTRAINT ") + GetQuotedIdentifier()
147 + wxT(" ON ") + GetQuotedSchemaPrefix(objectSchema) + qtIdent(objectName)
148 + wxT(" IS ") + qtDbString(GetComment()) + wxT(";\n");
149 }
150 }
151
152 return sql;
153 }
154
155
ShowTreeDetail(ctlTree * browser,frmMain * form,ctlListView * properties,ctlSQLBox * sqlPane)156 void pgCheck::ShowTreeDetail(ctlTree *browser, frmMain *form, ctlListView *properties, ctlSQLBox *sqlPane)
157 {
158 if (properties)
159 {
160 CreateListColumns(properties);
161
162 properties->AppendItem(_("Name"), GetName());
163 properties->AppendItem(_("OID"), GetOid());
164 properties->AppendItem(_("Definition"), GetDefinition());
165 if (GetDatabase()->BackendMinimumVersion(9, 2))
166 {
167 properties->AppendItem(_("No Inherit?"), BoolToYesNo(GetNoInherit()));
168 properties->AppendItem(_("Valid?"), BoolToYesNo(GetValid()));
169 }
170 // Check constraints on a domain don't have comments
171 if (objectKind.Upper() == wxT("TABLE"))
172 properties->AppendItem(_("Comment"), firstLineOnly(GetComment()));
173 }
174 }
175
176
Refresh(ctlTree * browser,const wxTreeItemId item)177 pgObject *pgCheck::Refresh(ctlTree *browser, const wxTreeItemId item)
178 {
179 pgObject *check = 0;
180
181 pgCollection *coll = browser->GetParentCollection(item);
182 if (coll)
183 check = checkFactory.CreateObjects(coll, 0, wxT("\n AND c.oid=") + GetOidStr());
184
185 return check;
186 }
187
188
Validate(frmMain * form)189 void pgCheck::Validate(frmMain *form)
190 {
191 wxString sql = wxT("ALTER ") + objectKind + wxT(" ")
192 + GetQuotedSchemaPrefix(objectSchema) + qtIdent(objectName)
193 + wxT("\n VALIDATE CONSTRAINT ") + GetQuotedIdentifier();
194 GetDatabase()->ExecuteVoid(sql);
195
196 iSetValid(true);
197 UpdateIcon(form->GetBrowser());
198 }
199
200
CreateObjects(pgCollection * coll,ctlTree * browser,const wxString & restriction)201 pgObject *pgCheckFactory::CreateObjects(pgCollection *coll, ctlTree *browser, const wxString &restriction)
202 {
203 pgSchemaObjCollection *collection = (pgSchemaObjCollection *)coll;
204 pgCheck *check = 0;
205
206 wxString connoinherit = collection->GetDatabase()->BackendMinimumVersion(9, 2) ? wxT(", connoinherit") : wxEmptyString;
207 wxString convalidated = collection->GetDatabase()->BackendMinimumVersion(9, 2) ? wxT(", convalidated") : wxEmptyString;
208
209 wxString sql =
210 wxT("SELECT 'TABLE' AS objectkind, c.oid, conname, relname, nspname, description,\n")
211 wxT(" pg_get_expr(conbin, conrelid") + collection->GetDatabase()->GetPrettyOption() + wxT(") as consrc\n")
212 + connoinherit + convalidated +
213 wxT(" FROM pg_constraint c\n")
214 wxT(" JOIN pg_class cl ON cl.oid=conrelid\n")
215 wxT(" JOIN pg_namespace nl ON nl.oid=relnamespace\n")
216 wxT(" LEFT OUTER JOIN pg_description des ON (des.objoid=c.oid AND des.classoid='pg_constraint'::regclass)\n")
217 wxT(" WHERE contype = 'c' AND conrelid = ") + NumToStr(collection->GetOid())
218 + restriction + wxT("::oid\n")
219 wxT("UNION\n")
220 wxT("SELECT 'DOMAIN' AS objectkind, c.oid, conname, typname as relname, nspname, description,\n")
221 wxT(" regexp_replace(pg_get_constraintdef(c.oid, true), E'CHECK \\\\((.*)\\\\).*', E'\\\\1') as consrc\n")
222 + connoinherit + convalidated +
223 wxT(" FROM pg_constraint c\n")
224 wxT(" JOIN pg_type t ON t.oid=contypid\n")
225 wxT(" JOIN pg_namespace nl ON nl.oid=typnamespace\n")
226 wxT(" LEFT OUTER JOIN pg_description des ON (des.objoid=t.oid AND des.classoid='pg_constraint'::regclass)\n")
227 wxT(" WHERE contype = 'c' AND contypid = ") + NumToStr(collection->GetOid())
228 + restriction + wxT("::oid\n")
229 wxT(" ORDER BY conname");
230
231 pgSet *checks = collection->GetDatabase()->ExecuteSet(sql);
232
233 if (checks)
234 {
235 while (!checks->Eof())
236 {
237 check = new pgCheck(collection->GetSchema()->GetSchema(), checks->GetVal(wxT("conname")));
238
239 check->iSetOid(checks->GetOid(wxT("oid")));
240 check->iSetDefinition(checks->GetVal(wxT("consrc")));
241 check->iSetObjectKind(checks->GetVal(wxT("objectkind")));
242 check->iSetObjectName(checks->GetVal(wxT("relname")));
243 check->iSetObjectSchema(checks->GetVal(wxT("nspname")));
244 if (collection->GetDatabase()->BackendMinimumVersion(9, 2))
245 {
246 check->iSetNoInherit(checks->GetBool(wxT("connoinherit")));
247 check->iSetValid(checks->GetBool(wxT("convalidated")));
248 }
249 check->iSetComment(checks->GetVal(wxT("description")));
250
251 if (browser)
252 {
253 browser->AppendObject(collection, check);
254 checks->MoveNext();
255 }
256 else
257 break;
258 }
259
260 delete checks;
261 }
262 return check;
263 }
264
265 /////////////////////////////
266
GetTranslatedMessage(int kindOfMessage) const267 wxString pgCheckCollection::GetTranslatedMessage(int kindOfMessage) const
268 {
269 wxString message = wxEmptyString;
270
271 switch (kindOfMessage)
272 {
273 case RETRIEVINGDETAILS:
274 message = _("Retrieving details on check constraints");
275 break;
276 case REFRESHINGDETAILS:
277 message = _("Refreshing check constraints");
278 break;
279 case OBJECTSLISTREPORT:
280 message = _("Check constraints list report");
281 break;
282 }
283
284 return message;
285 }
286
287 /////////////////////////////
288
289 #include "images/check.pngc"
290 #include "images/checkbad.pngc"
291
pgCheckFactory()292 pgCheckFactory::pgCheckFactory()
293 : pgSchemaObjFactory(__("Check"), __("New Check..."), __("Create a new Check constraint."), check_png_img)
294 {
295 metaType = PGM_CHECK;
296 collectionFactory = &constraintCollectionFactory;
297 closedId = addIcon(checkbad_png_img);
298 }
299
300
301 pgCheckFactory checkFactory;
302
validateCheckFactory(menuFactoryList * list,wxMenu * mnu,ctlMenuToolbar * toolbar)303 validateCheckFactory::validateCheckFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : contextActionFactory(list)
304 {
305 mnu->Append(id, _("Validate check constraint"), _("Validate the selected check constraint."));
306 }
307
308
StartDialog(frmMain * form,pgObject * obj)309 wxWindow *validateCheckFactory::StartDialog(frmMain *form, pgObject *obj)
310 {
311 ((pgCheck *)obj)->Validate(form);
312 ((pgCheck *)obj)->SetDirty();
313
314 wxTreeItemId item = form->GetBrowser()->GetSelection();
315 if (obj == form->GetBrowser()->GetObject(item))
316 {
317 obj->ShowTreeDetail(form->GetBrowser(), 0, form->GetProperties());
318 form->GetSqlPane()->SetReadOnly(false);
319 form->GetSqlPane()->SetText(((pgCheck *)obj)->GetSql(form->GetBrowser()));
320 form->GetSqlPane()->SetReadOnly(true);
321 }
322 form->GetMenuFactories()->CheckMenu(obj, form->GetMenuBar(), (ctlMenuToolbar *)form->GetToolBar());
323
324 return 0;
325 }
326
327
CheckEnable(pgObject * obj)328 bool validateCheckFactory::CheckEnable(pgObject *obj)
329 {
330 return obj && obj->IsCreatedBy(checkFactory) && obj->CanEdit()
331 && ((pgCheck *)obj)->GetConnection()->BackendMinimumVersion(9, 2)
332 && !((pgCheck *)obj)->GetValid();
333 }
334