Hi, Here's a new version of copy / paste table(s)!
I hope this is much better than the previous one.. Best regards, Vladimir Kokovic, DP senior, Belgrade, Serbia
frm-module.mk.diff
Description: Binary data
frmMain.cpp.diff
Description: Binary data
frmMain.h.diff
Description: Binary data
//////////////////////////////////////////////////////////////////////////
//
// 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 <errno.h>
frmPasteObject::frmPasteObject(frmMain *form, pgObject *sourceobj, pgObject *targetobj)
{
this->mainform = form;
this->sourceobj= sourceobj;
this->targetobj= targetobj;
}
wxArrayString frmPasteObject::getSchemaTables(pgSchema *srcschema)
{
wxArrayString objArray;
wxString srcname = srcschema->GetQuotedIdentifier();
if (wxString(srcname[0]) == wxT("\""))
{
srcname = srcname.Mid(1, srcname.length() - 2);
srcname.Replace(wxT("'"), wxT("''"), true);
}
wxString query = wxT("SELECT relname ")
wxT("FROM pg_namespace n ")
wxT("LEFT JOIN pg_class c ON n.oid=c.relnamespace AND relkind='r' ")
wxT("WHERE nspname='") + srcname + wxT("'");
query += wxT("ORDER BY relname");
pgSet *objects = srcschema->GetDatabase()->ExecuteSet(query);
if (objects)
{
while (!objects->Eof())
{
if (!objects->GetVal(wxT("relname")).IsNull())
{
objArray.Add(objects->GetVal(wxT("relname")));
}
objects->MoveNext();
}
delete objects;
}
return objArray;
}
bool frmPasteObject::tableExists(pgSchema *srcschema, wxString quotedtablename)
{
wxString nspname = srcschema->GetQuotedIdentifier();
if (wxString(nspname[0]) == wxT("\""))
{
nspname.Replace(wxT("'"), wxT("''"), true);
nspname = nspname.Mid(1, nspname.length() - 2);
}
wxString relname = quotedtablename;
if (wxString(relname[0]) == wxT("\""))
{
relname.Replace(wxT("'"), wxT("''"), true);
relname = relname.Mid(1, relname.length() - 2);
}
wxString query = wxT("SELECT relname ")
wxT("FROM pg_namespace n ")
wxT("LEFT JOIN pg_class c ON n.oid=c.relnamespace AND relkind='r' ")
wxT("WHERE nspname='") + nspname + wxT("' AND relname='") + relname + wxT("'");
wxString result = srcschema->GetDatabase()->ExecuteScalar(query);
return !result.IsEmpty();
}
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;
lastResultError.formatted_msg = wxT("");
for (;;)
{
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 (;;)
{
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++;
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);
}
}
wxArrayString frmPasteObject::stringToArray(wxString & src, wxString pattern)
{
wxArrayString resArray;
int pos, prevpos = 0;
pos = src.find(pattern);
while (pos != wxNOT_FOUND)
{
wxString subs = src.Mid(prevpos, pos - prevpos);
if (!subs.IsEmpty())
{
resArray.Add(subs);
}
resArray.Add(pattern);
prevpos = pos + pattern.length();
pos = src.find(pattern, prevpos);
}
if (!resArray.IsEmpty()){
wxString subs = src.Mid(prevpos);
if (!subs.IsEmpty())
{
resArray.Add(subs);
}
}
return resArray;
}
void frmPasteObject::copyTable(ctlTree *browser, pgSchema *srcschema, pgSchema *targetschema, pgTable *table1)
{
lastResultError.formatted_msg = wxT("");
pgConn *sourceconn = srcschema->GetConnection();
pgConn *targetconn = targetschema->GetConnection();
bool rc;
rc = tableExists(targetschema, table1->GetQuotedIdentifier());
if (rc)
{
lastResultError.formatted_msg = wxT("TABLE EXISTS");
return;
}
rc = targetconn->ExecuteVoid(wxT("BEGIN"));
if (!rc)
{
lastResultError = targetconn->GetLastResultError();
lastResultError.formatted_msg = pastemsg + wxT("\n") + lastResultError.formatted_msg;
return;
}
table1->ShowTreeDetail(browser);
pgCollection *columns = table1->GetColumnCollection(browser);
treeObjectIterator colIt(browser, columns);
pgColumn *column;
wxString colName, defval, serialname;
while ((column = (pgColumn *)colIt.GetNextObject()) != 0)
{
column->ShowTreeDetail(browser);
if (column->GetColNumber() > 0)
{
colName = column->GetName();
serialname = column->GetSerialSequence();
defval = column->GetDefault();
//uniqueid integer DEFAULT nextval(('ps_nalog_uniqueid_seq'::text)::regclass),
if (!defval.IsNull() && serialname.IsEmpty() && defval.StartsWith(wxT("nextval(")))
{
wxString oidstr;
wxString seqsch, seqname;
int pos = wxString(wxT("nextval(")).length();
if (wxString(defval[pos]) == wxT("("))
{
pos++;
}
pos++;
if (wxString(defval[pos]) == wxT("\""))
{
wxString newdefval = defval.Mid(pos + 1);
newdefval.Replace(wxT("\"\""), wxT(" "), true);
int subseq = newdefval.Find(wxT("\"."));
if (subseq == wxNOT_FOUND)
{
lastResultError.formatted_msg = _("Can't find schema sequence delimiter:") + defval;
return;
}
seqsch = defval.Mid(pos + 1, subseq);
seqsch.Replace(wxT("\"\""), wxT("\""), true);
seqsch = wxT("\"") + seqsch + wxT("\"");
subseq += 2;
int subseq1 = newdefval.Mid(subseq + 2).Find(wxT("'::text)"));
if (subseq1 == wxNOT_FOUND)
{
subseq1 = newdefval.Mid(subseq + 2).Find(wxT("'::regclass)"));
if (subseq1 == wxNOT_FOUND)
{
lastResultError.formatted_msg = _("Can't find sequence name:") + defval;
return;
}
}
seqname = defval.Mid(pos + subseq + 1, subseq1 + 2);
if (wxString(seqname[0]) == wxT("\""))
{
seqname = seqname.Mid(1, seqname.length() - 2);
seqname.Replace(wxT("\"\""), wxT("\""), true);
seqname = wxT("\"") + seqname + wxT("\"");
}
}
else
{
bool nextval = false;
wxArrayString resarray = stringToArray(defval, wxT("nextval("));
for(unsigned int j = 0; j < resarray.Count(); j++)
{
wxString part = resarray.Item(j);
if (part == wxT("nextval("))
{
nextval = true;
continue;
}
if (!nextval)
{
continue;
}
nextval = false;
int subseq = part.Find('.');
if (subseq == wxNOT_FOUND)
{
seqsch = wxT("public");
seqname = part;
if (seqname.StartsWith(wxT("(")))
{
seqname = seqname.Mid(1);
}
if (seqname.StartsWith(wxT("'")))
{
seqname = seqname.Mid(1);
}
int pos = seqname.find(wxT("'::text)"));
if (pos == wxNOT_FOUND)
{
pos = seqname.find(wxT("'::regclass)"));
if (pos == wxNOT_FOUND)
{
lastResultError.formatted_msg = _("Can't find sequence name delimiter::regclass)") + defval;
return;
}
}
seqname = seqname.Mid(0, pos);
} else
{
if (part.StartsWith(wxT("(")))
{
part = part.Mid(1);
}
seqsch = part.Mid(1, subseq - 1);
seqname = part.Mid(subseq + 1);
int subseq = seqname.Find(wxT("'"));
if (subseq == wxNOT_FOUND)
{
lastResultError.formatted_msg = _("Can't find sequence name delimiter:") + defval;
return;
}
seqname = seqname.Mid(0, subseq);
}
break;
}
}
if (seqsch == srcschema->GetIdentifier())
{
oidstr = srcschema->GetOidStr();
}
else
{
wxString seqsch1 = seqsch;
if (wxString(seqsch[0]) == wxT("\""))
{
seqsch1 = seqsch.Mid(1, seqsch.length() - 2);
}
pgSet *seqcat = srcschema->GetDatabase()->ExecuteSet(
wxT("SELECT oid\n")
wxT(" FROM pg_namespace\n")
wxT(" WHERE nspname = '") + seqsch1 + wxT("'\n"));
if (seqcat)
{
OID nspoid = seqcat->GetOid(wxT("oid"));
oidstr = NumToStr(nspoid) + wxT("::oid");
delete seqcat;
} else
{
lastResultError = sourceconn->GetLastResultError();
lastResultError.formatted_msg = pastemsg + wxT("\n") + lastResultError.formatted_msg;
return;
}
}
wxLongLong lastValue, minValue, maxValue, cacheValue, increment;
bool cycled, called;
wxString owner, comment, acl;
pgSequence seq = pgSequence(srcschema, seqname);
pgSet *seqcat = srcschema->GetDatabase()->ExecuteSet(
wxT("SELECT pg_get_userbyid(relowner) AS seqowner, relacl, description\n")
wxT(" FROM pg_class cl\n")
wxT(" LEFT OUTER JOIN pg_description des ON des.objoid=cl.oid\n")
wxT(" WHERE relkind = 'S' AND relnamespace = ") + oidstr +
wxT(" AND relname = '") + seqname + wxT("'\n"));
if (seqcat)
{
comment = seqcat->GetVal(wxT("description"));
owner = seqcat->GetVal(wxT("seqowner"));
acl = seqcat->GetVal(wxT("relacl"));
delete seqcat;
} else
{
lastResultError = sourceconn->GetLastResultError();
lastResultError.formatted_msg = pastemsg + wxT("\n") + lastResultError.formatted_msg;
return;
}
seq.iSetAcl(acl);
pgSet *sequence = srcschema->GetDatabase()->ExecuteSet(
wxT("SELECT last_value, min_value, max_value, cache_value, is_cycled, increment_by, is_called\n")
wxT(" FROM ") + seq.GetQuotedFullIdentifier());
if (sequence)
{
lastValue = sequence->GetLongLong(wxT("last_value"));
minValue = sequence->GetLongLong(wxT("min_value"));
maxValue = sequence->GetLongLong(wxT("max_value"));
cacheValue = sequence->GetLongLong(wxT("cache_value"));
increment = sequence->GetLongLong(wxT("increment_by"));
cycled = sequence->GetBool(wxT("is_cycled"));
called = sequence->GetBool(wxT("is_called"));
delete sequence;
} else
{
lastResultError = sourceconn->GetLastResultError();
lastResultError.formatted_msg = pastemsg + wxT("\n") + lastResultError.formatted_msg;
return;
}
wxString QuotedFullIdentifier = targetschema->GetQuotedIdentifier() + wxT(".");
QuotedFullIdentifier += seqname;
wxString sql = wxT("-- Sequence: ") + QuotedFullIdentifier + wxT("\n\n")
+ wxT("-- DROP SEQUENCE ") + QuotedFullIdentifier + wxT(";")
+ wxT("\n\nCREATE SEQUENCE ") + QuotedFullIdentifier
+ wxT("\n INCREMENT ") + increment.ToString()
+ wxT("\n MINVALUE ") + minValue.ToString()
+ wxT("\n MAXVALUE ") + maxValue.ToString()
+ wxT("\n START ") + lastValue.ToString()
+ wxT("\n CACHE ") + cacheValue.ToString();
if (cycled)
sql += wxT("\n CYCLE");
sql += wxT(";\nALTER TABLE ")
+ QuotedFullIdentifier + wxT(" OWNER TO ") + qtIdent(owner) + wxT(";\n");
if (!seq.GetConnection()->BackendMinimumVersion(8, 2))
sql += seq.GetGrant(wxT("arwdRxt"), wxT("TABLE ") + QuotedFullIdentifier);
else
sql += seq.GetGrant(wxT("rwU"), wxT("TABLE ") + QuotedFullIdentifier);
wxString cmt;
if (!comment.IsNull())
{
cmt = wxT("COMMENT ON SEQUENCE ") + QuotedFullIdentifier
+ wxT(" IS ") + targetschema->qtDbString(comment) + wxT(";\n");
sql += cmt;
}
rc = targetconn->ExecuteVoid(sql, false);
if (!rc)
{
lastResultError = targetconn->GetLastResultError();
lastResultError.formatted_msg = pastemsg + wxT("\n") + lastResultError.formatted_msg;
return;
}
}
}
}
{
wxString createsql = table1->GetSql(browser);
createsql.Replace(srcschema->GetQuotedIdentifier() + wxT("."), targetschema->GetQuotedIdentifier() + wxT("."), true);
wxString createsql1;
bool nextval = false;
wxArrayString resarray = stringToArray(createsql, wxT("nextval("));
if (resarray.Count() > 1)
{
for(unsigned int j = 0; j < resarray.Count(); j++)
{
wxString token = resarray.Item(j);
if (token == wxT("nextval("))
{
createsql1 += token;
nextval = true;
}
else
{
if (!nextval)
{
createsql1 += token;
continue;
}
else
{
nextval = false;
int pos = token.find(wxT("'::text)"));
if (pos == wxNOT_FOUND)
{
pos = token.find(wxT("'::regclass)"));
if (pos == wxNOT_FOUND)
{
createsql1 += token;
continue;
}
}
wxString token1 = token.Mid(0, pos);
bool haspar = false;
if (token1.StartsWith(wxT("(")))
{
token1 = token1.Mid(1);
haspar = true;
}
token1 = token1.Mid(1);
wxString token2 = token1;
token2.Replace(wxT("\"\""), wxT(" "), true);
int subseq = token2.Find(wxT("\"."));
if (subseq == wxNOT_FOUND)
{
int subseq = token2.Find(wxT("."));
if (subseq == wxNOT_FOUND)
{
token1 = targetschema->GetQuotedIdentifier() + wxT(".") + token1;
}
else
{
token1 = targetschema->GetQuotedIdentifier() + wxT(".") + token1.Mid(subseq + 1);
}
}
else
{
token1 = targetschema->GetQuotedIdentifier() + wxT(".") + token1.Mid(subseq + 2);
}
token1.Replace(wxT("'"), wxT("''"), true);
token1 = wxT("'") + token1;
if (haspar)
{
token1 = wxT("(") + token1;
}
token = token1 + token.Mid(pos);
createsql1 += token;
}
}
}
createsql = createsql1;
}
wxString searchPath = targetconn->ExecuteScalar(wxT("SHOW search_path"));
createsql = wxT("SET search_path=") + targetschema->GetQuotedIdentifier() + wxT(";") + createsql;
rc = targetconn->ExecuteVoid(createsql, false);
if (!rc)
{
lastResultError = targetconn->GetLastResultError();
lastResultError.formatted_msg = pastemsg + wxT("\n") + lastResultError.formatted_msg;
return;
}
if (!searchPath.IsEmpty())
{
rc = targetconn->ExecuteVoid(wxT("SET search_path=") + searchPath, false);
if (!rc)
{
lastResultError = targetconn->GetLastResultError();
lastResultError.formatted_msg = pastemsg + wxT("\n") + lastResultError.formatted_msg;
return;
}
}
if (sourceconn->GetDbname() == targetconn->GetDbname() && sourceconn->GetHost() == targetconn->GetHost())
{
wxString copysql =
wxT("\nINSERT INTO ")
+ targetschema->GetQuotedPrefix() + table1->GetQuotedIdentifier()
+ wxT(" (SELECT * FROM ")
+ srcschema->GetQuotedPrefix() + table1->GetQuotedIdentifier()
+ wxT(")\n\n");
rc = targetconn->ExecuteVoid(copysql, false);
if (!rc)
{
lastResultError = targetconn->GetLastResultError();
lastResultError.formatted_msg = pastemsg + wxT("\n") + lastResultError.formatted_msg;
return;
}
}
else
{
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;
}
wxString copysql =
wxT("COPY ")
+ srcschema->GetQuotedPrefix() + table1->GetQuotedIdentifier()
+ wxT(" TO STDOUT");
do_copy(sourceconn, copysql, tmpFile);
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;
}
copysql =
wxT("COPY ")
+ targetschema->GetQuotedPrefix() + table1->GetQuotedIdentifier()
+ wxT(" FROM STDIN");
do_copy(targetconn, copysql, tmpFile);
}
tmpFile.Close();
wxRemoveFile(tmpFilename);
}
}
}
void frmPasteObject::process()
{
if (!sourceobj || !targetobj)
{
return;
}
wxArrayString srcObjArray;
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;
}
}
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;
}
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;
}
}
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;
}
if (srcschema)
{
srcObjArray = getSchemaTables(srcschema);
}
else
{
srcObjArray.Add(table->GetIdentifier());
srcschema = table->GetSchema();
}
if (srcschema->GetQuotedIdentifier() == targetschema->GetQuotedIdentifier())
{
wxMessageBox(_("Source and target schema should be different schema for paste table(s) operation !"));
return;
}
srcschema->ShowTreeDetail(mainform->GetBrowser());
wxString msg;
int copied = 0;
for(unsigned int i = 0; i < srcObjArray.Count(); i++)
{
pastemsg = _("COPY TABLE:") +
srcschema->GetDatabase()->GetQuotedIdentifier() + wxT(".") + srcschema->GetQuotedIdentifier() + wxT(".") +
srcObjArray.Item(i) +
_(" INTO:") + targetschema->GetDatabase()->GetQuotedIdentifier() + wxT(".") + targetschema->GetQuotedIdentifier();
mainform->GetStatusBar()->SetStatusText(pastemsg, 1);
pastemsg = _("COPY TABLE:\n") +
srcschema->GetDatabase()->GetQuotedIdentifier() + wxT(".") + srcschema->GetQuotedIdentifier() + wxT(".") +
srcObjArray.Item(i) +
_("\nINTO:\n") + targetschema->GetDatabase()->GetQuotedIdentifier() + wxT(".") + targetschema->GetQuotedIdentifier();
pgTable *table1 = 0;
wxTreeItemIdValue schemacookie;
wxTreeItemId schemaid = srcschema->GetId();
wxTreeItemId schemaitem = mainform->GetBrowser()->GetFirstChild(schemaid, schemacookie);
bool found = false;
while (schemaitem && !found)
{
pgObject *obj = mainform->GetBrowser()->GetObject(schemaitem);
if (obj && obj->GetMetaType() == PGM_TABLE)
{
wxTreeItemIdValue tablecookie;
wxTreeItemId tableitem = mainform->GetBrowser()->GetFirstChild(obj->GetId(), tablecookie);
while (tableitem)
{
table1 = (pgTable *)mainform->GetBrowser()->GetObject(tableitem);
if (table1->GetIdentifier() == srcObjArray.Item(i))
{
found = true;
break;
}
table1 = 0;
tableitem = mainform->GetBrowser()->GetNextChild(obj->GetId(), tablecookie);
}
}
schemaitem = mainform->GetBrowser()->GetNextChild(schemaid, schemacookie);
}
if (!table1)
{
msg = _("WARNING SOURCE TABLE DISAPEARED:\n") +
srcschema->GetDatabase()->GetQuotedIdentifier() + wxT(".") + srcschema->GetQuotedIdentifier() + wxT(".") +
srcObjArray.Item(i);
continue;
}
else
{
copyTable(mainform->GetBrowser(), srcschema, targetschema, table1);
if (lastResultError.formatted_msg == wxT("TABLE EXISTS"))
{
continue;
}
if (lastResultError.formatted_msg.IsEmpty())
{
targetschema->GetConnection()->ExecuteVoid(wxT("COMMIT"));
lastResultError = targetschema->GetConnection()->GetLastResultError();
if (!lastResultError.formatted_msg.IsEmpty())
{
lastResultError.formatted_msg = pastemsg + wxT("\n") + lastResultError.formatted_msg;
msg = lastResultError.formatted_msg;
}
}
else
{
targetschema->GetConnection()->ExecuteVoid(wxT("ROLLBACK"));
msg = lastResultError.formatted_msg;
}
if (!lastResultError.formatted_msg.IsEmpty())
{
wxMessageBox(msg,
_("Cannot paste table:") +
targetschema->GetDatabase()->GetQuotedIdentifier() + wxT(".") + targetschema->GetQuotedIdentifier() +
wxT(".") + table1->GetQuotedIdentifier(),
wxOK | wxICON_ERROR);
continue;
}
}
copied++;
}
msg = wxString::Format(_("%d of %d TABLE(s) COPIED FROM %s TO %s"), copied, srcObjArray.Count(),
(srcschema->GetDatabase()->GetQuotedIdentifier() + wxT(".") + srcschema->GetQuotedIdentifier()).c_str(),
(targetschema->GetDatabase()->GetQuotedIdentifier() + wxT(".") + targetschema->GetQuotedIdentifier()).c_str());
if (copied) {
mainform->Refresh(targetobj);
}
mainform->GetStatusBar()->SetStatusText(msg, 1);
}
frmPasteObject::~frmPasteObject()
{
}
//////////////////////////////////////////////////////////////////////////
//
// 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 "pgAdmin3.h"
#include "frm/frmMain.h"
#include "schema/pgObject.h"
#include "schema/pgSchema.h"
#include "schema/pgTable.h"
class frmPasteObject
{
public:
frmPasteObject(frmMain *form, pgObject *sourceobj, pgObject *targetobj);
void process();
virtual ~frmPasteObject();
private:
wxArrayString getSchemaTables(pgSchema *srcschema);
bool tableExists(pgSchema *srcschema, wxString quotedtablename);
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);
wxArrayString stringToArray(wxString & src, wxString pattern);
void copyTable(ctlTree *browser, pgSchema *srcschema, pgSchema *targetschema, pgTable *table1);
frmMain *mainform;
pgObject *sourceobj;
pgObject *targetobj;
pgError lastResultError;
wxString pastemsg;
};
#endif /* FRMPASTEOBJECT_H */
pgColumn.cpp.diff
Description: Binary data
pgConn.cpp.diff
Description: Binary data
pgConn.h.diff
Description: Binary data
-- Sent via pgadmin-hackers mailing list ([email protected]) To make changes to your subscription: http://www.postgresql.org/mailpref/pgadmin-hackers
