Skip to content

Commit

Permalink
fixup! verionsing using oid
Browse files Browse the repository at this point in the history
  • Loading branch information
mlt committed Aug 31, 2017
1 parent 6b92758 commit 4b6e2a6
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 107 deletions.
7 changes: 5 additions & 2 deletions expected/renaming.out
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ SELECT pg_sleep(0.1);

(1 row)

CREATE SCHEMA IF NOT EXISTS new;
ALTER TABLE versioning_new_history SET SCHEMA new;
-- Delete.
BEGIN;
DELETE FROM versioning_new;
Expand All @@ -155,7 +157,7 @@ SELECT * FROM versioning_new;
---+-----+------------
(0 rows)

SELECT a, c, upper(sys_period) = CURRENT_TIMESTAMP FROM versioning_new_history ORDER BY a, sys_period;
SELECT a, c, upper(sys_period) = CURRENT_TIMESTAMP FROM new.versioning_new_history ORDER BY a, sys_period;
a | c | ?column?
---+---+----------
1 | | t
Expand All @@ -172,4 +174,5 @@ SELECT a, "b b" FROM versioning_new WHERE lower(sys_period) = CURRENT_TIMESTAMP

END;
DROP TABLE versioning_new;
DROP TABLE versioning_new_history;
DROP TABLE new.versioning_new_history;
DROP SCHEMA new;
9 changes: 6 additions & 3 deletions sql/renaming.sql
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ SELECT pg_sleep(0.1);

-- Rename both tables
ALTER TABLE versioning RENAME TO versioning_new;

ALTER TABLE versioning_history RENAME TO versioning_new_history;

-- Delete.
Expand All @@ -93,18 +92,22 @@ END;
-- Make sure that the next transaction's CURRENT_TIMESTAMP is different.
SELECT pg_sleep(0.1);

CREATE SCHEMA IF NOT EXISTS new;
ALTER TABLE versioning_new_history SET SCHEMA new;

-- Delete.
BEGIN;

DELETE FROM versioning_new;

SELECT * FROM versioning_new;

SELECT a, c, upper(sys_period) = CURRENT_TIMESTAMP FROM versioning_new_history ORDER BY a, sys_period;
SELECT a, c, upper(sys_period) = CURRENT_TIMESTAMP FROM new.versioning_new_history ORDER BY a, sys_period;

SELECT a, "b b" FROM versioning_new WHERE lower(sys_period) = CURRENT_TIMESTAMP ORDER BY a, sys_period;

END;

DROP TABLE versioning_new;
DROP TABLE versioning_new_history;
DROP TABLE new.versioning_new_history;
DROP SCHEMA new;
127 changes: 25 additions & 102 deletions versioning.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ PGDLLEXPORT Datum versioning(PG_FUNCTION_ARGS);
PGDLLEXPORT Datum versioning2(PG_FUNCTION_ARGS);
PGDLLEXPORT Datum set_system_time(PG_FUNCTION_ARGS);

static Datum versioning_common(bool has_oid, PG_FUNCTION_ARGS);

PG_FUNCTION_INFO_V1(versioning);
PG_FUNCTION_INFO_V1(versioning2);
PG_FUNCTION_INFO_V1(set_system_time);
Expand All @@ -53,6 +55,7 @@ typedef struct VersioningHashEntry
{
Oid relid; /* hash key (must be first) */
Oid history_relid; /* OID of the history relation */
char history_relname[NAMEDATALEN];
TupleDesc tupdesc; /* tuple descriptor of the versioned relation */
TupleDesc history_tupdesc; /* tuple descriptor of the history relation */

Expand Down Expand Up @@ -185,8 +188,8 @@ static VersioningHashEntry *lookup_versioning_hash_entry(Oid relid,
* FOR EACH ROW EXECUTE PROCEDURE
* versioning(<system_period_column_name>, <history_relation>, <adjust>).
*/
Datum
versioning(PG_FUNCTION_ARGS)
static Datum
versioning_common(bool has_oid, PG_FUNCTION_ARGS)
{
TriggerData *trigdata;
Trigger *trigger;
Expand Down Expand Up @@ -273,9 +276,14 @@ versioning(PG_FUNCTION_ARGS)
return versioning_insert(trigdata, typcache, period_attnum);
else
{
RangeVar *relrv = makeRangeVarFromNameList(stringToQualifiedNameList(args[1]));
Oid history_relation_oid = RangeVarGetRelid(relrv, AccessShareLock, false);;

Oid history_relation_oid;
if (has_oid)
history_relation_oid = strtoul(args[1], NULL, 10);
else
{
RangeVar *relrv = makeRangeVarFromNameList(stringToQualifiedNameList(args[1]));
history_relation_oid = RangeVarGetRelid(relrv, AccessShareLock, false);;
}
if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
return versioning_update(trigdata, typcache,
period_attnum, period_attname,
Expand All @@ -289,104 +297,15 @@ versioning(PG_FUNCTION_ARGS)
}

Datum
versioning2(PG_FUNCTION_ARGS)
versioning(PG_FUNCTION_ARGS)
{
TriggerData *trigdata;
Trigger *trigger;
char **args;
Relation relation;
TupleDesc tupdesc;
char *period_attname;
int period_attnum;
Form_pg_attribute period_attr;
TypeCacheEntry *typcache;

trigdata = (TriggerData *)fcinfo->context;

/* Check that the trigger function was called in expected context. */
if (!CALLED_AS_TRIGGER(fcinfo))
ereport(ERROR,
(errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
errmsg("function \"versioning2\" was not called by trigger manager")));

/* Check proper event. */
if (!TRIGGER_FIRED_BEFORE(trigdata->tg_event) ||
!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
ereport(ERROR,
(errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
errmsg("function \"versioning2\" must be fired BEFORE ROW")));

if (!TRIGGER_FIRED_BY_INSERT(trigdata->tg_event) &&
!TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event) &&
!TRIGGER_FIRED_BY_DELETE(trigdata->tg_event))
ereport(ERROR,
(errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
errmsg("function \"versioning2\" must be fired for INSERT or UPDATE or DELETE")));

trigger = trigdata->tg_trigger;

/* Check number of arguments. */
if (trigger->tgnargs != 3)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("wrong number of parameters for function \"versioning2\""),
errdetail("expected 3 parameters but got %d",
trigger->tgnargs)));

args = trigger->tgargs;

relation = trigdata->tg_relation;

tupdesc = RelationGetDescr(relation);

period_attname = args[0];

/* Check that system period attribute exists in the versioned relation. */
period_attnum = SPI_fnumber(tupdesc, period_attname);

if (period_attnum == SPI_ERROR_NOATTRIBUTE)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_COLUMN),
errmsg("column \"%s\" of relation \"%s\" does not exist",
period_attname,
RelationGetRelationName(relation))));

period_attr = tupdesc->attrs[period_attnum - 1];

/* Check that system period attribute is not dropped. */
if (period_attr->attisdropped)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_COLUMN),
errmsg("column \"%s\" of relation \"%s\" does not exist",
period_attname,
RelationGetRelationName(relation))));

/* Check that system period attribute is not an array. */
if (period_attr->attndims != 0)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("system period column \"%s\" of relation \"%s\" is not a range but an array",
period_attname,
RelationGetRelationName(relation))));

/* Locate the typcache entry for the type of system period attribute. */
typcache = get_period_typcache(fcinfo, period_attr, relation);
return versioning_common(false, fcinfo);
}

if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
return versioning_insert(trigdata, typcache, period_attnum);
else
{
Oid oid = strtoul(args[1], NULL, 10);
if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
return versioning_update(trigdata, typcache,
period_attnum, period_attname,
oid, args[2]);
else
/* otherwise this is ON DELETE trigger */
return versioning_delete(trigdata, typcache,
period_attnum, period_attname,
oid, args[2]);
}
Datum
versioning2(PG_FUNCTION_ARGS)
{
return versioning_common(true, fcinfo);
}

/*
Expand Down Expand Up @@ -677,6 +596,7 @@ fill_versioning_hash_entry(VersioningHashEntry *hash_entry,
oldcontext = MemoryContextSwitchTo(TopMemoryContext);

hash_entry->history_relid = RelationGetRelid(history_relation);
memcpy(hash_entry->history_relname, NameStr(history_relation->rd_rel->relname), NAMEDATALEN);
hash_entry->tupdesc = CreateTupleDescCopyConstr(tupdesc);
hash_entry->history_tupdesc = CreateTupleDescCopyConstr(history_tupdesc);

Expand Down Expand Up @@ -743,11 +663,14 @@ insert_history_row(HeapTuple tuple,
* Then check that the structure of the versioned table and the history
* table is intact by comparing the cached TupleDesc with the current
* one.
*
* Also check whether history table name has changed.
*/
if (hash_entry->natts == -1 ||
RelationGetRelid(history_relation) != hash_entry->history_relid ||
!equalTupleDescs(tupdesc, hash_entry->tupdesc) ||
!equalTupleDescs(history_tupdesc, hash_entry->history_tupdesc))
!equalTupleDescs(history_tupdesc, hash_entry->history_tupdesc) ||
0 != strncmp(NameStr(history_relation->rd_rel->relname), hash_entry->history_relname, NAMEDATALEN))
{
/* Mark the entry invalid. */
hash_entry->natts = -1;
Expand Down

0 comments on commit 4b6e2a6

Please sign in to comment.