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 // dlgForeignDataWrapper.cpp - PostgreSQL ForeignDataWrapper Property
9 //
10 //////////////////////////////////////////////////////////////////////////
11
12 // wxWindows headers
13 #include <wx/wx.h>
14
15 // App headers
16 #include "pgAdmin3.h"
17 #include "utils/misc.h"
18 #include "utils/pgDefs.h"
19
20 #include "dlg/dlgForeignDataWrapper.h"
21 #include "schema/pgForeignDataWrapper.h"
22
23
24 // pointer to controls
25 #define cbHandler CTRL_COMBOBOX("cbHandler")
26 #define cbValidator CTRL_COMBOBOX("cbValidator")
27 #define lstOptions CTRL_LISTVIEW("lstOptions")
28 #define txtOption CTRL_TEXT("txtOption")
29 #define txtValue CTRL_TEXT("txtValue")
30 #define btnAdd CTRL_BUTTON("wxID_ADD")
31 #define btnRemove CTRL_BUTTON("wxID_REMOVE")
32
33
CreateDialog(frmMain * frame,pgObject * node,pgObject * parent)34 dlgProperty *pgForeignDataWrapperFactory::CreateDialog(frmMain *frame, pgObject *node, pgObject *parent)
35 {
36 return new dlgForeignDataWrapper(this, frame, (pgForeignDataWrapper *)node);
37 }
38
39
40 BEGIN_EVENT_TABLE(dlgForeignDataWrapper, dlgSecurityProperty)
41 EVT_TEXT(XRCID("cbHandler"), dlgProperty::OnChange)
42 EVT_COMBOBOX(XRCID("cbHandler"), dlgProperty::OnChange)
43 EVT_TEXT(XRCID("cbValidator"), dlgProperty::OnChange)
44 EVT_COMBOBOX(XRCID("cbValidator"), dlgProperty::OnChange)
45 EVT_LIST_ITEM_SELECTED(XRCID("lstOptions"), dlgForeignDataWrapper::OnSelChangeOption)
46 EVT_TEXT(XRCID("txtOption"), dlgForeignDataWrapper::OnChangeOptionName)
47 EVT_BUTTON(wxID_ADD, dlgForeignDataWrapper::OnAddOption)
48 EVT_BUTTON(wxID_REMOVE, dlgForeignDataWrapper::OnRemoveOption)
49 END_EVENT_TABLE();
50
51
dlgForeignDataWrapper(pgaFactory * f,frmMain * frame,pgForeignDataWrapper * node)52 dlgForeignDataWrapper::dlgForeignDataWrapper(pgaFactory *f, frmMain *frame, pgForeignDataWrapper *node)
53 : dlgSecurityProperty(f, frame, node, wxT("dlgForeignDataWrapper"), wxT("USAGE"), "U")
54 {
55 fdw = node;
56 }
57
58
GetObject()59 pgObject *dlgForeignDataWrapper::GetObject()
60 {
61 return fdw;
62 }
63
64
Go(bool modal)65 int dlgForeignDataWrapper::Go(bool modal)
66 {
67 wxString val;
68
69 if(!connection->BackendMinimumVersion(9, 1))
70 cbHandler->Disable();
71
72 // Fill handler combobox
73 cbHandler->Append(wxT(""));
74 pgSet *set = connection->ExecuteSet(
75 wxT("SELECT nspname, proname\n")
76 wxT(" FROM pg_proc p\n")
77 wxT(" JOIN pg_namespace nsp ON nsp.oid=pronamespace\n")
78 wxT(" WHERE pronargs=0")
79 wxT(" AND prorettype=") + NumToStr(PGOID_TYPE_HANDLER));
80 if (set)
81 {
82 while (!set->Eof())
83 {
84 wxString procname = database->GetSchemaPrefix(set->GetVal(wxT("nspname"))) + set->GetVal(wxT("proname"));
85 cbHandler->Append(procname);
86 set->MoveNext();
87 }
88 delete set;
89 }
90 cbHandler->SetSelection(0);
91
92 // Fill validator combobox
93 cbValidator->Append(wxT(""));
94 set = connection->ExecuteSet(
95 wxT("SELECT nspname, proname\n")
96 wxT(" FROM pg_proc p\n")
97 wxT(" JOIN pg_namespace nsp ON nsp.oid=pronamespace\n")
98 wxT(" WHERE proargtypes[0]=") + NumToStr(PGOID_TYPE_TEXT_ARRAY) +
99 wxT(" AND proargtypes[1]=") + NumToStr(PGOID_TYPE_OID));
100 if (set)
101 {
102 while (!set->Eof())
103 {
104 wxString procname = database->GetSchemaPrefix(set->GetVal(wxT("nspname"))) + set->GetVal(wxT("proname"));
105 cbValidator->Append(procname);
106 set->MoveNext();
107 }
108 delete set;
109 }
110 cbValidator->SetSelection(0);
111
112 // Initialize options listview and buttons
113 lstOptions->AddColumn(_("Option"), 80);
114 lstOptions->AddColumn(_("Value"), 40);
115 txtOption->SetValue(wxT(""));
116 txtValue->SetValue(wxT(""));
117 btnAdd->Disable();
118 btnRemove->Disable();
119
120 if (fdw)
121 {
122 // edit mode
123 txtName->Enable(connection->BackendMinimumVersion(9, 2));
124
125 val = fdw->GetHandlerProc();
126 if (!val.IsEmpty())
127 {
128 for (unsigned int i = 0 ; i < cbHandler->GetCount() ; i++)
129 {
130 if (cbHandler->GetString(i) == val)
131 cbHandler->SetSelection(i);
132 }
133 }
134
135 val = fdw->GetValidatorProc();
136 if (!val.IsEmpty())
137 {
138 for (unsigned int i = 0 ; i < cbValidator->GetCount() ; i++)
139 {
140 if (cbValidator->GetString(i) == val)
141 cbValidator->SetSelection(i);
142 }
143 }
144
145 wxString options = fdw->GetOptions();
146 wxString option, optionname, optionvalue;
147 while (options.Length() > 0)
148 {
149 option = options.BeforeFirst(',');
150 optionname = option.BeforeFirst(wxT('=')).Trim(false).Trim();
151 optionvalue = option.AfterFirst(wxT('=')).Trim(false).Trim();
152 lstOptions->AppendItem(optionname, optionvalue);
153 options = options.AfterFirst(',');
154 }
155 }
156 else
157 {
158 // create mode
159 }
160
161 return dlgSecurityProperty::Go(modal);
162 }
163
164
CreateObject(pgCollection * collection)165 pgObject *dlgForeignDataWrapper::CreateObject(pgCollection *collection)
166 {
167 wxString name = txtName->GetValue();
168
169 pgObject *obj = foreignDataWrapperFactory.CreateObjects(collection, 0, wxT("\n AND fdwname ILIKE ") + qtDbString(name));
170 return obj;
171 }
172
173
CheckChange()174 void dlgForeignDataWrapper::CheckChange()
175 {
176 bool didChange = true;
177 wxString name = txtName->GetValue();
178 if (fdw)
179 {
180 didChange = name != fdw->GetName()
181 || cbOwner->GetValue() != fdw->GetOwner()
182 || txtComment->GetValue() != fdw->GetComment()
183 || cbHandler->GetValue() != fdw->GetHandlerProc()
184 || cbValidator->GetValue() != fdw->GetValidatorProc()
185 || GetOptionsSql().Length() > 0;
186 EnableOK(didChange);
187 }
188 else
189 {
190 bool enable = true;
191
192 CheckValid(enable, !name.IsEmpty(), _("Please specify name."));
193 EnableOK(enable);
194 }
195 }
196
197
198
OnChangeOptionName(wxCommandEvent & ev)199 void dlgForeignDataWrapper::OnChangeOptionName(wxCommandEvent &ev)
200 {
201 btnAdd->Enable(txtOption->GetValue().Length() > 0);
202 }
203
204
OnSelChangeOption(wxListEvent & ev)205 void dlgForeignDataWrapper::OnSelChangeOption(wxListEvent &ev)
206 {
207 int row = lstOptions->GetSelection();
208 if (row >= 0)
209 {
210 txtOption->SetValue(lstOptions->GetText(row, 0));
211 txtValue->SetValue(lstOptions->GetText(row, 1));
212 }
213
214 btnRemove->Enable(row >= 0);
215 }
216
217
OnAddOption(wxCommandEvent & ev)218 void dlgForeignDataWrapper::OnAddOption(wxCommandEvent &ev)
219 {
220 bool found = false;
221
222 for (int pos = 0 ; pos < lstOptions->GetItemCount() ; pos++)
223 {
224 if (lstOptions->GetText(pos).IsSameAs(txtOption->GetValue(), false))
225 {
226 lstOptions->SetItem(pos, 1, txtValue->GetValue());
227 found = true;
228 break;
229 }
230 }
231
232 if (!found)
233 {
234 lstOptions->AppendItem(txtOption->GetValue(), txtValue->GetValue());
235 }
236
237 txtOption->SetValue(wxT(""));
238 txtValue->SetValue(wxT(""));
239 btnAdd->Disable();
240
241 CheckChange();
242 }
243
244
OnRemoveOption(wxCommandEvent & ev)245 void dlgForeignDataWrapper::OnRemoveOption(wxCommandEvent &ev)
246 {
247 int sel = lstOptions->GetSelection();
248 lstOptions->DeleteItem(sel);
249
250 txtOption->SetValue(wxT(""));
251 txtValue->SetValue(wxT(""));
252 btnRemove->Disable();
253
254 CheckChange();
255 }
256
257
GetOptionsSql()258 wxString dlgForeignDataWrapper::GetOptionsSql()
259 {
260 wxString options = fdw->GetOptions();
261 wxString option, optionname, optionvalue, sqloptions;
262 bool found;
263 int pos;
264
265 while (options.Length() > 0)
266 {
267 option = options.BeforeFirst(',');
268 optionname = option.BeforeFirst(wxT('=')).Trim(false).Trim();
269 optionvalue = option.AfterFirst(wxT('=')).Trim(false).Trim();
270
271 // check for options
272 found = false;
273 for (pos = 0 ; pos < lstOptions->GetItemCount() && !found; pos++)
274 {
275 found = lstOptions->GetText(pos, 0).Cmp(optionname) == 0;
276 if (found) break;
277 }
278
279 if (found)
280 {
281 if (lstOptions->GetText(pos, 1).Cmp(optionvalue) != 0)
282 {
283 if (sqloptions.Length() > 0)
284 sqloptions += wxT(", ");
285 sqloptions += wxT("SET ") + optionname + wxT(" '") + lstOptions->GetText(pos, 1) + wxT("'");
286 }
287 }
288 else
289 {
290 if (sqloptions.Length() > 0)
291 sqloptions += wxT(", ");
292 sqloptions += wxT("DROP ") + optionname;
293 }
294
295 options = options.AfterFirst(',');
296 }
297
298 for (pos = 0 ; pos < lstOptions->GetItemCount() ; pos++)
299 {
300 options = fdw->GetOptions();
301 found = false;
302
303 while (options.Length() > 0 && !found)
304 {
305 option = options.BeforeFirst(',');
306 optionname = option.BeforeFirst(wxT('=')).Trim(false).Trim();
307 found = lstOptions->GetText(pos, 0).Cmp(optionname) == 0;
308 options = options.AfterFirst(',');
309 }
310
311 if (!found)
312 {
313 optionvalue = option.AfterFirst(wxT('=')).Trim(false).Trim();
314
315 if (sqloptions.Length() > 0)
316 sqloptions += wxT(", ");
317 sqloptions += wxT("ADD ") + lstOptions->GetText(pos, 0) + wxT(" '") + lstOptions->GetText(pos, 1) + wxT("'");
318 }
319 }
320
321 return sqloptions;
322 }
323
324
GetSql()325 wxString dlgForeignDataWrapper::GetSql()
326 {
327 wxString sql, name;
328 name = txtName->GetValue();
329
330 if (fdw)
331 {
332 // edit mode
333 sql = wxEmptyString;
334
335 AppendNameChange(sql);
336
337 if (cbHandler->GetValue() != fdw->GetHandlerProc())
338 {
339 if (cbHandler->GetValue().IsEmpty())
340 sql += wxT("ALTER FOREIGN DATA WRAPPER ") + qtIdent(name)
341 + wxT("\n NO HANDLER;\n");
342 else
343 sql += wxT("ALTER FOREIGN DATA WRAPPER ") + qtIdent(name)
344 + wxT("\n HANDLER ") + qtIdent(cbHandler->GetValue())
345 + wxT(";\n");
346 }
347
348 if (cbValidator->GetValue() != fdw->GetValidatorProc())
349 {
350 if (cbValidator->GetValue().IsEmpty())
351 sql += wxT("ALTER FOREIGN DATA WRAPPER ") + qtIdent(name)
352 + wxT("\n NO VALIDATOR;\n");
353 else
354 sql += wxT("ALTER FOREIGN DATA WRAPPER ") + qtIdent(name)
355 + wxT("\n VALIDATOR ") + qtIdent(cbValidator->GetValue())
356 + wxT(";\n");
357 }
358
359 wxString sqloptions = GetOptionsSql();
360 if (sqloptions.Length() > 0)
361 {
362 sql += wxT("ALTER FOREIGN DATA WRAPPER ") + name
363 + wxT(" OPTIONS (") + sqloptions + wxT(");");
364 }
365
366 AppendOwnerChange(sql, wxT("FOREIGN DATA WRAPPER ") + qtIdent(name));
367 }
368 else
369 {
370 // create mode
371 sql = wxT("CREATE FOREIGN DATA WRAPPER ") + qtIdent(name);
372 AppendIfFilled(sql, wxT("\n HANDLER "), qtIdent(cbHandler->GetValue()));
373 AppendIfFilled(sql, wxT("\n VALIDATOR "), qtIdent(cbValidator->GetValue()));
374
375 // check for options
376 if (lstOptions->GetItemCount() > 0)
377 {
378 wxString options = wxEmptyString;
379 for (int pos = 0 ; pos < lstOptions->GetItemCount() ; pos++)
380 {
381 if (options.Length() > 0)
382 options += wxT(", ");
383
384 options += lstOptions->GetText(pos, 0)
385 + wxT(" '") + lstOptions->GetText(pos, 1) + wxT("' ");
386 }
387 sql += wxT("\n OPTIONS (") + options + wxT(")");
388 }
389
390 sql += wxT(";\n");
391 AppendOwnerNew(sql, wxT("FOREIGN DATA WRAPPER ") + qtIdent(name));
392 }
393
394 sql += GetGrant(wxT("U"), wxT("FOREIGN DATA WRAPPER ") + qtIdent(name));
395 AppendComment(sql, wxT("FOREIGN DATA WRAPPER"), 0, fdw);
396
397 return sql;
398 }
399
400
401