*** a/pgadmin/db/pgConn.cpp
--- b/pgadmin/db/pgConn.cpp
***************
*** 704,709 **** bool pgConn::ExecuteVoid(const wxString &sql, bool reportError)
--- 704,738 ----
  }
  
  
+ //////////////////////////////////////////////////////////////////////////
+ // Execute SQL with optional result set
+ //////////////////////////////////////////////////////////////////////////
+ PGresult * pgConn::ExecuteOptionalResult(const wxString &sql, bool reportError)
+ {
+ 	PGresult *qryRes = 0;
+ 
+ 	if (GetStatus() != PGCONN_OK)
+ 		return qryRes;
+ 
+ 	// Execute the query and get the status.
+ 	
+ 
+ 	wxLogSql(wxT("Void query (%s:%d): %s"), this->GetHost().c_str(), this->GetPort(), sql.c_str());
+ 	qryRes = PQexec(conn, sql.mb_str(*conv));
+ 	lastResultStatus = PQresultStatus(qryRes);
+ 	SetLastResultError(qryRes);
+ 
+ 	// Check for errors
+ 	if (lastResultStatus != PGRES_COMMAND_OK && lastResultStatus != PGRES_COPY_IN && lastResultStatus != PGRES_COPY_OUT)
+ 	{
+ 		LogError(!reportError);
+ 		PQclear(qryRes);
+ 		qryRes = 0;
+ 	}
+ 
+ 	return qryRes;
+ }
+ 
  
  wxString pgConn::ExecuteScalar(const wxString &sql)
  {
*** a/pgadmin/frm/events.cpp
--- b/pgadmin/frm/events.cpp
***************
*** 38,43 ****
--- 38,46 ----
  #include "schema/pgTable.h"
  #include "dlg/dlgProperty.h"
  
+ // custom events
+ DEFINE_EVENT_TYPE(EVT_THREAD_COPYPASTE_UPDATE_GUI)
+ 
  // Event table
  BEGIN_EVENT_TABLE(frmMain, pgFrame)
  	EVT_CHILD_FOCUS(			frmMain::OnChildFocus)
***************
*** 73,78 **** BEGIN_EVENT_TABLE(frmMain, pgFrame)
--- 76,83 ----
  	EVT_AUI_PANE_CLOSE(                     frmMain::OnAuiUpdate)
  	EVT_AUINOTEBOOK_PAGE_CLOSE(wxID_ANY,    frmMain::OnAuiNotebookPageClose)
  
+ 	EVT_COMMAND(wxID_ANY, EVT_THREAD_COPYPASTE_UPDATE_GUI, frmMain::OnThreadCopypasteUpdateGUI)
+ 
  #ifdef __WXGTK__
  	EVT_TREE_KEY_DOWN(CTL_BROWSER,          frmMain::OnTreeKeyDown)
  #endif
***************
*** 147,152 **** void frmMain::OnExit(wxCommandEvent &event)
--- 152,177 ----
  
  void frmMain::OnClose(wxCloseEvent &event)
  {
+ 	if (frmPasteObject::isActive())
+ 	{
+ 		frmPasteObject *copypasteobject = GetCopypasteobject();
+ 		if (copypasteobject)
+ 		{
+ 			if (wxMessageBox(
+ 				_("Paste table(s) is active !\nDo you really want to quit ?\n"),
+ 				_("Paste table(s) is active"), wxYES_NO) == wxNO)
+ 			{
+ 				return;
+ 			}
+ 			if (copypasteobject->thread)
+ 			{
+ 				copypasteobject->thread->Delete();
+ 				delete copypasteobject->thread;
+ 				copypasteobject->thread = NULL;
+ 			}
+ 		}
+ 	}
+ 
  	wxWindow *fr;
  	windowList::Node *node;
  	while ((node = frames.GetFirst()) != NULL)
*** a/pgadmin/frm/frmMain.cpp
--- b/pgadmin/frm/frmMain.cpp
***************
*** 90,95 **** frmMain::frmMain(const wxString &title)
--- 90,96 ----
  	msgLevel = 0;
  	lastPluginUtility = NULL;
  	pluginUtilityCount = 0;
+ 	copytObject = NULL;
  
  	dlgName = wxT("frmMain");
  	SetMinSize(wxSize(600, 450));
***************
*** 356,361 **** void frmMain::CreateMenus()
--- 357,366 ----
  	new reassignDropOwnedFactory(menuFactories, editMenu, 0);
  	editMenu->AppendSeparator();
  
+ 	new copyObjectFactory(menuFactories, editMenu, toolBar);
+ 	new pasteObjectFactory(menuFactories, editMenu, toolBar);
+ 	editMenu->AppendSeparator();
+ 
  	new separatorFactory(menuFactories);
  
  	toolBar->AddSeparator();
***************
*** 1392,1394 **** wxWindow *bugReportFactory::StartDialog(frmMain *form, pgObject *obj)
--- 1397,1570 ----
  	DisplayHelp(wxT("bugreport"), HELP_PGADMIN);
  	return 0;
  }
+ 
+ 
+ copyObjectFactory::copyObjectFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : contextActionFactory(list)
+ {
+ 	mnu->Append(id, _("&Copy table(s)..."), _("Store table(s) reference for later paste"));
+ }
+ 
+ 
+ wxWindow *copyObjectFactory::StartDialog(frmMain *form, pgObject *obj)
+ {
+ 	if (!frmPasteObject::isActive())
+ 	{
+ 		winMain->SetCopytObject(obj);
+ 		form->GetMenuFactories()->CheckMenu(obj, form->GetMenuBar(), (ctlMenuToolbar *)form->GetToolBar());
+ 	}
+ 	return 0;
+ }
+ 
+ 
+ bool copyObjectFactory::CheckEnable(pgObject *obj)
+ {
+ 	if (!obj || frmPasteObject::isActive())
+ 		return false;
+ 
+ 	if (obj->GetConnection())
+ 	{
+ 		//tree item 'Tables' has GetMetaType() == PGM_TABLE !
+ 		pgTable *table = (obj->GetMetaType() == PGM_TABLE) ? dynamic_cast<pgTable *>(obj) : 0;
+ 		if (table)
+ 			return true;
+ 		//tree item 'Schemas' has GetMetaType() == PGM_SCHEMA !
+ 		pgSchema *schema = (obj->GetMetaType() == PGM_SCHEMA) ? dynamic_cast<pgSchema *>(obj) : 0;
+ 		if (schema)
+ 			return true;
+ 	}
+ 	return false;
+ }
+ 
+ 
+ pasteObjectFactory::pasteObjectFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : contextActionFactory(list)
+ {
+ 	mnu->Append(id, _("&Paste table(s)..."), _("Paste table(s)"));
+ 	this->toolbar = toolbar;
+ 	toolbar->AddTool(id, _("Paste table(s)"), *pasteobject_png_bmp, _("Paste table(s) into schema."), wxITEM_NORMAL);
+ }
+ 
+ 
+ wxWindow *pasteObjectFactory::StartDialog(frmMain *form, pgObject *obj)
+ {
+ 	//Until the pgadmin has thread list or task list, copy/paste tables is singleton !
+ 	//That means that only one instance is allowed.
+ 	//Additional requests are simple(silently) ignored !
+ 	pgObject *copyobj = winMain->GetCopytObject();
+ 	pgDatabase *targetdatabase = ((pgSchema *)obj)->GetDatabase();
+ 	if (copyobj)
+ 	{
+ 		pgTable *table = dynamic_cast<pgTable *>(copyobj);
+ 		if (table == 0)
+ 		{
+ 			pgSchema *schema = dynamic_cast<pgSchema *>(copyobj);
+ 			if (schema == 0)
+ 			{
+ 				copyobj = NULL;
+ 				winMain->SetCopytObject(NULL);
+ 			}
+ 		}
+ 	}
+ 	if (copyobj && !frmPasteObject::isActive())
+ 	{
+ 		frmPasteObject::setActive(true);
+ 		wxString targetschemaname = ((pgSchema *)obj)->GetIdentifier();
+ 		frmPasteObject *copypasteobject = new frmPasteObject(winMain, copyobj, obj, this);
+ 		int numtables = copypasteobject->process();
+ 		if (numtables == 0)
+ 		{
+ 			form->SetCopytObject(NULL);
+ 			delete copypasteobject;
+ 			form->SetCopypasteobject(NULL);
+ 			frmPasteObject::setActive(false);
+ 		}
+ 		else
+ 		{
+ 			form->SetCopypasteobject(copypasteobject);
+ 		}
+ 		form->GetMenuFactories()->CheckMenu((pgSchema *)obj, form->GetMenuBar(), (ctlMenuToolbar *)form->GetToolBar());
+ 	}
+ 	return 0;
+ }
+ 
+ 
+ bool pasteObjectFactory::CheckEnable(pgObject *obj)
+ {
+ 	if (!obj)
+ 		return false;
+ 
+ 	if (obj->GetConnection())
+ 	{
+ 		//tree item 'Schemas' has GetMetaType() == PGM_SCHEMA !
+ 		pgSchema *schema = (obj->GetMetaType() == PGM_SCHEMA) ? dynamic_cast<pgSchema *>(obj) : 0;
+ 		if (schema && winMain->GetCopytObject())
+ 			return true;
+ 	}
+ 	return false;
+ }
+ 
+ void frmMain::OnThreadCopypasteUpdateGUI(wxCommandEvent &ev)
+ {
+ 	struct transfer_tag *transfer = (transfer_tag *)ev.GetClientData();
+ 	if (transfer->THIS->thread)
+ 	{
+ 		transfer->THIS->thread->Delete();
+ 		delete transfer->THIS->thread;
+ 		transfer->THIS->thread = NULL;
+ 	}
+ 	transfer->THIS->commitChanges();
+ 	int numfiles = transfer->numberOfCopypasteTables;
+ 	numfiles--;
+ 	if (numfiles < 1)
+ 	{
+ 		SetCopytObject(NULL);
+ 		wxString pastemsg = wxString::Format(_("%d of %d TABLE(s) COPIED FROM %s TO %s"),
+ 			transfer->THIS->copied,
+ 			transfer->THIS->tableCopyPasteArray->Count(),
+ 			(transfer->srcdatabase->GetQuotedIdentifier() + wxT(".") + transfer->srcschemaname).c_str(),
+ 			(transfer->targetdatabase->GetQuotedIdentifier() + wxT(".") + transfer->targetschemaname).c_str());
+ 		if (transfer->THIS->copied && transfer->targetdatabase)
+ 		{
+ 			pgSchema *targetschema = transfer->THIS->findSchema(transfer->targetdatabase, transfer->targetschemaname);
+ 			if (targetschema)
+ 			{
+ 				Refresh(transfer->targetschema);
+ 				targetschema = transfer->THIS->findSchema(transfer->targetdatabase, transfer->targetschemaname);
+ 				if (targetschema)
+ 				{
+ 					targetschema->ShowTreeDetail(GetBrowser());
+ 					GetMenuFactories()->CheckMenu(targetschema, GetMenuBar(), (ctlMenuToolbar *)GetToolBar());
+ 				}
+ 			}
+ 		}
+ 		GetStatusBar()->SetStatusText(pastemsg, 1);
+ 		if (transfer->sourceconn->GetDbname() == transfer->targetconn->GetDbname() &&
+ 			transfer->sourceconn->GetHost() == transfer->targetconn->GetHost() &&
+ 			transfer->sourceconn->GetPort() == transfer->targetconn->GetPort())
+ 		{
+ 			//same DB server
+ 		}
+ 		else
+ 		{
+ 			delete transfer->targetconn;
+ 		}
+ 		delete transfer->sourceconn;
+ 		transfer->THIS->tableCopyPasteArray->Empty();
+ 		delete transfer->THIS->tableCopyPasteArray;
+ 		transfer->THIS->GetFactory()->GetToolbar()->SetToolShortHelp(transfer->THIS->GetFactory()->GetId(), pastemsg);
+ 		delete transfer->THIS;
+ 		delete transfer;
+ 		SetCopypasteobject(NULL);
+ 		frmPasteObject::setActive(false);
+ 		return;
+ 	}
+ 	transfer->numberOfCopypasteTables = numfiles;
+ 	transfer->THIS->pasteNextTable();
+ }
+ 
+ void frmMain::SetCopypasteobject(frmPasteObject* copypasteobject) {
+ 	this->copypasteobject = copypasteobject;
+ }
+ 
+ frmPasteObject* frmMain::GetCopypasteobject() const {
+ 	return copypasteobject;
+ }
*** /dev/null
--- b/pgadmin/frm/frmPasteObject.cpp
***************
*** 0 ****
--- 1,1448 ----
+ //////////////////////////////////////////////////////////////////////////
+ //
+ // pgAdmin III - PostgreSQL Tools
+ //
+ // Copyright (C) 2002 - 2011, The pgAdmin Development Team
+ // This software is released under the PostgreSQL Licence
+ //
+ // frmPasteObject.cpp - Copy/Paste table(s) functions
+ //
+ //////////////////////////////////////////////////////////////////////////
+ 
+ // wxWindows headers
+ #include <wx/wfstream.h>
+ 
+ // PostgreSQL headers
+ #include <libpq-fe.h>
+ 
+ #include "frm/frmPasteObject.h"
+ #include "schema/pgColumn.h"
+ #include "schema/pgSequence.h"
+ #include "schema/pgIndexConstraint.h"
+ #include "schema/pgForeignKey.h"
+ #include "schema/pgCheck.h"
+ #include "ctl/ctlMenuToolbar.h"
+ 
+ #include <errno.h>
+ 
+ #include <wx/arrimpl.cpp>
+ WX_DEFINE_OBJARRAY(pgTableCopyPasteArray);
+ 
+ bool frmPasteObject::active = false;
+ 
+ frmPasteObject::frmPasteObject(frmMain *form, pgObject *sourceobj, pgObject *targetobj, pasteObjectFactory *factory)
+ {
+ 	this->mainform = form;
+ 	this->sourceobj= sourceobj;
+ 	this->targetobj= targetobj;
+ 	this->factory= factory;
+ }
+ 
+ bool frmPasteObject::tableExists(pgSchema *srcschema, pgTable *table1)
+ {
+ 	ctlTree *browser = mainform->GetBrowser();
+ 	pgCollection *tables = browser->FindCollection(tableFactory, srcschema->GetId());
+ 	if (tables)
+ 	{
+ 		pgObject *obj;
+ 		pgTable *srctable;
+ 		treeObjectIterator colIt(browser, tables);
+ 		while ((obj = colIt.GetNextObject()) != 0) {
+ 			srctable = (pgTable *)obj;
+ 			if (srctable->GetId() == table1->GetId())
+ 				return true;
+ 		}	
+ 	}
+ 	return false;
+ }
+ 
+ pgSchema *frmPasteObject::findSchema(pgDatabase *database, wxString schemaname)
+ {
+ 	ctlTree *browser = mainform->GetBrowser();
+ 	pgCollection *schemas = browser->FindCollection(schemaFactory, database->GetId());
+ 	if (schemas)
+ 	{
+ 		pgObject *obj;
+ 		pgSchema *srcschema;
+ 		treeObjectIterator colIt(browser, schemas);
+ 		while ((obj = colIt.GetNextObject()) != 0) {
+ 			srcschema = (pgSchema *)obj;
+ 			if (srcschema->GetIdentifier() == schemaname)
+ 				return srcschema;
+ 		}	
+ 	}
+ 	return 0;
+ }
+ 
+ void frmPasteObject::GetLastResultError(pgConn *conn, PGresult *res, const wxString &msg)
+ {
+ 	if (res)
+ 	{
+ 		lastResultError.severity = wxString(PQresultErrorField(res, PG_DIAG_SEVERITY), *conn->GetConv());
+ 		lastResultError.sql_state = wxString(PQresultErrorField(res, PG_DIAG_SQLSTATE), *conn->GetConv());
+ 		lastResultError.msg_primary = wxString(PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY), *conn->GetConv());
+ 		lastResultError.msg_detail = wxString(PQresultErrorField(res, PG_DIAG_MESSAGE_DETAIL), *conn->GetConv());
+ 		lastResultError.msg_hint = wxString(PQresultErrorField(res, PG_DIAG_MESSAGE_HINT), *conn->GetConv());
+ 		lastResultError.statement_pos = wxString(PQresultErrorField(res, PG_DIAG_STATEMENT_POSITION), *conn->GetConv());
+ 		lastResultError.internal_pos = wxString(PQresultErrorField(res, PG_DIAG_INTERNAL_POSITION), *conn->GetConv());
+ 		lastResultError.internal_query = wxString(PQresultErrorField(res, PG_DIAG_INTERNAL_QUERY), *conn->GetConv());
+ 		lastResultError.context = wxString(PQresultErrorField(res, PG_DIAG_CONTEXT), *conn->GetConv());
+ 		lastResultError.source_file = wxString(PQresultErrorField(res, PG_DIAG_SOURCE_FILE), *conn->GetConv());
+ 		lastResultError.source_line = wxString(PQresultErrorField(res, PG_DIAG_SOURCE_LINE), *conn->GetConv());
+ 		lastResultError.source_function = wxString(PQresultErrorField(res, PG_DIAG_SOURCE_FUNCTION), *conn->GetConv());
+ 	}
+ 	else
+ 	{
+ 		lastResultError.severity = wxEmptyString;
+ 		lastResultError.sql_state = wxEmptyString;
+ 		if (msg.IsEmpty())
+ 			lastResultError.msg_primary = conn->GetLastError();
+ 		else
+ 			lastResultError.msg_primary = msg;
+ 		lastResultError.msg_detail = wxEmptyString;
+ 		lastResultError.msg_hint = wxEmptyString;
+ 		lastResultError.statement_pos = wxEmptyString;
+ 		lastResultError.internal_pos = wxEmptyString;
+ 		lastResultError.internal_query = wxEmptyString;
+ 		lastResultError.context = wxEmptyString;
+ 		lastResultError.source_file = wxEmptyString;
+ 		lastResultError.source_line = wxEmptyString;
+ 		lastResultError.source_function = wxEmptyString;
+ 	}
+ 
+ 	wxString errMsg;
+ 
+ 	if (lastResultError.severity != wxEmptyString && lastResultError.msg_primary != wxEmptyString)
+ 		errMsg = lastResultError.severity + wxT(": ") + lastResultError.msg_primary;
+ 	else if (lastResultError.msg_primary != wxEmptyString)
+ 		errMsg = lastResultError.msg_primary;
+ 
+ 	if (!lastResultError.sql_state.IsEmpty())
+ 	{
+ 		if (!errMsg.EndsWith(wxT("\n")))
+ 			errMsg += wxT("\n");
+ 		errMsg += _("SQL state: ");
+ 		errMsg += lastResultError.sql_state;
+ 	}
+ 
+ 	if (!lastResultError.msg_detail.IsEmpty())
+ 	{
+ 		if (!errMsg.EndsWith(wxT("\n")))
+ 			errMsg += wxT("\n");
+ 		errMsg += _("Detail: ");
+ 		errMsg += lastResultError.msg_detail;
+ 	}
+ 
+ 	if (!lastResultError.msg_hint.IsEmpty())
+ 	{
+ 		if (!errMsg.EndsWith(wxT("\n")))
+ 			errMsg += wxT("\n");
+ 		errMsg += _("Hint: ");
+ 		errMsg += lastResultError.msg_hint;
+ 	}
+ 
+ 	if (!lastResultError.statement_pos.IsEmpty())
+ 	{
+ 		if (!errMsg.EndsWith(wxT("\n")))
+ 			errMsg += wxT("\n");
+ 		errMsg += _("Character: ");
+ 		errMsg += lastResultError.statement_pos;
+ 	}
+ 
+ 	if (!lastResultError.context.IsEmpty())
+ 	{
+ 		if (!errMsg.EndsWith(wxT("\n")))
+ 			errMsg += wxT("\n");
+ 		errMsg += _("Context: ");
+ 		errMsg += lastResultError.context;
+ 	}
+ 	lastResultError.formatted_msg = errMsg;
+ }
+ 
+ /*
+  * Functions for handling COPY IN/OUT data transfer->
+  *
+  * If you want to use COPY TO STDOUT/FROM STDIN in your application,
+  * this is the code to steal ;)
+  */
+ 
+ /*
+  * handleCopyOut
+  * receives data as a result of a COPY ... TO STDOUT command
+  *
+  * conn should be a database connection that you just issued COPY TO on
+  * and got back a PGRES_COPY_OUT result.
+  * copystream is the file stream for the data to go to.
+  *
+  * result is true if successful, false if not.
+  */
+ void frmPasteObject::handleCopyOut(pgConn *conn, wxFile & copystream)
+ {
+ 	bool		OK = true;
+ 	char	   *buf;
+ 	int			ret;
+ 	PGresult   *res;
+ 	int			counter = 0;
+ 
+ 	lastResultError.formatted_msg = wxT("");
+ 	for (;;)
+ 	{
+ 		counter++;
+ 		if (counter % 100)
+ 		{
+ 			if (transfer->THIS->thread && transfer->THIS->thread->TestDestroy())
+ 				break;
+ 		}
+ 		ret = PQgetCopyData(conn->connection(), &buf, 0);
+ 
+ 		if (ret < 0)
+ 			break;				/* done or error */
+ 
+ 		if (buf)
+ 		{
+ 			int n = copystream.Write(wxString(buf, wxConvUTF8));
+ 			if (n != 1)
+ 			{
+ 				if (OK)			/* complain only once, keep reading data */
+ 					lastResultError.formatted_msg.Format(_("could not write COPY data: %s\n"), strerror(errno));
+ 				OK = false;
+ 			}
+ 			PQfreemem(buf);
+ 		}
+ 	}
+ 
+ 	if (OK && !copystream.Flush())
+ 	{
+ 		lastResultError.formatted_msg.Format(_("could not write COPY data: %s\n"), strerror(errno));
+ 		OK = false;
+ 	}
+ 
+ 	if (ret == -2)
+ 	{
+ 		lastResultError.formatted_msg.Format(_("COPY data transfer failed: %s"), PQerrorMessage(conn->connection()));
+ 		OK = false;
+ 	}
+ 
+ 	/* Check command status and return to normal libpq state */
+ 	res = PQgetResult(conn->connection());
+ 	if (PQresultStatus(res) != PGRES_COMMAND_OK)
+ 	{
+ 		if (lastResultError.formatted_msg.IsEmpty()) {
+ 			GetLastResultError(conn, res);
+ 		}
+ 		OK = false;
+ 	}
+ 	PQclear(res);
+ }
+ 
+ /*
+  * handleCopyIn
+  * sends data to complete a COPY ... FROM STDIN command
+  *
+  * conn should be a database connection that you just issued COPY FROM on
+  * and got back a PGRES_COPY_IN result.
+  * copystream is the file stream to read the data from.
+  * isbinary can be set from PQbinaryTuples().
+  *
+  * result is true if successful, false if not.
+  */
+ 
+ /* read chunk size for COPY IN - size is not critical */
+ #define COPYBUFSIZ 8192
+ 
+ void frmPasteObject::handleCopyIn(pgConn *conn, wxFile & copystream, bool isbinary)
+ {
+ 	bool		OK;
+ 	char		buf[COPYBUFSIZ];
+ 	PGresult    *res;
+ 	int			counter = 0;
+ 
+ 	OK = true;
+ 
+ 	if (isbinary)
+ 	{
+ 		for (;;)
+ 		{
+ 			counter++;
+ 			if (counter % 100)
+ 			{
+ 				if (transfer->THIS->thread && transfer->THIS->thread->TestDestroy())
+ 					break;
+ 			}
+ 			int			buflen;;
+ 			buflen = copystream.Read(buf, 1);
+ 			if (buflen <= 0)
+ 				break;
+ 			if (PQputCopyData(conn->connection(), buf, buflen) <= 0)
+ 			{
+ 				OK = false;
+ 				break;
+ 			}
+ 		}
+ 	}
+ 	else
+ 	{
+ 		wxFileInputStream input(copystream);
+ 		wxTextInputStream textfile(input);
+ 
+ 		while (input.CanRead()) /* for each bufferload in line ... */
+ 		{
+ 			counter++;
+ 			if (counter % 100)
+ 			{
+ 				if (transfer->THIS->thread && transfer->THIS->thread->TestDestroy())
+ 					break;
+ 			}
+ 			wxString buf1 = textfile.ReadLine() + wxT("\n");
+ 			int buflen = buf1.Length();
+ 			if (buf1 == wxT("\n"))
+ 			{
+ 				break;
+ 			}
+ 			const wxCharBuffer wc = buf1.ToUTF8();
+ 			const char *tmp = wc.data();
+ 			int lenc = strlen(tmp);
+ 			if (PQputCopyData(conn->connection(), tmp, lenc) <= 0)
+ 			{
+ 				OK = false;
+ 				break;
+ 			}
+ 		}
+ 	}
+ 
+ 	/* Terminate data transfer */
+ 	const char *errmsg = "aborted because of read failure";
+ 	if (PQputCopyEnd(conn->connection(), OK ? NULL : errmsg) <= 0)
+ 		OK = false;
+ 
+ 	/* Check command status and return to normal libpq state */
+ 	res = PQgetResult(conn->connection());
+ 	if (PQresultStatus(res) != PGRES_COMMAND_OK)
+ 	{		
+ 		GetLastResultError(conn, res);
+ 		OK = false;
+ 	}
+ 	PQclear(res);
+ }
+ 
+ /*
+  * Execute a \copy command (frontend copy). We have to open a file, then
+  * submit a COPY query to the backend and either feed it data from the
+  * file or route its response into the file.
+  */
+ void frmPasteObject::do_copy(pgConn *conn, wxString & sql, wxFile & copystream)
+ {
+ 	PGresult   *result;
+ 	struct stat st;
+ 
+ 	result = conn->ExecuteOptionalResult(sql);
+ 	switch (PQresultStatus(result))
+ 	{
+ 		case PGRES_COPY_OUT:
+ 			handleCopyOut(conn, copystream);
+ 			break;
+ 		case PGRES_COPY_IN:
+ 			handleCopyIn(conn, copystream, PQbinaryTuples(result));
+ 			break;
+ 		case PGRES_NONFATAL_ERROR:
+ 		case PGRES_FATAL_ERROR:
+ 		case PGRES_BAD_RESPONSE:
+ 			lastResultError.formatted_msg.Format(_("copy error: %s\n%s\n"), PQerrorMessage(conn->connection()), sql.c_str());
+ 			break;
+ 		default:
+ 			lastResultError.formatted_msg.Format(
+ 			_("copy error: unexpected response (%d)\n%s\n"), PQresultStatus(result), sql.c_str());
+ 			break;
+ 	}
+ 
+ 	PQclear(result);
+ 
+ 	/*
+ 	 * Make sure we have pumped libpq dry of results; else it may still be in
+ 	 * ASYNC_BUSY state, leading to false readings in, eg, get_prompt().
+ 	 */
+ 	while ((result = PQgetResult(conn->connection())) != NULL)
+ 	{
+ 		lastResultError.formatted_msg.Format(_("copy: unexpected response (%d)\n"), PQresultStatus(result));
+ 		/* if still in COPY IN state, try to get out of it */
+ 		if (PQresultStatus(result) == PGRES_COPY_IN)
+ 			PQputCopyEnd(conn->connection(), (const char *)_("trying to exit copy mode"));
+ 		PQclear(result);
+ 	}
+ }
+ 
+ void frmPasteObject::myLogNotice(const wxChar *szFormat, ...)
+ {
+ 	wxLogLevel savedlogLevel = sysLogger::logLevel;
+ 	sysLogger::logLevel = LOG_NOTICE;
+ 	va_list argptr;
+ 	va_start(argptr, szFormat);
+ 	wxVLogNotice(szFormat, argptr);
+ 	va_end(argptr);
+ 	sysLogger::logLevel = savedlogLevel;
+ }
+ 
+ void frmPasteObject::copyTable(struct transfer_tag *transfer)
+ {
+ 	lastResultError.formatted_msg = wxT("");
+ 	bool rc;
+ 
+ 	if (transfer->THIS->thread && transfer->THIS->thread->TestDestroy())
+ 		return;
+ 	myLogNotice(wxT("CopyPaste=\"\n%s\""), transfer->createsql.c_str());
+ 	rc = transfer->targetconn->ExecuteVoid(transfer->createsql, false);
+ 	if (!rc)
+ 	{
+ 		lastResultError = transfer->targetconn->GetLastResultError();
+ 		lastResultError.formatted_msg = pastemsg + wxT("\n") + lastResultError.formatted_msg;
+ 		return;
+ 	}
+ 	if (transfer->THIS->thread && transfer->THIS->thread->TestDestroy())
+ 		return;
+ 	if (!transfer->searchPath.IsEmpty())
+ 	{
+ 		rc = transfer->targetconn->ExecuteVoid(wxT("SET search_path=") + transfer->searchPath, false);
+ 		if (!rc)
+ 		{
+ 			lastResultError = transfer->targetconn->GetLastResultError();
+ 			lastResultError.formatted_msg = pastemsg + wxT("\n") + lastResultError.formatted_msg;
+ 			return;
+ 		}
+ 	}
+ 
+ 	if (transfer->THIS->thread && transfer->THIS->thread->TestDestroy())
+ 		return;
+ 	if (transfer->sourceconn->GetDbname() == transfer->targetconn->GetDbname() &&
+ 			transfer->sourceconn->GetHost() == transfer->targetconn->GetHost() &&
+ 			transfer->sourceconn->GetPort() == transfer->targetconn->GetPort())
+ 	{
+ 		//same DB server
+ 		wxString tablenamenew = transfer->table->Getsrctable()->GetQuotedIdentifier();
+ 		if (transfer->srcschema->GetId() == transfer->targetschema->GetId())
+ 		{
+ 			if (tablenamenew.StartsWith(wxT("\"")))
+ 			{
+ 				tablenamenew = tablenamenew.Mid(1, tablenamenew.length() - 1) + transfer->table->copysuffix;
+ 				tablenamenew = wxT("\"") + tablenamenew + wxT("\"");
+ 			}
+ 			else
+ 				tablenamenew += transfer->table->copysuffix;
+ 		}
+ 		wxString copysql = 
+ 			wxT("\nINSERT INTO ")
+ 			+ transfer->targetschema->GetQuotedPrefix() + tablenamenew
+ 			+ wxT(" (SELECT * FROM ")
+ 			+ transfer->srcschema->GetQuotedPrefix() + transfer->table->Getsrctable()->GetQuotedIdentifier()
+ 			+ wxT(")\n\n");
+ 		rc = transfer->targetconn->ExecuteVoid(copysql, false);
+ 		if (!rc)
+ 		{
+ 			lastResultError = transfer->targetconn->GetLastResultError();
+ 			lastResultError.formatted_msg = pastemsg + wxT("\n") + lastResultError.formatted_msg;
+ 			return;
+ 		}
+ 		if (transfer->THIS->thread && transfer->THIS->thread->TestDestroy())
+ 			return;
+ 	}
+ 	else
+ 	{
+ 		//different DB servers
+ 		wxString tmpFilename;
+ 		wxFile tmpFile;
+ 		tmpFilename = wxFileName::CreateTempFileName(wxT("copytable"));
+ 		tmpFile.Open(tmpFilename.c_str(), wxFile::write);
+ 		if (!tmpFile.IsOpened())
+ 		{
+ 			lastResultError.formatted_msg = _("Can't create temporary file: ") + tmpFilename;
+ 			return;
+ 		}
+ 		if (transfer->THIS->thread && transfer->THIS->thread->TestDestroy())
+ 			return;
+ 		wxString copysql =
+ 			wxT("COPY ")
+ 			+ transfer->srcschema->GetQuotedPrefix() + transfer->table->Getsrctable()->GetQuotedIdentifier()
+ 			+ wxT(" TO STDOUT");
+ 		do_copy(transfer->sourceconn, copysql, tmpFile);
+ 		if (transfer->THIS->thread && transfer->THIS->thread->TestDestroy())
+ 			return;
+ 		if (lastResultError.formatted_msg.IsEmpty())
+ 		{
+ 			tmpFile.Close();
+ 			tmpFile.Open(tmpFilename.c_str(), wxFile::read);
+ 			if (!tmpFile.IsOpened())
+ 			{
+ 				lastResultError.formatted_msg = _("Can't open temporary file: ") + tmpFilename;
+ 				wxRemoveFile(tmpFilename);
+ 				return;
+ 			}
+ 			if (transfer->THIS->thread && transfer->THIS->thread->TestDestroy())
+ 			{
+ 				wxRemoveFile(tmpFilename);
+ 				return;
+ 			}
+ 			copysql =
+ 				wxT("COPY ")
+ 				+ transfer->targetschema->GetQuotedPrefix() + transfer->table->Getsrctable()->GetQuotedIdentifier()
+ 				+ wxT(" FROM STDIN");
+ 			do_copy(transfer->targetconn, copysql, tmpFile);
+ 		}
+ 		tmpFile.Close();
+ 		wxRemoveFile(tmpFilename);
+ 	}
+ 	copied++;
+ }
+ 
+ void *copyPasteThread::Entry()
+ {
+ 	transfer->THIS->copyTable(transfer);
+ 	if (!TestDestroy())
+ 	{
+ 		wxCommandEvent event(EVT_THREAD_COPYPASTE_UPDATE_GUI);
+ 		event.SetClientData(transfer);
+ 		wxPostEvent(winMain->GetEventHandler(), event);
+ 	}
+ 	return(NULL);
+ }
+ 
+ int frmPasteObject::process()
+ {
+ 	if (!sourceobj || !targetobj)
+ 	{
+ 		return 0;
+ 	}
+ 
+ 	pgSchema *targetschema = (pgSchema *)targetobj;
+ 	pgSchema *srcschema = 0;
+ 
+ 	//tree item 'Tables' has GetMetaType() == PGM_TABLE !
+ 	pgTable *table = (sourceobj->GetMetaType() == PGM_TABLE) ? dynamic_cast<pgTable *>(sourceobj) : 0;
+ 	if (table)
+ 	{
+ 		if (wxMessageBox(
+ 			_("Paste source table ?\n") +
+ 			table->GetSchema()->GetDatabase()->GetQuotedIdentifier() + wxT(".") + table->GetSchema()->GetQuotedIdentifier() +
+ 			wxT(".") + table->GetQuotedIdentifier() + wxT("\n") +
+ 			wxT(" into schema\n") + targetschema->GetDatabase()->GetQuotedIdentifier() + wxT(".") +
+ 			targetschema->GetQuotedIdentifier(), _("Paste table"), wxYES_NO) == wxNO)
+ 		{
+ 			return 0;
+ 		}
+ 		srcschema = table->GetSchema();
+ 	}
+ 	else
+ 	{
+ 		//tree item 'Schemas' has GetMetaType() == PGM_SCHEMA !
+ 		srcschema = dynamic_cast<pgSchema *>(sourceobj);
+ 		if (!srcschema) {
+ 			//tree item 'Tables' has GetMetaType() == PGM_TABLE or
+ 			//tree item 'Schemas' has GetMetaType() == PGM_SCHEMA !
+ 			return 0;
+ 		}
+ 		if (wxMessageBox(
+ 			_("Paste schema tables ?\n") +
+ 			srcschema->GetDatabase()->GetQuotedIdentifier() + wxT(".") + srcschema->GetQuotedIdentifier() + wxT("\n") +
+ 			wxT(" into schema\n") +
+ 			targetschema->GetDatabase()->GetQuotedIdentifier() + wxT(".") + targetschema->GetQuotedIdentifier(),
+ 			_("Paste schema tables"), wxYES_NO) == wxNO)
+ 			{
+ 				return 0;
+ 			}
+ 	}
+ 
+ 	pgConn *sourceconn = sourceobj->GetConnection();
+ 	pgConn *targetconn = targetobj->GetConnection();
+ 
+ 	if (!sourceconn || !targetconn)
+ 	{
+ 		wxMessageBox(
+ 			_("Both source and target schema connections should be established before paste table(s) operation !"));
+ 		return 0;
+ 	}
+ 
+ 	static wxString copysuffix = wxT("_copy_1");
+ 	if (srcschema->GetId() == targetschema->GetId())
+ 	{
+ 		copysuffix = wxGetTextFromUser(
+ 				_("Target schema is the same as source schema.\n"
+ 				"Enter suffix name for all the table copied objects"),
+ 				_("New Suffix Name"),
+ 				copysuffix);
+ 	}
+ 
+ 	ctlTree *browser = mainform->GetBrowser();
+ 	srcschema->ShowTreeDetail(browser);
+ 	targetschema->ShowTreeDetail(browser);
+ 	tableCopyPasteArray = new pgTableCopyPasteArray();
+ 	pgTableCopyPaste *tablenew;
+ 	pgCollection *tables = browser->FindCollection(tableFactory, srcschema->GetId());
+ 	pgCollection *sequences = browser->FindCollection(sequenceFactory, srcschema->GetId());
+ 
+ 	if (table)
+ 	{
+ 		table->ShowTreeDetail(browser);
+ 		pgCollection *constraints = browser->FindCollection(primaryKeyFactory, table->GetId());
+ 		if (constraints)
+ 		{
+ 			constraints->ShowTreeDetail(browser);
+ 			treeObjectIterator consIt(browser, constraints);
+ 			pgObject *data;
+ 			while ((data = consIt.GetNextObject()) != 0)
+ 			{
+ 				data->ShowTreeDetail(browser);
+ 			}
+ 		}
+ 		pgCollection *columns = browser->FindCollection(columnFactory, table->GetId());
+ 		if (columns)
+ 			columns->ShowTreeDetail(browser);
+ 		tablenew = new pgTableCopyPaste(table, targetschema, copysuffix, columns, constraints, tables, sequences);
+ 		tableCopyPasteArray->Add(tablenew);
+ 	}
+ 	else
+ 	{
+ 		if (tables)
+ 		{
+ 			pgObject *obj;
+ 			pgTable *srctable;
+ 			treeObjectIterator colIt(browser, tables);
+ 			while ((obj = colIt.GetNextObject()) != 0) {
+ 				srctable = (pgTable *)obj;
+ 				srctable->ShowTreeDetail(browser);
+ 				pgCollection *constraints = browser->FindCollection(primaryKeyFactory, srctable->GetId());
+ 				if (constraints)
+ 				{
+ 					constraints->ShowTreeDetail(browser);
+ 					treeObjectIterator consIt(browser, constraints);
+ 					pgObject *data;
+ 					while ((data = consIt.GetNextObject()) != 0)
+ 					{
+ 						data->ShowTreeDetail(browser);
+ 					}
+ 				}
+ 				pgCollection *columns = browser->FindCollection(columnFactory, srctable->GetId());
+ 				if (columns)
+ 					columns->ShowTreeDetail(browser);
+ 				tablenew = new pgTableCopyPaste(srctable, targetschema, copysuffix, columns, constraints, tables, sequences);
+ 				tableCopyPasteArray->Add(tablenew);
+ 			}	
+ 		}
+ 	}
+ 
+ 	transfer = new struct transfer_tag();
+ 
+ 	transfer->THIS = this;
+ 	transfer->srcdatabase = srcschema->GetDatabase();
+ 	transfer->targetdatabase = targetschema->GetDatabase();
+ 	transfer->srcschemaname = srcschema->GetIdentifier();
+ 	transfer->targetschemaname = targetschema->GetIdentifier();
+ 
+ 	pgConn *newtargetconn = 0;
+     pgConn *newsourceconn = sourceconn->Duplicate();
+ 	if (newsourceconn->GetDbname() == targetconn->GetDbname() &&
+ 			newsourceconn->GetHost() == targetconn->GetHost() &&
+ 			newsourceconn->GetPort() == targetconn->GetPort())
+ 	{
+ 		//same DB server
+ 		newtargetconn = newsourceconn;
+ 	}
+ 	else
+ 	{
+ 		newtargetconn = targetconn->Duplicate();
+ 	}
+ 
+ 	transfer->sourceconn = newsourceconn;
+ 	transfer->targetconn = newtargetconn;
+ 
+ 	transfer->numberOfCopypasteTables = tableCopyPasteArray->Count();
+ 
+ 	copied = 0;
+ 	pasteNextTable();
+ 	return tableCopyPasteArray->Count();
+ }
+ 
+ void frmPasteObject::pasteNextTable()
+ {
+ 	wxString srcdatabasename = transfer->srcdatabase->GetQuotedIdentifier();
+ 	wxString targetdatabasename = transfer->targetdatabase->GetQuotedIdentifier();
+ 
+ 	int i = transfer->numberOfCopypasteTables - 1;
+ 
+ 	ctlTree *browser = mainform->GetBrowser();
+ 
+ 	pgTableCopyPaste &item = tableCopyPasteArray->Item(i);
+ 	transfer->table = &item;
+ 	pastemsg = _("COPY TABLE:") +
+ 		srcdatabasename + wxT(".") + qtIdent(transfer->srcschemaname) + wxT(".") +
+ 		item.Getsrctable()->GetQuotedIdentifier() +
+ 		_(" INTO:") + targetdatabasename + wxT(".") + qtIdent(transfer->targetschemaname);
+ 	mainform->GetStatusBar()->SetStatusText(pastemsg, 1);
+ 	pastemsg = _("COPY TABLE:\n") +
+ 		srcdatabasename + wxT(".") + qtIdent(transfer->srcschemaname) + wxT(".") +
+ 		item.Getsrctable()->GetQuotedIdentifier() +
+ 		_("\nINTO:\n") + targetdatabasename + wxT(".") + qtIdent(transfer->targetschemaname);
+ 
+ 	factory->GetToolbar()->SetToolShortHelp(factory->GetId(), pastemsg);
+ 
+ 	thread = new copyPasteThread(transfer);
+ 	wxThreadError rc = thread->Create();
+ 	bool err = false;
+ 	if (rc != wxTHREAD_NO_ERROR)
+ 	{
+ 		lastResultError.formatted_msg.Format(_("Create thread error: rc=%d\n"), rc);
+ 	}
+ 	else
+ 	{
+ 		transfer->srcschema = findSchema(transfer->srcdatabase, transfer->srcschemaname);
+ 		if (!transfer->srcschema)
+ 		{
+ 			lastResultError.formatted_msg = pastemsg + wxT("\n") + _("Source schema disappeared");
+ 			err = true;
+ 		}
+ 		if (!err)
+ 		{
+ 			transfer->targetschema = findSchema(transfer->targetdatabase, transfer->targetschemaname);
+ 			if (!transfer->targetschema)
+ 			{
+ 				lastResultError.formatted_msg = pastemsg + wxT("\n") + _("Target schema disappeared");
+ 				err = true;
+ 			}
+ 		}
+ 
+ 		if (!err && transfer->srcschema->GetId() != transfer->targetschema->GetId())
+ 		{
+ 			err = tableExists(transfer->targetschema, item.Getsrctable());
+ 			if (err)
+ 			{
+ 				lastResultError.formatted_msg = wxT("TABLE EXISTS");
+ 			}
+ 		}
+ 		if (!err)
+ 		{
+ 			bool rc = transfer->targetconn->ExecuteVoid(wxT("BEGIN"));
+ 			if (!rc)
+ 			{
+ 				lastResultError = transfer->targetconn->GetLastResultError();
+ 				lastResultError.formatted_msg = pastemsg + wxT("\n") + lastResultError.formatted_msg;
+ 			}
+ 			else
+ 			{
+ 				transfer->createsql = transfer->table->GetSql(browser);
+ 				transfer->searchPath = transfer->targetconn->ExecuteScalar(wxT("SHOW search_path"));
+ 				transfer->createsql = wxT("SET search_path=") + transfer->targetschema->GetQuotedIdentifier() +
+ 						wxT(";\n") + transfer->createsql;
+ 				thread->Run();
+ 				return;
+ 			}
+ 		}
+ 	}
+ 	commitChanges();
+ }
+ 
+ void frmPasteObject::commitChanges()
+ {
+ 	wxString msg;
+ 	if (lastResultError.formatted_msg != wxT("TABLE EXISTS"))
+ 	{
+ 		if (lastResultError.formatted_msg.IsEmpty())
+ 		{
+ 			transfer->targetconn->ExecuteVoid(wxT("COMMIT"));
+ 			lastResultError = transfer->targetconn->GetLastResultError();
+ 			if (!lastResultError.formatted_msg.IsEmpty())
+ 			{
+ 				lastResultError.formatted_msg = pastemsg + wxT("\n") + lastResultError.formatted_msg;
+ 				msg = lastResultError.formatted_msg;
+ 			}
+ 		}
+ 		else
+ 		{
+ 			transfer->targetconn->ExecuteVoid(wxT("ROLLBACK"));
+ 			msg = lastResultError.formatted_msg;
+ 		}
+ 	}
+ 	if (!lastResultError.formatted_msg.IsEmpty())
+ 	{
+ 		wxMessageBox(msg,
+ 			_("Cannot paste table:") +
+ 			transfer->targetdatabase->GetQuotedIdentifier() + wxT(".") + transfer->targetschemaname +
+ 			wxT(".") + transfer->table->Getsrctable()->GetQuotedIdentifier(),
+ 			wxOK | wxICON_ERROR);
+ 	}
+ }
+ 
+ frmPasteObject::~frmPasteObject()
+ {
+ }
+ 
+ pgTableCopyPaste::pgTableCopyPaste(pgTable *srctable, pgSchema *targetschema, wxString copysuffix1,
+ 		pgCollection *columns1, pgCollection *constraints1, pgCollection *tables1, pgCollection *sequences1)
+ {
+ 	this->srctable = srctable;
+ 	this->targetschema = targetschema;
+ 	this->copysuffix = copysuffix1;
+ 	this->columns = columns1;
+ 	this->constraints = constraints1;
+ 	this->tables = tables1;
+ 	this->sequences = sequences1;
+ }
+ 
+ wxString pgTableCopyPaste::GetSequenceName(wxString definition, bool schemaonly)
+ {
+     //Supported formats:
+     //1. nextval('"""".id_gk_vrsta_naloga'::regclass)
+     //2. nextval(('ps_nalog_id_seq'::text)::regclass)
+ 
+     //Schema and sequence name combinations:
+     //1. "schema.name"."seq.name"
+     //2. "schema.name".seq_name
+     //3  schema_name."seq.name"
+     //4  schema_name.seq_name
+     //5  "seq.name"
+     //6  seq_name
+ 
+     wxString defval = definition;
+     wxString schemaname, seqname;
+     int pos = wxString(wxT("nextval(")).length();
+     if (wxString(defval[pos]) == wxT("("))
+     {
+         pos++;  //skip left brace
+     }
+     pos++;  //skip starting apostrophe
+     if (wxString(defval[pos]) == wxT("\""))
+     {
+ 		//start parsing after the first "
+         wxString newdefval = defval.Mid(pos + 1);
+ 		//eliminate Ambiguous ". from the definition field
+         newdefval.Replace(wxT("\"\""), wxT("  "), true);
+ 
+         int subseq = newdefval.Find(wxT("\"."));
+         if (subseq == wxNOT_FOUND)
+         {
+ 			//case 5 quoted sequence name without schema name
+ 			subseq = newdefval.rfind(wxT("\"'"));
+ 			if (subseq == wxNOT_FOUND)
+ 				return wxEmptyString;
+ 			schemaname = wxT("public");
+ 			seqname = defval.Mid(pos, subseq + 1);
+         }
+ 		else
+ 		{
+ 			//quoted schema name
+ 			schemaname = defval.Mid(pos + 1, subseq);
+ 			schemaname.Replace(wxT("\"\""), wxT("\""), true);
+ 			schemaname = wxT("\"") + schemaname + wxT("\"");
+ 			subseq += 3;
+ 			int subseq1 = newdefval.Mid(subseq + 2).rfind(wxT("'"));
+ 			if (subseq1 == wxNOT_FOUND)
+ 				return wxEmptyString;
+             //case 1, 2 quoted schema name
+ 			seqname = defval.Mid(pos + subseq, subseq1 + 3);
+ 		}
+         if (wxString(seqname[0]) == wxT("\""))
+         {
+             seqname = seqname.Mid(1, seqname.length() - 2);
+             seqname.Replace(wxT("\"\""), wxT("\""), true);
+ 			seqname.Replace(wxT("''"), wxT("'"), true);
+             seqname = wxT("\"") + seqname + wxT("\"");
+         }
+     }
+     else
+     {
+ 		//case 3, 4, 5, 6 not quoted schema name
+ 		wxString newdefval = defval.Mid(pos);
+         int subseq = newdefval.Find(wxT("."));
+         if (subseq == wxNOT_FOUND)
+         {
+ 			//case 5, 6 sequence name without schema name
+ 			subseq = newdefval.rfind(wxT("'"));
+ 			if (subseq == wxNOT_FOUND)
+ 				return wxEmptyString;
+ 			schemaname = wxT("public");
+ 			seqname = defval.Mid(pos, subseq);
+         }
+ 		else
+ 		{
+ 			//case 3, 4 not quoted schema name
+ 			schemaname = defval.Mid(pos, subseq);
+ 			subseq += 1;
+ 			int subseq1 = newdefval.Mid(subseq + 1).rfind(wxT("'"));
+ 			if (subseq1 == wxNOT_FOUND)
+ 				return wxEmptyString;
+ 			seqname = defval.Mid(pos + subseq, subseq1 + 1);
+ 		}
+         if (wxString(seqname[0]) == wxT("\""))
+         {
+             seqname = seqname.Mid(1, seqname.length() - 2);
+             seqname.Replace(wxT("\"\""), wxT("\""), true);
+ 			seqname.Replace(wxT("''"), wxT("'"), true);
+             seqname = wxT("\"") + seqname + wxT("\"");
+         }
+     }
+ 
+     return (schemaonly) ? schemaname : seqname;
+ }
+ 
+ wxString pgTableCopyPaste::GetSql(ctlTree *browser)
+ {
+ 	wxString colDetails, conDetails;
+ 	wxString prevComment;
+ 	wxString cols_sql;
+ 	wxString sql;
+ 	wxString sqlcreate;
+ 	wxString sqlsequence = wxT("\n");
+ 	wxString columnPrivileges;
+ 	wxString newtablename;
+ 	wxString qtfullident;
+ 	wxString qtfullidentsrc = srctable->GetQuotedFullIdentifier();
+     bool sameschema = (srctable->GetSchema()->GetId() == targetschema->GetId());
+ 
+ 	if (sameschema)
+ 	{
+ 		newtablename = srctable->GetIdentifier() + copysuffix;
+ 		if (!tables)
+ 			return sql;
+ 		pgObject *obj;
+ 		pgTable *srctable;
+ 		bool fnd = false;
+ 		treeObjectIterator colIt(browser, tables);
+ 		while ((obj = colIt.GetNextObject()) != 0) {
+ 			srctable = (pgTable *)obj;
+ 			if (srctable->GetIdentifier() == newtablename)
+ 			{
+ 				fnd = true;
+ 				break;
+ 			}
+ 		}
+ 		if (!fnd)
+ 		{
+ 			qtfullident = targetschema->GetQuotedPrefix() + qtIdent(newtablename);
+ 		}
+ 	}
+     else
+     {
+         qtfullident = targetschema->GetQuotedPrefix() + srctable->GetQuotedIdentifier();
+     }
+ 
+ 	sqlcreate = wxT("-- Table: ") + qtfullident + wxT("\n\n")
+ 			+ wxT("-- DROP TABLE ") + qtfullident + wxT(";");
+ 	sql = wxT("\n\nCREATE ");
+ 	if (srctable->GetUnlogged())
+ 		sql += wxT("UNLOGGED ");
+ 	sql += wxT("TABLE ") + qtfullident;
+ 
+ 	// of type (9.0 material)
+ 	if (srctable->GetOfTypeOid() > 0)
+ 		sql += wxT("\nOF ") + qtIdent(srctable->GetOfType());
+ 
+ 	// Get a count of the constraints.
+ 	int consCount = 0;
+ 	if (constraints)
+ 		consCount = browser->GetChildrenCount(constraints->GetId());
+ 
+ 	// Get the columns
+ 	if (columns)
+ 	{
+ 		treeObjectIterator colIt1(browser, columns);
+ 		treeObjectIterator colIt2(browser, columns);
+ 
+ 		int lastRealCol = 0;
+ 		int currentCol = 0;
+ 		pgColumn *column;
+ 
+ 		// Iterate the columns to find the last 'real' one
+ 		while ((column = (pgColumn *) colIt1.GetNextObject()) != 0)
+ 		{
+ 			currentCol++;
+ 
+ 			if (column->GetInheritedCount() == 0)
+ 				lastRealCol = currentCol;
+ 		}
+ 
+ 		// Now build the actual column list
+ 		int colCount = 0;
+ 		while ((column = (pgColumn *) colIt2.GetNextObject()) != 0)
+ 		{
+ 			if (column->GetColNumber() > 0)
+ 			{
+ 				if (colCount)
+ 				{
+ 					// Only add a comma if this isn't the last 'real' column, or if there are constraints
+ 					if (colCount != lastRealCol || consCount)
+ 						cols_sql += wxT(",");
+ 					if (!prevComment.IsEmpty())
+ 						cols_sql += wxT(" -- ") + firstLineOnly(prevComment);
+ 
+ 					cols_sql += wxT("\n");
+ 				}
+ 
+ 				if (column->GetInheritedCount() > 0)
+ 				{
+ 					if (!column->GetIsLocal())
+ 					{
+ 						cols_sql += wxString::Format(wxT("-- %s "), _("Inherited"))
+ 								+ wxT("from table ") + column->GetInheritedTableName() + wxT(":");
+ 					}
+ 				}
+ 
+ 				if (srctable->GetOfTypeOid() > 0)
+ 				{
+ 					if (column->GetDefinition().Length() == 0)
+ 					{
+ 						cols_sql += wxString::Format(wxT("-- %s "), _("Inherited"))
+ 								+ wxT("from type ") + srctable->GetOfType() + wxT(": ")
+ 								+ column->GetQuotedIdentifier();
+ 					}
+ 					else
+ 					{
+ 						cols_sql += wxT("  ") + column->GetQuotedIdentifier() + wxT(" WITH OPTIONS ")
+ 								+ column->GetDefinition();
+ 					}
+ 				}
+ 				else
+ 				{
+ 					wxString coldef = column->GetDefault();
+ 					wxString colseq = column->GetSerialSequence();
+ 					if (colseq.IsEmpty() && coldef.StartsWith(wxT("nextval(")))
+ 					{
+ 						wxString newseqname, origseqname;
+ 						bool fnd = false;
+ 						wxString seqname = GetSequenceName(coldef, false);
+ 						if (!seqname.IsEmpty())
+ 						{
+ 							if (srctable->GetSchema()->GetId() == targetschema->GetId())
+ 							{
+ 								if (!sequences)
+ 									return sql;
+ 								pgObject *obj;
+ 								pgSequence *srcsequence = 0, *tmpsequence;
+ 								bool fnd = false;
+                                 newseqname = origseqname = seqname;
+ 								if (seqname.StartsWith(wxT("\"")))
+ 								{
+ 									newseqname = seqname.Mid(1, seqname.length() - 2);
+ 									origseqname = seqname.Mid(1, seqname.length() - 2);
+ 								}
+                                 newseqname += copysuffix;
+ 								treeObjectIterator colIt(browser, sequences);
+ 								while ((obj = colIt.GetNextObject()) != 0) {
+ 									tmpsequence = (pgSequence *)obj;
+ 									if (tmpsequence->GetIdentifier() == newseqname)
+ 									{
+ 										fnd = true;
+ 										break;
+ 									}
+ 									if (tmpsequence->GetIdentifier() == origseqname)
+ 									{
+ 										srcsequence = tmpsequence;
+ 									}
+ 								}
+ 								if (fnd)
+ 									return sql;
+ 								pgSequenceCopyPaste seqcp(srcsequence, targetschema, copysuffix);
+ 								sqlsequence += seqcp.GetSql(browser);
+ 								wxString schseqname = GetSequenceName(coldef, true);
+ 								if (schseqname.StartsWith(wxT("\"")))
+ 								{
+ 									schseqname = schseqname.Mid(1, schseqname.length() - 2);
+ 								}
+ 								wxString coldef = column->GetDefinition();
+ 								newseqname = qtIdent(newseqname);
+ 								if (newseqname.StartsWith(wxT("\"")))
+ 								{
+ 									newseqname = newseqname.Mid(1, newseqname.length() - 2);
+ 								}
+ 								wxString qtfullidentseq = targetschema->GetQuotedPrefix() + qtIdent(newseqname);
+ 								qtfullidentseq.Replace(wxT("'"), wxT("''"));
+ 								origseqname.Replace(wxT("'"), wxT("''"));
+ 								coldef.Replace(qtIdent(schseqname) + wxT(".") + qtIdent(origseqname), qtfullidentseq, true);
+ 								cols_sql += wxT("  ") + column->GetQuotedIdentifier() + wxT(" ") + coldef;
+ 							}
+ 							else
+ 							{
+ 								if (!tables)
+ 									return sql;
+ 								pgObject *obj;
+ 								pgSequence *srcsequence;
+ 								wxString seqname1 = seqname;
+ 								if (seqname1.StartsWith(wxT("\"")))
+ 								{
+ 									seqname1 = seqname1.Mid(1, seqname1.length() - 2);
+ 								}
+ 								treeObjectIterator colIt(browser, sequences);
+ 								while ((obj = colIt.GetNextObject()) != 0) {
+ 									srcsequence = (pgSequence *)obj;
+ 									if (srcsequence->GetIdentifier() == seqname1)
+ 									{
+ 										fnd = true;
+ 										break;
+ 									}
+ 								}
+ 								if (!fnd)
+ 									return sql;
+ 								pgSequenceCopyPaste seqcp(srcsequence, targetschema, copysuffix);
+ 								sqlsequence += seqcp.GetSql(browser);
+ 								wxString schseqname = GetSequenceName(coldef, true);
+ 								if (schseqname.StartsWith(wxT("\"")))
+ 								{
+ 									schseqname = schseqname.Mid(1, schseqname.length() - 2);
+ 								}
+ 								wxString coldef = column->GetDefinition();
+ 								wxString qtfullidentseq = targetschema->GetQuotedPrefix() + qtIdent(seqname1);
+ 								qtfullidentseq.Replace(wxT("'"), wxT("''"));
+ 								seqname1.Replace(wxT("'"), wxT("''"));
+ 								coldef.Replace(qtIdent(schseqname) + wxT(".") + qtIdent(seqname1), qtfullidentseq, true);
+ 								cols_sql += wxT("  ") + column->GetQuotedIdentifier() + wxT(" ") + coldef;
+ 							}
+ 						}
+ 					}
+ 					else
+ 						cols_sql += wxT("  ") + column->GetQuotedIdentifier() + wxT(" ")
+ 								+ column->GetDefinition();
+ 				}
+ 
+ 				prevComment = column->GetComment();
+ 
+ 				// Whilst we are looping round the columns, grab their comments as well.
+ 				wxString comment = column->GetCommentSql();
+ 				comment.Replace(qtfullidentsrc, qtfullident, false);
+ 				colDetails += comment;
+ 				if (colDetails.Length() > 0)
+ 					if (colDetails.Last() != '\n')
+ 						colDetails += wxT("\n");
+ 				colDetails += column->GetStorageSql();
+ 				if (colDetails.Length() > 0)
+ 					if (colDetails.Last() != '\n')
+ 						colDetails += wxT("\n");
+ 				colDetails += column->GetAttstattargetSql();
+ 				if (colDetails.Length() > 0)
+ 					if (colDetails.Last() != '\n')
+ 						colDetails += wxT("\n");
+ 
+ 				colCount++;
+ 				columnPrivileges += column->GetPrivileges();
+ 			}
+ 		}
+ 	}
+ 
+ 	// Now iterate the constraints
+ 	if (constraints)
+ 	{
+         wxString constraintname;
+ 		treeObjectIterator consIt(browser, constraints);
+ 
+ 		pgObject *data;
+ 
+ 		while ((data = consIt.GetNextObject()) != 0)
+ 		{
+ 			cols_sql += wxT(",");
+ 
+ 			if (!prevComment.IsEmpty())
+ 				cols_sql += wxT(" -- ") + firstLineOnly(prevComment);
+ 
+ 			constraintname = data->GetQuotedIdentifier();
+ 			if (sameschema)
+ 			{
+ 				if (constraintname.StartsWith(wxT("\"")))
+ 				{
+ 					constraintname = constraintname.Mid(1, constraintname.length() - 1) + copysuffix;
+ 					constraintname = wxT("\"") + constraintname + wxT("\"");
+ 				}
+ 				else
+ 					constraintname += copysuffix;
+ 			}
+ 			cols_sql += wxT("\n  CONSTRAINT ") + constraintname
+ 					+ wxT(" ") + data->GetTypeName().Upper()
+ 					+ wxT(" ");
+ 
+ 			prevComment = data->GetComment();
+ 			if (!data->GetComment().IsEmpty())
+ 				conDetails += wxT("COMMENT ON CONSTRAINT ") + constraintname +
+ 				wxT(" ON ") + srctable->GetQuotedFullIdentifier() +
+ 				wxT(" IS ") + srctable->qtDbString(data->GetComment()) + wxT(";\n");
+ 
+ 			switch (data->GetMetaType())
+ 			{
+ 				case PGM_PRIMARYKEY:
+ 				case PGM_UNIQUE:
+ 				case PGM_EXCLUDE:
+ 					cols_sql += ((pgIndexConstraint *) data)->GetDefinition();
+ 					break;
+ 				case PGM_FOREIGNKEY:
+ 					cols_sql += ((pgForeignKey *) data)->GetDefinition();
+ 					break;
+ 				case PGM_CHECK:
+ 					cols_sql += wxT("(") + ((pgCheck *) data)->GetDefinition() + wxT(")");
+ 					break;
+ 			}
+ 		}
+ 	}
+ 	if (!prevComment.IsEmpty())
+ 		cols_sql += wxT(" -- ") + firstLineOnly(prevComment);
+ 
+ 	sql += wxT("\n(\n") + cols_sql + wxT("\n)");
+ 
+ 	if (srctable->GetInheritedTableCount())
+ 	{
+ 		sql += wxT("\nINHERITS (") + srctable->GetQuotedInheritedTables() + wxT(")");
+ 	}
+ 
+ 	if (srctable->GetConnection()->BackendMinimumVersion(8, 2))
+ 	{
+ 		sql += wxT("\nWITH (");
+ 		if (srctable->GetFillFactor().Length() > 0)
+ 			sql += wxT("\n  FILLFACTOR=") + srctable->GetFillFactor() + wxT(", ");
+ 		if (srctable->GetAppendOnly().Length() > 0)
+ 			sql += wxT("APPENDONLY=") + srctable->GetAppendOnly() + wxT(", ");
+ 		if (srctable->GetCompressLevel().Length() > 0)
+ 			sql += wxT("COMPRESSLEVEL=") + srctable->GetCompressLevel() + wxT(", ");
+ 		if (srctable->GetOrientation().Length() > 0)
+ 			sql += wxT("ORIENTATION=") + srctable->GetOrientation() + wxT(", ");
+ 		if (srctable->GetCompressType().Length() > 0)
+ 			sql += wxT("COMPRESSTYPE=") + srctable->GetCompressType() + wxT(", ");
+ 		if (srctable->GetBlocksize().Length() > 0)
+ 			sql += wxT("BLOCKSIZE=") + srctable->GetBlocksize() + wxT(", ");
+ 		if (srctable->GetChecksum().Length() > 0)
+ 			sql += wxT("CHECKSUM=") + srctable->GetChecksum() + wxT(", ");
+ 		if (srctable->GetHasOids())
+ 			sql += wxT("\n  OIDS=TRUE");
+ 		else
+ 			sql += wxT("\n  OIDS=FALSE");
+ 		if (srctable->GetConnection()->BackendMinimumVersion(8, 4)) {
+ 			if (srctable->GetCustomAutoVacuumEnabled()) {
+ 				if (srctable->GetAutoVacuumEnabled() == 1)
+ 					sql += wxT(",\n  autovacuum_enabled=true");
+ 				else if (srctable->GetCustomAutoVacuumEnabled() == 0)
+ 					sql += wxT(",\n  autovacuum_enabled=false");
+ 				if (!srctable->GetAutoVacuumVacuumThreshold().IsEmpty())
+ 				{
+ 					sql += wxT(",\n  autovacuum_vacuum_threshold=") + srctable->GetAutoVacuumVacuumThreshold();
+ 				}
+ 				if (!srctable->GetAutoVacuumVacuumScaleFactor().IsEmpty())
+ 				{
+ 					sql += wxT(",\n  autovacuum_vacuum_scale_factor=") + srctable->GetAutoVacuumVacuumScaleFactor();
+ 				}
+ 				if (!srctable->GetAutoVacuumAnalyzeThreshold().IsEmpty())
+ 				{
+ 					sql += wxT(",\n  autovacuum_analyze_threshold=") + srctable->GetAutoVacuumAnalyzeThreshold();
+ 				}
+ 				if (!srctable->GetAutoVacuumAnalyzeScaleFactor().IsEmpty())
+ 				{
+ 					sql += wxT(",\n  autovacuum_analyze_scale_factor=") + srctable->GetAutoVacuumAnalyzeScaleFactor();
+ 				}
+ 				if (!srctable->GetAutoVacuumVacuumCostDelay().IsEmpty())
+ 				{
+ 					sql += wxT(",\n  autovacuum_vacuum_cost_delay=") + srctable->GetAutoVacuumVacuumCostDelay();
+ 				}
+ 				if (!srctable->GetAutoVacuumVacuumCostLimit().IsEmpty())
+ 				{
+ 					sql += wxT(",\n  autovacuum_vacuum_cost_limit=") + srctable->GetAutoVacuumVacuumCostLimit();
+ 				}
+ 				if (!srctable->GetAutoVacuumFreezeMinAge().IsEmpty())
+ 				{
+ 					sql += wxT(",\n  autovacuum_freeze_min_age=") + srctable->GetAutoVacuumFreezeMinAge();
+ 				}
+ 				if (!srctable->GetAutoVacuumFreezeMaxAge().IsEmpty())
+ 				{
+ 					sql += wxT(",\n  autovacuum_freeze_max_age=") + srctable->GetAutoVacuumFreezeMaxAge();
+ 				}
+ 				if (!srctable->GetAutoVacuumFreezeTableAge().IsEmpty())
+ 				{
+ 					sql += wxT(",\n  autovacuum_freeze_table_age=") + srctable->GetAutoVacuumFreezeTableAge();
+ 				}
+ 			}
+ 			if (srctable->GetHasToastTable() && srctable->GetToastCustomAutoVacuumEnabled())
+ 			{
+ 				if (srctable->GetToastAutoVacuumEnabled() == 1)
+ 					sql += wxT(",\n  toast.autovacuum_enabled=true");
+ 				else if (srctable->GetToastAutoVacuumEnabled() == 0)
+ 					sql += wxT(",\n  toast.autovacuum_enabled=false");
+ 				if (!srctable->GetToastAutoVacuumVacuumThreshold().IsEmpty())
+ 				{
+ 					sql += wxT(",\n  toast.autovacuum_vacuum_threshold=") + srctable->GetToastAutoVacuumVacuumThreshold();
+ 				}
+ 				if (!srctable->GetToastAutoVacuumVacuumScaleFactor().IsEmpty())
+ 				{
+ 					sql += wxT(",\n  toast.autovacuum_vacuum_scale_factor=") + srctable->GetToastAutoVacuumVacuumScaleFactor();
+ 				}
+ 				if (!srctable->GetToastAutoVacuumAnalyzeThreshold().IsEmpty())
+ 				{
+ 					sql += wxT(",\n  toast.autovacuum_analyze_threshold=") + srctable->GetToastAutoVacuumAnalyzeThreshold();
+ 				}
+ 				if (!srctable->GetToastAutoVacuumAnalyzeScaleFactor().IsEmpty())
+ 				{
+ 					sql += wxT(",\n  toast.autovacuum_analyze_scale_factor=") + srctable->GetToastAutoVacuumAnalyzeScaleFactor();
+ 				}
+ 				if (!srctable->GetToastAutoVacuumVacuumCostDelay().IsEmpty())
+ 				{
+ 					sql += wxT(",\n  toast.autovacuum_vacuum_cost_delay=") + srctable->GetToastAutoVacuumVacuumCostDelay();
+ 				}
+ 				if (!srctable->GetToastAutoVacuumVacuumCostLimit().IsEmpty())
+ 				{
+ 					sql += wxT(",\n  toast.autovacuum_vacuum_cost_limit=") + srctable->GetToastAutoVacuumVacuumCostLimit();
+ 				}
+ 				if (!srctable->GetToastAutoVacuumFreezeMinAge().IsEmpty())
+ 				{
+ 					sql += wxT(",\n  toast.autovacuum_freeze_min_age=") + srctable->GetToastAutoVacuumFreezeMinAge();
+ 				}
+ 				if (!srctable->GetToastAutoVacuumFreezeMaxAge().IsEmpty())
+ 				{
+ 					sql += wxT(",\n  toast.autovacuum_freeze_max_age=") + srctable->GetToastAutoVacuumFreezeMaxAge();
+ 				}
+ 				if (!srctable->GetToastAutoVacuumFreezeTableAge().IsEmpty())
+ 				{
+ 					sql += wxT(",\n  toast.autovacuum_freeze_table_age=") + srctable->GetToastAutoVacuumFreezeTableAge();
+ 				}
+ 			}
+ 		}
+ 		sql += wxT("\n)");
+ 	}
+ 	else
+ 	{
+ 		if (srctable->GetHasOids())
+ 			sql += wxT("\nWITH OIDS");
+ 		else
+ 			sql += wxT("\nWITHOUT OIDS");
+ 	}
+ 
+ 	if (srctable->GetConnection()->BackendMinimumVersion(8, 0) &&
+ 			srctable->GetTablespace() != srctable->GetDatabase()->GetDefaultTablespace())
+ 		sql += wxT("\nTABLESPACE ") + qtIdent(srctable->GetTablespace());
+ 
+ 	if (srctable->GetConnection()->GetIsGreenplum())
+ 	{
+ 		// Add Greenplum DISTRIBUTED BY
+ 		if (srctable->GetDistributionIsRandom())
+ 		{
+ 			sql += wxT("\nDISTRIBUTED RANDOMLY");
+ 		}
+ 		else if (srctable->GetDistributionColNumbers().Length() == 0)
+ 		{
+ 			// catalog table or other non-distributed table
+ 		}
+ 		else
+ 		{
+ 			// convert list of columns numbers to column names
+ 			wxStringTokenizer collist(srctable->GetDistributionColNumbers(), wxT(","));
+ 			wxString cn;
+ 			wxString distributionColumns;
+ 			while (collist.HasMoreTokens())
+ 			{
+ 				cn = collist.GetNextToken();
+ 				pgSet *set = srctable->ExecuteSet(
+ 						wxT("SELECT attname\n")
+ 						wxT("  FROM pg_attribute\n")
+ 						wxT(" WHERE attrelid=") + srctable->GetOidStr() + wxT(" AND attnum IN (") + cn + wxT(")"));
+ 				if (set)
+ 				{
+ 					if (!distributionColumns.IsNull())
+ 					{
+ 						distributionColumns += wxT(", ");
+ 					}
+ 					distributionColumns += qtIdent(set->GetVal(0));
+ 					delete set;
+ 				}
+ 			}
+ 
+ 			sql += wxT("\nDISTRIBUTED BY (");
+ 			sql += distributionColumns;
+ 
+ 			sql += wxT(")");
+ 		}
+ 
+ 		if (srctable->GetIsPartitioned())
+ 			if (srctable->GetConnection()->BackendMinimumVersion(8, 2, 9) && srctable->GetConnection()->GetIsGreenplum())
+ 				if (srctable->GetPartitionDef().Length() == 0)
+ 				{
+ 					wxString query = wxT("SELECT pg_get_partition_def(");
+ 					query += srctable->GetOidStr();
+ 					query += wxT(", true) ");
+ 					wxString partition_def = srctable->GetDatabase()->ExecuteScalar(query);
+ 					srctable->iSetPartitionDef(partition_def);
+ 					// pg_get_partition_def() doesn't work on partitions
+ 					if (srctable->GetPartitionDef().Length() == 0)
+ 						srctable->iSetPartitionDef(wxT("-- This partition has subpartitions"));
+ 				}
+ 		if (srctable->GetPartitionDef().Length() > 0)
+ 			sql += wxT("\n") + srctable->GetPartitionDef() + wxT("\n");
+ 	}
+ 
+ 
+ 	sql += wxT(";\n")
+ 			+ srctable->GetOwnerSql(7, 3, wxT("TABLE ") + qtfullident);
+ 
+ 	if (srctable->GetConnection()->BackendMinimumVersion(8, 2))
+ 		sql += srctable->GetGrant(wxT("arwdxt"), wxT("TABLE ") + qtfullident);
+ 	else
+ 		sql += srctable->GetGrant(wxT("arwdRxt"), wxT("TABLE ") + qtfullident);
+ 
+ 	wxString comment = srctable->GetCommentSql();
+ 	comment.Replace(qtfullidentsrc, qtfullident);
+ 	sql += comment;
+ 
+ 	// Column/constraint comments
+ 	if (!colDetails.IsEmpty())
+ 		sql += colDetails + wxT("\n");
+ 
+ 	if (!conDetails.IsEmpty())
+ 		sql += conDetails + wxT("\n");
+ 
+ 	if (!columnPrivileges.IsEmpty()) {
+ 		sql += columnPrivileges + wxT("\n");
+ 	}
+ 
+ 	return sqlcreate + sqlsequence + sql;
+ }
+ 
+ pgTableCopyPaste::~pgTableCopyPaste()
+ {
+ }
+ 
+ pgSequenceCopyPaste::pgSequenceCopyPaste(pgSequence *srcseq, pgSchema *targetschema, wxString copysuffix1)
+ {
+ 	this->srcseq = srcseq;
+ 	this->targetschema = targetschema;
+ 	this->copysuffix = copysuffix1;
+ }
+ 
+ wxString pgSequenceCopyPaste::GetSql(ctlTree *browser)
+ {
+ 	wxString sql = wxEmptyString;
+ 	wxString qtfullident;
+ 	wxString newtablename;
+ 	bool sameschema = (srcseq->GetSchema()->GetId() == targetschema->GetId());
+ 	if (sameschema)
+ 	{
+ 		newtablename = srcseq->GetIdentifier() + copysuffix;
+ 		qtfullident = targetschema->GetQuotedPrefix() + qtIdent(newtablename);
+ 	}
+ 	else
+ 		qtfullident = targetschema->GetQuotedPrefix() + srcseq->GetQuotedIdentifier();;
+ 	wxString qtfullidentsrc = srcseq->GetQuotedFullIdentifier();
+ 
+ 	srcseq->UpdateValues();
+ 	sql = wxT("-- Sequence: ") + qtfullident + wxT("\n\n")
+ 		  + wxT("-- DROP SEQUENCE ") + qtfullident + wxT(";")
+ 		  + wxT("\n\nCREATE SEQUENCE ") + qtfullident
+ 		  + wxT("\n  INCREMENT ") + srcseq->GetIncrement().ToString()
+ 		  + wxT("\n  MINVALUE ") + srcseq->GetMinValue().ToString()
+ 		  + wxT("\n  MAXVALUE ") + srcseq->GetMaxValue().ToString()
+ 		  + wxT("\n  START ") + srcseq->GetLastValue().ToString()
+ 		  + wxT("\n  CACHE ") + srcseq->GetCacheValue().ToString();
+ 	if (srcseq->GetCycled())
+ 		sql += wxT("\n  CYCLE");
+ 	sql += wxT(";\n")
+ 		   + srcseq->GetOwnerSql(7, 3, wxT("TABLE ") + qtfullident);
+ 
+ 	if (!srcseq->GetConnection()->BackendMinimumVersion(8, 2))
+ 		sql += srcseq->GetGrant(wxT("arwdRxt"), wxT("TABLE ") + qtfullident);
+ 	else
+ 		sql += srcseq->GetGrant(wxT("rwU"), wxT("TABLE ") + qtfullident);
+ 
+ 	wxString comment = srcseq->GetCommentSql();
+ 	comment.Replace(qtfullidentsrc, qtfullident);
+ 	sql += comment;
+ 
+ 	return sql;
+ }
+ 
+ pgSequenceCopyPaste::~pgSequenceCopyPaste()
+ {
+ }
*** a/pgadmin/frm/module.mk
--- b/pgadmin/frm/module.mk
***************
*** 33,39 **** pgadmin3_SOURCES += \
  	$(srcdir)/frm/frmRestore.cpp \
  	$(srcdir)/frm/frmSplash.cpp \
  	$(srcdir)/frm/frmStatus.cpp \
! 	$(srcdir)/frm/plugins.cpp
  
  EXTRA_DIST += \
      $(srcdir)/frm/module.mk
--- 33,40 ----
  	$(srcdir)/frm/frmRestore.cpp \
  	$(srcdir)/frm/frmSplash.cpp \
  	$(srcdir)/frm/frmStatus.cpp \
! 	$(srcdir)/frm/plugins.cpp \
! 	$(srcdir)/frm/frmPasteObject.cpp
  
  EXTRA_DIST += \
      $(srcdir)/frm/module.mk
*** a/pgadmin/include/db/pgConn.h
--- b/pgadmin/include/db/pgConn.h
***************
*** 124,129 **** public:
--- 124,130 ----
  	void Close();
  	bool Reconnect();
  	bool ExecuteVoid(const wxString &sql, bool reportError = true);
+ 	PGresult * ExecuteOptionalResult(const wxString &sql, bool reportError = true);
  	wxString ExecuteScalar(const wxString &sql);
  	pgSet *ExecuteSet(const wxString &sql);
  	wxString GetHostAddr() const
*** a/pgadmin/include/frm/frmMain.h
--- b/pgadmin/include/frm/frmMain.h
***************
*** 24,29 ****
--- 24,30 ----
  #include "frm/frmQuery.h"
  #include "dlg/dlgClasses.h"
  #include "utils/factory.h"
+ #include "frm/frmPasteObject.h"
  
  //
  // This number MUST be incremented if changing any of the default perspectives
***************
*** 75,80 **** enum
--- 76,85 ----
  	NBP_DEPENDENTS
  };
  
+ // custom event declarations
+ BEGIN_DECLARE_EVENT_TYPES()
+ 	DECLARE_EVENT_TYPE(EVT_THREAD_COPYPASTE_UPDATE_GUI, -1)
+ END_DECLARE_EVENT_TYPES()
  
  // Class declarations
  class frmMain : public pgFrame
***************
*** 146,151 **** public:
--- 151,164 ----
  		return pluginsMenu;
  	}
  
+ 	pgObject *GetCopytObject() {
+ 		return copytObject;
+ 	}
+ 
+ 	void SetCopytObject(pgObject *obj) {
+ 		copytObject = obj;
+ 	}
+ 
  	wxString GetCurrentNodePath();
  	bool SetCurrentNode(wxTreeItemId node, const wxString &path);
  
***************
*** 155,160 **** public:
--- 168,178 ----
  
  	void SetItemBackgroundColour(wxTreeItemId item, wxColour colour);
  
+ 	wxString GetNodePath(wxTreeItemId node);
+ 
+ 	void SetCopypasteobject(frmPasteObject* copypasteobject);
+ 	frmPasteObject* GetCopypasteobject() const;
+ 
  private:
  	wxAuiManager manager;
  	ctlTree *browser;
***************
*** 177,182 **** private:
--- 195,203 ----
  	actionFactory *scriptingMenuFactory;
  	actionFactory *viewdataMenuFactory;
  
+ 	pgObject *copytObject;
+ 	frmPasteObject *copypasteobject;
+ 
  	wxStopWatch stopwatch;
  	wxString timermsg;
  	long msgLevel;
***************
*** 233,239 **** private:
  
  	void GetExpandedChildNodes(wxTreeItemId node, wxArrayString &expandedNodes);
  	void ExpandChildNodes(wxTreeItemId node, wxArrayString &expandedNodes);
- 	wxString GetNodePath(wxTreeItemId node);
  
  	void PopulatePluginButtonMenu(wxCommandEvent &event);
  
--- 254,259 ----
***************
*** 243,248 **** private:
--- 263,270 ----
  	void CreatePluginUtility(PluginUtility *util);
  	void ClearPluginUtility(PluginUtility *util);
  
+ 	void OnThreadCopypasteUpdateGUI(wxCommandEvent &ev);
+ 
  	DECLARE_EVENT_TABLE()
  };
  
***************
*** 337,340 **** private:
--- 359,384 ----
  	bool enableButton;
  };
  
+ class copyObjectFactory : public contextActionFactory
+ {
+ public:
+ 	copyObjectFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar);
+ 	wxWindow *StartDialog(frmMain *form, pgObject *obj);
+ 	bool CheckEnable(pgObject *obj);
+ };
+ 
+ class pasteObjectFactory : public contextActionFactory
+ {
+ public:
+ 	pasteObjectFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar);
+ 	wxWindow *StartDialog(frmMain *form, pgObject *obj);
+ 	bool CheckEnable(pgObject *obj);
+ 	ctlMenuToolbar *GetToolbar()
+ 	{
+ 		return toolbar;
+ 	}
+ private:
+ 	ctlMenuToolbar *toolbar;
+ };
+ 
  #endif
*** /dev/null
--- b/pgadmin/include/frm/frmPasteObject.h
***************
*** 0 ****
--- 1,143 ----
+ //////////////////////////////////////////////////////////////////////////
+ //
+ // pgAdmin III - PostgreSQL Tools
+ //
+ // Copyright (C) 2002 - 2011, The pgAdmin Development Team
+ // This software is released under the PostgreSQL Licence
+ //
+ // frmPasteObject.h - Copy/Paste object functions
+ //
+ //////////////////////////////////////////////////////////////////////////
+ 
+ #ifndef FRMPASTEOBJECT_H
+ #define	FRMPASTEOBJECT_H
+ 
+ #include <wx/wx.h>
+ #include <wx/thread.h>
+ 
+ class frmPasteObject;
+ 
+ #include "pgAdmin3.h"
+ #include "frm/frmMain.h"
+ #include "schema/pgObject.h"
+ #include "schema/pgSchema.h"
+ #include "schema/pgTable.h"
+ #include "schema/pgSequence.h"
+ 
+ // Icons
+ #include "images/pasteobject.pngc"
+ 
+ class frmPasteObject;
+ class pgTableCopyPaste;
+ class pgTableCopyPasteArray;
+ 
+ struct transfer_tag
+ {
+ 	frmPasteObject *THIS;
+ 	pgDatabase *srcdatabase;
+ 	wxString srcschemaname;
+ 	pgSchema *srcschema;
+ 	pgDatabase *targetdatabase;
+ 	wxString targetschemaname;
+ 	pgSchema *targetschema;
+ 	pgTableCopyPaste *table;
+ 	wxString createsql;
+ 	wxString searchPath;
+ 	pgConn *sourceconn;
+ 	pgConn *targetconn;
+ 	int numberOfCopypasteTables;
+ };
+ 
+ class copyPasteThread : public wxThread
+ {
+ private:
+ 	struct transfer_tag *transfer;
+ public:
+ 	copyPasteThread(struct transfer_tag *transfer1)
+ 	: wxThread(wxTHREAD_JOINABLE), transfer(transfer1)
+ 	{}
+ 	virtual void *Entry();
+ };
+ 
+ class pgTableCopyPaste
+ {
+ public:
+ 	pgTableCopyPaste(pgTable *srctable, pgSchema *targetschema, wxString copysuffix,
+ 			pgCollection *columns1, pgCollection *constraints1, pgCollection *tables1, pgCollection *sequences1);
+ 	virtual ~pgTableCopyPaste();
+ 	virtual wxString GetSql(ctlTree *browser);
+ 	pgTable *Getsrctable() { return srctable; }
+ 	pgSchema *Gettargetschema() { return targetschema; }
+ 	wxString copysuffix;
+ private:
+ 	pgTable *srctable;
+ 	pgSchema *targetschema;
+ 	pgCollection *columns;
+ 	pgCollection *constraints;
+ 	pgCollection *tables;
+ 	pgCollection *sequences;
+ 	wxString GetSequenceName(wxString definition, bool schemaonly = false);
+ };
+ 
+ class pasteObjectFactory;
+ class frmPasteObject
+ {
+ public:
+ 	frmPasteObject(frmMain *form, pgObject *sourceobj, pgObject *targetobj, pasteObjectFactory *factory);
+ 	int process();
+ 	void pasteNextTable();
+ 	void commitChanges();
+ 	virtual ~frmPasteObject();
+ 	void copyTable(struct transfer_tag *transfer);
+ 	pgSchema *findSchema(pgDatabase *database, wxString schemaname);
+ 	frmMain *Getmainform()
+ 	{
+ 		return mainform;
+ 	}
+ 	pasteObjectFactory *GetFactory()
+ 	{
+ 		return factory;
+ 	}
+     static void setActive(bool active)
+ 	{
+ 		frmPasteObject::active = active;
+ 	}
+     static bool isActive() {
+ 		return frmPasteObject::active;
+ 	}
+ 	int copied;
+ 	pgTableCopyPasteArray *tableCopyPasteArray;
+ 	copyPasteThread *thread;
+ private:
+ 	bool tableExists(pgSchema *srcschema, pgTable *table1);
+ 	void GetLastResultError(pgConn *conn, PGresult *res, const wxString &msg = wxT(""));
+ 	void handleCopyOut(pgConn *conn, wxFile & copystream);
+ 	void handleCopyIn(pgConn *conn, wxFile & copystream, bool isbinary);
+ 	void do_copy(pgConn *conn, wxString & sql, wxFile & copystream);
+ 	void myLogNotice(const wxChar *szFormat, ...);
+ 
+ 	frmMain  *mainform;
+ 	pgObject *sourceobj;
+ 	pgObject *targetobj;
+ 	pgError  lastResultError;
+ 	wxString pastemsg;
+ 	struct transfer_tag *transfer;
+ 	pasteObjectFactory *factory;
+ 	static bool active;
+ };
+ 
+ class pgSequenceCopyPaste
+ {
+ public:
+ 	pgSequenceCopyPaste(pgSequence *srcseq, pgSchema *targetschema, wxString copysuffix);
+ 	virtual ~pgSequenceCopyPaste();
+ 	virtual wxString GetSql(ctlTree *browser);
+ private:
+ 	pgSequence *srcseq;
+ 	pgSchema *targetschema;
+ 	wxString copysuffix;
+ };
+ 
+ WX_DECLARE_OBJARRAY(pgTableCopyPaste, pgTableCopyPasteArray);
+ #endif	/* FRMPASTEOBJECT_H */
+ 
*** a/pgadmin/include/frm/module.mk
--- b/pgadmin/include/frm/module.mk
***************
*** 1,38 ****
! #######################################################################
! #
! # pgAdmin III - PostgreSQL Tools
! # 
! # Copyright (C) 2002 - 2011, The pgAdmin Development Team
! # This software is released under the PostgreSQL Licence
! #
! # module.mk - pgadmin/include/frm/ Makefile fragment
! #
! #######################################################################
! 
! pgadmin3_SOURCES += \
! 	$(srcdir)/include/frm/frmAbout.h \
! 	$(srcdir)/include/frm/frmBackup.h \
! 	$(srcdir)/include/frm/frmBackupGlobals.h \
! 	$(srcdir)/include/frm/frmBackupServer.h \
! 	$(srcdir)/include/frm/frmConfig.h \
! 	$(srcdir)/include/frm/frmEditGrid.h \
! 	$(srcdir)/include/frm/frmExport.h \
!   	$(srcdir)/include/frm/frmGrantWizard.h \
!   	$(srcdir)/include/frm/frmHbaConfig.h \
! 	$(srcdir)/include/frm/frmHint.h \
! 	$(srcdir)/include/frm/frmMain.h \
! 	$(srcdir)/include/frm/frmMainConfig.h \
! 	$(srcdir)/include/frm/frmMaintenance.h \
! 	$(srcdir)/include/frm/frmOptions.h \
! 	$(srcdir)/include/frm/frmPassword.h \
! 	$(srcdir)/include/frm/frmPgpassConfig.h \
! 	$(srcdir)/include/frm/frmQuery.h \
! 	$(srcdir)/include/frm/frmReport.h \
! 	$(srcdir)/include/frm/frmRestore.h \
! 	$(srcdir)/include/frm/frmSplash.h \
! 	$(srcdir)/include/frm/frmStatus.h \
!     $(srcdir)/include/frm/menu.h
! 
! EXTRA_DIST += \
!     $(srcdir)/include/frm/module.mk
! 
--- 1,39 ----
! #######################################################################
! #
! # pgAdmin III - PostgreSQL Tools
! # 
! # Copyright (C) 2002 - 2011, The pgAdmin Development Team
! # This software is released under the PostgreSQL Licence
! #
! # module.mk - pgadmin/include/frm/ Makefile fragment
! #
! #######################################################################
! 
! pgadmin3_SOURCES += \
! 	$(srcdir)/include/frm/frmAbout.h \
! 	$(srcdir)/include/frm/frmBackup.h \
! 	$(srcdir)/include/frm/frmBackupGlobals.h \
! 	$(srcdir)/include/frm/frmBackupServer.h \
! 	$(srcdir)/include/frm/frmConfig.h \
! 	$(srcdir)/include/frm/frmEditGrid.h \
! 	$(srcdir)/include/frm/frmExport.h \
!   	$(srcdir)/include/frm/frmGrantWizard.h \
!   	$(srcdir)/include/frm/frmHbaConfig.h \
! 	$(srcdir)/include/frm/frmHint.h \
! 	$(srcdir)/include/frm/frmMain.h \
! 	$(srcdir)/include/frm/frmMainConfig.h \
! 	$(srcdir)/include/frm/frmMaintenance.h \
! 	$(srcdir)/include/frm/frmOptions.h \
! 	$(srcdir)/include/frm/frmPassword.h \
! 	$(srcdir)/include/frm/frmPgpassConfig.h \
! 	$(srcdir)/include/frm/frmQuery.h \
! 	$(srcdir)/include/frm/frmReport.h \
! 	$(srcdir)/include/frm/frmRestore.h \
! 	$(srcdir)/include/frm/frmSplash.h \
! 	$(srcdir)/include/frm/frmStatus.h \
! 	$(srcdir)/include/frm/menu.h \
! 	$(srcdir)/include/frm/frmPasteObject.h
! 
! EXTRA_DIST += \
!     $(srcdir)/include/frm/module.mk
! 
*** a/pgadmin/include/schema/pgTable.h
--- b/pgadmin/include/schema/pgTable.h
***************
*** 117,122 **** public:
--- 117,126 ----
  		distributionColNumbers = s;    // for Greenplum
  		if (s.Length() > 0) distributionIsRandom = false;
  	}
+ 	bool GetDistributionIsRandom() const
+ 	{
+ 		return distributionIsRandom;    // for Greenplum
+ 	}
  	void iSetDistributionIsRandom()
  	{
  		distributionIsRandom = true;
*** a/pgadmin/schema/pgColumn.cpp
--- b/pgadmin/schema/pgColumn.cpp
***************
*** 298,303 **** wxString pgColumn::GetDefinition()
--- 298,304 ----
  {
  	wxString sql = wxEmptyString;
  	wxString seqDefault1, seqDefault2;
+ 	bool sequence9 = (GetDatabase()->BackendMinimumVersion(9, 0));
  
  	if (table->GetOfTypeOid() == 0)
  		sql += GetQuotedTypename();
***************
*** 324,330 **** wxString pgColumn::GetDefinition()
  
  	if ((sql == wxT("integer") || sql == wxT("bigint") ||
  	        sql == wxT("pg_catalog.integer") || sql == wxT("pg_catalog.bigint"))
! 	        && (GetDefault() == seqDefault1 || GetDefault() == seqDefault2))
  	{
  		if (sql.Right(6) == wxT("bigint"))
  			sql = wxT("bigserial");
--- 325,332 ----
  
  	if ((sql == wxT("integer") || sql == wxT("bigint") ||
  	        sql == wxT("pg_catalog.integer") || sql == wxT("pg_catalog.bigint"))
! 			&& ((sequence9 && !GetSerialSequence().IsEmpty()) ||
! 			(!sequence9 && (GetDefault() == seqDefault1 || GetDefault() == seqDefault2))))
  	{
  		if (sql.Right(6) == wxT("bigint"))
  			sql = wxT("bigserial");