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 (pgadmin-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgadmin-hackers