Skip to content

Instantly share code, notes, and snippets.

@Pentusha
Last active September 5, 2019 11:14
Show Gist options
  • Save Pentusha/551b68da4d6e9b4e1d434916e732b872 to your computer and use it in GitHub Desktop.
Save Pentusha/551b68da4d6e9b4e1d434916e732b872 to your computer and use it in GitHub Desktop.
Дельта - множество строк которые есть в версии X и которых нет в версии Y. Третий вариант самый дешёвый.
WITH subquery AS (
SELECT (%s BETWEEN init_ver AND last_ver) X_includes
, (%s BETWEEN init_ver AND last_ver) Y_includes
, *
FROM {table_name} T
JOIN {intervals_name} I ON I.row_hash = T._hash
)
SELECT {x_fields}
FROM (SELECT * FROM subquery WHERE X_includes) X
LEFT JOIN (SELECT _hash FROM subquery WHERE Y_includes) Y
ON X._hash = Y._hash
WHERE Y._hash IS NULL ORDER BY {order};
SELECT {x_fields}
FROM (
SELECT *
FROM {table_name} T
JOIN {intervals_name} I ON I.row_hash = T._hash
WHERE %s BETWEEN init_ver AND last_ver
) X
LEFT JOIN (
SELECT *
FROM {table_name} T
JOIN {intervals_name} I ON I.row_hash = T._hash
WHERE %s BETWEEN init_ver AND last_ver
) Y
ON X._hash = Y._hash
WHERE Y._hash IS NULL ORDER BY {order};
WITH Z AS (
SELECT * FROM {table_name} T
JOIN {intervals_name} I ON I.row_hash = T._hash
),
X AS (SELECT * FROM Z WHERE %s BETWEEN init_ver AND last_ver),
Y AS (SELECT * FROM Z WHERE %s BETWEEN init_ver AND last_ver)
SELECT {x_fields} FROM X
LEFT JOIN Y ON X._hash = Y._hash
WHERE Y._hash IS NULL ORDER BY {order};
CREATE TABLE IF NOT EXISTS "{table_name}"
( "_id" SERIAL
, "_hash" BYTEA
{columns}
, CONSTRAINT {table_name}_id PRIMARY KEY (_id)
, CONSTRAINT {table_name}_hash UNIQUE (_hash)
);
CREATE INDEX IF NOT EXISTS {table_name}_hash_idx
ON {table_name} USING hash (_hash);
CREATE TABLE IF NOT EXISTS "{intervals_name}"
( id SERIAL PRIMARY KEY
, row_hash BYTEA
, init_ver INTEGER DEFAULT 1
, last_ver INTEGER DEFAULT 1
, CONSTRAINT {intervals_name}_hash_ver_unique UNIQUE (row_hash, last_ver)
);
CREATE INDEX IF NOT EXISTS {intervals_name}_hash_idx
ON {intervals_name} USING hash (row_hash);
CREATE INDEX IF NOT EXISTS {intervals_name}_last_ver_idx
ON {intervals_name} USING btree (last_ver);
CREATE INDEX IF NOT EXISTS {intervals_name}_ver
ON {intervals_name} USING btree (init_ver, last_ver);
CREATE TEMPORARY TABLE IF NOT EXISTS {table_name}_temp (
{columns}
) ON COMMIT DROP;
INSERT INTO {table_name}_temp ({columns_insert_wo_hash}) VALUES {values};
WITH
data_to_insert_with_hash AS (
SELECT D.*
, md5(CAST((D.*) AS text))::bytea _hash
FROM {table_name}_temp D
)
, existing_hashes AS (
UPDATE {intervals_name} SET last_ver = {version} WHERE id IN (
SELECT I.id FROM {intervals_name} I
JOIN data_to_insert_with_hash E ON I.row_hash = E._hash
WHERE last_ver = {version} - 1
)
RETURNING row_hash
)
, hashes_to_insert AS (
SELECT _hash FROM data_to_insert_with_hash E
WHERE NOT EXISTS (
SELECT 1 FROM existing_hashes H
WHERE H.row_hash = E._hash
)
)
, inserted_intervals AS (
INSERT INTO {intervals_name} (row_hash, init_ver, last_ver)
SELECT _hash, {version} init_ver, {version} end_ver FROM hashes_to_insert
ON CONFLICT ON CONSTRAINT {intervals_name}_hash_ver_unique DO NOTHING
RETURNING *
)
, inserted_rows AS (
INSERT INTO {table_name} ({columns_insert})
SELECT {columns_insert} FROM data_to_insert_with_hash D
WHERE EXISTS (SELECT 1 FROM hashes_to_insert H WHERE H._hash = D._hash)
ON CONFLICT DO NOTHING
RETURNING *
)
SELECT 1;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment