-- 登录数据库,切换postgres用户,输入创建用户自定函数语句.用下面的命令为PostgreSQL定义这些函数:
-- 创建的函数名为sahe_add(text, text, text),该函数输入两个text类型的数据,返回类型为text的计算结果.
-- 其余函数#sahe_addplain,sahe_substract,sahe_multiply,sahe_negate,smhe_multiply,smhe_multiplyplain,
-- smhe_divide,smhe_pow,smhe_inverse,以此类推.
--  $libdir的实际目录位置可以用pg_config --pkglibdir命令找到。
CREATE OR REPLACE FUNCTION sahe_add(text, text, text, text) RETURNS text
AS
'$libdir/libudf',
'sahe_add'
    COST 5000
    PARALLEL SAFE
    LANGUAGE C;
CREATE OR REPLACE FUNCTION sahe_addplain(text, INTEGER) RETURNS text
AS
'$libdir/libudf',
'sahe_addplain'
    COST 5000
    PARALLEL SAFE
    LANGUAGE C;
CREATE OR REPLACE FUNCTION sahe_substract(text, text, text, text) RETURNS text
AS
'$libdir/libudf',
'sahe_substract'
    COST 5000
    PARALLEL SAFE
    LANGUAGE C;
CREATE OR REPLACE FUNCTION sahe_sbustract(text, text, text, text) RETURNS text
AS
'$libdir/libudf',
'sahe_substract'
    COST 5000
    PARALLEL SAFE
    LANGUAGE C;
CREATE OR REPLACE FUNCTION sahe_multiply(text, INTEGER) RETURNS text
AS
'$libdir/libudf',
'sahe_multiply'
    COST 5000
    PARALLEL SAFE
    LANGUAGE C;
CREATE OR REPLACE FUNCTION sahe_negate(text) RETURNS text
AS
'$libdir/libudf',
'sahe_negate'
    COST 5000
    PARALLEL SAFE
    LANGUAGE C;
CREATE OR REPLACE FUNCTION smhe_multiply(text, text, text, text) RETURNS text
AS
'$libdir/libudf',
'smhe_multiply'
    COST 5000
    PARALLEL SAFE
    LANGUAGE C;
CREATE OR REPLACE FUNCTION smhe_multiplyplain(text, INTEGER) RETURNS text
AS
'$libdir/libudf',
'smhe_multiplyplain'
    COST 5000
    PARALLEL SAFE
    LANGUAGE C;
CREATE OR REPLACE FUNCTION smhe_divide(text, text, text, text) RETURNS text
AS
'$libdir/libudf',
'smhe_divide'
    COST 5000
    PARALLEL SAFE
    LANGUAGE C;
CREATE OR REPLACE FUNCTION smhe_pow(text, text, INTEGER) RETURNS text
AS
'$libdir/libudf',
'smhe_pow'
    COST 5000
    PARALLEL SAFE
    LANGUAGE C;
CREATE OR REPLACE FUNCTION smhe_inverse(text) RETURNS text
AS
'$libdir/libudf',
'smhe_inverse'
    COST 5000
    PARALLEL SAFE
    LANGUAGE C;
CREATE OR REPLACE FUNCTION udf_ore_lt(text, text, text, text) RETURNS BOOLEAN
AS
'$libdir/libudf',
'udf_ore_lt'
    COST 5000
    PARALLEL SAFE
    LANGUAGE C;
CREATE OR REPLACE FUNCTION udf_ore_le(text, text, text, text) RETURNS BOOLEAN
AS
'$libdir/libudf',
'udf_ore_le'
    COST 5000
    PARALLEL SAFE
    LANGUAGE C;
CREATE OR REPLACE FUNCTION udf_ore_gt(text, text, text, text) RETURNS BOOLEAN
    IMMUTABLE
AS
'$libdir/libudf',
'udf_ore_gt'
    COST 5000
    PARALLEL SAFE
    LANGUAGE C;
CREATE OR REPLACE FUNCTION udf_ore_ge(text, text, text, text) RETURNS BOOLEAN
AS
'$libdir/libudf',
'udf_ore_ge'
    COST 5000
    PARALLEL SAFE
    LANGUAGE C;
CREATE OR REPLACE FUNCTION udf_ore_ee(text, text, text, text) RETURNS BOOLEAN
AS
'$libdir/libudf',
'udf_ore_ee'
    COST 5000
    PARALLEL SAFE
    LANGUAGE C;
CREATE OR REPLACE FUNCTION udf_ore_ne(text, text, text, text) RETURNS BOOLEAN
AS
'$libdir/libudf',
'udf_ore_ne'
    COST 5000
    PARALLEL SAFE
    LANGUAGE C;
DROP AGGREGATE IF EXISTS sahe_sum(text, text);
DROP AGGREGATE IF EXISTS ore_max(text, text);
DROP AGGREGATE IF EXISTS ore_min(text, text);
CREATE OR REPLACE FUNCTION sum_sahe_sfunc(text, text, text) RETURNS text
AS
'$libdir/libudf',
'sum_sahe_sfunc'
    COST 5000
    LANGUAGE C
    IMMUTABLE
    STRICT;
CREATE AGGREGATE sahe_sum(text, text)
    (
    sfunc = sum_sahe_sfunc,
    stype = text,
    initcond = ''
    );
CREATE OR REPLACE FUNCTION ore_max_sfunc(text, text, text) RETURNS text
AS
'$libdir/libudf',
'ore_max_sfunc'
    COST 5000
    PARALLEL SAFE
    LANGUAGE C
    IMMUTABLE
    STRICT;
CREATE OR REPLACE FUNCTION ore_max_final(text) RETURNS text
AS
'$libdir/libudf',
'ore_max_final'
    COST 5000
    PARALLEL SAFE
    LANGUAGE C
    IMMUTABLE
    STRICT;
CREATE AGGREGATE ore_max(text, text)
    (
    sfunc = ore_max_sfunc,
    finalfunc = ore_max_final,
    stype = text,
    initcond = ''
    );
CREATE OR REPLACE FUNCTION ore_min_sfunc(text, text, text) RETURNS text
AS
'$libdir/libudf',
'ore_min_sfunc'
    COST 5000
    PARALLEL SAFE
    LANGUAGE C
    IMMUTABLE
    STRICT;
CREATE OR REPLACE FUNCTION ore_min_final(text) RETURNS text
AS
'$libdir/libudf',
'ore_min_final'
    COST 5000
    PARALLEL SAFE
    LANGUAGE C
    IMMUTABLE
    STRICT;
CREATE AGGREGATE ore_min(text, text)
    (
    sfunc = ore_min_sfunc,
    finalfunc = ore_min_final,
    stype = text,
    initcond = ''
    );
CREATE TYPE ore_en;
CREATE OR REPLACE FUNCTION ore_en_in(cstring) RETURNS ore_en
AS
'$libdir/libudf'
    LANGUAGE C IMMUTABLE
               STRICT;
CREATE OR REPLACE FUNCTION ore_en_out(ore_en) RETURNS cstring
AS
'$libdir/libudf'
    LANGUAGE C IMMUTABLE
               STRICT;
/*
CREATE FUNCTION ore_en_recv(internal) RETURNS ore_en
AS '$libdir/libudf'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION ore_en_send(ore_en) RETURNS bytea
AS '$libdir/libudf'
LANGUAGE C IMMUTABLE STRICT;
*/
CREATE TYPE ore_en
(
    input = ore_en_in,
    output = ore_en_out, --RECEIVE        = ore_en_recv,
--SEND           = ore_en_send,
    INTERNALLENGTH = VARIABLE,
    STORAGE = extended,
    CATEGORY = 'S',
    PREFERRED = false,
    COLLATABLE = true
);
CREATE FUNCTION ore_en_abs_lt(ore_en, ore_en) RETURNS bool AS
'$libdir/libudf' LANGUAGE C IMMUTABLE
                            STRICT;
CREATE FUNCTION ore_en_abs_le(ore_en, ore_en) RETURNS bool AS
'$libdir/libudf' LANGUAGE C IMMUTABLE
                            STRICT;
CREATE FUNCTION ore_en_abs_gt(ore_en, ore_en) RETURNS bool AS
'$libdir/libudf' LANGUAGE C IMMUTABLE
                            STRICT;
CREATE FUNCTION ore_en_abs_ge(ore_en, ore_en) RETURNS bool AS
'$libdir/libudf' LANGUAGE C IMMUTABLE
                            STRICT;
CREATE FUNCTION ore_en_abs_eq(ore_en, ore_en) RETURNS bool AS
'$libdir/libudf' LANGUAGE C IMMUTABLE
                            STRICT;
CREATE FUNCTION ore_en_abs_ne(ore_en, ore_en) RETURNS bool AS
'$libdir/libudf' LANGUAGE C IMMUTABLE
                            STRICT;
CREATE OPERATOR < (
    leftarg = ore_en, rightarg = ore_en, procedure = ore_en_abs_lt,
    commutator = > , negator = >= ,
    restrict = scalarltsel, join = scalarltjoinsel
    );
CREATE OPERATOR <= (
    leftarg = ore_en, rightarg = ore_en, procedure = ore_en_abs_le,
    commutator = >= , negator = > ,
    restrict = scalarltsel, join = scalarltjoinsel
    );
CREATE OPERATOR = (
    leftarg = ore_en, rightarg = ore_en, procedure = ore_en_abs_eq,
    commutator = = ,
    restrict = eqsel, join = eqjoinsel
    );
CREATE OPERATOR <> (
    leftarg = ore_en, rightarg = ore_en, procedure = ore_en_abs_ne,
    commutator = <> ,
    restrict = neqsel, join = neqjoinsel
    );
CREATE OPERATOR >= (
    leftarg = ore_en, rightarg = ore_en, procedure = ore_en_abs_ge,
    commutator = <= , negator = < ,
    restrict = scalargtsel, join = scalargtjoinsel
    );
CREATE OPERATOR > (
    leftarg = ore_en, rightarg = ore_en, procedure = ore_en_abs_gt,
    commutator = < , negator = <= ,
    restrict = scalargtsel, join = scalargtjoinsel
    );
CREATE FUNCTION ore_en_abs_cmp(ore_en, ore_en) RETURNS int4
AS
'$libdir/libudf' LANGUAGE C IMMUTABLE
                            STRICT;
CREATE OPERATOR CLASS ore_en_abs_ops
    DEFAULT FOR TYPE ore_en USING btree AS
    OPERATOR 1 < ,
    OPERATOR 2 <= ,
    OPERATOR 3 <> ,
    OPERATOR 4 >= ,
    OPERATOR 5 > ,
    FUNCTION 1 ore_en_abs_cmp(ore_en, ore_en);
CREATE OR REPLACE FUNCTION ore_en_min_sfunc(ore_en, ore_en, text) RETURNS ore_en
AS
'$libdir/libudf',
'ore_en_min_sfunc'
    LANGUAGE C IMMUTABLE
               STRICT;
CREATE OR REPLACE FUNCTION ore_en_min_final(ore_en) RETURNS ore_en
AS
'$libdir/libudf',
'ore_en_min_final'
    LANGUAGE C IMMUTABLE
               STRICT;
CREATE AGGREGATE ore_min(ore_en, text)
    (
    sfunc = ore_en_min_sfunc,
    finalfunc = ore_en_min_final,
    stype = ore_en,
    initcond = ''
    );
CREATE OR REPLACE FUNCTION ore_en_max_sfunc(ore_en, ore_en, text) RETURNS ore_en
AS
'$libdir/libudf',
'ore_en_max_sfunc'
    LANGUAGE C IMMUTABLE
               STRICT;
CREATE OR REPLACE FUNCTION ore_en_max_final(ore_en) RETURNS ore_en
AS
'$libdir/libudf',
'ore_en_max_final'
    LANGUAGE C IMMUTABLE
               STRICT;
CREATE AGGREGATE ore_max(ore_en, text)
    (
    sfunc = ore_en_max_sfunc,
    finalfunc = ore_en_max_final,
    stype = ore_en,
    initcond = ''
    );



UPDATE pg_aggregate
SET agginitval = NULL
WHERE aggfnoid IN (SELECT oid
                   FROM pg_proc
                   WHERE proname IN ('ore_max', 'ore_min', 'sahe_sum'));


-- 添加rotate_id列
CREATE OR REPLACE FUNCTION add_rotate_id_column()
RETURNS event_trigger AS $$
DECLARE
    obj record;
BEGIN
    FOR obj IN SELECT * FROM pg_event_trigger_ddl_commands() WHERE command_tag = 'CREATE TABLE' LOOP
        IF obj.object_type = 'table' AND obj.schema_name NOT IN ('pg_catalog', 'information_schema') THEN
            BEGIN
                EXECUTE format(
                  'ALTER TABLE %s ADD COLUMN rotate_id SERIAL UNIQUE',
                  obj.object_identity
                );
                RAISE NOTICE 'Added rotate_id to %', obj.object_identity;
            EXCEPTION
                WHEN OTHERS THEN
                    RAISE WARNING 'Failed to add rotate_id to %: %', obj.object_identity, SQLERRM;
            END;
        END IF;
    END LOOP;
END;
$$ LANGUAGE plpgsql;

-- DROP FUNCTION add_rotate_id_column();

-- 创建事件触发器
CREATE EVENT TRIGGER add_rotate_id_trigger 
ON ddl_command_end
WHEN TAG IN ('CREATE TABLE')
EXECUTE FUNCTION add_rotate_id_column();

-- 如果需要删除触发器（测试时可能需要）
-- DROP EVENT TRIGGER IF EXISTS add_rotate_id_trigger;
