>From e1bd9f1f660f8bef10964b6d566547e2db8fbffb Mon Sep 17 00:00:00 2001
From: Guillaume Lelarge <guillaume@lelarge.info>
Date: Fri, 9 May 2014 21:29:44 +0200
Subject: [PATCH] Handle the 9.4 MOVE clause of ALTER TABLESPACE

---
 pgadmin/dlg/dlgMoveTablespace.cpp       | 119 ++++++++++++++++++++++++++++++++
 pgadmin/dlg/module.mk                   |   1 +
 pgadmin/frm/frmMain.cpp                 |   2 +
 pgadmin/include/dlg/dlgMoveTablespace.h |  44 ++++++++++++
 pgadmin/include/dlg/module.mk           |   1 +
 pgadmin/include/schema/pgTablespace.h   |   9 +++
 pgadmin/schema/pgTablespace.cpp         |  40 +++++++++++
 pgadmin/ui/dlgMoveTablespace.xrc        |  95 +++++++++++++++++++++++++
 pgadmin/ui/module.mk                    |   1 +
 9 files changed, 312 insertions(+)
 create mode 100644 pgadmin/dlg/dlgMoveTablespace.cpp
 create mode 100644 pgadmin/include/dlg/dlgMoveTablespace.h
 create mode 100644 pgadmin/ui/dlgMoveTablespace.xrc

diff --git a/pgadmin/dlg/dlgMoveTablespace.cpp b/pgadmin/dlg/dlgMoveTablespace.cpp
new file mode 100644
index 0000000..90a4472
--- /dev/null
+++ b/pgadmin/dlg/dlgMoveTablespace.cpp
@@ -0,0 +1,119 @@
+//////////////////////////////////////////////////////////////////////////
+//
+// pgAdmin III - PostgreSQL Tools
+//
+// Copyright (C) 2002 - 2014, The pgAdmin Development Team
+// This software is released under the PostgreSQL Licence
+//
+// dlgMoveTablespace.cpp - Reassign or drop owned objects
+//
+//////////////////////////////////////////////////////////////////////////
+
+#include "pgAdmin3.h"
+
+// wxWindows headers
+#include <wx/wx.h>
+
+// App headers
+#include "pgAdmin3.h"
+#include "utils/pgDefs.h"
+#include "frm/frmMain.h"
+#include "dlg/dlgMoveTablespace.h"
+#include "utils/misc.h"
+#include "schema/pgTablespace.h"
+
+
+// pointer to controls
+#define cbMoveTo          CTRL_COMBOBOX("cbMoveTo")
+#define cbKind            CTRL_COMBOBOX("cbKind")
+#define cbOwner           CTRL_COMBOBOX("cbOwner")
+#define btnOK             CTRL_BUTTON("wxID_OK")
+
+
+BEGIN_EVENT_TABLE(dlgMoveTablespace, pgDialog)
+	EVT_BUTTON(wxID_OK,                       dlgMoveTablespace::OnOK)
+END_EVENT_TABLE()
+
+
+dlgMoveTablespace::dlgMoveTablespace(frmMain *win, pgConn *conn, pgTablespace *tblspc)
+{
+	wxString query;
+
+	connection = conn;
+	parent = win;
+
+	SetFont(settings->GetSystemFont());
+	LoadResource(win, wxT("dlgMoveTablespace"));
+	RestorePosition();
+
+	cbKind->Clear();
+	cbKind->Append(_("All"));
+	cbKind->Append(_("Tables"));
+	cbKind->Append(_("Indexes"));
+	cbKind->Append(_("Materialized views"));
+	cbKind->SetSelection(0);
+
+	cbMoveTo->Clear();
+	query = wxT("SELECT spcname FROM pg_tablespace WHERE spcname<>") + conn->qtDbString(tblspc->GetName()) + wxT(" ORDER BY spcname");
+	pgSetIterator tblspcs(connection, query);
+	while (tblspcs.RowsLeft())
+	{
+		cbMoveTo->Append(tblspcs.GetVal(wxT("spcname")));
+	}
+	cbMoveTo->SetSelection(0);
+
+	cbOwner->Clear();
+	cbOwner->Append(wxEmptyString);
+	query = wxT("SELECT rolname FROM pg_roles ORDER BY rolname");
+	pgSetIterator roles(connection, query);
+	while (roles.RowsLeft())
+	{
+		cbOwner->Append(roles.GetVal(wxT("rolname")));
+	}
+	cbOwner->SetSelection(0);
+	cbOwner->Enable(cbOwner->GetStrings().Count() > 0);
+
+	SetSize(330, 160);
+}
+
+dlgMoveTablespace::~dlgMoveTablespace()
+{
+	SavePosition();
+}
+
+
+void dlgMoveTablespace::OnOK(wxCommandEvent &ev)
+{
+	EndModal(wxID_OK);
+}
+
+
+void dlgMoveTablespace::OnCancel(wxCommandEvent &ev)
+{
+	EndModal(wxID_CANCEL);
+}
+
+wxString dlgMoveTablespace::GetTablespace()
+{
+	return cbMoveTo->GetValue();
+}
+
+wxString dlgMoveTablespace::GetKind()
+{
+    wxString kind;
+
+	if (cbKind->GetValue().Cmp(_("Tables")) == 0)
+        return wxT("TABLES");
+	if (cbKind->GetValue().Cmp(_("Indexes")) == 0)
+        return wxT("INDEXES");
+	if (cbKind->GetValue().Cmp(_("Materialized views")) == 0)
+        return wxT("MATERIALIZED VIEWS");
+
+    return wxT("ALL");
+}
+
+wxString dlgMoveTablespace::GetOwner()
+{
+	return cbOwner->GetValue();
+}
+
diff --git a/pgadmin/dlg/module.mk b/pgadmin/dlg/module.mk
index 70d83f5..46f4209 100644
--- a/pgadmin/dlg/module.mk
+++ b/pgadmin/dlg/module.mk
@@ -37,6 +37,7 @@ pgadmin3_SOURCES += \
 	dlg/dlgLanguage.cpp \
 	dlg/dlgMainConfig.cpp \
 	dlg/dlgManageFavourites.cpp \
+	dlg/dlgMoveTablespace.cpp \
 	dlg/dlgOperator.cpp \
 	dlg/dlgPackage.cpp \
 	dlg/dlgPgpassConfig.cpp \
diff --git a/pgadmin/frm/frmMain.cpp b/pgadmin/frm/frmMain.cpp
index b9c7c64..c8d65c0 100644
--- a/pgadmin/frm/frmMain.cpp
+++ b/pgadmin/frm/frmMain.cpp
@@ -79,6 +79,7 @@
 #include "schema/pgRole.h"
 #include "schema/pgRule.h"
 #include "schema/pgServer.h"
+#include "schema/pgTablespace.h"
 #include "slony/slCluster.h"
 #include "slony/slSet.h"
 #include "schema/pgForeignKey.h"
@@ -382,6 +383,7 @@ void frmMain::CreateMenus()
 	new resetTableStatsFactory(menuFactories, editMenu, 0);
 	new resetFunctionStatsFactory(menuFactories, editMenu, 0);
 	new reassignDropOwnedFactory(menuFactories, editMenu, 0);
+	new moveTablespaceFactory(menuFactories, editMenu, 0);
 	new searchObjectFactory(menuFactories, editMenu, 0);
 	editMenu->AppendSeparator();
 
diff --git a/pgadmin/include/dlg/dlgMoveTablespace.h b/pgadmin/include/dlg/dlgMoveTablespace.h
new file mode 100644
index 0000000..b2fe199
--- /dev/null
+++ b/pgadmin/include/dlg/dlgMoveTablespace.h
@@ -0,0 +1,44 @@
+//////////////////////////////////////////////////////////////////////////
+//
+// pgAdmin III - PostgreSQL Tools
+//
+// Copyright (C) 2002 - 2014, The pgAdmin Development Team
+// This software is released under the PostgreSQL Licence
+//
+// dlgMoveTablespace.h - Reassign or drop owned objects
+//
+//////////////////////////////////////////////////////////////////////////
+
+#ifndef dlgMoveTablespace_H
+#define dlgMoveTablespace_H
+
+// wxWindows headers
+#include <wx/wx.h>
+#include <wx/settings.h>
+
+
+#include "dlg/dlgClasses.h"
+class pgConn;
+class pgTablespace;
+
+// Class declarations
+class dlgMoveTablespace : public pgDialog
+{
+public:
+	dlgMoveTablespace(frmMain *win, pgConn *conn, pgTablespace *tblspc);
+	~dlgMoveTablespace();
+	wxString GetTablespace();
+	wxString GetKind();
+	wxString GetOwner();
+
+private:
+	pgConn *connection;
+	frmMain *parent;
+
+	void OnOK(wxCommandEvent &ev);
+	void OnCancel(wxCommandEvent &ev);
+	void OnChange(wxCommandEvent &ev);
+	DECLARE_EVENT_TABLE()
+};
+
+#endif
diff --git a/pgadmin/include/dlg/module.mk b/pgadmin/include/dlg/module.mk
index 11d21f4..84e1297 100644
--- a/pgadmin/include/dlg/module.mk
+++ b/pgadmin/include/dlg/module.mk
@@ -37,6 +37,7 @@ pgadmin3_SOURCES += \
 	include/dlg/dlgLanguage.h \
 	include/dlg/dlgMainConfig.h \
 	include/dlg/dlgManageFavourites.h \
+	include/dlg/dlgMoveTablespace.h \
 	include/dlg/dlgOperator.h \
 	include/dlg/dlgPackage.h \
 	include/dlg/dlgPgpassConfig.h \
diff --git a/pgadmin/include/schema/pgTablespace.h b/pgadmin/include/schema/pgTablespace.h
index 389b322..cc3031e 100644
--- a/pgadmin/include/schema/pgTablespace.h
+++ b/pgadmin/include/schema/pgTablespace.h
@@ -57,6 +57,7 @@ public:
 	pgConn *connection();
 
 	wxString GetSql(ctlTree *browser);
+    void MoveTablespace(frmMain *form);
 	pgObject *Refresh(ctlTree *browser, const wxTreeItemId item);
 
 	bool HasStats()
@@ -86,5 +87,13 @@ public:
 	void ShowStatistics(frmMain *form, ctlListView *statistics);
 };
 
+class moveTablespaceFactory : public contextActionFactory
+{
+public:
+	moveTablespaceFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar);
+	wxWindow *StartDialog(frmMain *form, pgObject *obj);
+	bool CheckEnable(pgObject *obj);
+};
+
 
 #endif
diff --git a/pgadmin/schema/pgTablespace.cpp b/pgadmin/schema/pgTablespace.cpp
index 15d4a2b..815e56e 100644
--- a/pgadmin/schema/pgTablespace.cpp
+++ b/pgadmin/schema/pgTablespace.cpp
@@ -20,6 +20,7 @@
 #include "schema/pgTablespace.h"
 #include "schema/pgDatabase.h"
 #include "frm/frmMain.h"
+#include "dlg/dlgMoveTablespace.h"
 
 
 pgTablespace::pgTablespace(const wxString &newName)
@@ -245,6 +246,27 @@ void pgTablespace::ShowStatistics(frmMain *form, ctlListView *statistics)
 }
 
 
+void pgTablespace::MoveTablespace(frmMain *form)
+{
+	wxString query;
+
+	dlgMoveTablespace rdo(form, GetConnection(), this);
+	if (rdo.ShowModal() != wxID_CANCEL)
+	{
+		if (wxMessageBox(_("Are you sure you wish to move objects from ") + GetQuotedFullIdentifier() + _(" to ") + rdo.GetTablespace() + _("?"), _("Move tablespace?"), wxYES_NO) != wxYES)
+			return;
+
+		query = wxT("ALTER TABLESPACE ") + GetQuotedFullIdentifier();
+        query += wxT(" MOVE ") + rdo.GetKind().Upper();
+        if (rdo.GetOwner().Length() > 0)
+            query += wxT(" OWNED BY ") + qtIdent(rdo.GetOwner());
+        query += wxT(" TO ") + qtIdent(rdo.GetTablespace());
+
+		GetConnection()->ExecuteVoid(query);
+	}
+}
+
+
 pgObject *pgTablespace::Refresh(ctlTree *browser, const wxTreeItemId item)
 {
 	pgObject *tablespace = 0;
@@ -408,3 +430,21 @@ pgCollection *pgTablespaceFactory::CreateCollection(pgObject *obj)
 
 pgTablespaceFactory tablespaceFactory;
 static pgaCollectionFactory cf(&tablespaceFactory, __("Tablespaces"), tablespaces_png_img);
+
+moveTablespaceFactory::moveTablespaceFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : contextActionFactory(list)
+{
+	mnu->Append(id, _("Move objects to..."), _("Move objects of the selected tablespace to another one."));
+}
+
+
+wxWindow *moveTablespaceFactory::StartDialog(frmMain *form, pgObject *obj)
+{
+	((pgTablespace *)obj)->MoveTablespace(form);
+
+	return 0;
+}
+
+bool moveTablespaceFactory::CheckEnable(pgObject *obj)
+{
+	return obj && obj->IsCreatedBy(tablespaceFactory) && ((pgTablespace *)obj)->GetConnection()->BackendMinimumVersion(9, 4);
+}
diff --git a/pgadmin/ui/dlgMoveTablespace.xrc b/pgadmin/ui/dlgMoveTablespace.xrc
new file mode 100644
index 0000000..77a6329
--- /dev/null
+++ b/pgadmin/ui/dlgMoveTablespace.xrc
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resource>
+  <object class="wxDialog" name="dlgMoveTablespace">
+    <title>Move objects to another tablespace</title>
+    <size>200,200d</size>
+    <style>wxDEFAULT_DIALOG_STYLE|wxCAPTION|wxSYSTEM_MENU</style>
+    <object class="wxFlexGridSizer">
+      <cols>1</cols>
+      <vgap>5</vgap>
+      <hgap>5</hgap>
+      <growablerows>0</growablerows>
+      <growablecols>0</growablecols>
+      <object class="sizeritem">
+        <object class="wxFlexGridSizer">
+          <cols>2</cols>
+          <vgap>5</vgap>
+          <hgap>5</hgap>
+          <growablecols>1</growablecols>
+          <object class="sizeritem">
+            <object class="wxStaticText" name="stMoveTo">
+              <label>&amp;New tablespace</label>
+            </object>
+            <flag>wxALIGN_CENTRE_VERTICAL|wxTOP|wxLEFT|wxRIGHT</flag>
+            <border>4</border>
+          </object>
+          <object class="sizeritem">
+            <object class="wxComboBox" name="cbMoveTo">
+              <content/>
+              <style>wxCB_READONLY|wxCB_DROPDOWN</style>
+            </object>
+            <flag>wxEXPAND|wxALIGN_CENTRE_VERTICAL|wxTOP|wxLEFT|wxRIGHT</flag>
+            <border>4</border>
+          </object>
+          <object class="sizeritem">
+            <object class="wxStaticText" name="stKind">
+              <label>Objects' kind</label>
+            </object>
+            <flag>wxALIGN_CENTRE_VERTICAL|wxTOP|wxLEFT|wxRIGHT</flag>
+            <border>4</border>
+          </object>
+          <object class="sizeritem">
+            <object class="wxComboBox" name="cbKind">
+              <content/>
+              <style>wxCB_READONLY|wxCB_DROPDOWN</style>
+            </object>
+            <flag>wxEXPAND|wxALIGN_CENTRE_VERTICAL|wxTOP|wxLEFT|wxRIGHT</flag>
+            <border>4</border>
+          </object>
+          <object class="sizeritem">
+            <object class="wxStaticText" name="stOwner">
+              <label>Objects' owner</label>
+            </object>
+            <flag>wxALIGN_CENTRE_VERTICAL|wxTOP|wxLEFT|wxRIGHT</flag>
+            <border>4</border>
+          </object>
+          <object class="sizeritem">
+            <object class="wxComboBox" name="cbOwner">
+              <content/>
+              <style>wxCB_READONLY|wxCB_DROPDOWN</style>
+            </object>
+            <flag>wxEXPAND|wxALIGN_CENTRE_VERTICAL|wxTOP|wxLEFT|wxRIGHT</flag>
+            <border>4</border>
+          </object>
+        </object>
+        <flag>wxEXPAND|wxALIGN_CENTRE|wxALL</flag>
+        <border>3</border>
+      </object>
+      <object class="sizeritem">
+        <object class="wxFlexGridSizer">
+          <cols>3</cols>
+          <growablecols>0</growablecols>
+          <object class="spacer">
+            <size>0,0d</size>
+          </object>
+          <object class="sizeritem">
+            <object class="wxButton" name="wxID_OK">
+              <label>&amp;OK</label>
+              <default>1</default>
+            </object>
+            <flag>wxEXPAND|wxALIGN_CENTER_VERTICAL|wxALL</flag>
+            <border>4</border>
+          </object>
+          <object class="sizeritem">
+            <object class="wxButton" name="wxID_CANCEL">
+              <label>&amp;Cancel</label>
+            </object>
+            <flag>wxEXPAND|wxALIGN_CENTER_VERTICAL|wxALL</flag>
+            <border>4</border>
+          </object>
+        </object>
+        <flag>wxEXPAND</flag>
+      </object>
+    </object>
+  </object>
+</resource>
diff --git a/pgadmin/ui/module.mk b/pgadmin/ui/module.mk
index 19af4ec..ead5b8b 100644
--- a/pgadmin/ui/module.mk
+++ b/pgadmin/ui/module.mk
@@ -45,6 +45,7 @@ TMP_ui += \
 	ui/dlgMainConfig.xrc \
 	ui/dlgManageFavourites.xrc \
 	ui/dlgManageMacros.xrc \
+	ui/dlgMoveTablespace.xrc \
 	ui/dlgOperator.xrc \
 	ui/dlgPackage.xrc \
 	ui/dlgPgpassConfig.xrc \
-- 
1.9.0

