feat(sql): Add function to generate a URL safe ID

This adds a SQL function that generates a secure random ID of at least
14 characters suitable for use as a public or private ID. IDs generated
with the function will only contain characters from the unreserved
character set defined in RFC 3986 Section 2.3 making them safe for use
in a URL.
pull/3251/head
Michael Gaffney 3 years ago committed by Timothy Messier
parent 94f77d36b3
commit 327d950a1e
No known key found for this signature in database
GPG Key ID: EFD2F184F7600572

@ -30,4 +30,19 @@ begin;
comment on domain wt_url_safe_id is
'An ID that contains only URL safe characters';
-- wt_url_safe_id is a function that generates a secure random ID of 14
-- characters suitable for use as a public or private ID. IDs generated with
-- this function will only contain characters from the unreserved character set
-- defined in RFC 3986 Section 2.3 making them safe for use in a URL.
-- See https://www.rfc-editor.org/rfc/rfc3986.html#section-2.3
create function wt_url_safe_id() returns text
as $$
select wt_encode_base64_url_safe(gen_random_bytes(10));
$$ language sql
volatile
parallel safe -- all of the functions called are parallel safe
cost 1; -- all of the functions called are cost 1
comment on function wt_url_safe_id is
'Returns a random ID of 14 characters containing URL safe characters only';
commit;

@ -0,0 +1,34 @@
-- Copyright (c) HashiCorp, Inc.
-- SPDX-License-Identifier: MPL-2.0
begin;
select plan(7);
-- Verify the function exists and is declared properly
select has_function('wt_url_safe_id');
select volatility_is('wt_url_safe_id', 'volatile');
select isnt_strict('wt_url_safe_id');
create table test_table (
id wt_url_safe_id default wt_url_safe_id() primary key,
test_num integer not null
);
create function test_setup_data(count integer) returns integer
as $$
begin
for i in 1..count loop
insert into test_table (test_num) values (i);
end loop;
return count;
end;
$$ language plpgsql;
select is(test_setup_data(100000), 100000);
select is(count(*), 100000::bigint, 'test_table should have 100000 rows') from test_table;
select is(count(*), 0::bigint, 'no id should be longer than 14 characters')
from test_table where length(id) > 14;
select is(count(*), 0::bigint, 'no id should be shorter than 14 characters')
from test_table where length(id) < 14;
select * from finish();
rollback;
Loading…
Cancel
Save