From 8e6b5c8b2763fccdaa6e15b055b244b5c9b8778c Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Sat, 19 Oct 2002 02:16:40 +0000
Subject: [PATCH] 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
---
 contrib/dbmirror/DBMirror.pl     |  8 +++----
 contrib/dbmirror/MirrorSetup.sql |  3 ++-
 contrib/dbmirror/README.dbmirror | 40 ++++++++++++++++++++++++++------
 contrib/dbmirror/pending.c       | 29 ++++++++++++++++-------
 4 files changed, 60 insertions(+), 20 deletions(-)

diff --git a/contrib/dbmirror/DBMirror.pl b/contrib/dbmirror/DBMirror.pl
index 9c9f197e919..a7c83670457 100755
--- a/contrib/dbmirror/DBMirror.pl
+++ b/contrib/dbmirror/DBMirror.pl
@@ -19,7 +19,7 @@
 #    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.
-    my $insertQuery = "INSERT INTO \"$tableName\" (";
+    my $insertQuery = "INSERT INTO $tableName (";
     my $valuesQuery = ") VALUES (";
     foreach $column (keys (%recordValues)) {
 	if($firstIteration==0) {
@@ -468,7 +468,7 @@ sub mirrorDelete($$$$$) {
     %dataHash = extractData($pendingResult,$currentTuple);
 
     my $counter=0;
-    my $deleteQuery = "DELETE FROM \"$tableName\" WHERE ";
+    my $deleteQuery = "DELETE FROM $tableName WHERE ";
     foreach $currentField (keys %dataHash) {
       if($firstField==0) {
 	$deleteQuery .= " AND ";
@@ -553,7 +553,7 @@ sub mirrorUpdate($$$$$) {
 
     my $counter;
     my $quotedValue;
-    my $updateQuery = "UPDATE \"$tableName\" SET ";
+    my $updateQuery = "UPDATE $tableName SET ";
     my $currentField;
 
 
diff --git a/contrib/dbmirror/MirrorSetup.sql b/contrib/dbmirror/MirrorSetup.sql
index 7597318411b..7f54fa29672 100644
--- a/contrib/dbmirror/MirrorSetup.sql
+++ b/contrib/dbmirror/MirrorSetup.sql
@@ -6,7 +6,8 @@ CREATE FUNCTION "recordchange" () RETURNS trigger AS
 
 CREATE TABLE "MirrorHost" (
 "MirrorHostId" serial,
-"HostName" varchar NOT NULL
+"HostName" varchar NOT NULL,
+PRIMARY KEY("MirrorHostId")
 );
 
 
diff --git a/contrib/dbmirror/README.dbmirror b/contrib/dbmirror/README.dbmirror
index 32eb7842764..397bc08ad7d 100644
--- a/contrib/dbmirror/README.dbmirror
+++ b/contrib/dbmirror/README.dbmirror
@@ -46,6 +46,7 @@ Pending tables.
 Installation Instructions
 ------------------------------------------------------------------------
 
+
 1) Compile pending.c
 
 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.
 
-The Makefile supplied assumes that the postgres include files are in 
-/usr/local/pgsql/include/server.  
+Postgres-7.3 Make Instructions:
+
+  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
 /usr/local/pgsql/include  (The server part is for 7.2+)
 
 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.
+
+  Compiling the trigger by hand requires that all postgres headers be installed
+  ,this is accomplished in postgresql(7.1 or 7.2) by running 
+  "make install-all-headers" in the postgres source directory.
 
-The trigger requires that all postgres headers be installed, this is
-accomplished in postgresql(7.1 or 7.2) by running "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).
 
@@ -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
 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.
 
@@ -199,6 +224,7 @@ RedHat Linux 7.1 & 6.2
 
 Mandrake Linux 8.0(Limited Testing)
  -Postgres 7.2
+ -Postgres 7.3
  -Perl 5.6
 
 
diff --git a/contrib/dbmirror/pending.c b/contrib/dbmirror/pending.c
index 911cd7ab47f..e8d2346f783 100644
--- a/contrib/dbmirror/pending.c
+++ b/contrib/dbmirror/pending.c
@@ -1,6 +1,6 @@
 /****************************************************************************
  * 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
  * to a pending table for mirroring.
@@ -22,7 +22,7 @@
 
 #include <executor/spi.h>
 #include <commands/trigger.h>
-
+#include <utils/lsyscache.h>
 enum FieldUsage
 {
 	PRIMARY = 0, NONPRIMARY, ALL, NUM_FIELDUSAGE
@@ -46,7 +46,7 @@ char *packageData(HeapTuple tTupleData, TupleDesc tTupleDecs,
 
 #define BUFFER_SIZE 256
 #define MAX_OID_LEN 10
-
+#define DEBUG_OUTPUT
 
 extern Datum recordchange(PG_FUNCTION_ARGS);
 
@@ -69,7 +69,8 @@ recordchange(PG_FUNCTION_ARGS)
 	HeapTuple	retTuple = NULL;
 	char	   *tblname;
 	char		op = 0;
-
+	char 	   *schemaname;
+	char	   *fullyqualtblname;
 	if (fcinfo->context != NULL)
 	{
 
@@ -81,6 +82,16 @@ recordchange(PG_FUNCTION_ARGS)
 		trigdata = (TriggerData *) fcinfo->context;
 		/* Extract the table name */
 		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;
 		if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
 		{
@@ -103,7 +114,7 @@ recordchange(PG_FUNCTION_ARGS)
 			op = 'd';
 		}
 
-		if (storePending(tblname, beforeTuple, afterTuple, tupdesc, trigdata, op))
+		if (storePending(fullyqualtblname, beforeTuple, afterTuple, tupdesc, trigdata, op))
 		{
 			/* An error occoured. Skip the operation. */
 			elog(ERROR, "Operation could not be mirrored");
@@ -113,6 +124,7 @@ recordchange(PG_FUNCTION_ARGS)
 #if defined DEBUG_OUTPUT
 		elog(NOTICE, "Returning on success");
 #endif
+		SPI_pfree(fullyqualtblname);
 		SPI_finish();
 		return PointerGetDatum(retTuple);
 	}
@@ -417,7 +429,7 @@ packageData(HeapTuple tTupleData, TupleDesc tTupleDesc,
 #if defined DEBUG_OUTPUT
 		elog(NOTICE, cpFieldName);
 #endif
-		while (iDataBlockSize - iUsedDataBlock < strlen(cpFieldName) + 4)
+		while (iDataBlockSize - iUsedDataBlock < strlen(cpFieldName) + 6)
 		{
 			cpDataBlock = SPI_repalloc(cpDataBlock, iDataBlockSize + BUFFER_SIZE);
 			iDataBlockSize = iDataBlockSize + BUFFER_SIZE;
@@ -436,7 +448,7 @@ packageData(HeapTuple tTupleData, TupleDesc tTupleDesc,
 		}
 		else
 		{
-			*cpFormatedPtr = ' ';
+			sprintf(cpFormatedPtr," ");
 			iUsedDataBlock++;
 			cpFormatedPtr++;
 			continue;
@@ -484,7 +496,8 @@ packageData(HeapTuple tTupleData, TupleDesc tTupleDesc,
 	if (tpPKeys != NULL)
 		SPI_pfree(tpPKeys);
 #if defined DEBUG_OUTPUT
-	elog(NOTICE, "Returning");
+	elog(NOTICE, "Returning: DataBlockSize:%d iUsedDataBlock:%d",iDataBlockSize,
+			iUsedDataBlock);
 #endif
 	memset(cpDataBlock + iUsedDataBlock, 0, iDataBlockSize - iUsedDataBlock);
 
-- 
GitLab