Le 02/11/2010 07:18, Guillaume Lelarge a écrit :
> Le 02/11/2010 05:49, Dave Page a écrit :
>> On Mon, Nov 1, 2010 at 2:51 PM, Guillaume Lelarge
>> <[email protected]> wrote:
>>> Le 31/10/2010 09:44, Guillaume Lelarge a écrit :
>>>> Le 31/10/2010 00:39, Dave Page a écrit :
>>>>> On Sun, Oct 31, 2010 at 1:56 AM, Guillaume Lelarge
>>>>> <[email protected]> wrote:
>>>>>> Le 30/10/2010 10:25, Dave Page a écrit :
>>>>>>
>>>>>>> Yeah, that's really nasty. I guess we need split the commands at ;.
>>>>>>
>>>>>> Yeah. If it's not between quotes. I don't like it at all, but I don't
>>>>>> see another way of doing it.
>>>>>>
>>>>>>> I guess we should pass a flag down somehow to tell the function that
>>>>>>> executes the query to do that and then we could also potentially get
>>>>>>> rid of the double SQL boxes. I'm not looking at the code, but I
>>>>>>> suspect that'll be nasty.
>>>>>>>
>>>>>>
>>>>>> We actually aren't required to add such a flag. We can check if the
>>>>>> query contains "ALTER TYPE", and "ADD AFTER" or "ADD BEFORE".
>>>>>
>>>>> That's knowledge I'd rather avoid hardwiring into the lower level
>>>>> machinery here.
>>>>>
>>>>
>>>> So do I. I tried a few things yesterday. Changing the apply() and
>>>> GetSql() parameters imply to change all GetSql for all dlg* source code.
>>>> That will be quite an invasive patch.
>>>>
>>>
>>> I've done the "split-the-queries" function. Seems to work great, but
>>> still doesn't cover dollar quoting. Anyway, it's less ugly than I
>>> thought. The interesting part is dlgProperty::SplitQueries(). Would love
>>> to get comments :)
>>
>> I just eyeballed the patch - if I'm reading it right, it splits *all*
>> queries and executes each part individually. Is that correct?
>>
>
> Right.
>
>> If so, we're going to need that flag. Most of the time, we want all
>> the query parts to be executed atomically, otherwise if we get and
>> error (particularly when using the Apply button where there is one),
>> the dialogue won't know what parts of the update work and what didn't,
>> and thus will have a difficult job refreshing the display
>> appropriately.
>>
>
> Yeah, that was the part I wanted to work on yesterday. I have an idea on
> this, I actually have the code, but it doesn't work :-/ Need some more work.
>
Done. I'm actually quite happy with how it turns out. Less nasty then I
previously thought. Complete patch attached (alterenum_v1.patch). The
last part of the work is available on the patch 0001* attached to this
email. Or you can get a look at my branch on github
(http://github.com/gleu/pgadmin3/commits/ticket269).
Probably I should change the method name... WannaSplitQueries is
probably not the best one we could find :)
Comments welcome.
--
Guillaume
http://www.postgresql.fr
http://dalibo.com
>From e335ce1cb0b43d64dc5f63d66874d779fdf0e01e Mon Sep 17 00:00:00 2001
From: Guillaume Lelarge <[email protected]>
Date: Tue, 2 Nov 2010 11:31:03 -0700
Subject: [PATCH] The "split the query" should only fire if necessary
New method "WannaSplitQueries", that returns true if the object's dialog
decids that the queries need to be splitted. Only occurs with enum types so
far.
---
pgadmin/dlg/dlgProperty.cpp | 5 ++++-
pgadmin/dlg/dlgType.cpp | 11 +++++++----
pgadmin/include/dlg/dlgProperty.h | 2 ++
pgadmin/include/dlg/dlgType.h | 3 +++
4 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/pgadmin/dlg/dlgProperty.cpp b/pgadmin/dlg/dlgProperty.cpp
index 5f8b4b0..484bf71 100644
--- a/pgadmin/dlg/dlgProperty.cpp
+++ b/pgadmin/dlg/dlgProperty.cpp
@@ -812,7 +812,10 @@ bool dlgProperty::apply(const wxString &sql, const wxString &sql2)
{
wxArrayString queries;
- queries= SplitQueries(BuildSql(sql));
+ if (WannaSplitQueries())
+ queries = SplitQueries(BuildSql(sql));
+ else
+ queries.Add(BuildSql(sql));
for (size_t index = 0; index < queries.GetCount(); index++)
{
diff --git a/pgadmin/dlg/dlgType.cpp b/pgadmin/dlg/dlgType.cpp
index 1939f5d..535c6a0 100644
--- a/pgadmin/dlg/dlgType.cpp
+++ b/pgadmin/dlg/dlgType.cpp
@@ -96,6 +96,8 @@ dlgType::dlgType(pgaFactory *f, frmMain *frame, pgType *node, pgSchema *sch)
lstMembers->CreateColumns(0, _("Member"), _("Data type"), -1);
lstLabels->InsertColumn(0, _("Label"), wxLIST_FORMAT_LEFT, GetClientSize().GetWidth());
+ queriesToBeSplitted = false;
+
wxNotifyEvent event;
OnTypeChange(event);
}
@@ -610,7 +612,7 @@ pgObject *dlgType::CreateObject(pgCollection *collection)
wxString dlgType::GetSql()
{
wxString sql,direction;
- int existingitems_index, listitems_index, offset;
+ size_t existingitems_index, listitems_index, offset;
if (type)
{
@@ -621,10 +623,11 @@ wxString dlgType::GetSql()
{
wxArrayString elements=type->GetLabelArray();
existingitems_index = 0;
- for (listitems_index=0 ; listitems_index < lstLabels->GetItemCount() ; listitems_index++)
+ for (listitems_index=0 ; listitems_index < (size_t)lstLabels->GetItemCount() ; listitems_index++)
{
- if (lstLabels->GetItemText(listitems_index) != elements.Item(existingitems_index))
+ if (existingitems_index >= elements.GetCount() || lstLabels->GetItemText(listitems_index) != elements.Item(existingitems_index))
{
+ queriesToBeSplitted = true;
if (listitems_index == 0)
{
direction = wxT("BEFORE");
@@ -773,7 +776,7 @@ wxString dlgType::GetSqlForTypes()
wxString sql = wxEmptyString;
wxString old_name, old_type, new_name, new_type;
wxArrayString elements=type->GetTypesArray();
- bool modified = lstMembers->GetItemCount()*2 != elements.GetCount();
+ bool modified = lstMembers->GetItemCount()*2 != (int)elements.GetCount();
size_t i;
// Check if there is a change
diff --git a/pgadmin/include/dlg/dlgProperty.h b/pgadmin/include/dlg/dlgProperty.h
index 0e02a20..6ee9817 100644
--- a/pgadmin/include/dlg/dlgProperty.h
+++ b/pgadmin/include/dlg/dlgProperty.h
@@ -89,6 +89,8 @@ public:
virtual int Go(bool modal=false);
virtual void CheckChange() =0;
+ virtual bool WannaSplitQueries() { return false; }
+
protected:
dlgProperty(pgaFactory *factory, frmMain *frame, const wxString &resName);
~dlgProperty();
diff --git a/pgadmin/include/dlg/dlgType.h b/pgadmin/include/dlg/dlgType.h
index d44b89d..273b655 100644
--- a/pgadmin/include/dlg/dlgType.h
+++ b/pgadmin/include/dlg/dlgType.h
@@ -28,6 +28,8 @@ public:
pgObject *CreateObject(pgCollection *collection);
pgObject *GetObject();
+ bool WannaSplitQueries() { return queriesToBeSplitted; }
+
int Go(bool modal);
private:
@@ -50,6 +52,7 @@ private:
wxString GetFullTypeName(int type);
wxArrayString memberTypes, memberLengths, memberPrecisions;
+ bool queriesToBeSplitted;
DECLARE_EVENT_TABLE()
};
--
1.7.1
diff --git a/pgadmin/dlg/dlgProperty.cpp b/pgadmin/dlg/dlgProperty.cpp
index ece5ea3..484bf71 100644
--- a/pgadmin/dlg/dlgProperty.cpp
+++ b/pgadmin/dlg/dlgProperty.cpp
@@ -799,6 +799,7 @@ void dlgProperty::ShowObject()
bool dlgProperty::apply(const wxString &sql, const wxString &sql2)
{
+ wxString tmp;
pgConn *myConn = connection;
if (GetDisconnectFirst())
@@ -809,37 +810,25 @@ bool dlgProperty::apply(const wxString &sql, const wxString &sql2)
if (!sql.IsEmpty())
{
- wxString tmp;
- if (cbClusterSet && cbClusterSet->GetSelection() > 0)
- {
- replClientData *data=(replClientData*)cbClusterSet->GetClientData(cbClusterSet->GetSelection());
+ wxArrayString queries;
- if (data->majorVer > 1 || (data->majorVer == 1 && data->minorVer >= 2))
- {
- tmp = wxT("SELECT ") + qtIdent(data->cluster)
- + wxT(".ddlscript_prepare(") + NumToStr(data->setId) + wxT(", 0);\n")
- + wxT("SELECT ") + qtIdent(data->cluster)
- + wxT(".ddlscript_complete(") + NumToStr(data->setId) + wxT(", ")
- + qtDbString(sql) + wxT(", 0);\n");
- }
- else
- {
- tmp = wxT("SELECT ") + qtIdent(data->cluster)
- + wxT(".ddlscript(") + NumToStr(data->setId) + wxT(", ")
- + qtDbString(sql) + wxT(", 0);\n");
- }
- }
+ if (WannaSplitQueries())
+ queries = SplitQueries(BuildSql(sql));
else
- tmp = sql;
+ queries.Add(BuildSql(sql));
- if (!myConn->ExecuteVoid(tmp))
+ for (size_t index = 0; index < queries.GetCount(); index++)
{
- // error message is displayed inside ExecuteVoid
- return false;
- }
+ tmp = queries.Item(index);
+ if (!myConn->ExecuteVoid(tmp))
+ {
+ // error message is displayed inside ExecuteVoid
+ return false;
+ }
- if (database)
- database->AppendSchemaChange(tmp);
+ if (database)
+ database->AppendSchemaChange(tmp);
+ }
}
// Process the second SQL statement. This is primarily only used by
@@ -847,28 +836,7 @@ bool dlgProperty::apply(const wxString &sql, const wxString &sql2)
// PostgreSQL 8.3+
if (!sql2.IsEmpty())
{
- wxString tmp;
- if (cbClusterSet && cbClusterSet->GetSelection() > 0)
- {
- replClientData *data=(replClientData*)cbClusterSet->GetClientData(cbClusterSet->GetSelection());
-
- if (data->majorVer > 1 || (data->majorVer == 1 && data->minorVer >= 2))
- {
- tmp = wxT("SELECT ") + qtIdent(data->cluster)
- + wxT(".ddlscript_prepare(") + NumToStr(data->setId) + wxT(", 0);\n")
- + wxT("SELECT ") + qtIdent(data->cluster)
- + wxT(".ddlscript_complete(") + NumToStr(data->setId) + wxT(", ")
- + qtDbString(sql2) + wxT(", 0);\n");
- }
- else
- {
- tmp = wxT("SELECT ") + qtIdent(data->cluster)
- + wxT(".ddlscript(") + NumToStr(data->setId) + wxT(", ")
- + qtDbString(sql2) + wxT(", 0);\n");
- }
- }
- else
- tmp = sql2;
+ tmp = BuildSql(sql2);
if (!myConn->ExecuteVoid(tmp))
{
@@ -891,6 +859,86 @@ bool dlgProperty::apply(const wxString &sql, const wxString &sql2)
}
+wxString dlgProperty::BuildSql(const wxString &sql)
+{
+ wxString tmp;
+
+ if (cbClusterSet && cbClusterSet->GetSelection() > 0)
+ {
+ replClientData *data=(replClientData*)cbClusterSet->GetClientData(cbClusterSet->GetSelection());
+
+ if (data->majorVer > 1 || (data->majorVer == 1 && data->minorVer >= 2))
+ {
+ tmp = wxT("SELECT ") + qtIdent(data->cluster)
+ + wxT(".ddlscript_prepare(") + NumToStr(data->setId) + wxT(", 0);\n")
+ + wxT("SELECT ") + qtIdent(data->cluster)
+ + wxT(".ddlscript_complete(") + NumToStr(data->setId) + wxT(", ")
+ + qtDbString(sql) + wxT(", 0);\n");
+ }
+ else
+ {
+ tmp = wxT("SELECT ") + qtIdent(data->cluster)
+ + wxT(".ddlscript(") + NumToStr(data->setId) + wxT(", ")
+ + qtDbString(sql) + wxT(", 0);\n");
+ }
+ }
+ else
+ tmp = sql;
+
+ return tmp;
+}
+
+
+wxArrayString dlgProperty::SplitQueries(const wxString &sql)
+{
+ wxArrayString queries;
+ wxString query;
+ wxString c;
+
+ bool antislash = false;
+ bool quote_string = false;
+ bool doublequote_string = false;
+
+ for (size_t item = 0; item < sql.Length(); item++)
+ {
+ c = sql.GetChar(item);
+
+ if (c == wxT("\\"))
+ antislash = true;
+
+ if (c == wxT("'"))
+ {
+ if (antislash)
+ antislash = false;
+ else if (quote_string)
+ quote_string = false;
+ else if (!doublequote_string)
+ quote_string = true;
+ }
+
+ if (c == wxT("\""))
+ {
+ if (antislash)
+ antislash = false;
+ else if (doublequote_string)
+ doublequote_string = false;
+ else if (!quote_string)
+ doublequote_string = true;
+ }
+
+ query = query + c;
+
+ if (c == wxT(";") && !antislash && !quote_string && !doublequote_string)
+ {
+ queries.Add(query);
+ query = wxEmptyString;
+ }
+ }
+
+ return queries;
+}
+
+
void dlgProperty::OnApply(wxCommandEvent &ev)
{
if (!IsUpToDate())
diff --git a/pgadmin/dlg/dlgType.cpp b/pgadmin/dlg/dlgType.cpp
index f96de46..535c6a0 100644
--- a/pgadmin/dlg/dlgType.cpp
+++ b/pgadmin/dlg/dlgType.cpp
@@ -47,7 +47,8 @@
#define btnAddMember CTRL_BUTTON("btnAddMember")
#define btnChangeMember CTRL_BUTTON("btnChangeMember")
#define btnRemoveMember CTRL_BUTTON("btnRemoveMember")
-#define btnAddLabel CTRL_BUTTON("btnAddLabel")
+#define btnAddAfterLabel CTRL_BUTTON("btnAddAfterLabel")
+#define btnAddBeforeLabel CTRL_BUTTON("btnAddBeforeLabel")
#define btnRemoveLabel CTRL_BUTTON("btnRemoveLabel")
#define pnlDefinition CTRL_PANEL("pnlDefinition")
#define pnlDefinitionExtern CTRL_PANEL("pnlDefinitionExtern")
@@ -68,7 +69,8 @@ BEGIN_EVENT_TABLE(dlgType, dlgTypeProperty)
EVT_BUTTON(XRCID("btnAddMember"), dlgType::OnMemberAdd)
EVT_BUTTON(XRCID("btnChangeMember"), dlgType::OnMemberChange)
EVT_BUTTON(XRCID("btnRemoveMember"), dlgType::OnMemberRemove)
- EVT_BUTTON(XRCID("btnAddLabel"), dlgType::OnLabelAdd)
+ EVT_BUTTON(XRCID("btnAddBeforeLabel"), dlgType::OnLabelAddBefore)
+ EVT_BUTTON(XRCID("btnAddAfterLabel"), dlgType::OnLabelAddAfter)
EVT_BUTTON(XRCID("btnRemoveLabel"), dlgType::OnLabelRemove)
EVT_LIST_ITEM_SELECTED(XRCID("lstMembers"), dlgType::OnMemberSelChange)
EVT_LIST_ITEM_SELECTED(XRCID("lstLabels"), dlgType::OnLabelSelChange)
@@ -94,6 +96,8 @@ dlgType::dlgType(pgaFactory *f, frmMain *frame, pgType *node, pgSchema *sch)
lstMembers->CreateColumns(0, _("Member"), _("Data type"), -1);
lstLabels->InsertColumn(0, _("Label"), wxLIST_FORMAT_LEFT, GetClientSize().GetWidth());
+ queriesToBeSplitted = false;
+
wxNotifyEvent event;
OnTypeChange(event);
}
@@ -194,9 +198,10 @@ int dlgType::Go(bool modal)
btnChangeMember->Enable(false);
btnRemoveMember->Enable(false);
- txtLabel->Enable(changeok);
- btnAddLabel->Enable(changeok);
- btnRemoveLabel->Enable(changeok);
+ txtLabel->Enable(connection->BackendMinimumVersion(9, 1));
+ btnAddBeforeLabel->Enable(connection->BackendMinimumVersion(9, 1));
+ btnAddAfterLabel->Enable(connection->BackendMinimumVersion(9, 1));
+ btnRemoveLabel->Disable();
wxArrayString elements=type->GetTypesArray();
wxString fullType, typeName, typeLength, typePrecision;
@@ -395,7 +400,8 @@ void dlgType::CheckChange()
{
EnableOK(txtComment->GetValue() != type->GetComment()
|| cbOwner->GetValue() != type->GetOwner()
- || (rdbType->GetSelection() == TYPE_COMPOSITE && GetSqlForTypes() != wxEmptyString));
+ || (rdbType->GetSelection() == TYPE_COMPOSITE && GetSqlForTypes() != wxEmptyString)
+ || (GetSql().Length() > 0 && connection->BackendMinimumVersion(9, 1)));
}
else
{
@@ -541,7 +547,28 @@ void dlgType::OnLabelSelChange(wxListEvent &ev)
}
-void dlgType::OnLabelAdd(wxCommandEvent &ev)
+void dlgType::OnLabelAddBefore(wxCommandEvent &ev)
+{
+ wxString label=txtLabel->GetValue().Strip(wxString::both);
+
+ if (!label.IsEmpty())
+ {
+ long pos=lstLabels->FindItem(-1, label);
+ if (pos < 0)
+ {
+ if (lstLabels->GetFirstSelected() >= 0)
+ pos = lstLabels->GetFirstSelected();
+ else
+ pos = 0;
+ lstLabels->InsertItem(pos, label, 0);
+ }
+ }
+ txtLabel->SetValue(wxEmptyString);
+ CheckChange();
+}
+
+
+void dlgType::OnLabelAddAfter(wxCommandEvent &ev)
{
wxString label=txtLabel->GetValue().Strip(wxString::both);
@@ -550,7 +577,10 @@ void dlgType::OnLabelAdd(wxCommandEvent &ev)
long pos=lstLabels->FindItem(-1, label);
if (pos < 0)
{
- pos = lstLabels->GetItemCount();
+ if (lstLabels->GetFirstSelected() >= 0)
+ pos = lstLabels->GetFirstSelected() + 1;
+ else
+ pos = lstLabels->GetItemCount();
lstLabels->InsertItem(pos, label, 0);
}
}
@@ -581,13 +611,44 @@ pgObject *dlgType::CreateObject(pgCollection *collection)
wxString dlgType::GetSql()
{
- wxString sql;
+ wxString sql,direction;
+ size_t existingitems_index, listitems_index, offset;
if (type)
{
// Edit Mode
AppendOwnerChange(sql, wxT("TYPE ") + type->GetQuotedFullIdentifier());
sql += GetSqlForTypes();
+ if (rdbType->GetSelection() == TYPE_ENUM && connection->BackendMinimumVersion(9, 1))
+ {
+ wxArrayString elements=type->GetLabelArray();
+ existingitems_index = 0;
+ for (listitems_index=0 ; listitems_index < (size_t)lstLabels->GetItemCount() ; listitems_index++)
+ {
+ if (existingitems_index >= elements.GetCount() || lstLabels->GetItemText(listitems_index) != elements.Item(existingitems_index))
+ {
+ queriesToBeSplitted = true;
+ if (listitems_index == 0)
+ {
+ direction = wxT("BEFORE");
+ offset = 0;
+ }
+ else
+ {
+ direction = wxT("AFTER");
+ offset = -1;
+ }
+
+ sql += wxT("ALTER TYPE ") + type->GetQuotedFullIdentifier()
+ + wxT(" ADD ") + connection->qtDbString(lstLabels->GetItemText(listitems_index))
+ + wxT(" ") + direction + wxT(" ")
+ + connection->qtDbString(elements.Item(existingitems_index + offset))
+ + wxT(";\n");
+ }
+ else
+ existingitems_index++;
+ }
+ }
}
else
{
@@ -715,7 +776,7 @@ wxString dlgType::GetSqlForTypes()
wxString sql = wxEmptyString;
wxString old_name, old_type, new_name, new_type;
wxArrayString elements=type->GetTypesArray();
- bool modified = lstMembers->GetItemCount()*2 != elements.GetCount();
+ bool modified = lstMembers->GetItemCount()*2 != (int)elements.GetCount();
size_t i;
// Check if there is a change
diff --git a/pgadmin/include/dlg/dlgProperty.h b/pgadmin/include/dlg/dlgProperty.h
index 682cb33..6ee9817 100644
--- a/pgadmin/include/dlg/dlgProperty.h
+++ b/pgadmin/include/dlg/dlgProperty.h
@@ -89,6 +89,8 @@ public:
virtual int Go(bool modal=false);
virtual void CheckChange() =0;
+ virtual bool WannaSplitQueries() { return false; }
+
protected:
dlgProperty(pgaFactory *factory, frmMain *frame, const wxString &resName);
~dlgProperty();
@@ -161,6 +163,8 @@ protected:
private:
bool tryUpdate(wxTreeItemId collectionItem);
bool apply(const wxString &sql, const wxString &sql2);
+ wxString BuildSql(const wxString &sql);
+ wxArrayString SplitQueries(const wxString &sql);
DECLARE_EVENT_TABLE()
};
diff --git a/pgadmin/include/dlg/dlgType.h b/pgadmin/include/dlg/dlgType.h
index e7481e4..273b655 100644
--- a/pgadmin/include/dlg/dlgType.h
+++ b/pgadmin/include/dlg/dlgType.h
@@ -28,6 +28,8 @@ public:
pgObject *CreateObject(pgCollection *collection);
pgObject *GetObject();
+ bool WannaSplitQueries() { return queriesToBeSplitted; }
+
int Go(bool modal);
private:
@@ -38,7 +40,8 @@ private:
void OnMemberChange(wxCommandEvent &ev);
void OnMemberRemove(wxCommandEvent &ev);
void OnMemberSelChange(wxListEvent &ev);
- void OnLabelAdd(wxCommandEvent &ev);
+ void OnLabelAddBefore(wxCommandEvent &ev);
+ void OnLabelAddAfter(wxCommandEvent &ev);
void OnLabelRemove(wxCommandEvent &ev);
void OnLabelSelChange(wxListEvent &ev);
void OnSelChangeTyp(wxCommandEvent &ev);
@@ -49,6 +52,7 @@ private:
wxString GetFullTypeName(int type);
wxArrayString memberTypes, memberLengths, memberPrecisions;
+ bool queriesToBeSplitted;
DECLARE_EVENT_TABLE()
};
diff --git a/pgadmin/schema/pgType.cpp b/pgadmin/schema/pgType.cpp
index abdba64..1eff28b 100644
--- a/pgadmin/schema/pgType.cpp
+++ b/pgadmin/schema/pgType.cpp
@@ -198,11 +198,14 @@ void pgType::ShowTreeDetail(ctlTree *browser, frmMain *form, ctlListView *proper
}
else if (GetTypeClass() == TYPE_ENUM)
{
- pgSet *set=ExecuteSet(
- wxT("SELECT enumlabel\n")
- wxT(" FROM pg_enum\n")
- wxT(" WHERE enumtypid=") + GetOidStr() + wxT("\n")
- wxT(" ORDER by oid"));
+ wxString query = wxT("SELECT enumlabel\n")
+ wxT(" FROM pg_enum\n")
+ wxT(" WHERE enumtypid=") + GetOidStr() + wxT("\n");
+ if (GetConnection()->BackendMinimumVersion(9, 1))
+ query += wxT(" ORDER by enumsortorder");
+ else
+ query += wxT(" ORDER by oid");
+ pgSet *set=ExecuteSet(query);
if (set)
{
int anzvar=0;
diff --git a/pgadmin/ui/dlgType.xrc b/pgadmin/ui/dlgType.xrc
index 7d8b7d7..8d65fd0 100644
--- a/pgadmin/ui/dlgType.xrc
+++ b/pgadmin/ui/dlgType.xrc
@@ -284,7 +284,7 @@
</object>
<object class="sizeritem">
<object class="wxFlexGridSizer">
- <cols>3</cols>
+ <cols>4</cols>
<rows>1</rows>
<vgap>5</vgap>
<hgap>5</hgap>
@@ -293,8 +293,15 @@
<size>2,2d</size>
</object>
<object class="sizeritem">
- <object class="wxButton" name="btnAddLabel">
- <label>Add</label>
+ <object class="wxButton" name="btnAddBeforeLabel">
+ <label>Add before</label>
+ </object>
+ <flag>wxALIGN_CENTRE_VERTICAL|wxALL</flag>
+ <border>4</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxButton" name="btnAddAfterLabel">
+ <label>Add after</label>
</object>
<flag>wxALIGN_CENTRE_VERTICAL|wxALL</flag>
<border>4</border>
--
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers