Fixes for problems found during initial testing.
authorKevin Grittner <[email protected]>
Thu, 2 Jun 2011 18:18:29 +0000 (13:18 -0500)
committerKevin Grittner <[email protected]>
Thu, 2 Jun 2011 18:18:29 +0000 (13:18 -0500)
contrib/dbtran/dbtran--unpackaged.sql
contrib/dbtran/dbtran.c

index 836806c84495151575fbab8ede89eec73447bf86..83372bf319bc55b6d85dfee03c8ef6cc910b4fa2 100644 (file)
@@ -12,6 +12,11 @@ grant usage on schema dbtran to cc, viewer;
 set role ccowner;
 set search_path = dbtran, public;
 
+create domain "LogRecordSeqNoT" integer;
+create domain "OperationT" varchar(1);
+create domain "TableNameT" varchar(18);
+create domain "ColumnNameT" varchar(18);
+
 drop table if exists "DbTranSummary";
 drop table if exists "DbTranSummary";
 create table "DbTranSummary"
@@ -158,8 +163,7 @@ begin
   -- We want the larger of the last seqno + 1 or the current timestamp.
   lock table dbtran."DbTranLock" in exclusive mode;
   endtime := clock_timestamp();
-  transeqno_from_time := extract(epoch from endtime) * 1000
-                       + extract(milliseconds from endtime);
+  transeqno_from_time := floor(extract(epoch from endtime) * 1000);
   transeqno_from_seq = nextval('"DbTranSeq"');
   if transeqno_from_time > transeqno_from_seq then
     perform setval('"DbTranSeq"', transeqno_from_time);
index 46d5c31d18b759da39f0f6a93c12e2f6b9ee64cb..7ba9f05039d0bca80e737271de4d2263c9fff204 100644 (file)
@@ -16,6 +16,7 @@
 #include "executor/spi.h"
 #include "utils/builtins.h"
 #include "utils/datum.h"
+#include "utils/syscache.h"
 
 PG_MODULE_MAGIC;
 
@@ -67,7 +68,7 @@ generate_dbtran_plans()
    {
        plan = SPI_prepare(query_ensuredbtransummary, 0, NULL);
        if (plan == NULL)
-           elog(ERROR, "SPI_prepare failed for \"%s\"", query_ensuredbtransummary);
+           elog(ERROR, "capture_replication_data: SPI_prepare failed for \"%s\"", query_ensuredbtransummary);
        plan_ensuredbtransummary = SPI_saveplan(plan);
    }
 
@@ -77,7 +78,7 @@ generate_dbtran_plans()
        argtypes[1] = TEXTOID;
        plan = SPI_prepare(query_insertop, 2, argtypes);
        if (plan == NULL)
-           elog(ERROR, "SPI_prepare failed for \"%s\"", query_insertop);
+           elog(ERROR, "capture_replication_data: SPI_prepare failed for \"%s\"", query_insertop);
        plan_insertop = SPI_saveplan(plan);
    }
 
@@ -89,7 +90,7 @@ generate_dbtran_plans()
        argtypes[3] = TEXTOID;
        plan = SPI_prepare(query_insertvaltext, 4, argtypes);
        if (plan == NULL)
-           elog(ERROR, "SPI_prepare failed for \"%s\"", query_insertvaltext);
+           elog(ERROR, "capture_replication_data: SPI_prepare failed for \"%s\"", query_insertvaltext);
        plan_insertvaltext = SPI_saveplan(plan);
    }
 
@@ -101,7 +102,7 @@ generate_dbtran_plans()
        argtypes[3] = INT8OID;
        plan = SPI_prepare(query_insertvalint, 4, argtypes);
        if (plan == NULL)
-           elog(ERROR, "SPI_prepare failed for \"%s\"", query_insertvalint);
+           elog(ERROR, "capture_replication_data: SPI_prepare failed for \"%s\"", query_insertvalint);
        plan_insertvalint = SPI_saveplan(plan);
    }
 
@@ -113,7 +114,7 @@ generate_dbtran_plans()
        argtypes[3] = NUMERICOID;
        plan = SPI_prepare(query_insertvalnumeric, 4, argtypes);
        if (plan == NULL)
-           elog(ERROR, "SPI_prepare failed for \"%s\"", query_insertvalnumeric);
+           elog(ERROR, "capture_replication_data: SPI_prepare failed for \"%s\"", query_insertvalnumeric);
        plan_insertvalnumeric = SPI_saveplan(plan);
    }
 
@@ -125,7 +126,7 @@ generate_dbtran_plans()
        argtypes[3] = BYTEAOID;
        plan = SPI_prepare(query_insertvalbinary, 4, argtypes);
        if (plan == NULL)
-           elog(ERROR, "SPI_prepare failed for \"%s\"", query_insertvalbinary);
+           elog(ERROR, "capture_replication_data: SPI_prepare failed for \"%s\"", query_insertvalbinary);
        plan_insertvalbinary = SPI_saveplan(plan);
    }
 
@@ -137,7 +138,7 @@ generate_dbtran_plans()
        argtypes[3] = BOOLOID;
        plan = SPI_prepare(query_insertvalboolean, 4, argtypes);
        if (plan == NULL)
-           elog(ERROR, "SPI_prepare failed for \"%s\"", query_insertvalboolean);
+           elog(ERROR, "capture_replication_data: SPI_prepare failed for \"%s\"", query_insertvalboolean);
        plan_insertvalboolean = SPI_saveplan(plan);
    }
 
@@ -149,7 +150,7 @@ generate_dbtran_plans()
        argtypes[3] = DATEOID;
        plan = SPI_prepare(query_insertvaldate, 4, argtypes);
        if (plan == NULL)
-           elog(ERROR, "SPI_prepare failed for \"%s\"", query_insertvaldate);
+           elog(ERROR, "capture_replication_data: SPI_prepare failed for \"%s\"", query_insertvaldate);
        plan_insertvaldate = SPI_saveplan(plan);
    }
 
@@ -161,7 +162,7 @@ generate_dbtran_plans()
        argtypes[3] = TIMEOID;
        plan = SPI_prepare(query_insertvaltime, 4, argtypes);
        if (plan == NULL)
-           elog(ERROR, "SPI_prepare failed for \"%s\"", query_insertvaltime);
+           elog(ERROR, "capture_replication_data: SPI_prepare failed for \"%s\"", query_insertvaltime);
        plan_insertvaltime = SPI_saveplan(plan);
    }
 
@@ -173,7 +174,7 @@ generate_dbtran_plans()
        argtypes[3] = TIMESTAMPTZOID;
        plan = SPI_prepare(query_insertvaltimestamp, 4, argtypes);
        if (plan == NULL)
-           elog(ERROR, "SPI_prepare failed for \"%s\"", query_insertvaltimestamp);
+           elog(ERROR, "capture_replication_data: SPI_prepare failed for \"%s\"", query_insertvaltimestamp);
        plan_insertvaltimestamp = SPI_saveplan(plan);
    }
 }
@@ -182,9 +183,22 @@ static void
 write_one_dbtran_value(Datum value, const TupleDesc tupdesc, int i,
                       Datum *args, const char *nulls)
 {
-   int spirc;
+   int     spirc;
+   HeapTuple       tuple;
+   Form_pg_type        typeTup;
+   Oid     typid = tupdesc->attrs[i]->atttypid;
 
-   switch (tupdesc->attrs[i]->atttypid)
+   tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
+   if (!HeapTupleIsValid(tuple))
+       elog(ERROR, "capture_replication_data: cache lookup failed for type %u", typid);
+
+   typeTup = (Form_pg_type) GETSTRUCT(tuple);
+   if (typeTup->typbasetype != 0)
+       typid = typeTup->typbasetype;
+
+   ReleaseSysCache(tuple);
+
+   switch (typid)
    {
        case TEXTOID:
            args[3] = value;
@@ -232,8 +246,12 @@ write_one_dbtran_value(Datum value, const TupleDesc tupdesc, int i,
            spirc = SPI_execp(plan_insertvaltimestamp, args, nulls, 4);
            break;
        default:
-           elog(ERROR, "unrecognized type");
+           elog(ERROR, "capture_replication_data: unrecognized type");
+           spirc = -1;  /* quiet compiler */
    }
+   
+   if (spirc < 0)
+       elog(ERROR, "capture_replication_data: SPI error %i while writing value", spirc);
 }
 
 
@@ -321,14 +339,14 @@ capture_replication_data(PG_FUNCTION_ARGS)
    /* Make sure we've got a summary row. */
    spirc = SPI_execp(plan_ensuredbtransummary, 0, NULL, 0);
    if (spirc != SPI_OK_SELECT)
-       elog(ERROR, "failed to insert transaction summary");
+       elog(ERROR, "capture_replication_data: failed to insert transaction summary");
 
    /* Insert a new operation row. */
    args[0] = CStringGetTextDatum(operation);
    args[1] = CStringGetTextDatum(RelationGetRelationName(rel));
    spirc = SPI_execp(plan_insertop, args, NULL, 2);
    if (spirc != SPI_OK_SELECT || SPI_processed != 1)
-       elog(ERROR, "failed to insert transaction operation");
+       elog(ERROR, "capture_replication_data: failed to insert transaction operation");
 
    /* Set those things which will be the same for all value roes below. */
    args[0] = SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, &isnull);