Files
operacle--checkcle/server/core_backend-server/migrations/postgres_functions.go
T
2026-07-13 12:31:02 +08:00

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
}