Yapf.net

Versiebeheer in de database PostgreSQL's Schemas

Schema's zijn namespaces voor database objecten en maken het mogelijk om meerdere versies van dezelfde objecten te hebben en daar tussen te kiezen.

Schema's zijn als namespaces binnen de database; elk object (tabel, view, function etc) staat physiek in één schema, maar de namen hoeven niet uniek te zijn over de verschillende schema's heen dus elk schema kan zijn eigen versie van een b.v. een view bevatten. Welke van de views je wilt gebruiken kun je aangeven door de naam te prefixen met de schemanaam: SELECT * FROM my_first_schema.data; Als geen schemanaam wordt opgegeven dan zal PostgreSQL de lijst van schema's in het schema-search-path bekijken in de volgorde waarin schema's daar genoemd worden. Als search_path is ingesteld op "v3, v2, v1, public" dan zal de database eerst kijken in het v3 schema, dan v2 , v1 en uiteindelijk public. Het eerste object dat wordt gevonden zal worden gebruikt en dat betekent dat je dus niet in elk schema altijd een kopie van alle objecten hoeft te hebben. Je kunt alle objecten gewoon in 'public' houden en uitzonderingen in nieuwe schema's doorvoeren. Op deze manier kun je dezelfde brontabellen op verschillende manieren benaderen voor b.v. verschillende apps en API's.

Dit alles is een stuk beter te volgen in een voorbeeld, so here we go.

Proof of concept

code
-- See what the current search_path is.
SHOW search_path;

-- Reset the search_path to the default value
SET search_path = public;

-- Create a table in the public schema and add some data.
CREATE TABLE public.data
(
    id    INT,
    title TEXT,
    price NUMERIC(8, 2)
);
INSERT INTO public.data VALUES (1, 'foo', 54.66);

-- Create the first update, which replaces the table with a view that hides the id.
CREATE SCHEMA v1;
CREATE VIEW v1.data AS (SELECT title, price FROM public.data);
-- Set the search_path so the new view will be found first.
SET search_path = v1,public;
SELECT * FROM data;


-- A new version is released and it modifies the data view to add the id back in.
CREATE SCHEMA v2;
CREATE VIEW v2.data AS (SELECT id, title, price FROM public.data);
-- Add the v2 to the search_path so it will find the new view or fallback to an older one.
SET search_path = v2, v1, public;
SELECT * FROM data;

-- Another update and this time a new column is added to indicate the release version.
CREATE SCHEMA v3;
CREATE VIEW v3.data AS (SELECT id, title, price, 'v3' AS release_number FROM public.data);
SET search_path = v3, v2, v1, public;
SELECT * FROM data;

-- Notice that you can still access the older versions of the view by adding the schemaname:
SELECT * FROM v2.data;

-- If you remove the v2 view and set the search_path to start at v2, it find the v1 version
DROP VIEW IF EXISTS v2.data;
SET search_path = v2, v1, public;
SELECT * FROM data;

-- Inserting into the data view will nog not accept the ID because that's not in the v1 version
INSERT INTO data (id, title, price) VALUES (2, 'bar', 42);
-- ERROR: column "id" of relation "data" does not exist

-- Leaving the id column out works
INSERT INTO data (title, price) VALUES ('bar',42);
SELECT * FROM data;

-- Going back to v3 does accept the id
SET search_path = v3, v2, v1, public;
INSERT INTO data (id, title, price) VALUES (3, 'wicked', 69);
SELECT * FROM data;