From 1aaae51eab737f05768487253dfcc2ebb95de887 Mon Sep 17 00:00:00 2001 From: Tau Date: Tue, 28 May 2019 15:35:33 -0400 Subject: [PATCH] Add ID generation sprocs for manual db interventions --- schema/init/meta.sql | 2 +- schema/init/util.sql | 81 +++++++++++++++++++++++ schema/migrate/M0001-add-helper-funcs.sql | 81 +++++++++++++++++++++++ 3 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 schema/init/util.sql create mode 100644 schema/migrate/M0001-add-helper-funcs.sql diff --git a/schema/init/meta.sql b/schema/init/meta.sql index 141bfe2..1cb26df 100644 --- a/schema/init/meta.sql +++ b/schema/init/meta.sql @@ -1,2 +1,2 @@ create table "meta" ("schemaver" integer not null); -insert into "meta" values (0); +insert into "meta" values (1); diff --git a/schema/init/util.sql b/schema/init/util.sql new file mode 100644 index 0000000..7302f4b --- /dev/null +++ b/schema/init/util.sql @@ -0,0 +1,81 @@ +-- Helper functions which might be useful in one-off queries. +-- These are not utilised by any services; those have their own ID generators. + +create or replace function idnum( + str text) + returns bigint as $$ +declare + num bigint; + x integer; +begin + num := 0; + + for i in 1..11 loop + x := ascii(substr(str, i, 1)); + num := num << 6; + + if x >= 65 and x <= 90 then + -- A to Z + num = num | (x - 65); + elsif x >= 97 and x <= 122 then + -- a to z + num = num | (x - 71); + elsif x >= 48 and x <= 58 then + -- 0 to 9 + num = num | (x + 4); + elsif x = 45 then + -- Dash + num = num | 62; + elsif x = 95 then + -- Underscore + num = num | 63; + else + raise 'Bad input'; + end if; + end loop; + + return num; +end; +$$ language plpgsql; + +create or replace function idstr( + num bigint) + returns text as $$ +declare + a text; + pos integer; + str text; +begin + a := 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'; + str := ''; + + for i in 1..11 loop + pos := (num & 63); + str := substr(a, pos + 1, 1) || str; + num := num >> 6; + end loop; + + return str; +end; +$$ language plpgsql; + +create or replace function newid() + returns bigint as $$ +declare + bytes bytea; + result bigint; +begin + bytes := gen_random_bytes(8); + result := 0; + + for i in 0..7 loop + result := (result << 8) | get_byte(bytes, i); + end loop; + + -- Truncate high bit to ensure result is positive + -- This value is just the decimal representation of 0x7FFFFFFF`FFFFFFFF. + + return result & 9223372036854775807; +end; +$$ language plpgsql; + diff --git a/schema/migrate/M0001-add-helper-funcs.sql b/schema/migrate/M0001-add-helper-funcs.sql new file mode 100644 index 0000000..7302f4b --- /dev/null +++ b/schema/migrate/M0001-add-helper-funcs.sql @@ -0,0 +1,81 @@ +-- Helper functions which might be useful in one-off queries. +-- These are not utilised by any services; those have their own ID generators. + +create or replace function idnum( + str text) + returns bigint as $$ +declare + num bigint; + x integer; +begin + num := 0; + + for i in 1..11 loop + x := ascii(substr(str, i, 1)); + num := num << 6; + + if x >= 65 and x <= 90 then + -- A to Z + num = num | (x - 65); + elsif x >= 97 and x <= 122 then + -- a to z + num = num | (x - 71); + elsif x >= 48 and x <= 58 then + -- 0 to 9 + num = num | (x + 4); + elsif x = 45 then + -- Dash + num = num | 62; + elsif x = 95 then + -- Underscore + num = num | 63; + else + raise 'Bad input'; + end if; + end loop; + + return num; +end; +$$ language plpgsql; + +create or replace function idstr( + num bigint) + returns text as $$ +declare + a text; + pos integer; + str text; +begin + a := 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'; + str := ''; + + for i in 1..11 loop + pos := (num & 63); + str := substr(a, pos + 1, 1) || str; + num := num >> 6; + end loop; + + return str; +end; +$$ language plpgsql; + +create or replace function newid() + returns bigint as $$ +declare + bytes bytea; + result bigint; +begin + bytes := gen_random_bytes(8); + result := 0; + + for i in 0..7 loop + result := (result << 8) | get_byte(bytes, i); + end loop; + + -- Truncate high bit to ensure result is positive + -- This value is just the decimal representation of 0x7FFFFFFF`FFFFFFFF. + + return result & 9223372036854775807; +end; +$$ language plpgsql; +