It includes

-Support for mirroring tables in different Schema's
-Improved documentation for compiling with 7.1.x and 7.2.x
-Fixes a buffer overrun bug.

Steven Singer
This commit is contained in:
Bruce Momjian 2002-10-19 02:16:40 +00:00
parent cabad378fc
commit 8e6b5c8b27
4 changed files with 60 additions and 20 deletions

View File

@ -19,7 +19,7 @@
# GNU General Public License for more details. # GNU General Public License for more details.
# #
############################################################################## ##############################################################################
# $Id: DBMirror.pl,v 1.2 2002/10/18 18:41:19 momjian Exp $ # $Id: DBMirror.pl,v 1.3 2002/10/19 02:16:40 momjian Exp $
# #
############################################################################## ##############################################################################
@ -387,7 +387,7 @@ sub mirrorInsert($$$$$) {
#Now build the insert query. #Now build the insert query.
my $insertQuery = "INSERT INTO \"$tableName\" ("; my $insertQuery = "INSERT INTO $tableName (";
my $valuesQuery = ") VALUES ("; my $valuesQuery = ") VALUES (";
foreach $column (keys (%recordValues)) { foreach $column (keys (%recordValues)) {
if($firstIteration==0) { if($firstIteration==0) {
@ -468,7 +468,7 @@ sub mirrorDelete($$$$$) {
%dataHash = extractData($pendingResult,$currentTuple); %dataHash = extractData($pendingResult,$currentTuple);
my $counter=0; my $counter=0;
my $deleteQuery = "DELETE FROM \"$tableName\" WHERE "; my $deleteQuery = "DELETE FROM $tableName WHERE ";
foreach $currentField (keys %dataHash) { foreach $currentField (keys %dataHash) {
if($firstField==0) { if($firstField==0) {
$deleteQuery .= " AND "; $deleteQuery .= " AND ";
@ -553,7 +553,7 @@ sub mirrorUpdate($$$$$) {
my $counter; my $counter;
my $quotedValue; my $quotedValue;
my $updateQuery = "UPDATE \"$tableName\" SET "; my $updateQuery = "UPDATE $tableName SET ";
my $currentField; my $currentField;

View File

@ -6,7 +6,8 @@ CREATE FUNCTION "recordchange" () RETURNS trigger AS
CREATE TABLE "MirrorHost" ( CREATE TABLE "MirrorHost" (
"MirrorHostId" serial, "MirrorHostId" serial,
"HostName" varchar NOT NULL "HostName" varchar NOT NULL,
PRIMARY KEY("MirrorHostId")
); );

View File

@ -46,6 +46,7 @@ Pending tables.
Installation Instructions Installation Instructions
------------------------------------------------------------------------ ------------------------------------------------------------------------
1) Compile pending.c 1) Compile pending.c
The file pending.c contains the recordchange trigger. This runs every The file pending.c contains the recordchange trigger. This runs every
@ -54,20 +55,35 @@ time a row inside of a table being mirrored changes.
To build the trigger run make on the "Makefile" in the DBMirror directory. To build the trigger run make on the "Makefile" in the DBMirror directory.
The Makefile supplied assumes that the postgres include files are in Postgres-7.3 Make Instructions:
/usr/local/pgsql/include/server.
If you have already run "configure" in the pgsql-server directory
then run "make" in the dbmirror directory to compile the trigger.
Postgres-7.1 & Postgres-7.2 Make Instructions:
The included Makefile is not compatible with postgres 7.1 and 7.2
The trigger will need to be built by hand.
Run the following commands
gcc -fpic -I/usr/local/pgsql/include/server -c pending.c -DNOSCHEMAS
ld -shared -o pending.so pending.o
Assuming the postgres include files are in /usr/local/pgsql/include/server.
Postgres-7.1.x installations should change this to Postgres-7.1.x installations should change this to
/usr/local/pgsql/include (The server part is for 7.2+) /usr/local/pgsql/include (The server part is for 7.2+)
If you have installed the postgres include files to another location then If you have installed the postgres include files to another location then
modify the Makefile to reflect this. modify the include path to reflect this.
The trigger requires that all postgres headers be installed, this is Compiling the trigger by hand requires that all postgres headers be installed
accomplished in postgresql(7.1 or 7.2) by running "make install-all-headers" ,this is accomplished in postgresql(7.1 or 7.2) by running
in the postgres source directory. "make install-all-headers" in the postgres source directory.
The Makefile should create a file named pending.so that contains the trigger.
You should now have a file named pending.so that contains the trigger.
Install this file in /usr/local/pgsql/lib (or another suitable location). Install this file in /usr/local/pgsql/lib (or another suitable location).
@ -93,6 +109,15 @@ To execute the script use psql as follows
where MyDatabaseName is the name of the database you wish to install mirroring where MyDatabaseName is the name of the database you wish to install mirroring
on(Your master). on(Your master).
Postgres-7.1 and 7.2 Notes:
-The syntax for creating a trigger function changed in Postgres-7.3.
Change the line in MirrorSetup.sql from
CREATE FUNCTION "recordchange" () RETURNS trigger AS
to
CREATE FUNCTION "recordchange" () RETURNS OPAQUE AS
3) Create slaveDatabase.conf files. 3) Create slaveDatabase.conf files.
@ -199,6 +224,7 @@ RedHat Linux 7.1 & 6.2
Mandrake Linux 8.0(Limited Testing) Mandrake Linux 8.0(Limited Testing)
-Postgres 7.2 -Postgres 7.2
-Postgres 7.3
-Perl 5.6 -Perl 5.6

View File

@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
* pending.c * pending.c
* $Id: pending.c,v 1.5 2002/09/26 05:24:30 momjian Exp $ * $Id: pending.c,v 1.6 2002/10/19 02:16:40 momjian Exp $
* *
* This file contains a trigger for Postgresql-7.x to record changes to tables * This file contains a trigger for Postgresql-7.x to record changes to tables
* to a pending table for mirroring. * to a pending table for mirroring.
@ -22,7 +22,7 @@
#include <executor/spi.h> #include <executor/spi.h>
#include <commands/trigger.h> #include <commands/trigger.h>
#include <utils/lsyscache.h>
enum FieldUsage enum FieldUsage
{ {
PRIMARY = 0, NONPRIMARY, ALL, NUM_FIELDUSAGE PRIMARY = 0, NONPRIMARY, ALL, NUM_FIELDUSAGE
@ -46,7 +46,7 @@ char *packageData(HeapTuple tTupleData, TupleDesc tTupleDecs,
#define BUFFER_SIZE 256 #define BUFFER_SIZE 256
#define MAX_OID_LEN 10 #define MAX_OID_LEN 10
#define DEBUG_OUTPUT
extern Datum recordchange(PG_FUNCTION_ARGS); extern Datum recordchange(PG_FUNCTION_ARGS);
@ -69,7 +69,8 @@ recordchange(PG_FUNCTION_ARGS)
HeapTuple retTuple = NULL; HeapTuple retTuple = NULL;
char *tblname; char *tblname;
char op = 0; char op = 0;
char *schemaname;
char *fullyqualtblname;
if (fcinfo->context != NULL) if (fcinfo->context != NULL)
{ {
@ -81,6 +82,16 @@ recordchange(PG_FUNCTION_ARGS)
trigdata = (TriggerData *) fcinfo->context; trigdata = (TriggerData *) fcinfo->context;
/* Extract the table name */ /* Extract the table name */
tblname = SPI_getrelname(trigdata->tg_relation); tblname = SPI_getrelname(trigdata->tg_relation);
#ifndef NOSCHEMAS
schemaname = get_namespace_name(RelationGetNamespace(trigdata->tg_relation));
fullyqualtblname = SPI_palloc(strlen(tblname) +
strlen(schemaname) + 4);
sprintf(fullyqualtblname,"\"%s\".\"%s\"",
schemaname,tblname);
#else
fullyqualtblname = SPI_palloc(strlen(tblname+3));
sprintf(fullyqualtblname,"\"%s\"",tblname);
#endif
tupdesc = trigdata->tg_relation->rd_att; tupdesc = trigdata->tg_relation->rd_att;
if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event)) if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
{ {
@ -103,7 +114,7 @@ recordchange(PG_FUNCTION_ARGS)
op = 'd'; op = 'd';
} }
if (storePending(tblname, beforeTuple, afterTuple, tupdesc, trigdata, op)) if (storePending(fullyqualtblname, beforeTuple, afterTuple, tupdesc, trigdata, op))
{ {
/* An error occoured. Skip the operation. */ /* An error occoured. Skip the operation. */
elog(ERROR, "Operation could not be mirrored"); elog(ERROR, "Operation could not be mirrored");
@ -113,6 +124,7 @@ recordchange(PG_FUNCTION_ARGS)
#if defined DEBUG_OUTPUT #if defined DEBUG_OUTPUT
elog(NOTICE, "Returning on success"); elog(NOTICE, "Returning on success");
#endif #endif
SPI_pfree(fullyqualtblname);
SPI_finish(); SPI_finish();
return PointerGetDatum(retTuple); return PointerGetDatum(retTuple);
} }
@ -417,7 +429,7 @@ packageData(HeapTuple tTupleData, TupleDesc tTupleDesc,
#if defined DEBUG_OUTPUT #if defined DEBUG_OUTPUT
elog(NOTICE, cpFieldName); elog(NOTICE, cpFieldName);
#endif #endif
while (iDataBlockSize - iUsedDataBlock < strlen(cpFieldName) + 4) while (iDataBlockSize - iUsedDataBlock < strlen(cpFieldName) + 6)
{ {
cpDataBlock = SPI_repalloc(cpDataBlock, iDataBlockSize + BUFFER_SIZE); cpDataBlock = SPI_repalloc(cpDataBlock, iDataBlockSize + BUFFER_SIZE);
iDataBlockSize = iDataBlockSize + BUFFER_SIZE; iDataBlockSize = iDataBlockSize + BUFFER_SIZE;
@ -436,7 +448,7 @@ packageData(HeapTuple tTupleData, TupleDesc tTupleDesc,
} }
else else
{ {
*cpFormatedPtr = ' '; sprintf(cpFormatedPtr," ");
iUsedDataBlock++; iUsedDataBlock++;
cpFormatedPtr++; cpFormatedPtr++;
continue; continue;
@ -484,7 +496,8 @@ packageData(HeapTuple tTupleData, TupleDesc tTupleDesc,
if (tpPKeys != NULL) if (tpPKeys != NULL)
SPI_pfree(tpPKeys); SPI_pfree(tpPKeys);
#if defined DEBUG_OUTPUT #if defined DEBUG_OUTPUT
elog(NOTICE, "Returning"); elog(NOTICE, "Returning: DataBlockSize:%d iUsedDataBlock:%d",iDataBlockSize,
iUsedDataBlock);
#endif #endif
memset(cpDataBlock + iUsedDataBlock, 0, iDataBlockSize - iUsedDataBlock); memset(cpDataBlock + iUsedDataBlock, 0, iDataBlockSize - iUsedDataBlock);