Thread: A new feature patch and a bug fix

A new feature patch and a bug fix

From
Guillaume Lelarge
Date:
Hi,

Let's begin with the bug fix. I've found that I can set the owner of an
object only from login role. pgAdmin doesn't allow me to set ownership
to a group. psql allows it, so I think this is a bug. The patch named
"dlgProperty.patch" fixes this issue.

I found this when I tried to add "reassign owned by" and "drop owned by"
functionalities to pgAdmin. I first thought I would add this with the
drop-user code but I prefer to make it available alone. So I used my
well known way : a new contextual menu (in fact two : "Reassign Owned
To..." and "Drop Owned"). The first one opens a wxSingleChoiceDialog
dialog for the user to choose a role from. The second one waits for a
confirmation and then fires the SQL statement. My problem is here : on a
user contextual menu, the only connection I can get is the maintenance
connection. So I will only be able to reassign or drop objects within
the maintenance database. I was wondering if there was a way to get a
handle to the last open connection ? or if there was another way ? for
example asking the user to choose the database to connect to and fire
the SQL statement ? or asking the user to select a database where he's
already connected to ?

Thanks.

Regards.


--
Guillaume.
 http://www.postgresqlfr.org
 http://dalibo.com
Index: pgadmin/dlg/dlgProperty.cpp
===================================================================
--- pgadmin/dlg/dlgProperty.cpp    (révision 6910)
+++ pgadmin/dlg/dlgProperty.cpp    (copie de travail)
@@ -432,7 +432,14 @@

 void dlgProperty::AddUsers(ctlComboBoxFix *cb1, ctlComboBoxFix *cb2)
 {
-    FillCombobox(wxT("SELECT usename FROM pg_user ORDER BY usename"), cb1, cb2);
+    if (connection->BackendMinimumVersion(8, 2))
+    {
+        FillCombobox(wxT("SELECT rolname FROM pg_roles ORDER BY 1"), cb1, cb2);
+    }
+    else
+    {
+        FillCombobox(wxT("SELECT usename FROM pg_user UNION SELECT groname FROM pg_group ORDER BY 1"), cb1, cb2);
+    }
 }


Index: pgadmin/include/schema/pgRole.h
===================================================================
--- pgadmin/include/schema/pgRole.h    (révision 6910)
+++ pgadmin/include/schema/pgRole.h    (copie de travail)
@@ -75,8 +75,10 @@
     void iSetUpdateCatalog(const bool b) { updateCatalog=b; }
     wxArrayString& GetRolesIn() { return rolesIn; }
     wxArrayString& GetConfigList() { return configList; }
+
+    void ReassignOwnedTo();
+    void DropOwned();

-
     // Tree object creation
     void ShowTreeDetail(ctlTree *browser, frmMain *form=0, ctlListView *properties=0, ctlSQLBox *sqlPane=0);
     void ShowDependents(frmMain *form, ctlListView *referencedBy, const wxString &where);
@@ -89,6 +91,7 @@
     bool HasStats() { return false; }
     bool HasDepends() { return true; }
     bool HasReferences() { return true; }
+
 private:
     wxString password;
     wxDateTime accountExpires;
@@ -112,6 +115,21 @@
     pgGroupRole(const wxString& newName = wxT(""));
 };

+class reassignOwnedFactory : public contextActionFactory
+{
+public:
+    reassignOwnedFactory(menuFactoryList *list, wxMenu *mnu, wxToolBar *toolbar);
+    wxWindow *StartDialog(frmMain *form, pgObject *obj);
+    bool CheckEnable(pgObject *obj);
+};

+class dropOwnedFactory : public contextActionFactory
+{
+public:
+    dropOwnedFactory(menuFactoryList *list, wxMenu *mnu, wxToolBar *toolbar);
+    wxWindow *StartDialog(frmMain *form, pgObject *obj);
+    bool CheckEnable(pgObject *obj);
+};

+
 #endif
Index: pgadmin/frm/frmMain.cpp
===================================================================
--- pgadmin/frm/frmMain.cpp    (révision 6910)
+++ pgadmin/frm/frmMain.cpp    (copie de travail)
@@ -67,6 +67,7 @@
 #include "schema/pgTable.h"
 #include "schema/pgIndex.h"
 #include "schema/pgTrigger.h"
+#include "schema/pgRole.h"
 #include "schema/pgRule.h"
 #include "schema/pgServer.h"
 #include "slony/slCluster.h"
@@ -326,6 +327,8 @@
     new dropCascadedFactory(menuFactories, editMenu, 0);
     new truncateFactory(menuFactories, editMenu, 0);
     new truncateCascadedFactory(menuFactories, editMenu, 0);
+    new reassignOwnedFactory(menuFactories, editMenu, 0);
+    new dropOwnedFactory(menuFactories, editMenu, 0);
     editMenu->AppendSeparator();

     new separatorFactory(menuFactories);
Index: pgadmin/schema/pgRole.cpp
===================================================================
--- pgadmin/schema/pgRole.cpp    (révision 6910)
+++ pgadmin/schema/pgRole.cpp    (copie de travail)
@@ -11,6 +11,7 @@

 // wxWindows headers
 #include <wx/wx.h>
+#include <wx/choicdlg.h>

 // App headers
 #include "pgAdmin3.h"
@@ -51,7 +52,7 @@

 bool pgRole::DropObject(wxFrame *frame, ctlTree *browser, bool cascaded)
 {
-    if (GetUpdateCatalog())
+    if (GetUpdateCatalog())
     {
         wxMessageDialog dlg(frame,
             _("Deleting a superuser might result in unwanted behaviour (e.g. when restoring the database).\nAre you
sure?"),
@@ -277,7 +278,38 @@
 }


+void pgRole::ReassignOwnedTo()
+{
+    wxArrayString rolesList;
+    wxString rolesquery;
+
+    rolesquery = wxT("SELECT rolname FROM pg_roles ORDER BY rolname");
+    pgSetIterator roles(GetConnection(), rolesquery);
+    while (roles.RowsLeft())
+    {
+        rolesList.Add(roles.GetVal(wxT("rolname")));
+    }
+
+    wxSingleChoiceDialog dialog(0,
+      wxT("Choose the user that will own all objects owned by the selected role."),
+      wxT("Please select a role"),
+      rolesList);
+
+    if (dialog.ShowModal() == wxID_OK)
+    {
+        rolesquery = wxT("REASSIGN OWNED BY ") + GetQuotedFullIdentifier() + wxT(" TO ") +
dialog.GetStringSelection();
+        GetConnection()->ExecuteVoid(rolesquery);
+    }
+}

+
+void pgRole::DropOwned()
+{
+    wxString query = wxT("DROP OWNED BY ") + GetQuotedFullIdentifier();
+    GetConnection()->ExecuteVoid(query);
+}
+
+
 pgObject *pgRole::Refresh(ctlTree *browser, const wxTreeItemId item)
 {
     pgObject *role=0;
@@ -394,3 +426,43 @@

 pgGroupRoleFactory groupRoleFactory;
 static pgaCollectionFactory gcf(&groupRoleFactory, __("Group Roles"), roles_xpm);
+
+
+reassignOwnedFactory::reassignOwnedFactory(menuFactoryList *list, wxMenu *mnu, wxToolBar *toolbar) :
contextActionFactory(list)
+{
+    mnu->Append(id, _("Reassign Owned To..."), _("Reassigned objects owned by this role to another one."));
+}
+
+
+wxWindow *reassignOwnedFactory::StartDialog(frmMain *form, pgObject *obj)
+{
+    ((pgRole*)obj)->ReassignOwnedTo();
+
+    return 0;
+}
+
+bool reassignOwnedFactory::CheckEnable(pgObject *obj)
+{
+    return obj && obj->IsCreatedBy(loginRoleFactory) && ((pgRole*)obj)->GetConnection()->BackendMinimumVersion(8, 2);
+}
+
+
+dropOwnedFactory::dropOwnedFactory(menuFactoryList *list, wxMenu *mnu, wxToolBar *toolbar) :
contextActionFactory(list)
+{
+    mnu->Append(id, _("Drop Owned"), _("Drop objects owned by the selected role."));
+}
+
+wxWindow *dropOwnedFactory::StartDialog(frmMain *form, pgObject *obj)
+{
+    if (wxMessageBox(_("Are you sure you wish to drop all objets owned by the selected role?"), _("Drop objects"),
wxYES_NO)== wxNO) 
+        return 0;
+
+    ((pgRole*)obj)->DropOwned();
+
+    return 0;
+}
+
+bool dropOwnedFactory::CheckEnable(pgObject *obj)
+{
+    return obj && obj->IsCreatedBy(loginRoleFactory) && ((pgRole*)obj)->GetConnection()->BackendMinimumVersion(8, 2);
+}

Re: A new feature patch and a bug fix

From
Dave Page
Date:
Guillaume Lelarge wrote:
> Hi,
>
> Let's begin with the bug fix. I've found that I can set the owner of an
> object only from login role. pgAdmin doesn't allow me to set ownership
> to a group. psql allows it, so I think this is a bug. The patch named
> "dlgProperty.patch" fixes this issue.

OK... but can you really assign ownership to a group as well as a group
role? For example, from:
http://www.postgresql.org/docs/8.0/interactive/sql-altertable.html

----
This form changes the owner of the table, index, sequence, or view to
the specified user.
----

That implies just users to me.

> I found this when I tried to add "reassign owned by" and "drop owned by"
> functionalities to pgAdmin. I first thought I would add this with the
> drop-user code but I prefer to make it available alone. So I used my
> well known way : a new contextual menu (in fact two : "Reassign Owned
> To..." and "Drop Owned"). The first one opens a wxSingleChoiceDialog
> dialog for the user to choose a role from. The second one waits for a
> confirmation and then fires the SQL statement. My problem is here : on a
> user contextual menu, the only connection I can get is the maintenance
> connection. So I will only be able to reassign or drop objects within
> the maintenance database. I was wondering if there was a way to get a
> handle to the last open connection ? or if there was another way ? for
> example asking the user to choose the database to connect to and fire
> the SQL statement ? or asking the user to select a database where he's
> already connected to ?

Yeah, I think that's going to be the only way - present a list of
databases on the server. Or do it the other way round and add the
functionality to the database object and present a list of roles to
choose from.

/D

Re: A new feature patch and a bug fix

From
Guillaume Lelarge
Date:
Dave Page wrote:
> Guillaume Lelarge wrote:
>> Let's begin with the bug fix. I've found that I can set the owner of an
>> object only from login role. pgAdmin doesn't allow me to set ownership
>> to a group. psql allows it, so I think this is a bug. The patch named
>> "dlgProperty.patch" fixes this issue.
>
> OK... but can you really assign ownership to a group as well as a group
> role? For example, from:
> http://www.postgresql.org/docs/8.0/interactive/sql-altertable.html
>
> ----
> This form changes the owner of the table, index, sequence, or view to
> the specified user.
> ----
>
> That implies just users to me.
>

I did it for a group, works great (8.1 and 8.2). Now, I don't really
know if this is really a feature or something overlooked. Either pgAdmin
is wrong either psql is.

>> I found this when I tried to add "reassign owned by" and "drop owned by"
>> functionalities to pgAdmin. I first thought I would add this with the
>> drop-user code but I prefer to make it available alone. So I used my
>> well known way : a new contextual menu (in fact two : "Reassign Owned
>> To..." and "Drop Owned"). The first one opens a wxSingleChoiceDialog
>> dialog for the user to choose a role from. The second one waits for a
>> confirmation and then fires the SQL statement. My problem is here : on a
>> user contextual menu, the only connection I can get is the maintenance
>> connection. So I will only be able to reassign or drop objects within
>> the maintenance database. I was wondering if there was a way to get a
>> handle to the last open connection ? or if there was another way ? for
>> example asking the user to choose the database to connect to and fire
>> the SQL statement ? or asking the user to select a database where he's
>> already connected to ?
>
> Yeah, I think that's going to be the only way - present a list of
> databases on the server. Or do it the other way round and add the
> functionality to the database object and present a list of roles to
> choose from.
>

I'll take a look at the query tool to see how to do this ("present a
list of databases on the server"). Another call to wxSingleChoiceDialod
seems a bad way to me... I'll need to add a new dialog, don't you think ?


--
Guillaume.
 http://www.postgresqlfr.org
 http://dalibo.com

Re: A new feature patch and a bug fix

From
Dave Page
Date:
Guillaume Lelarge wrote:
> I did it for a group, works great (8.1 and 8.2). Now, I don't really
> know if this is really a feature or something overlooked. Either pgAdmin
> is wrong either psql is.

No, in 8.1+ it works for roles whether they are what we would call login
roles or group roles. In 8.0 and below we had separate users and groups,
but I'm not sure you could assign ownership to a group back then.

> I'll take a look at the query tool to see how to do this ("present a
> list of databases on the server"). Another call to wxSingleChoiceDialod
> seems a bad way to me... I'll need to add a new dialog, don't you think ?

Yes, I don't think it should be two dialogues.

/D


Re: A new feature patch and a bug fix

From
Guillaume Lelarge
Date:
Dave Page wrote:
> Guillaume Lelarge wrote:
>> I did it for a group, works great (8.1 and 8.2). Now, I don't really
>> know if this is really a feature or something overlooked. Either pgAdmin
>> is wrong either psql is.
>
> No, in 8.1+ it works for roles whether they are what we would call login
> roles or group roles. In 8.0 and below we had separate users and groups,
> but I'm not sure you could assign ownership to a group back then.
>

You're right. I checked this on a 7.4 (I don't have a 8.0 release
available) and, with this release, a group can't be the owner of a table.

Do you think I should raise the issue (group owner on 8.1+) on
pgsql-hackers ?

>> I'll take a look at the query tool to see how to do this ("present a
>> list of databases on the server"). Another call to wxSingleChoiceDialod
>> seems a bad way to me... I'll need to add a new dialog, don't you think ?
>
> Yes, I don't think it should be two dialogues.
>

I'm working on it now.


--
Guillaume.
 http://www.postgresqlfr.org
 http://dalibo.com

Re: A new feature patch and a bug fix

From
Dave Page
Date:
Guillaume Lelarge wrote:
> Dave Page wrote:
>> Guillaume Lelarge wrote:
>>> I did it for a group, works great (8.1 and 8.2). Now, I don't really
>>> know if this is really a feature or something overlooked. Either pgAdmin
>>> is wrong either psql is.
>> No, in 8.1+ it works for roles whether they are what we would call login
>> roles or group roles. In 8.0 and below we had separate users and groups,
>> but I'm not sure you could assign ownership to a group back then.
>>
>
> You're right. I checked this on a 7.4 (I don't have a 8.0 release
> available) and, with this release, a group can't be the owner of a table.
>
> Do you think I should raise the issue (group owner on 8.1+) on
> pgsql-hackers ?

No - I think it just works because pg_group is a view over pg_role (or
whatever it's called ) on 8.1. I would try something like:

Index: pgadmin/dlg/dlgProperty.cpp
===================================================================
--- pgadmin/dlg/dlgProperty.cpp    (révision 6910)
+++ pgadmin/dlg/dlgProperty.cpp    (copie de travail)
@@ -432,7 +432,14 @@

 void dlgProperty::AddUsers(ctlComboBoxFix *cb1, ctlComboBoxFix *cb2)
 {
-    FillCombobox(wxT("SELECT usename FROM pg_user ORDER BY usename"),
cb1, cb2);
+    if (connection->BackendMinimumVersion(8, 1))
+    {
+        FillCombobox(wxT("SELECT rolname FROM pg_roles ORDER BY 1"),
cb1, cb2);
+    }
+    else
+    {
+        FillCombobox(wxT("SELECT usename FROM pg_user ORDER BY 1"),
cb1, cb2);
+    }
 }


>>> I'll take a look at the query tool to see how to do this ("present a
>>> list of databases on the server"). Another call to wxSingleChoiceDialod
>>> seems a bad way to me... I'll need to add a new dialog, don't you think ?
>> Yes, I don't think it should be two dialogues.
>>
>
> I'm working on it now.

'K.

/D


Re: A new feature patch and a bug fix

From
Guillaume Lelarge
Date:
Dave Page wrote:
> Guillaume Lelarge wrote:
>> Dave Page wrote:
>>> Guillaume Lelarge wrote:
>>>> I did it for a group, works great (8.1 and 8.2). Now, I don't really
>>>> know if this is really a feature or something overlooked. Either pgAdmin
>>>> is wrong either psql is.
>>> No, in 8.1+ it works for roles whether they are what we would call login
>>> roles or group roles. In 8.0 and below we had separate users and groups,
>>> but I'm not sure you could assign ownership to a group back then.
>>>
>> You're right. I checked this on a 7.4 (I don't have a 8.0 release
>> available) and, with this release, a group can't be the owner of a table.
>>
>> Do you think I should raise the issue (group owner on 8.1+) on
>> pgsql-hackers ?
>
> No - I think it just works because pg_group is a view over pg_role (or
> whatever it's called ) on 8.1. I would try something like:
>
> Index: pgadmin/dlg/dlgProperty.cpp
> ===================================================================
> --- pgadmin/dlg/dlgProperty.cpp    (révision 6910)
> +++ pgadmin/dlg/dlgProperty.cpp    (copie de travail)
> @@ -432,7 +432,14 @@
>
>  void dlgProperty::AddUsers(ctlComboBoxFix *cb1, ctlComboBoxFix *cb2)
>  {
> -    FillCombobox(wxT("SELECT usename FROM pg_user ORDER BY usename"),
> cb1, cb2);
> +    if (connection->BackendMinimumVersion(8, 1))
> +    {
> +        FillCombobox(wxT("SELECT rolname FROM pg_roles ORDER BY 1"),
> cb1, cb2);
> +    }
> +    else
> +    {
> +        FillCombobox(wxT("SELECT usename FROM pg_user ORDER BY 1"),
> cb1, cb2);
> +    }
>  }
>

I'm OK with this.

Thanks.


--
Guillaume.
 http://www.postgresqlfr.org
 http://dalibo.com

Re: A new feature patch and a bug fix

From
Dave Page
Date:
Guillaume Lelarge wrote:
> Dave Page wrote:
>> Index: pgadmin/dlg/dlgProperty.cpp
>> ===================================================================
>> --- pgadmin/dlg/dlgProperty.cpp    (révision 6910)
>> +++ pgadmin/dlg/dlgProperty.cpp    (copie de travail)
>> @@ -432,7 +432,14 @@
>>
>>  void dlgProperty::AddUsers(ctlComboBoxFix *cb1, ctlComboBoxFix *cb2)
>>  {
>> -    FillCombobox(wxT("SELECT usename FROM pg_user ORDER BY usename"),
>> cb1, cb2);
>> +    if (connection->BackendMinimumVersion(8, 1))
>> +    {
>> +        FillCombobox(wxT("SELECT rolname FROM pg_roles ORDER BY 1"),
>> cb1, cb2);
>> +    }
>> +    else
>> +    {
>> +        FillCombobox(wxT("SELECT usename FROM pg_user ORDER BY 1"),
>> cb1, cb2);
>> +    }
>>  }
>>
>
> I'm OK with this.

Please go ahead and commit at your leisure :-)

/D

Re: A new feature patch and a bug fix

From
Guillaume Lelarge
Date:
Dave Page wrote:
> Guillaume Lelarge wrote:
> [...]
>>>> I'll take a look at the query tool to see how to do this ("present a
>>>> list of databases on the server"). Another call to wxSingleChoiceDialod
>>>> seems a bad way to me... I'll need to add a new dialog, don't you think ?
>>> Yes, I don't think it should be two dialogues.
>>>
>> I'm working on it now.
>
> 'K.
>

I've finally done it. It's the first time I create a new dialog, so it
probably need some tweaks. I attached the patch and a tar.gz file for
the new files.

Regards.


--
Guillaume.
 http://www.postgresqlfr.org
 http://dalibo.com
Index: pgadmin/include/schema/pgRole.h
===================================================================
--- pgadmin/include/schema/pgRole.h    (révision 6919)
+++ pgadmin/include/schema/pgRole.h    (copie de travail)
@@ -75,6 +75,8 @@
     void iSetUpdateCatalog(const bool b) { updateCatalog=b; }
     wxArrayString& GetRolesIn() { return rolesIn; }
     wxArrayString& GetConfigList() { return configList; }
+
+    void ReassignDropOwnedTo(frmMain *form);


     // Tree object creation
@@ -112,6 +114,13 @@
     pgGroupRole(const wxString& newName = wxT(""));
 };

+class reassignDropOwnedFactory : public contextActionFactory
+{
+public:
+    reassignDropOwnedFactory(menuFactoryList *list, wxMenu *mnu, wxToolBar *toolbar);
+    wxWindow *StartDialog(frmMain *form, pgObject *obj);
+    bool CheckEnable(pgObject *obj);
+};


 #endif
Index: pgadmin/frm/frmMain.cpp
===================================================================
--- pgadmin/frm/frmMain.cpp    (révision 6919)
+++ pgadmin/frm/frmMain.cpp    (copie de travail)
@@ -67,6 +67,7 @@
 #include "schema/pgTable.h"
 #include "schema/pgIndex.h"
 #include "schema/pgTrigger.h"
+#include "schema/pgRole.h"
 #include "schema/pgRule.h"
 #include "schema/pgServer.h"
 #include "slony/slCluster.h"
@@ -326,6 +327,7 @@
     new dropCascadedFactory(menuFactories, editMenu, 0);
     new truncateFactory(menuFactories, editMenu, 0);
     new truncateCascadedFactory(menuFactories, editMenu, 0);
+    new reassignDropOwnedFactory(menuFactories, editMenu, 0);
     editMenu->AppendSeparator();

     new separatorFactory(menuFactories);
Index: pgadmin/schema/pgRole.cpp
===================================================================
--- pgadmin/schema/pgRole.cpp    (révision 6919)
+++ pgadmin/schema/pgRole.cpp    (copie de travail)
@@ -11,12 +11,15 @@

 // wxWindows headers
 #include <wx/wx.h>
+#include <wx/choicdlg.h>

 // App headers
 #include "pgAdmin3.h"
 #include "utils/misc.h"
 #include "schema/pgRole.h"
 #include "frm/frmMain.h"
+#include "dlg/dlgReassignDropOwned.h"
+#include "dlg/dlgSelectConnection.h"
 #include "utils/pgDefs.h"
 #include "schema/pgDatabase.h"
 #include "schema/pgTablespace.h"
@@ -51,7 +54,7 @@

 bool pgRole::DropObject(wxFrame *frame, ctlTree *browser, bool cascaded)
 {
-    if (GetUpdateCatalog())
+    if (GetUpdateCatalog())
     {
         wxMessageDialog dlg(frame,
             _("Deleting a superuser might result in unwanted behaviour (e.g. when restoring the database).\nAre you
sure?"),
@@ -276,8 +279,43 @@
     }
 }

+void pgRole::ReassignDropOwnedTo(frmMain *form)
+{
+    wxString query;
+
+    dlgReassignDropOwned rdo(form, GetConnection(), this);
+    if (rdo.ShowModal() != wxID_CANCEL)
+    {
+        pgConn *conn;
+        conn = new pgConn(GetConnection()->GetHost(),
+                     rdo.GetDatabase(),
+                     GetConnection()->GetUser(),
+                     GetConnection()->GetPassword(),
+                     GetConnection()->GetPort(),
+                     GetConnection()->GetSslMode());
+
+        if (conn->GetStatus() == PGCONN_OK)
+        {
+            if (rdo.IsReassign())
+            {
+                if (wxMessageBox(_("Are you sure you wish to reassign all objets owned by the selected role?"),
_("Reassignobjects"), wxYES_NO) == wxNO) 
+                    return;

+                query = wxT("REASSIGN OWNED BY ") + GetQuotedFullIdentifier() + wxT(" TO ") + rdo.GetRole();
+            }
+            else
+            {
+                if (wxMessageBox(_("Are you sure you wish to drop all objets owned by the selected role?"), _("Drop
objects"),wxYES_NO) == wxNO) 
+                    return;

+                query = wxT("DROP OWNED BY ") + GetQuotedFullIdentifier();
+            }
+            conn->ExecuteVoid(query);
+        }
+    }
+}
+
+
 pgObject *pgRole::Refresh(ctlTree *browser, const wxTreeItemId item)
 {
     pgObject *role=0;
@@ -394,3 +432,22 @@

 pgGroupRoleFactory groupRoleFactory;
 static pgaCollectionFactory gcf(&groupRoleFactory, __("Group Roles"), roles_xpm);
+
+
+reassignDropOwnedFactory::reassignDropOwnedFactory(menuFactoryList *list, wxMenu *mnu, wxToolBar *toolbar) :
contextActionFactory(list)
+{
+    mnu->Append(id, _("Reassign/Drop Owned..."), _("Reassigned or drop objects owned by the selected role."));
+}
+
+
+wxWindow *reassignDropOwnedFactory::StartDialog(frmMain *form, pgObject *obj)
+{
+    ((pgRole*)obj)->ReassignDropOwnedTo(form);
+
+    return 0;
+}
+
+bool reassignDropOwnedFactory::CheckEnable(pgObject *obj)
+{
+    return obj && obj->IsCreatedBy(loginRoleFactory) && ((pgRole*)obj)->GetConnection()->BackendMinimumVersion(8, 2);
+}
Index: pgadmin/dlg/module.mk
===================================================================
--- pgadmin/dlg/module.mk    (révision 6919)
+++ pgadmin/dlg/module.mk    (copie de travail)
@@ -35,6 +35,7 @@
     $(srcdir)/dlg/dlgPackage.cpp \
     $(srcdir)/dlg/dlgPgpassConfig.cpp \
     $(srcdir)/dlg/dlgProperty.cpp \
+    $(srcdir)/dlg/dlgReassignDropOwned.cpp \
     $(srcdir)/dlg/dlgRole.cpp \
     $(srcdir)/dlg/dlgRule.cpp \
     $(srcdir)/dlg/dlgSchema.cpp \
Index: pgadmin/ui/module.mk
===================================================================
--- pgadmin/ui/module.mk    (révision 6919)
+++ pgadmin/ui/module.mk    (copie de travail)
@@ -39,6 +39,7 @@
     $(srcdir)/ui/dlgOperator.xrc \
     $(srcdir)/ui/dlgPackage.xrc \
     $(srcdir)/ui/dlgPgpassConfig.xrc \
+    $(srcdir)/ui/dlgReassignDropOwned.xrc \
     $(srcdir)/ui/dlgRepCluster.xrc \
     $(srcdir)/ui/dlgRepClusterUpgrade.xrc \
     $(srcdir)/ui/dlgRepListen.xrc \

Attachment

Re: A new feature patch and a bug fix

From
"Dave Page"
Date:
Hi Guillaume,

On 22/12/2007, Guillaume Lelarge <guillaume@lelarge.info> wrote:
> I've finally done it. It's the first time I create a new dialog, so it
> probably need some tweaks. I attached the patch and a tar.gz file for
> the new files.

Finally, some feedback for you!!

- In pgRole::ReassignDropOwnedTo, objets should be objects.

- In pgRole::ReassignDropOwnedTo an error should be raised if the
connection cannot be opened.

- The database selection in dlgReassignDropOwned should respect the DB
restriction setting for the server.

- Remember to append a 'd' to all size/position values in XRC files to
denote cross-platform friendly dialog units.

- The dialog needs some work. Get yourself a copy of XRCed - it will
help enormously. Try to keep the layout and sizing in line with other
dialogues. Use sizers to keep everything in line rather than absolute
positioning (new dialogues do this, older ones might not). It's a bit
fiddly until you get the hang of them, but it does make things much
easier to get right across platforms.

Thanks, Dave

Re: A new feature patch and a bug fix

From
Guillaume Lelarge
Date:
Hi Dave,

Finally, I found some time to work on my patches :)

Dave Page wrote:
> On 22/12/2007, Guillaume Lelarge <guillaume@lelarge.info> wrote:
>> I've finally done it. It's the first time I create a new dialog, so it
>> probably need some tweaks. I attached the patch and a tar.gz file for
>> the new files.
>
> Finally, some feedback for you!!
>
> - In pgRole::ReassignDropOwnedTo, objets should be objects.
>

Oops, I used the french word.

> - In pgRole::ReassignDropOwnedTo an error should be raised if the
> connection cannot be opened.
>
> - The database selection in dlgReassignDropOwned should respect the DB
> restriction setting for the server.
>
> - Remember to append a 'd' to all size/position values in XRC files to
> denote cross-platform friendly dialog units.
>

All are done.

> - The dialog needs some work. Get yourself a copy of XRCed - it will
> help enormously. Try to keep the layout and sizing in line with other
> dialogues. Use sizers to keep everything in line rather than absolute
> positioning (new dialogues do this, older ones might not). It's a bit
> fiddly until you get the hang of them, but it does make things much
> easier to get right across platforms.
>

I'm not sure I get this right. It took me much more time than the four
previous stuff. XRCed is not really easy getting used to. So bad there's
no better (free) XRC editor out there. Anyways, I've done something I'm
quite happy with. But perhaps I need to add more sizers ?

Cheers.


--
Guillaume.
  http://www.postgresqlfr.org
  http://dalibo.com
Index: pgadmin/include/schema/pgRole.h
===================================================================
--- pgadmin/include/schema/pgRole.h    (révision 7050)
+++ pgadmin/include/schema/pgRole.h    (copie de travail)
@@ -75,8 +75,9 @@
     void iSetUpdateCatalog(const bool b) { updateCatalog=b; }
     wxArrayString& GetRolesIn() { return rolesIn; }
     wxArrayString& GetConfigList() { return configList; }
+
+    void ReassignDropOwnedTo(frmMain *form);

-
     // Tree object creation
     void ShowTreeDetail(ctlTree *browser, frmMain *form=0, ctlListView *properties=0, ctlSQLBox *sqlPane=0);
     void ShowDependents(frmMain *form, ctlListView *referencedBy, const wxString &where);
@@ -112,6 +113,12 @@
     pgGroupRole(const wxString& newName = wxT(""));
 };

+class reassignDropOwnedFactory : public contextActionFactory
+{
+public:
+    reassignDropOwnedFactory(menuFactoryList *list, wxMenu *mnu, wxToolBar *toolbar);
+    wxWindow *StartDialog(frmMain *form, pgObject *obj);
+    bool CheckEnable(pgObject *obj);
+};

-
 #endif
Index: pgadmin/frm/frmMain.cpp
===================================================================
--- pgadmin/frm/frmMain.cpp    (révision 7050)
+++ pgadmin/frm/frmMain.cpp    (copie de travail)
@@ -67,6 +67,7 @@
 #include "schema/pgTable.h"
 #include "schema/pgIndex.h"
 #include "schema/pgTrigger.h"
+#include "schema/pgRole.h"
 #include "schema/pgRule.h"
 #include "schema/pgServer.h"
 #include "slony/slCluster.h"
@@ -326,6 +327,7 @@
     new dropCascadedFactory(menuFactories, editMenu, 0);
     new truncateFactory(menuFactories, editMenu, 0);
     new truncateCascadedFactory(menuFactories, editMenu, 0);
+    new reassignDropOwnedFactory(menuFactories, editMenu, 0);
     editMenu->AppendSeparator();

     new separatorFactory(menuFactories);
Index: pgadmin/schema/pgRole.cpp
===================================================================
--- pgadmin/schema/pgRole.cpp    (révision 7050)
+++ pgadmin/schema/pgRole.cpp    (copie de travail)
@@ -11,12 +11,15 @@

 // wxWindows headers
 #include <wx/wx.h>
+#include <wx/choicdlg.h>

 // App headers
 #include "pgAdmin3.h"
 #include "utils/misc.h"
 #include "schema/pgRole.h"
 #include "frm/frmMain.h"
+#include "dlg/dlgReassignDropOwned.h"
+#include "dlg/dlgSelectConnection.h"
 #include "utils/pgDefs.h"
 #include "schema/pgDatabase.h"
 #include "schema/pgTablespace.h"
@@ -51,7 +54,7 @@

 bool pgRole::DropObject(wxFrame *frame, ctlTree *browser, bool cascaded)
 {
-    if (GetUpdateCatalog())
+    if (GetUpdateCatalog())
     {
         wxMessageDialog dlg(frame,
             _("Deleting a superuser might result in unwanted behaviour (e.g. when restoring the database).\nAre you
sure?"),
@@ -276,8 +279,47 @@
     }
 }

+void pgRole::ReassignDropOwnedTo(frmMain *form)
+{
+    wxString query;
+
+    dlgReassignDropOwned rdo(form, GetConnection(), this, GetServer()->GetDbRestriction());
+    if (rdo.ShowModal() != wxID_CANCEL)
+    {
+        pgConn *conn;
+        conn = new pgConn(GetConnection()->GetHost(),
+                     rdo.GetDatabase(),
+                     GetConnection()->GetUser(),
+                     GetConnection()->GetPassword(),
+                     GetConnection()->GetPort(),
+                     GetConnection()->GetSslMode());
+
+        if (conn->GetStatus() == PGCONN_OK)
+        {
+            if (rdo.IsReassign())
+            {
+                if (wxMessageBox(_("Are you sure you wish to reassign all objects owned by the selected role?"),
_("Reassignobjects"), wxYES_NO) == wxNO) 
+                    return;

+                query = wxT("REASSIGN OWNED BY ") + GetQuotedFullIdentifier() + wxT(" TO ") + rdo.GetRole();
+            }
+            else
+            {
+                if (wxMessageBox(_("Are you sure you wish to drop all objects owned by the selected role?"), _("Drop
objects"),wxYES_NO) == wxNO) 
+                    return;

+                query = wxT("DROP OWNED BY ") + GetQuotedFullIdentifier();
+            }
+            conn->ExecuteVoid(query);
+        }
+        else
+        {
+            wxMessageBox(wxT("Connection failed: ") + conn->GetLastError());
+        }
+    }
+}
+
+
 pgObject *pgRole::Refresh(ctlTree *browser, const wxTreeItemId item)
 {
     pgObject *role=0;
@@ -394,3 +436,22 @@

 pgGroupRoleFactory groupRoleFactory;
 static pgaCollectionFactory gcf(&groupRoleFactory, __("Group Roles"), roles_xpm);
+
+
+reassignDropOwnedFactory::reassignDropOwnedFactory(menuFactoryList *list, wxMenu *mnu, wxToolBar *toolbar) :
contextActionFactory(list)
+{
+    mnu->Append(id, _("Reassign/Drop Owned..."), _("Reassigned or drop objects owned by the selected role."));
+}
+
+
+wxWindow *reassignDropOwnedFactory::StartDialog(frmMain *form, pgObject *obj)
+{
+    ((pgRole*)obj)->ReassignDropOwnedTo(form);
+
+    return 0;
+}
+
+bool reassignDropOwnedFactory::CheckEnable(pgObject *obj)
+{
+    return obj && obj->IsCreatedBy(loginRoleFactory) && ((pgRole*)obj)->GetConnection()->BackendMinimumVersion(8, 2);
+}
Index: pgadmin/dlg/module.mk
===================================================================
--- pgadmin/dlg/module.mk    (révision 7050)
+++ pgadmin/dlg/module.mk    (copie de travail)
@@ -35,6 +35,7 @@
     $(srcdir)/dlg/dlgPackage.cpp \
     $(srcdir)/dlg/dlgPgpassConfig.cpp \
     $(srcdir)/dlg/dlgProperty.cpp \
+    $(srcdir)/dlg/dlgReassignDropOwned.cpp \
     $(srcdir)/dlg/dlgRole.cpp \
     $(srcdir)/dlg/dlgRule.cpp \
     $(srcdir)/dlg/dlgSchema.cpp \
Index: pgadmin/ui/module.mk
===================================================================
--- pgadmin/ui/module.mk    (révision 7050)
+++ pgadmin/ui/module.mk    (copie de travail)
@@ -39,6 +39,7 @@
     $(srcdir)/ui/dlgOperator.xrc \
     $(srcdir)/ui/dlgPackage.xrc \
     $(srcdir)/ui/dlgPgpassConfig.xrc \
+    $(srcdir)/ui/dlgReassignDropOwned.xrc \
     $(srcdir)/ui/dlgRepCluster.xrc \
     $(srcdir)/ui/dlgRepClusterUpgrade.xrc \
     $(srcdir)/ui/dlgRepListen.xrc \

Attachment

Re: A new feature patch and a bug fix

From
"Dave Page"
Date:
Hi Guillaume

On Feb 5, 2008 9:46 AM, Guillaume Lelarge <guillaume@lelarge.info> wrote:
> Hi Dave,
>
> Finally, I found some time to work on my patches :)

:-)

> I'm not sure I get this right. It took me much more time than the four
> previous stuff. XRCed is not really easy getting used to. So bad there's
> no better (free) XRC editor out there. Anyways, I've done something I'm
> quite happy with. But perhaps I need to add more sizers ?

Yeah, there's still some problems.

- On Windows, the dialogue is too small. Removing the size form the
dialogue iutself seems to cure that in my limited testing.

- There should be a border around the tab control so it's not tight to
the edges of the dialogue. I think we use 5d elsewhere.

- I'm not actually sure we need the tab control there anyway - maybe
the change password dialogue would be a better model?

- It should probably be a fixed size dialogue.

I heard a rumour that DialogBlocks now supports XRC format. Not sure
it if can do a better job.

Unfortunately I don't have time at the moment to hack it about myself,
otherwise I'd see what I could do.

/D

Re: A new feature patch and a bug fix

From
Guillaume Lelarge
Date:
Dave Page wrote:
> On Feb 5, 2008 9:46 AM, Guillaume Lelarge <guillaume@lelarge.info> wrote:
> [...]
>> I'm not sure I get this right. It took me much more time than the four
>> previous stuff. XRCed is not really easy getting used to. So bad there's
>> no better (free) XRC editor out there. Anyways, I've done something I'm
>> quite happy with. But perhaps I need to add more sizers ?
>
> Yeah, there's still some problems.
>
> - On Windows, the dialogue is too small. Removing the size form the
> dialogue iutself seems to cure that in my limited testing.
>

Because of the fixed size dialog, I think I have to specify the dialog's
size, don't I ?

> - There should be a border around the tab control so it's not tight to
> the edges of the dialogue. I think we use 5d elsewhere.
>
> - I'm not actually sure we need the tab control there anyway - maybe
> the change password dialogue would be a better model?
>

I wasn't sure either. I used the frmBackup.xrc as a model to build
dlgReassignDropOwned.xrc. But the tab seems too much. I removed it...
but now it really looks like my previous dlgReassignDropOwned.xrc.

> - It should probably be a fixed size dialogue.
>

+1

The XRC file attached is one with a dialog size specified, a modal
dialog, and no notebook/panel/tab widgets. But I'm not sure about the
correct sizing. XRCed shows me the dialog in a way and pgAdmin in
another one. I don't quite understand this.

> I heard a rumour that DialogBlocks now supports XRC format. Not sure
> it if can do a better job.
>

I tried DialogBlocks a few times but I never was able to use it on my
Kubuntu.


--
Guillaume.
  http://www.postgresqlfr.org
  http://dalibo.com
<?xml version="1.0" encoding="UTF-8"?>
<resource>
  <object class="wxDialog" name="dlgReassignDropOwned">
    <title>Reassign/Drop Owned</title>
    <size>170,80d</size>
    <style>wxDEFAULT_DIALOG_STYLE|wxCAPTION|wxSYSTEM_MENU|wxDIALOG_MODAL</style>
    <object class="wxRadioButton" name="rbReassignTo">
      <label>&Reassign objects to</label>
      <pos>5,7</pos>
    </object>
    <object class="wxComboBox" name="cbRoles">
      <content/>
      <pos>180,5</pos>
      <style>wxCB_READONLY|wxCB_DROPDOWN</style>
    </object>
    <object class="wxRadioButton" name="rbDrop">
      <label>&Drop</label>
      <pos>5,37</pos>
    </object>
    <object class="wxStaticText" name="stDatabases">
      <label>&From Database</label>
      <pos>5,82</pos>
    </object>
    <object class="wxComboBox" name="cbDatabases">
      <content/>
      <pos>180,82</pos>
      <style>wxCB_READONLY|wxCB_DROPDOWN</style>
    </object>
    <object class="wxButton" name="wxID_OK">
      <label>&OK</label>
      <default>1</default>
      <pos>70,60d</pos>
    </object>
    <object class="wxButton" name="wxID_CANCEL">
      <label>&Cancel</label>
      <pos>115,60d</pos>
    </object>
  </object>
</resource>

Re: A new feature patch and a bug fix

From
"Dave Page"
Date:
On Feb 5, 2008 4:43 PM, Guillaume Lelarge <guillaume@lelarge.info> wrote:
> Dave Page wrote:
> > On Feb 5, 2008 9:46 AM, Guillaume Lelarge <guillaume@lelarge.info> wrote:
> > [...]
> >> I'm not sure I get this right. It took me much more time than the four
> >> previous stuff. XRCed is not really easy getting used to. So bad there's
> >> no better (free) XRC editor out there. Anyways, I've done something I'm
> >> quite happy with. But perhaps I need to add more sizers ?
> >
> > Yeah, there's still some problems.
> >
> > - On Windows, the dialogue is too small. Removing the size form the
> > dialogue iutself seems to cure that in my limited testing.
> >
>
> Because of the fixed size dialog, I think I have to specify the dialog's
> size, don't I ?

Not necessarily - the sizer should be able to handle it. Look at the
passowrd dialogue though... I was kinda thinking sequentially :-)

/D

Re: A new feature patch and a bug fix

From
Guillaume Lelarge
Date:
Dave Page wrote:
> On Feb 5, 2008 4:43 PM, Guillaume Lelarge <guillaume@lelarge.info> wrote:
>> Dave Page wrote:
>>> On Feb 5, 2008 9:46 AM, Guillaume Lelarge <guillaume@lelarge.info> wrote:
>>> [...]
>>>> I'm not sure I get this right. It took me much more time than the four
>>>> previous stuff. XRCed is not really easy getting used to. So bad there's
>>>> no better (free) XRC editor out there. Anyways, I've done something I'm
>>>> quite happy with. But perhaps I need to add more sizers ?
>>> Yeah, there's still some problems.
>>>
>>> - On Windows, the dialogue is too small. Removing the size form the
>>> dialogue iutself seems to cure that in my limited testing.
>>>
>> Because of the fixed size dialog, I think I have to specify the dialog's
>> size, don't I ?
>
> Not necessarily - the sizer should be able to handle it. Look at the
> passowrd dialogue though... I was kinda thinking sequentially :-)
>

The password dialogue is the frmPassword.xrc file, right ? I don't see
the difference between it and my xrc file. It's a fixed size dialog,
style is the same. All widgets have a specific position, only entry one
have a specific size.

Or perhaps you talked about the dlgConnect.xrc file ? It's also a fixed
size dialog but there's a wxFlexGridSizer. Yeah, I think that's the one
you're talking about. I'll use it to build my dialog...


--
Guillaume.
  http://www.postgresqlfr.org
  http://dalibo.com

Re: A new feature patch and a bug fix

From
"Dave Page"
Date:
On Feb 6, 2008 9:55 AM, Guillaume Lelarge <guillaume@lelarge.info> wrote:
>
> The password dialogue is the frmPassword.xrc file, right ? I don't see
> the difference between it and my xrc file. It's a fixed size dialog,
> style is the same. All widgets have a specific position, only entry one
> have a specific size.

Yeah, that one. It's fixed size unlike yours (by which I mean that
it's not sizeable, not that you have specified the size explicitly),
doesn't have the tab set, and have nice spacing between all the
controls within the dialogue boundaries. It's very basic and should be
easy to copy.

Regards, Dave

Re: A new feature patch and a bug fix

From
"Dave Page"
Date:
On Feb 6, 2008 10:49 AM, Guillaume Lelarge <guillaume@lelarge.info> wrote:
>
> OK. Here is one, fixed but not specified size, no tab, nice spacing (at
> least, it seems to me on my linux laptop). Is it getting better ? :)

OK, I've tweaked it on windows. There were 2 things I changed:

- Defined the fixed size for the dialogue as it was mch wider than the
controls on Windows.
- Widened the space for the labels as some languages are more verbose
than English.

Please check it on your linux box and if it looks OK, go ahead and commit :-)

--
Dave Page
EnterpriseDB UK: http://www.enterprisedb.com
The Oracle-compatible database company

Attachment

Re: A new feature patch and a bug fix

From
Guillaume Lelarge
Date:
Dave Page wrote:
> On Feb 6, 2008 10:49 AM, Guillaume Lelarge <guillaume@lelarge.info> wrote:
>> OK. Here is one, fixed but not specified size, no tab, nice spacing (at
>> least, it seems to me on my linux laptop). Is it getting better ? :)
>
> OK, I've tweaked it on windows. There were 2 things I changed:
>
> - Defined the fixed size for the dialogue as it was mch wider than the
> controls on Windows.
> - Widened the space for the labels as some languages are more verbose
> than English.
>
> Please check it on your linux box and if it looks OK, go ahead and commit :-)
>

It works great on my linux box. The dialog takes a bit more place but it
feels better. Thanks a lot :)

Now back to my "set schema" patch.


--
Guillaume.
  http://www.postgresqlfr.org
  http://dalibo.com