mirror of
https://github.com/levinsv/pgadmin3.git
synced 2026-05-15 14:15:49 -06:00
443 lines
12 KiB
C++
443 lines
12 KiB
C++
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// pgAdmin III - PostgreSQL Tools
|
|
//
|
|
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
|
|
// This software is released under the PostgreSQL Licence
|
|
//
|
|
// dlgDomain.cpp - PostgreSQL Domain Property
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// wxWindows headers
|
|
#include <wx/wx.h>
|
|
|
|
// App headers
|
|
#include "pgAdmin3.h"
|
|
#include "frm/frmMain.h"
|
|
#include "utils/misc.h"
|
|
#include "utils/pgDefs.h"
|
|
|
|
#include "dlg/dlgDomain.h"
|
|
#include "dlg/dlgCheck.h"
|
|
#include "schema/pgSchema.h"
|
|
#include "schema/pgCheck.h"
|
|
#include "schema/pgDomain.h"
|
|
#include "schema/pgDatatype.h"
|
|
#include "ctl/ctlSeclabelPanel.h"
|
|
|
|
|
|
// pointer to controls
|
|
#define chkNotNull CTRL_CHECKBOX("chkNotNull")
|
|
#define txtDefault CTRL_TEXT("txtDefault")
|
|
#define cbCollation CTRL_COMBOBOX("cbCollation")
|
|
#define lstConstraints CTRL_LISTVIEW("lstConstraints")
|
|
#define btnAddConstr CTRL_BUTTON("btnAddConstr")
|
|
#define cbConstrType CTRL_COMBOBOX("cbConstrType")
|
|
#define btnRemoveConstr CTRL_BUTTON("btnRemoveConstr")
|
|
|
|
BEGIN_EVENT_TABLE(dlgDomain, dlgTypeProperty)
|
|
EVT_TEXT(XRCID("txtLength"), dlgProperty::OnChange)
|
|
EVT_TEXT(XRCID("txtPrecision"), dlgProperty::OnChange)
|
|
EVT_TEXT(XRCID("cbDatatype"), dlgDomain::OnSelChangeTyp)
|
|
EVT_COMBOBOX(XRCID("cbDatatype"), dlgDomain::OnSelChangeTyp)
|
|
EVT_TEXT(XRCID("txLength"), dlgProperty::OnChange)
|
|
EVT_TEXT(XRCID("txtDefault"), dlgProperty::OnChange)
|
|
EVT_CHECKBOX(XRCID("chkNotNull"), dlgProperty::OnChange)
|
|
EVT_BUTTON(XRCID("btnAddConstr"), dlgDomain::OnAddConstr)
|
|
EVT_BUTTON(XRCID("btnRemoveConstr"), dlgDomain::OnRemoveConstr)
|
|
EVT_LIST_ITEM_SELECTED(XRCID("lstConstraints"), dlgDomain::OnSelChangeConstr)
|
|
END_EVENT_TABLE();
|
|
|
|
|
|
dlgProperty *pgDomainFactory::CreateDialog(frmMain *frame, pgObject *node, pgObject *parent)
|
|
{
|
|
return new dlgDomain(this, frame, (pgDomain *)node, (pgSchema *)parent);
|
|
}
|
|
|
|
|
|
dlgDomain::dlgDomain(pgaFactory *f, frmMain *frame, pgDomain *node, pgSchema *sch)
|
|
: dlgTypeProperty(f, frame, wxT("dlgDomain"))
|
|
{
|
|
schema = sch;
|
|
domain = node;
|
|
|
|
seclabelPage = new ctlSeclabelPanel(nbNotebook);
|
|
|
|
txtLength->Disable();
|
|
txtPrecision->Disable();
|
|
|
|
lstConstraints->CreateColumns(0, _("Constraint name"), _("Definition"), 90);
|
|
}
|
|
|
|
|
|
pgObject *dlgDomain::GetObject()
|
|
{
|
|
return domain;
|
|
}
|
|
|
|
|
|
int dlgDomain::Go(bool modal)
|
|
{
|
|
if (connection->BackendMinimumVersion(9, 1))
|
|
{
|
|
seclabelPage->SetConnection(connection);
|
|
seclabelPage->SetObject(domain);
|
|
this->Connect(EVT_SECLABELPANEL_CHANGE, wxCommandEventHandler(dlgDomain::OnChange));
|
|
}
|
|
else
|
|
seclabelPage->Disable();
|
|
|
|
if (domain)
|
|
{
|
|
// edit mode
|
|
cbSchema->Enable(connection->BackendMinimumVersion(8, 1));
|
|
cbDatatype->Append(domain->GetBasetype());
|
|
AddType(wxT(" "), 0, domain->GetBasetype());
|
|
cbDatatype->SetSelection(0);
|
|
if (domain->GetLength() >= 0)
|
|
{
|
|
txtLength->SetValue(NumToStr(domain->GetLength()));
|
|
if (domain->GetPrecision() >= 0)
|
|
txtPrecision->SetValue(NumToStr(domain->GetPrecision()));
|
|
}
|
|
chkNotNull->SetValue(domain->GetNotNull());
|
|
txtDefault->SetValue(domain->GetDefault());
|
|
|
|
wxCookieType cookie;
|
|
pgObject *data = 0;
|
|
wxTreeItemId item = mainForm->GetBrowser()->GetFirstChild(domain->GetId(), cookie);
|
|
while (item)
|
|
{
|
|
data = mainForm->GetBrowser()->GetObject(item);
|
|
pgaFactory *factory = data->GetFactory();
|
|
if (factory == checkFactory.GetCollectionFactory())
|
|
constraintsItem = item;
|
|
else if (data->GetMetaType() == PGM_CONSTRAINT)
|
|
constraintsItem = item;
|
|
|
|
if (constraintsItem)
|
|
break;
|
|
|
|
item = mainForm->GetBrowser()->GetNextChild(domain->GetId(), cookie);
|
|
}
|
|
|
|
if (constraintsItem)
|
|
{
|
|
pgCollection *coll = (pgCollection *)mainForm->GetBrowser()->GetObject(constraintsItem);
|
|
// make sure all constraints are appended
|
|
coll->ShowTreeDetail(mainForm->GetBrowser());
|
|
// this is the constraints collection
|
|
item = mainForm->GetBrowser()->GetFirstChild(constraintsItem, cookie);
|
|
|
|
// add constraints
|
|
while (item)
|
|
{
|
|
data = mainForm->GetBrowser()->GetObject(item);
|
|
switch (data->GetMetaType())
|
|
{
|
|
case PGM_CHECK:
|
|
{
|
|
pgCheck *obj = (pgCheck *)data;
|
|
|
|
lstConstraints->AppendItem(data->GetIconId(), obj->GetName(), obj->GetDefinition());
|
|
constraintsDefinition.Add(obj->GetDefinition());
|
|
previousConstraints.Add(obj->GetQuotedIdentifier()
|
|
+ wxT(" ") + obj->GetTypeName().Upper() + wxT(" ") + obj->GetDefinition());
|
|
break;
|
|
}
|
|
}
|
|
|
|
item = mainForm->GetBrowser()->GetNextChild(constraintsItem, cookie);
|
|
}
|
|
}
|
|
|
|
cbDatatype->Disable();
|
|
|
|
cbCollation->SetValue(domain->GetQuotedCollation());
|
|
cbCollation->Disable();
|
|
|
|
if (!connection->BackendMinimumVersion(7, 4))
|
|
{
|
|
cbOwner->Disable();
|
|
txtDefault->Disable();
|
|
chkNotNull->Disable();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// create mode
|
|
FillDatatype(cbDatatype, false);
|
|
|
|
cbCollation->Enable(connection->BackendMinimumVersion(9, 1));
|
|
if (connection->BackendMinimumVersion(9, 1))
|
|
{
|
|
// fill collation combobox
|
|
cbCollation->Append(wxEmptyString);
|
|
pgSet *set = connection->ExecuteSet(
|
|
wxT("SELECT nspname, collname\n")
|
|
wxT(" FROM pg_collation c, pg_namespace n\n")
|
|
wxT(" WHERE c.collnamespace=n.oid\n")
|
|
wxT(" ORDER BY nspname, collname"));
|
|
if (set)
|
|
{
|
|
while (!set->Eof())
|
|
{
|
|
wxString name = qtIdent(set->GetVal(wxT("nspname"))) + wxT(".") + qtIdent(set->GetVal(wxT("collname")));
|
|
cbCollation->Append(name);
|
|
set->MoveNext();
|
|
}
|
|
delete set;
|
|
}
|
|
cbCollation->SetSelection(0);
|
|
}
|
|
}
|
|
|
|
cbConstrType->Clear();
|
|
cbConstrType->Append(_("Check"));
|
|
cbConstrType->SetSelection(0);
|
|
btnRemoveConstr->Disable();
|
|
|
|
return dlgProperty::Go(modal);
|
|
}
|
|
|
|
|
|
pgObject *dlgDomain::CreateObject(pgCollection *collection)
|
|
{
|
|
wxString name = GetName();
|
|
|
|
pgObject *obj = domainFactory.CreateObjects(collection, 0,
|
|
wxT(" AND d.typname=") + qtDbString(name) +
|
|
wxT("\n AND d.typnamespace=") + schema->GetOidStr() +
|
|
wxT("\n"));
|
|
return obj;
|
|
}
|
|
|
|
|
|
void dlgDomain::CheckChange()
|
|
{
|
|
bool enable = true;
|
|
|
|
if (domain)
|
|
{
|
|
enable = false;
|
|
if (connection->BackendMinimumVersion(7, 4) || lstColumns->GetItemCount() > 0)
|
|
{
|
|
enable = !GetSql().IsEmpty();
|
|
}
|
|
if (seclabelPage && connection->BackendMinimumVersion(9, 1))
|
|
enable = enable || !(seclabelPage->GetSqlForSecLabels().IsEmpty());
|
|
}
|
|
else
|
|
{
|
|
wxString name = GetName();
|
|
long varlen = StrToLong(txtLength->GetValue()),
|
|
varprec = StrToLong(txtPrecision->GetValue());
|
|
|
|
txtPrecision->Enable(isVarPrec && varlen > 0);
|
|
|
|
CheckValid(enable, !name.IsEmpty(), _("Please specify name."));
|
|
CheckValid(enable, cbDatatype->GetGuessedSelection() >= 0, _("Please select a datatype."));
|
|
CheckValid(enable, !isVarLen || txtLength->GetValue().IsEmpty()
|
|
|| (varlen >= minVarLen && varlen <= maxVarLen && NumToStr(varlen) == txtLength->GetValue()),
|
|
_("Please specify valid length."));
|
|
CheckValid(enable, !txtPrecision->IsEnabled()
|
|
|| (varprec >= 0 && varprec <= varlen && NumToStr(varprec) == txtPrecision->GetValue()),
|
|
_("Please specify valid numeric precision (0..") + NumToStr(varlen) + wxT(")."));
|
|
}
|
|
EnableOK(enable);
|
|
}
|
|
|
|
|
|
|
|
void dlgDomain::OnSelChangeTyp(wxCommandEvent &ev)
|
|
{
|
|
if (!domain)
|
|
{
|
|
cbDatatype->GuessSelection(ev);
|
|
CheckLenEnable();
|
|
txtLength->Enable(isVarLen);
|
|
CheckChange();
|
|
}
|
|
}
|
|
|
|
|
|
void dlgDomain::OnChangeValidate(wxCommandEvent &ev)
|
|
{
|
|
CheckChange();
|
|
}
|
|
|
|
|
|
wxString dlgDomain::GetSql()
|
|
{
|
|
wxString sql, name;
|
|
int pos;
|
|
wxString definition;
|
|
int index = -1;
|
|
wxArrayString tmpDef = previousConstraints;
|
|
wxString tmpsql = wxEmptyString;
|
|
|
|
if (domain)
|
|
{
|
|
// edit mode
|
|
name = GetName();
|
|
|
|
if (txtName->GetValue() != domain->GetName())
|
|
{
|
|
|
|
if (connection->BackendMinimumVersion(9, 2))
|
|
AppendNameChange(sql, wxT("DOMAIN ") + domain->GetQuotedFullIdentifier());
|
|
else
|
|
AppendNameChange(sql, wxT("TYPE ") + domain->GetQuotedFullIdentifier());
|
|
}
|
|
if (chkNotNull->GetValue() != domain->GetNotNull())
|
|
{
|
|
sql += wxT("ALTER DOMAIN ") + domain->GetQuotedFullIdentifier();
|
|
if (chkNotNull->GetValue())
|
|
sql += wxT("\n SET NOT NULL;\n");
|
|
else
|
|
sql += wxT("\n DROP NOT NULL;\n");
|
|
}
|
|
if (txtDefault->GetValue() != domain->GetDefault())
|
|
{
|
|
sql += wxT("ALTER DOMAIN ") + domain->GetQuotedFullIdentifier();
|
|
if (txtDefault->GetValue().IsEmpty())
|
|
sql += wxT("\n DROP DEFAULT;\n");
|
|
else
|
|
sql += wxT("\n SET DEFAULT ") + txtDefault->GetValue() + wxT(";\n");
|
|
}
|
|
|
|
// Build a temporary list of ADD CONSTRAINTs, and fixup the list to remove
|
|
for (pos = 0; pos < lstConstraints->GetItemCount() ; pos++)
|
|
{
|
|
wxString conname = qtIdent(lstConstraints->GetItemText(pos));
|
|
definition = conname;
|
|
definition += wxT(" CHECK ") + constraintsDefinition.Item(pos);
|
|
index = tmpDef.Index(definition);
|
|
if (index >= 0)
|
|
tmpDef.RemoveAt(index);
|
|
else
|
|
{
|
|
tmpsql += wxT("ALTER DOMAIN ") + domain->GetQuotedFullIdentifier()
|
|
+ wxT("\n ADD");
|
|
if (!conname.IsEmpty())
|
|
tmpsql += wxT(" CONSTRAINT ");
|
|
|
|
tmpsql += definition + wxT(";\n");
|
|
}
|
|
}
|
|
|
|
// Add the DROP CONSTRAINTs...
|
|
for (index = 0 ; index < (int)tmpDef.GetCount() ; index++)
|
|
{
|
|
definition = tmpDef.Item(index);
|
|
if (definition[0U] == '"')
|
|
definition = definition.Mid(1).BeforeFirst('"');
|
|
else
|
|
definition = definition.BeforeFirst(' ');
|
|
sql += wxT("ALTER DOMAIN ") + domain->GetQuotedFullIdentifier()
|
|
+ wxT("\n DROP CONSTRAINT ") + qtIdent(definition) + wxT(";\n");
|
|
|
|
}
|
|
|
|
// Add the ADD CONSTRAINTs...
|
|
sql += tmpsql;
|
|
|
|
AppendOwnerChange(sql, wxT("DOMAIN ") + domain->GetQuotedFullIdentifier());
|
|
AppendSchemaChange(sql, wxT("DOMAIN ") + domain->GetQuotedFullIdentifier());
|
|
}
|
|
else
|
|
{
|
|
// create mode
|
|
name = qtIdent(cbSchema->GetValue()) + wxT(".") + qtIdent(GetName());
|
|
sql = wxT("CREATE DOMAIN ") + name
|
|
+ wxT("\n AS ") + GetQuotedTypename(cbDatatype->GetGuessedSelection());
|
|
|
|
if (!cbCollation->GetValue().IsEmpty() && cbCollation->GetValue() != wxT("pg_catalog.\"default\""))
|
|
sql += wxT("\n COLLATE ") + cbCollation->GetValue();
|
|
|
|
AppendIfFilled(sql, wxT("\n DEFAULT "), txtDefault->GetValue());
|
|
|
|
if (chkNotNull->GetValue())
|
|
sql += wxT("\n NOT NULL");
|
|
|
|
for (pos = 0 ; pos < lstConstraints->GetItemCount() ; pos++)
|
|
{
|
|
wxString name = lstConstraints->GetItemText(pos);
|
|
wxString definition = constraintsDefinition.Item(pos);
|
|
if (!name.IsEmpty())
|
|
sql += wxT("\n CONSTRAINT ") + qtIdent(name) + wxT(" CHECK ") + definition;
|
|
else
|
|
sql += wxT("\n CHECK ") + definition;
|
|
}
|
|
|
|
sql += wxT(";\n");
|
|
|
|
AppendOwnerNew(sql, wxT("DOMAIN ") + name);
|
|
}
|
|
|
|
AppendComment(sql, wxT("DOMAIN ") + qtIdent(cbSchema->GetValue()) + wxT(".") + qtIdent(GetName()), domain);
|
|
|
|
if (seclabelPage && connection->BackendMinimumVersion(9, 1))
|
|
sql += seclabelPage->GetSqlForSecLabels(wxT("DOMAIN"), name);
|
|
|
|
return sql;
|
|
}
|
|
|
|
void dlgDomain::OnChange(wxCommandEvent &event)
|
|
{
|
|
CheckChange();
|
|
}
|
|
|
|
void dlgDomain::OnAddConstr(wxCommandEvent &ev)
|
|
{
|
|
int sel = cbConstrType->GetCurrentSelection();
|
|
|
|
switch (sel)
|
|
{
|
|
case 0: // Check
|
|
{
|
|
dlgCheck chk(&checkFactory, mainForm);
|
|
chk.CenterOnParent();
|
|
chk.SetDatabase(database);
|
|
if (chk.Go(true) != wxID_CANCEL)
|
|
{
|
|
wxString tmpDef = chk.GetDefinition();
|
|
tmpDef.Replace(wxT("\n"), wxT(" "));
|
|
|
|
lstConstraints->AppendItem(checkFactory.GetIconId(), chk.GetName(), tmpDef);
|
|
constraintsDefinition.Add(tmpDef);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
CheckChange();
|
|
}
|
|
|
|
|
|
void dlgDomain::OnRemoveConstr(wxCommandEvent &ev)
|
|
{
|
|
if (settings->GetConfirmDelete())
|
|
{
|
|
if (wxMessageBox(_("Are you sure you wish to remove the selected constraint?"), _("Remove constraint?"), wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION) != wxYES)
|
|
return;
|
|
}
|
|
|
|
int pos = lstConstraints->GetSelection();
|
|
if (pos < 0)
|
|
return;
|
|
|
|
lstConstraints->DeleteItem(pos);
|
|
constraintsDefinition.RemoveAt(pos);
|
|
btnRemoveConstr->Disable();
|
|
|
|
CheckChange();
|
|
}
|
|
|
|
|
|
void dlgDomain::OnSelChangeConstr(wxListEvent &ev)
|
|
{
|
|
btnRemoveConstr->Enable();
|
|
}
|
|
|
|
|