rihack.sql
text/x-sql
Filename: rihack.sql
Type: text/x-sql
Part: 0
-- relational integrity hacking: attempting to create non-equality FK
-- relationships.
-- parent relation has (non-overlapping) BOX keys, child relation has POINT
-- keys.
BEGIN;
DROP SCHEMA IF EXISTS rihack CASCADE;
CREATE SCHEMA rihack;
SET search_path TO rihack, public;
CREATE DOMAIN INTBOX AS BOX CHECK (
(VALUE[0])[0] = ROUND((VALUE[0])[0]) AND
(VALUE[0])[1] = ROUND((VALUE[0])[1]) AND
(VALUE[1])[0] = ROUND((VALUE[1])[0]) AND
(VALUE[1])[1] = ROUND((VALUE[1])[1])
);
CREATE DOMAIN INTPOINT AS POINT CHECK (
VALUE[0] = ROUND(VALUE[0]) AND VALUE[1] = ROUND(VALUE[1])
);
CREATE TABLE boxes (
id SERIAL PRIMARY KEY,
region INTBOX NOT NULL,
name TEXT NOT NULL,
CONSTRAINT boxes_cannot_overlap EXCLUDE USING gist (region WITH &&)
);
CREATE TABLE points (
region_id INTEGER REFERENCES boxes,
poi INTPOINT NOT NULL,
score INTEGER NOT NULL
);
-- Now, what we want to do is define an FK relationship:
-- FOREIGN KEY points.poi REFERENCES boxes.region WITH <@
-- We're going to hijack the existing constraint on the points table:
-- FOREIGN KEY points.region_id REFERENCES boxes.id WITH =
-- oids of operators:
-- POINT <@ BOX 511
-- BOX @> POINT 433 [commutator of op 511]
-- BOX ~= BOX 499
-- POINT ~= POINT 510
UPDATE pg_constraint SET conkey='{2}',
confkey='{2}',
conpfeqop='{433}',
conppeqop='{499}',
conffeqop='{510}'
WHERE conname='points_region_id_fkey';
-- these should all work:
INSERT INTO boxes (region, name) VALUES (box(point(2,2), point(5,5)), 'A');
INSERT INTO boxes (region, name) VALUES (box(point(7,7), point(10,10)), 'A');
INSERT INTO points (region_id, poi, score) VALUES (1, point(3,3), 10);
INSERT INTO points (region_id, poi, score) VALUES (1, point(4,4), 5);
INSERT INTO points (region_id, poi, score) VALUES (2, point(8,8), 15);
COMMIT;
-- this should fail:
INSERT INTO points (region_id, poi, score) VALUES (1, point(1,1), 15);