📄 pg_backup_db.c
字号:
} /* We found an unquoted newline */ qry[loc] = '\0'; appendPQExpBuffer(AH->pgCopyBuf, "%s\n", qry); isEnd = (strcmp(AH->pgCopyBuf->data, "\\.\n") == 0); /*--------- * fprintf(stderr, "Sending '%s' via * COPY (at end = %d)\n\n", AH->pgCopyBuf->data, isEnd); *--------- */ if (PQputline(AH->connection, AH->pgCopyBuf->data) != 0) die_horribly(AH, modulename, "error returned by PQputline\n"); resetPQExpBuffer(AH->pgCopyBuf); /* * fprintf(stderr, "Buffer is '%s'\n", AH->pgCopyBuf->data); */ if (isEnd) { if (PQendcopy(AH->connection) != 0) die_horribly(AH, modulename, "error returned by PQendcopy\n"); AH->pgCopyIn = 0; } return qry + loc + 1;}/* * Used by ExecuteSqlCommandBuf to send one buffered line of SQL (not data for the copy command). */static char *_sendSQLLine(ArchiveHandle *AH, char *qry, char *eos){ int pos = 0; /* Current position */ /* * The following is a mini state machine to assess the end of an SQL * statement. It really only needs to parse good SQL, or at least * that's the theory... End-of-statement is assumed to be an unquoted, * un commented semi-colon. */ /* * fprintf(stderr, "Buffer at start is: '%s'\n\n", AH->sqlBuf->data); */ for (pos = 0; pos < (eos - qry); pos++) { appendPQExpBufferChar(AH->sqlBuf, qry[pos]); /* fprintf(stderr, " %c",qry[pos]); */ switch (AH->sqlparse.state) { case SQL_SCAN: /* Default state == 0, set in _allocAH */ if (qry[pos] == ';' && AH->sqlparse.braceDepth == 0) { /* Send It & reset the buffer */ /* * fprintf(stderr, " sending: '%s'\n\n", * AH->sqlBuf->data); */ ExecuteSqlCommand(AH, AH->sqlBuf, "could not execute query", false); resetPQExpBuffer(AH->sqlBuf); AH->sqlparse.lastChar = '\0'; /* * Remove any following newlines - so that embedded * COPY commands don't get a starting newline. */ pos++; for (; pos < (eos - qry) && qry[pos] == '\n'; pos++); /* We've got our line, so exit */ return qry + pos; } else { if (qry[pos] == '"' || qry[pos] == '\'') { /* fprintf(stderr,"[startquote]\n"); */ AH->sqlparse.state = SQL_IN_QUOTE; AH->sqlparse.quoteChar = qry[pos]; AH->sqlparse.backSlash = 0; } else if (qry[pos] == '-' && AH->sqlparse.lastChar == '-') AH->sqlparse.state = SQL_IN_SQL_COMMENT; else if (qry[pos] == '*' && AH->sqlparse.lastChar == '/') AH->sqlparse.state = SQL_IN_EXT_COMMENT; else if (qry[pos] == '(') AH->sqlparse.braceDepth++; else if (qry[pos] == ')') AH->sqlparse.braceDepth--; AH->sqlparse.lastChar = qry[pos]; } break; case SQL_IN_SQL_COMMENT: if (qry[pos] == '\n') AH->sqlparse.state = SQL_SCAN; break; case SQL_IN_EXT_COMMENT: if (AH->sqlparse.lastChar == '*' && qry[pos] == '/') AH->sqlparse.state = SQL_SCAN; break; case SQL_IN_QUOTE: if (!AH->sqlparse.backSlash && AH->sqlparse.quoteChar == qry[pos]) { /* fprintf(stderr,"[endquote]\n"); */ AH->sqlparse.state = SQL_SCAN; } else { if (qry[pos] == '\\') { if (AH->sqlparse.lastChar == '\\') AH->sqlparse.backSlash = !AH->sqlparse.backSlash; else AH->sqlparse.backSlash = 1; } else AH->sqlparse.backSlash = 0; } break; } AH->sqlparse.lastChar = qry[pos]; /* fprintf(stderr, "\n"); */ } /* * If we get here, we've processed entire string with no complete SQL * stmt */ return eos;}/* Convenience function to send one or more queries. Monitors result to handle COPY statements */intExecuteSqlCommandBuf(ArchiveHandle *AH, void *qryv, size_t bufLen){ char *qry = (char *) qryv; char *eos = qry + bufLen; /* * fprintf(stderr, "\n\n*****\n * Buffer:\n\n%s\n*******************\n\n", qry); */ /* Could switch between command and COPY IN mode at each line */ while (qry < eos) { if (AH->pgCopyIn) qry = _sendCopyLine(AH, qry, eos); else qry = _sendSQLLine(AH, qry, eos); } return 1;}voidFixupBlobRefs(ArchiveHandle *AH, TocEntry *te){ PQExpBuffer tblName; PQExpBuffer tblQry; PGresult *res, *uRes; int i, n; if (strcmp(te->tag, BLOB_XREF_TABLE) == 0) return; tblName = createPQExpBuffer(); tblQry = createPQExpBuffer(); if (te->namespace && strlen(te->namespace) > 0) appendPQExpBuffer(tblName, "%s.", fmtId(te->namespace)); appendPQExpBuffer(tblName, "%s", fmtId(te->tag)); appendPQExpBuffer(tblQry, "SELECT a.attname, t.typname FROM " "pg_catalog.pg_attribute a, pg_catalog.pg_type t " "WHERE a.attnum > 0 AND a.attrelid = '%s'::pg_catalog.regclass " "AND a.atttypid = t.oid AND t.typname in ('oid', 'lo')", tblName->data); res = PQexec(AH->blobConnection, tblQry->data); if (!res) die_horribly(AH, modulename, "could not find OID columns of table \"%s\": %s", te->tag, PQerrorMessage(AH->connection)); if ((n = PQntuples(res)) == 0) { /* nothing to do */ ahlog(AH, 1, "no OID type columns in table %s\n", te->tag); } for (i = 0; i < n; i++) { char *attr; char *typname; bool typeisoid; attr = PQgetvalue(res, i, 0); typname = PQgetvalue(res, i, 1); typeisoid = (strcmp(typname, "oid") == 0); ahlog(AH, 1, "fixing large object cross-references for %s.%s\n", te->tag, attr); resetPQExpBuffer(tblQry); /* * Note: we use explicit typename() cast style here because if we * are dealing with a dump from a pre-7.3 database containing LO * columns, the dump probably will not have CREATE CAST commands * for lo<->oid conversions. What it will have is functions, * which we will invoke as functions. */ /* Can't use fmtId more than once per call... */ appendPQExpBuffer(tblQry, "UPDATE %s SET %s = ", tblName->data, fmtId(attr)); if (typeisoid) appendPQExpBuffer(tblQry, "%s.newOid", BLOB_XREF_TABLE); else appendPQExpBuffer(tblQry, "%s(%s.newOid)", fmtId(typname), BLOB_XREF_TABLE); appendPQExpBuffer(tblQry, " FROM %s WHERE %s.oldOid = ", BLOB_XREF_TABLE, BLOB_XREF_TABLE); if (typeisoid) appendPQExpBuffer(tblQry, "%s.%s", tblName->data, fmtId(attr)); else appendPQExpBuffer(tblQry, "oid(%s.%s)", tblName->data, fmtId(attr)); ahlog(AH, 10, "SQL: %s\n", tblQry->data); uRes = PQexec(AH->blobConnection, tblQry->data); if (!uRes) die_horribly(AH, modulename, "could not update column \"%s\" of table \"%s\": %s", attr, te->tag, PQerrorMessage(AH->blobConnection)); if (PQresultStatus(uRes) != PGRES_COMMAND_OK) die_horribly(AH, modulename, "error while updating column \"%s\" of table \"%s\": %s", attr, te->tag, PQerrorMessage(AH->blobConnection)); PQclear(uRes); } PQclear(res); destroyPQExpBuffer(tblName); destroyPQExpBuffer(tblQry);}/********** * Convenient SQL calls **********/voidCreateBlobXrefTable(ArchiveHandle *AH){ PQExpBuffer qry = createPQExpBuffer(); /* IF we don't have a BLOB connection, then create one */ if (!AH->blobConnection) AH->blobConnection = _connectDB(AH, NULL, NULL); ahlog(AH, 1, "creating table for large object cross-references\n"); appendPQExpBuffer(qry, "Create Temporary Table %s(oldOid pg_catalog.oid, newOid pg_catalog.oid);", BLOB_XREF_TABLE); ExecuteSqlCommand(AH, qry, "could not create large object cross-reference table", true); resetPQExpBuffer(qry); appendPQExpBuffer(qry, "Create Unique Index %s_ix on %s(oldOid)", BLOB_XREF_TABLE, BLOB_XREF_TABLE); ExecuteSqlCommand(AH, qry, "could not create index on large object cross-reference table", true); destroyPQExpBuffer(qry);}voidInsertBlobXref(ArchiveHandle *AH, Oid old, Oid new){ PQExpBuffer qry = createPQExpBuffer(); appendPQExpBuffer(qry, "Insert Into %s(oldOid, newOid) Values ('%u', '%u');", BLOB_XREF_TABLE, old, new); ExecuteSqlCommand(AH, qry, "could not create large object cross-reference entry", true); destroyPQExpBuffer(qry);}voidStartTransaction(ArchiveHandle *AH){ PQExpBuffer qry = createPQExpBuffer(); appendPQExpBuffer(qry, "Begin;"); ExecuteSqlCommand(AH, qry, "could not start database transaction", false); AH->txActive = true; destroyPQExpBuffer(qry);}voidStartTransactionXref(ArchiveHandle *AH){ PQExpBuffer qry = createPQExpBuffer(); appendPQExpBuffer(qry, "Begin;"); ExecuteSqlCommand(AH, qry, "could not start transaction for large object cross-references", true); AH->blobTxActive = true; destroyPQExpBuffer(qry);}voidCommitTransaction(ArchiveHandle *AH){ PQExpBuffer qry = createPQExpBuffer(); appendPQExpBuffer(qry, "Commit;"); ExecuteSqlCommand(AH, qry, "could not commit database transaction", false); AH->txActive = false; destroyPQExpBuffer(qry);}voidCommitTransactionXref(ArchiveHandle *AH){ PQExpBuffer qry = createPQExpBuffer(); appendPQExpBuffer(qry, "Commit;"); ExecuteSqlCommand(AH, qry, "could not commit transaction for large object cross-references", true); AH->blobTxActive = false; destroyPQExpBuffer(qry);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -