From 0b22e718bd262fd630555d35779989687155ff15 Mon Sep 17 00:00:00 2001 From: Marc Bir Date: Wed, 4 Mar 2020 20:18:58 -0800 Subject: [PATCH 1/2] Fix integer division truncate on guard_count When calculating guard_count: length( alphabet )/ guard_div -> since both values are integers it will truncate the result (https://www.postgresql.org/docs/current/functions-math.html) forcing length to float corrects the issue to spec. Also removed extraneous drop statement. --- hashids.sql | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/hashids.sql b/hashids.sql index 5e34d57..cdd2e8b 100644 --- a/hashids.sql +++ b/hashids.sql @@ -134,7 +134,7 @@ create or replace function hashids._prepare( ) as $$ declare min_alphabet_length integer := 16; - sep_div integer := 3.5; + sep_div float := 3.5; guard_div integer := 12; guard_count integer; cur_sep varchar; @@ -174,7 +174,7 @@ begin separators := hashids.shuffle( separators, salt ); if ( length( separators ) < 1 or ( length( alphabet ) / length( separators ) ) > sep_div ) then - separators_length = ceil( length( alphabet ) / sep_div ); + separators_length = ceil( length( alphabet )::float / sep_div ); if ( separators_length > length( separators ) ) then diff := separators_length - length( separators ); @@ -184,7 +184,7 @@ begin end if; alphabet := hashids.shuffle( alphabet, salt ); - guard_count := ceil( length( alphabet ) / guard_div ); + guard_count := ceil( length( alphabet )::float / guard_div ); if length( alphabet ) < 3 then guards := substr( separators, 1, guard_count ); @@ -401,8 +401,6 @@ begin end; $$ language plpgsql; -drop function hashids.decode_hex; - create or replace function hashids.decode_hex( id varchar, salt varchar = '', From 8ca3c262c30a1f186529884316dddf4d54dab5da Mon Sep 17 00:00:00 2001 From: Marc Bir Date: Wed, 4 Mar 2020 22:12:10 -0800 Subject: [PATCH 2/2] Fix issue when len(separators) < min --- hashids.sql | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/hashids.sql b/hashids.sql index cdd2e8b..02c1152 100644 --- a/hashids.sql +++ b/hashids.sql @@ -119,6 +119,7 @@ begin end; $$ language plpgsql; + create or replace function hashids._prepare( inout alphabet varchar, in salt varchar = '', @@ -138,7 +139,8 @@ declare guard_div integer := 12; guard_count integer; cur_sep varchar; - diff varchar; + diff integer; + temp_sep varchar; begin if alphabet is null then alphabet := 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'; @@ -162,25 +164,20 @@ begin raise exception '[hash_id] error: Alphabet cannot contain spaces'; end if; - for i in 1..length( separators ) loop - cur_sep := array_position( original_alphabet_arr, separators_arr [i] ); - - if cur_sep is null then - separators := substr( separators, 1, i ) || ' ' || substr( separators, i + 1 ); + temp_sep := ''; + foreach cur_sep in ARRAY separators_arr loop + if array_position( original_alphabet_arr, cur_sep ) is not null then + temp_sep := temp_sep || cur_sep; end if; end loop; - separators := regexp_replace( separators, '[ ]', '', 'g' ); - separators := hashids.shuffle( separators, salt ); + separators := hashids.shuffle( temp_sep, salt ); - if ( length( separators ) < 1 or ( length( alphabet ) / length( separators ) ) > sep_div ) then - separators_length = ceil( length( alphabet )::float / sep_div ); - - if ( separators_length > length( separators ) ) then + separators_length = ceil( length( alphabet )::float / sep_div ); + if ( separators_length > length( separators ) ) then diff := separators_length - length( separators ); separators := separators || substr( alphabet, 1, diff ); - alphabet := substr( alphabet, diff ); - end if; + alphabet := substr( alphabet, diff+1 ); end if; alphabet := hashids.shuffle( alphabet, salt );