66 lines
2.2 KiB
PL/PgSQL
66 lines
2.2 KiB
PL/PgSQL
/*
|
|
* Copyright 2023 Viascom Ltd liab. Co
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one
|
|
* or more contributor license agreements. See the NOTICE file
|
|
* distributed with this work for additional information
|
|
* regarding copyright ownership. The ASF licenses this file
|
|
* to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance
|
|
* with the License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing,
|
|
* software distributed under the License is distributed on an
|
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
* KIND, either express or implied. See the License for the
|
|
* specific language governing permissions and limitations
|
|
* under the License.
|
|
*/
|
|
|
|
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
|
|
|
CREATE OR REPLACE FUNCTION nanoid(
|
|
size int DEFAULT 21,
|
|
alphabet text DEFAULT '_-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
|
)
|
|
RETURNS text
|
|
LANGUAGE plpgsql
|
|
volatile
|
|
AS
|
|
$$
|
|
DECLARE
|
|
idBuilder text := '';
|
|
counter int := 0;
|
|
bytes bytea;
|
|
alphabetIndex int;
|
|
alphabetArray text[];
|
|
alphabetLength int;
|
|
mask int;
|
|
step int;
|
|
BEGIN
|
|
alphabetArray := regexp_split_to_array(alphabet, '');
|
|
alphabetLength := array_length(alphabetArray, 1);
|
|
mask := (2 << cast(floor(log(alphabetLength - 1) / log(2)) as int)) - 1;
|
|
step := cast(ceil(1.6 * mask * size / alphabetLength) AS int);
|
|
|
|
while true
|
|
loop
|
|
bytes := gen_random_bytes(step);
|
|
while counter < step
|
|
loop
|
|
alphabetIndex := (get_byte(bytes, counter) & mask) + 1;
|
|
if alphabetIndex <= alphabetLength then
|
|
idBuilder := idBuilder || alphabetArray[alphabetIndex];
|
|
if length(idBuilder) = size then
|
|
return idBuilder;
|
|
end if;
|
|
end if;
|
|
counter := counter + 1;
|
|
end loop;
|
|
|
|
counter := 0;
|
|
end loop;
|
|
END
|
|
$$; |