104 lines
2.8 KiB
Go
104 lines
2.8 KiB
Go
package migrations
|
|
|
|
import "github.com/pocketbase/dbx"
|
|
|
|
func createSQLiteEquivalentFunctions(db dbx.Builder) error {
|
|
if getDriverName(db) != "postgres" {
|
|
return nil
|
|
}
|
|
|
|
//PostgreSQL:
|
|
// 1. Check existance
|
|
sql := `SELECT EXISTS (SELECT 1 FROM pg_proc WHERE proname = 'uuid_generate_v7');`
|
|
var exists bool
|
|
if err := db.NewQuery(sql).Row(&exists); err != nil {
|
|
return err
|
|
} else if exists {
|
|
// The function already exists, no need to create it again
|
|
return nil
|
|
}
|
|
|
|
// Postgres:
|
|
// 2. Create function
|
|
funcDef := `
|
|
-- Enable built-in pgcrypto extension to use gen_random_bytes function
|
|
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
|
|
|
|
-- Adding "nocase" collation to be compatible with SQLite's built-in "nocase" collation
|
|
CREATE COLLATION IF NOT EXISTS "nocase" (
|
|
provider = icu, -- Specify ICU as the provider
|
|
locale = 'und-u-ks-level2', -- Undetermined locale, Unicode extension (-u-), collation strength (ks) level 2 (level2)
|
|
deterministic = false -- Case-insensitive collations are typically non-deterministic
|
|
);
|
|
|
|
-- Alias [hex] to encode(..., 'hex')
|
|
CREATE OR REPLACE FUNCTION hex(data bytea)
|
|
RETURNS text
|
|
LANGUAGE SQL
|
|
IMMUTABLE
|
|
AS $$
|
|
SELECT encode(data, 'hex')
|
|
$$;
|
|
|
|
-- Alias [randomblob] to gen_random_bytes(...)
|
|
CREATE OR REPLACE FUNCTION randomblob(length integer)
|
|
RETURNS bytea
|
|
LANGUAGE SQL
|
|
IMMUTABLE
|
|
AS $$
|
|
SELECT gen_random_bytes(length)
|
|
$$;
|
|
|
|
-- Create the uuid_generate_v7 function
|
|
create or replace function uuid_generate_v7()
|
|
returns uuid
|
|
as $$
|
|
begin
|
|
-- use random v4 uuid as starting point (which has the same variant we need)
|
|
-- then overlay timestamp
|
|
-- then set version 7 by flipping the 2 and 1 bit in the version 4 string
|
|
return encode(
|
|
set_bit(
|
|
set_bit(
|
|
overlay(uuid_send(gen_random_uuid())
|
|
placing substring(int8send(floor(extract(epoch from clock_timestamp()) * 1000)::bigint) from 3)
|
|
from 1 for 6
|
|
),
|
|
52, 1
|
|
),
|
|
53, 1
|
|
),
|
|
'hex')::uuid;
|
|
end
|
|
$$
|
|
language plpgsql
|
|
volatile;
|
|
|
|
-- Create json_valid function
|
|
CREATE OR REPLACE FUNCTION json_valid(text) RETURNS boolean AS $$
|
|
BEGIN
|
|
PERFORM $1::jsonb;
|
|
RETURN TRUE;
|
|
EXCEPTION WHEN others THEN
|
|
RETURN FALSE;
|
|
END;
|
|
$$ LANGUAGE plpgsql IMMUTABLE;
|
|
|
|
-- Create a json_query_or_null function that handles any types.
|
|
CREATE OR REPLACE FUNCTION json_query_or_null(p_input jsonb, p_query text) RETURNS jsonb AS $$
|
|
SELECT JSON_QUERY(p_input, p_query)
|
|
$$ LANGUAGE sql IMMUTABLE;
|
|
|
|
-- Create a json_query_or_null function that handles any types.
|
|
CREATE OR REPLACE FUNCTION json_query_or_null(p_input anyelement, p_query text) RETURNS jsonb AS $$
|
|
BEGIN
|
|
RETURN JSON_QUERY(p_input::text::jsonb, p_query);
|
|
EXCEPTION WHEN others THEN
|
|
RETURN NULL;
|
|
END;
|
|
$$ LANGUAGE plpgsql STABLE;
|
|
`
|
|
_, err := db.NewQuery(funcDef).Execute()
|
|
return err
|
|
}
|