table_version

PostgreSQL table versioning extension

Overview

PackageVersionCategoryLicenseLanguage
table_version1.11.1TIMEBSD 3-ClauseSQL
IDExtensionBinLibLoadCreateTrustRelocSchema
1060table_versionNoYesNoYesNoNotable_version
Relatedplpgsql periods temporal_tables emaj pg_cron timescaledb timescaledb_toolkit timeseries pg_task

Version

TypeRepoVersionPG VerPackageDeps
EXTMIXED1.11.11817161514table_versionplpgsql
RPMPIGSTY1.11.11817161514table_version_$v-
DEBPIGSTY1.11.11817161514postgresql-$v-table-version-
OS / PGPG18PG17PG16PG15PG14
el8.x86_64
el8.aarch64
el9.x86_64
el9.aarch64
el10.x86_64
el10.aarch64
d12.x86_64
d12.aarch64
PIGSTY 1.11.1
PIGSTY 1.11.1
PIGSTY 1.11.1
PIGSTY 1.11.1
PIGSTY 1.11.1
d13.x86_64
PIGSTY 1.11.1
PIGSTY 1.11.1
PIGSTY 1.11.1
PIGSTY 1.11.1
PIGSTY 1.11.1
d13.aarch64
PIGSTY 1.11.1
PIGSTY 1.11.1
PIGSTY 1.11.1
PIGSTY 1.11.1
PIGSTY 1.11.1
u22.x86_64
PIGSTY 1.11.1
PIGSTY 1.11.1
PIGSTY 1.11.1
PIGSTY 1.11.1
PIGSTY 1.11.1
u22.aarch64
PIGSTY 1.11.1
PIGSTY 1.11.1
PIGSTY 1.11.1
PIGSTY 1.11.1
PIGSTY 1.11.1
u24.x86_64
PIGSTY 1.11.1
PIGSTY 1.11.1
PIGSTY 1.11.1
PIGSTY 1.11.1
PIGSTY 1.11.1
u24.aarch64
PIGSTY 1.11.1
PIGSTY 1.11.1
PIGSTY 1.11.1
PIGSTY 1.11.1
PIGSTY 1.11.1
u26.x86_64
u26.aarch64
PIGSTY 1.11.1
PIGSTY 1.11.1
PIGSTY 1.11.1
PIGSTY 1.11.1
PIGSTY 1.11.1

Build

You can build the DEB packages for table_version using pig build:

pig build pkg table_version         # build DEB packages

Install

You can install table_version directly. First, make sure the PGDG and PIGSTY repositories are added and enabled:

pig repo add pgsql -u          # Add repo and update cache

Install the extension using pig or apt/yum/dnf:

pig install table_version;          # Install for current active PG version
pig ext install -y table_version -v 18  # PG 18
pig ext install -y table_version -v 17  # PG 17
pig ext install -y table_version -v 16  # PG 16
pig ext install -y table_version -v 15  # PG 15
pig ext install -y table_version -v 14  # PG 14
dnf install -y table_version_18       # PG 18
dnf install -y table_version_17       # PG 17
dnf install -y table_version_16       # PG 16
dnf install -y table_version_15       # PG 15
dnf install -y table_version_14       # PG 14
apt install -y postgresql-18-table-version   # PG 18
apt install -y postgresql-17-table-version   # PG 17
apt install -y postgresql-16-table-version   # PG 16
apt install -y postgresql-15-table-version   # PG 15
apt install -y postgresql-14-table-version   # PG 14

Create Extension:

CREATE EXTENSION table_version CASCADE;  -- requires: plpgsql

Usage

table_version: PostgreSQL table versioning extension

PostgreSQL table versioning extension, recording row modifications and its history. The extension provides APIs for accessing snapshots of a table at certain revisions and the difference generated between any two given revisions. It uses a PL/PgSQL trigger based system to record and provide access to row revisions.

Quick Start

CREATE EXTENSION table_version;

CREATE SCHEMA foo;
SET search_path TO foo, public;

CREATE TABLE foo.bar (
    id INTEGER NOT NULL PRIMARY KEY,
    baz TEXT
);

-- Enable versioning
SELECT table_version.ver_enable_versioning('foo', 'bar');

-- Create a revision and insert data
SELECT table_version.ver_create_revision('Insert data');
INSERT INTO foo.bar (id, baz) VALUES
  (1, 'foo bar 1'),
  (2, 'foo bar 2'),
  (3, 'foo bar 3');
SELECT table_version.ver_complete_revision();

-- Show differences between revisions
SELECT * FROM table_version.ver_get_foo_bar_diff(1001, 1002);

How It Works

When a table is versioned, the original table data is left untouched and a new revision table is created with all the same fields plus _revision_created and _revision_expired fields. A row-level trigger is set up on the original table to record every insert, update and delete in the revision data table. A statement-level trigger is set up to forbid TRUNCATE.

Table Prerequisites

  • The table must have a unique non-composite integer, bigint, text or varchar column
  • The table must not be temporary

Auto Revisions

If you don’t want to call ver_create_revision and ver_complete_revision explicitly, auto-revision mode groups edits by transactions:

SELECT table_version.ver_enable_versioning('foo', 'bar');

BEGIN;
INSERT INTO foo.bar (id, baz) VALUES (1, 'foo bar 1');
INSERT INTO foo.bar (id, baz) VALUES (2, 'foo bar 2');
COMMIT;

BEGIN;
UPDATE foo.bar SET baz = 'foo bar 1 edit' WHERE id = 1;
COMMIT;

SELECT * FROM table_version.foo_bar_revision;

The revision message will be automatically created based on the transaction ID.

Replicate Data Using Table Differences

To maintain a copy of table data on a remote system:

-- 1. Determine which tables are versioned
SELECT * FROM table_version.ver_get_versioned_tables();

-- 2. Get the base revision
SELECT table_version.ver_get_table_base_revision('foo', 'bar');

-- 3. Create a base snapshot
CREATE TABLE foo_bar_copy AS
SELECT * FROM table_version.ver_get_foo_bar_revision(
    table_version.ver_get_table_base_revision('foo', 'bar')
);

-- 4. Get differences to apply incremental updates
SELECT * FROM table_version.ver_get_foo_bar_diff(
    my_last_revision,
    table_version.ver_get_table_last_revision('foo', 'bar')
);

Security Model

  • Anyone can create revisions
  • Revisions can only be completed by their creators
  • Only those who have ownership privileges on a table can enable/disable versioning
  • Only empty revisions can be deleted
  • Only the creator of a revision can delete it

Note: Disabling versioning on a table results in all history for that table being deleted.

Key Functions

FunctionDescription
ver_enable_versioning(schema, table)Enable versioning on a table
ver_disable_versioning(schema, table)Disable versioning and remove history
ver_create_revision(comment)Create a new revision
ver_complete_revision()Mark current revision as complete
ver_get_<schema>_<table>_diff(rev1, rev2)Get differences between two revisions
ver_get_<schema>_<table>_revision(rev)Get snapshot at a specific revision
ver_get_versioned_tables()List all versioned tables
ver_get_last_revision()Get the last revision number

Last Modified 2026-05-01: update extension data (aaef844)