12 Star 43 Fork 14

enmotech / compat-tools

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
MySQL_Functions.sql 112.75 KB
一键复制 编辑 原始数据 按行查看 历史
DarkAthena 提交于 2024-04-16 01:06 . Update MySQL_Functions.sql
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001
-- This scripts contains following function's definition:
-- =============================================================================
-- NULL 相关函数
-- 注意: ifnull 效果等同于通用函数 coalesce,在条件允许的情况下,建议修改 SQL 使用 coalesce 函数,该函数几乎在各个数据库中均支持
-- ifnull(text,text)
-- ifnull(numeric,numeric)
-- ifnull(timestamp,timestamp)
-- ifnull(timestamptz,timestamptz)
-- isnull(text)
-- isnull(numeric)
-- isnull(timestamptz)
-- 条件控制函数
-- if(bool,bool,bool)
-- if(bool,text,text)
-- if(bool,numeric,numeric)
-- if(bool,timestamptz,timestamptz)
-- 字符函数
-- find_in_set(text,text)
-- find_in_set(text,text[])
-- field(text,text[])
-- elt(int4,text[])
-- strcmp(text,text)
-- insert(text,int8,int8,text)
-- lcase(text)
-- ucase(text)
-- space(int4)
-- mid(text,int8,int8)
-- locate(text,text,int4)
-- to_base64(text)
-- from_base64(text)
-- 数字函数
-- field(numeric,numeric[])
-- log10(numeric)
-- log10(float8)
-- rand(int4)
-- 时间函数
-- unix_timestamp(timestamp)
-- unix_timestamp(timestamptz)
-- from_unixtime(int8)
-- from_unixtime(numeric)
-- from_unixtime(numeric,text)
-- to_days(timestamp)
-- to_days(timestamptz)
-- to_days(text)
-- to_days(text,text)
-- to_days(int8)
-- to_seconds(timestamp)
-- to_seconds(timestamptz)
-- timediff(timestamptz,timestamptz)
-- time_to_sec(time)
-- sec_to_time(int4)
-- date_format(timestamp,text)
-- date_format(timestamptz,text)
-- timestampdiff(text,timestamptz,timestamptz)
-- str_to_date(text,text)
-- curdate()
-- yearweek(timestamp,int4)
-- yearweek(timestamptz,int4)
-- yearweek(text,int4)
-- date_add(timestamp,interval)
-- date_add(timestamptz,interval)
-- 其他函数
-- uuid()
-- uuid_to_bin(uuid,int4)
-- bin_to_uuid(bytea,int4)
-- conv(text,int4,int4)
-- json_extract(json,text)
-- json_extract(json,text[])
set client_min_messages='warning';
set time zone 'UTC';
set statement_timeout = 60000;
set behavior_compat_options = '';
-- =============================================================================
-- Create Schema
-- =============================================================================
do $$
declare
l_cnt bigint;
l_version varchar(10);
begin
set client_min_messages='warning';
select count(*) into l_cnt from pg_catalog.pg_namespace where nspname = 'compat_tools';
if l_cnt = 0
then
create schema compat_tools;
end if;
end;
$$ language plpgsql;
-- =============================================================================
-- Version Table
-- =============================================================================
create table if not exists compat_tools.compat_version
(
compat_type varchar(10), -- VIEW, FUNCTION, PROCEDURE
object_name varchar(128), -- Compat object name
object_version varchar(10), -- Compat object version
constraint pk_compat_version primary key(compat_type, object_name)
);
-- =============================================================================
-- Table: compat_tools.pg_function_list
-- =============================================================================
drop table if exists compat_tools.pg_function_list;
create table compat_tools.pg_function_list as
select p.oid
, l.lanname as language
, n.nspname as schema_name
, p.proname || '(' || string_agg(case when a.typname is not null then a.typname||'[]' else t.typname end, ',' order by p.id) || ')' as function_name
from (select oid
, pronamespace
, proname
, prolang
, case when proallargtypes is null then proargtypes else proallargtypes end as proallargtypes
, generate_series(1, array_length(case when proallargtypes is null then proargtypes else proallargtypes end, 1)) as id
, unnest(case when proallargtypes is null then proargtypes else proallargtypes end) as protype
from pg_catalog.pg_proc
) as p
join pg_catalog.pg_namespace as n on p.pronamespace = n.oid
join pg_catalog.pg_language as l on p.prolang = l.oid
join pg_catalog.pg_type as t on p.protype = t.oid
left join pg_catalog.pg_type as a on t.typcategory = 'A' and t.typelem = a.oid -- for array type
group by p.proname, p.proallargtypes, l.lanname, p.oid, n.nspname
union all
select p.oid, l.lanname, n.nspname, p.proname||'()'
from pg_catalog.pg_proc as p
join pg_catalog.pg_namespace as n on p.pronamespace = n.oid
join pg_catalog.pg_language as l on p.prolang = l.oid
where (oidvectortypes(p.proargtypes) is null or oidvectortypes(p.proargtypes) = '');
-- =============================================================================
-- Table: compat_tools.pg_depend_list
-- =============================================================================
drop table if exists compat_tools.pg_depend_list;
create table compat_tools.pg_depend_list as
select distinct dep.classid::regclass::text as object_type
, coalesce(typ_n.nspname, coalesce(cls_n.nspname, dep.objid::text)) as schema_name
, coalesce(typ.typname, coalesce(cls.relname, dep.objid::text)) as object_name
, dep.refclassid::regclass::text as ref_object_type
, cpt.object_name as ref_object_name
, cpt.compat_type
, case dep.deptype when 'n' then 'NORMAL' when 'a' then 'AUTO' when 'i' then 'INTERNAL' when 'e' then 'EXTENSION' when 'p' then 'PIN' when 'x' then 'AUTO_EXTENSION' when 'I' then 'INTERNAL_AUTO' else dep.deptype::text end as DEPENDENCY_TYPE
from pg_depend as dep
join (select v.compat_type, v.object_name, l.language, coalesce(l.oid, c.oid) as oid
from compat_tools.compat_version as v
left join compat_tools.pg_function_list as l on v.object_name = l.schema_name||'.'||l.function_name
left join (select cls.oid, nsp.nspname||'.'||cls.relname object_name
from pg_catalog.pg_class as cls
join pg_catalog.pg_namespace as nsp on cls.relnamespace = nsp.oid
) as c on v.object_name = c.object_name
where v.compat_type in ('aggregate', 'procedure', 'function', 'view')) as cpt on dep.refobjid = cpt.oid
left join pg_type as typ on dep.classid = 'pg_type'::regclass and dep.objid = typ.oid
left join pg_namespace as typ_n on typ_n.oid = typ.typnamespace
left join pg_rewrite as rwt on dep.classid = 'pg_rewrite'::regclass and dep.objid = rwt.oid
left join pg_class as cls on rwt.ev_class = cls.oid
left join pg_namespace as cls_n on cls_n.oid = cls.relnamespace
where coalesce(typ_n.nspname, coalesce(cls_n.nspname, dep.objid::text)) != 'compat_tools';
-- =============================================================================
-- Version Function
-- =============================================================================
drop function if exists compat_tools.drop_compat_function(varchar, varchar, varchar, varchar, varchar);
create or replace function compat_tools.drop_compat_function( p_object_type varchar(10)
, p_object_name varchar(128)
, p_object_version varchar(10)
, p_function_lang varchar(16) default 'sql'
, p_object_schema varchar(128) default 'pg_catalog')
returns boolean
as $$
declare
l_version varchar(10);
l_language varchar(16);
l_result boolean := true;
l_operation varchar(128);
l_depend_cnt bigint;
l_app_name varchar(128) := current_setting('application_name');
begin
CREATE temporary table if not exists temp_result
(
object_type varchar(10),
object_name varchar(128),
local_version varchar(10),
script_version varchar(10),
local_language varchar(10),
script_language varchar(10),
operation varchar(128)
);
-- 字符串参数统一转小写
p_object_name := lower(p_object_name);
p_object_type := lower(p_object_type);
p_object_schema := lower(p_object_schema);
select max(object_version) into l_version
from compat_tools.compat_version
where object_name = p_object_schema||'.'||p_object_name
and compat_type = p_object_type;
-- 获取已有同名同参数函数/存储过程的语言,存入 l_language 变量
select max(language) into l_language
from compat_tools.pg_function_list
where schema_name = p_object_schema
and function_name = p_object_name;
-- 获取非 Compat Tools 依赖对象数量
select count(*) into l_depend_cnt
from compat_tools.pg_depend_list
where ref_object_name = p_object_schema||'.'||p_object_name;
if l_language is null
then
l_operation := 'Initial creation';
elsif l_language != p_function_lang
then
l_result = 'false';
l_operation := 'Skip due to language';
elsif l_version is null
then
l_operation := 'Initial creation (Ver)';
elsif l_version < p_object_version
then
l_operation := 'Upgrade';
else
l_result = 'false';
l_operation := 'Skip due to version';
end if;
if l_app_name != 'checkMe'
then
if l_result
then
begin
-- 若系统中存在非 compat_tools 对象依赖本对象,无法删除,可尝试直接创建
if l_depend_cnt = 0
then
if instr(p_object_name, '(') > 0
then
execute 'drop '||p_object_type||' if exists "'||p_object_schema||'"."'||replace(p_object_name, '(', '"(')||' cascade';
else
execute 'drop '||p_object_type||' if exists "'||p_object_schema||'"."'||p_object_name||'" cascade';
end if;
insert into compat_tools.compat_version
values (p_object_type, p_object_schema||'.'||p_object_name, p_object_version)
ON DUPLICATE KEY UPDATE object_version = p_object_version;
else
l_operation := l_operation||' - dependence';
end if;
exception
when others then
l_result := 'false';
get stacked diagnostics l_operation = message_text;
l_operation = substr(l_operation, 1, 32);
end;
else
insert into compat_tools.compat_version
values (p_object_type, p_object_schema||'.'||p_object_name, p_object_version)
ON DUPLICATE KEY UPDATE NOTHING;
end if;
end if;
-- 插入本次临时结果表
insert into temp_result values ( p_object_type
, p_object_schema||'.'||p_object_name
, l_version
, p_object_version
, l_language
, p_function_lang
, l_operation);
-- 返回函数结果
if l_app_name = 'checkMe'
then
return 'false';
else
return l_result;
end if;
end;
$$ language plpgsql;
-- =============================================================================
-- Testing Table/Procedure
-- =============================================================================
create table if not exists compat_tools.compat_testing
(
test_expr text, -- 测试表达式
test_result text, -- 表达式结果
expect_result text, -- 预期结果
test_ok bool, -- 测试是否通过
test_timestamp timestamp default now(), -- 测试时间
constraint pk_compat_testing_expr primary key(test_expr)
);
drop procedure if exists compat_tools.f_unit_test(text, text, text, text);
create or replace procedure compat_tools.f_unit_test( p_test_expr text
, p_expect text
, p_compare_type text default '='
, p_db_compat text default NULL)
as
declare
l_compat_valid bool := 'true'::bool;
l_error_code text;
l_error_mesg text;
l_test_result text;
l_test_ok bool;
l_app_name varchar(128) := current_setting('application_name');
begin
if l_app_name != 'checkMe'
then
if p_db_compat is not null
then
select count(*)::bool
into l_compat_valid
from pg_database
where datname = current_database()
and datcompatibility = p_db_compat;
end if;
if l_compat_valid
then
execute immediate 'select '||p_test_expr||', cast('||p_test_expr||' as text) '||p_compare_type||' '||p_expect
into l_test_result, l_test_ok;
insert into compat_tools.compat_testing
values (p_test_expr, l_test_result, p_compare_type||' '||p_expect, l_test_ok)
on DUPLICATE KEY UPDATE test_result = EXCLUDED.test_result
, expect_result = EXCLUDED.expect_result
, test_ok = EXCLUDED.test_ok
, test_timestamp = now();
end if;
end if;
exception
when others then
get stacked diagnostics l_error_code = returned_sqlstate, l_error_mesg = message_text;
insert into compat_tools.compat_testing
values (p_test_expr, l_error_code||': '||l_error_mesg, p_compare_type||' '||p_expect, l_error_code||': '||l_error_mesg = trim(p_expect, ''''))
on DUPLICATE KEY UPDATE test_result = EXCLUDED.test_result
, expect_result = EXCLUDED.expect_result
, test_ok = EXCLUDED.test_ok
, test_timestamp = now();
end;
/
-- =============================================================================
-- Version Comparison Function
-- Result:
-- version_a > version_b => 1
-- version_a = version_b => 0
-- version_a < version_b => -1
-- =============================================================================
create or replace function pg_catalog.f_version_compare ( version_a text
, version_b text)
returns int IMMUTABLE strict as $$
declare
l_rec record;
begin
if version_a !~ '^\d+(\.\d+)*$' or version_b !~ '^\d+(\.\d+)*$'
then
return null;
end if;
for l_rec in select coalesce(t1.ver, -1) as ver_1, coalesce(t2.ver, -1) as ver_2
from (select rownum as id, t1::int as ver from regexp_split_to_table(version_a, '\.') as t1) as t1
full outer join (select rownum as id, t2::int as ver from regexp_split_to_table(version_b, '\.') as t2) as t2
on t1.id = t2.id
loop
if l_rec.ver_1 > l_rec.ver_2
then
return 1;
elsif l_rec.ver_1 < l_rec.ver_2
then
return -1;
end if;
end loop;
return 0;
end;
$$ language plpgsql;
-- =========================================================================
-- 测试用例:
-- ----------
-- select compat_tools.f_unit_test('f_version_compare (''1.1.1'', ''2.0.0'')', '-1');
-- select compat_tools.f_unit_test('f_version_compare (''2.1.1'', ''2.0.0'')', '1');
-- select compat_tools.f_unit_test('f_version_compare (''1.2.3'', ''1.2.3'')', '0');
-- select compat_tools.f_unit_test('f_version_compare (''1.2.3'', ''1.12.3'')', '-1');
-- select compat_tools.f_unit_test('f_version_compare (''1.2.3.4'', ''1.2.3'')', '1');
-- select compat_tools.f_unit_test('f_version_compare (''1.2.3'', ''1.2.3.4'')', '-1');
-- select compat_tools.f_unit_test('f_version_compare (''1.2...3'', ''1.2.3.4'')', 'NULL', 'IS');
-- select compat_tools.f_unit_test('f_version_compare (null, ''1.2.3.4'')', 'NULL', 'IS');
-- select * from compat_tools.compat_testing where test_expr like 'f_version_compare%';
-- =========================================================================
-- =============================================================================
-- All creations are running in ANONYMOUS BLOCK
-- =============================================================================
do $VIEW_CREATION$
declare
l_cnt bigint;
l_result text;
begin
begin
execute 'set dolphin.sql_mode = ''sql_mode_full_group,pipes_as_concat,ansi_quotes,pad_char_to_full_length''';
exception when others then null;
end;
-- =========================================================================
-- 注意: ifnull 效果等同于 coalesce 函数,在条件允许的情况下,建议修改 SQL 使用 coalesce 函数,几乎在各个数据库中均支持
-- ifnull(text,text)
-- ifnull(numeric,numeric)
-- ifnull(timestamp,timestamp)
-- ifnull(timestamptz,timestamptz)
-- =========================================================================
if compat_tools.drop_compat_function('function', 'ifnull(text,text)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.ifnull(p1 text, p2 text)
RETURNS text IMMUTABLE AS $$
SELECT coalesce(p1, p2);
$$ LANGUAGE sql;
end if;
if compat_tools.drop_compat_function('function', 'ifnull(numeric,numeric)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.ifnull(p1 numeric, p2 numeric)
RETURNS numeric IMMUTABLE AS $$
SELECT coalesce(p1, p2);
$$ LANGUAGE sql;
end if;
if compat_tools.drop_compat_function('function', 'ifnull(timestamp,timestamp)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.ifnull(p1 timestamp, p2 timestamp)
RETURNS timestamp IMMUTABLE AS $$
SELECT coalesce(p1, p2);
$$ LANGUAGE sql;
end if;
if compat_tools.drop_compat_function('function', 'ifnull(timestamptz,timestamptz)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.ifnull(p1 timestamptz, p2 timestamptz)
RETURNS timestamptz IMMUTABLE AS $$
SELECT coalesce(p1, p2);
$$ LANGUAGE sql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
if f_version_compare((regexp_split_to_array(substr(version(), instr(version(), '(') + 1), '\s+'))[2], '3.1.0') = 1 then
select compat_tools.f_unit_test('pg_typeof(ifnull(123, 1111))', '''numeric''',p_db_compat =>'A') into l_result;
select compat_tools.f_unit_test('pg_typeof(ifnull(123, 1111))', '''numeric''',p_db_compat =>'PG') into l_result;
select compat_tools.f_unit_test('pg_typeof(ifnull(123, 1111))', '''integer''',p_db_compat =>'B') into l_result;
else
select compat_tools.f_unit_test('pg_typeof(ifnull(123, 1111))', '''numeric''') into l_result;
end if;
select compat_tools.f_unit_test('pg_typeof(ifnull(''xyz'', ''abc''))', '''text''') into l_result;
select compat_tools.f_unit_test('pg_typeof(ifnull(now()::timestamp without time zone, now()::timestamp without time zone))', '''timestamp without time zone''') into l_result;
select compat_tools.f_unit_test('pg_typeof(ifnull(''xyz''::text, 1111))', '''text''') into l_result;
select compat_tools.f_unit_test('ifnull(null, null)', 'NULL', 'IS') into l_result;
select compat_tools.f_unit_test('ifnull(123, 1111)', '123') into l_result;
select compat_tools.f_unit_test('ifnull(null, 1111)', '1111') into l_result;
select compat_tools.f_unit_test('ifnull(123, null)', '123') into l_result;
select compat_tools.f_unit_test('ifnull(''xyz'', ''abc'')', '''xyz''') into l_result;
select compat_tools.f_unit_test('ifnull(null, ''abc'')', '''abc''') into l_result;
select compat_tools.f_unit_test('ifnull(''xyz'', null)', '''xyz''') into l_result;
select compat_tools.f_unit_test('ifnull(''2012-12-12 12:12:12''::timestamp, ''1111-11-11 11:11:11''::timestamp)', '''2012-12-12 12:12:12''') into l_result;
select compat_tools.f_unit_test('ifnull(null, ''1111-11-11 11:11:11''::timestamp)', '''1111-11-11 11:11:11''') into l_result;
select compat_tools.f_unit_test('ifnull(''2012-12-12 12:12:12''::timestamp, null)', '''2012-12-12 12:12:12''') into l_result;
select compat_tools.f_unit_test('ifnull(''xyz''::text, 1111)', '''xyz''') into l_result;
select compat_tools.f_unit_test('ifnull(null::text, 1111)', '''1111''') into l_result;
select compat_tools.f_unit_test('ifnull(''xyz''::text, null)', '''xyz''') into l_result;
-- =========================================================================
-- =========================================================================
-- find_in_set(text,text)
-- find_in_set(text,text[])
-- =========================================================================
if compat_tools.drop_compat_function('function', 'find_in_set(text,text)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.find_in_set(str text, strlist text)
RETURNS bigint IMMUTABLE AS $$
select case when str is null or strlist is null then null
else (select coalesce(min(id), 0) from (select rownum as id, unnest(string_to_array(strlist, ',')) as elem) as x where elem = str)
end;
$$ LANGUAGE sql;
end if;
if compat_tools.drop_compat_function('function', 'find_in_set(text,text[])', '1.0')
then
CREATE or replace FUNCTION pg_catalog.find_in_set(str text, strlist text[])
RETURNS bigint IMMUTABLE AS $$
select case when str is null or strlist is null then null
else (select coalesce(min(id), 0) from (select rownum as id, unnest(strlist) as elem) as x where elem = str)
end;
$$ LANGUAGE sql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
select compat_tools.f_unit_test('find_in_set(''b'', ''a,b,c,dx'')', '2') into l_result;
select compat_tools.f_unit_test('find_in_set(''x'', ''a,b,c,dx'')', '0') into l_result;
select compat_tools.f_unit_test('find_in_set(''d'', ''a,b,c,dx'')', '0') into l_result;
select compat_tools.f_unit_test('find_in_set(''dx'', ''a,b,c,dx'')', '4') into l_result;
select compat_tools.f_unit_test('find_in_set(null,''a,b,c,dx'')', 'NULL', 'IS') into l_result;
select compat_tools.f_unit_test('find_in_set(''x'',null)', 'NULL', 'IS') into l_result;
select compat_tools.f_unit_test('find_in_set('''',''a,b,c,dx'')', '0', p_db_compat => 'B') into l_result; -- Failed in A
select compat_tools.f_unit_test('find_in_set('''',''a,b,c,dx'')', '0', p_db_compat => 'PG') into l_result; -- Failed in A
select compat_tools.f_unit_test('find_in_set(''x'','''')', '0', p_db_compat => 'B') into l_result; -- Failed in A
select compat_tools.f_unit_test('find_in_set(''x'','''')', '0', p_db_compat => 'PG') into l_result; -- Failed in A
select compat_tools.f_unit_test('find_in_set('''',''a,b,c,,dx'')', '4', p_db_compat => 'B') into l_result; -- Failed in A
select compat_tools.f_unit_test('find_in_set('''',''a,b,c,,dx'')', '4', p_db_compat => 'PG') into l_result; -- Failed in A
select compat_tools.f_unit_test('find_in_set(''b'', string_to_array(''a,b,c,dx'', '',''))', '2') into l_result;
select compat_tools.f_unit_test('find_in_set(''x'', string_to_array(''a,b,c,dx'', '',''))', '0') into l_result;
select compat_tools.f_unit_test('find_in_set(''d'', string_to_array(''a,b,c,dx'', '',''))', '0') into l_result;
select compat_tools.f_unit_test('find_in_set(''dx'', string_to_array(''a,b,c,dx'', '',''))', '4') into l_result;
select compat_tools.f_unit_test('find_in_set(null, string_to_array(''a,b,c,dx'', '',''))', 'NULL', 'IS') into l_result;
select compat_tools.f_unit_test('find_in_set('''', string_to_array(''a,b,c,dx'', '',''))', '0', p_db_compat => 'B') into l_result; -- Failed in A
select compat_tools.f_unit_test('find_in_set('''', string_to_array(''a,b,c,dx'', '',''))', '0', p_db_compat => 'PG') into l_result; -- Failed in A
select compat_tools.f_unit_test('find_in_set(''x'', string_to_array('''', '',''))', '0', p_db_compat => 'B') into l_result; -- Failed in A
select compat_tools.f_unit_test('find_in_set(''x'', string_to_array('''', '',''))', '0', p_db_compat => 'PG') into l_result; -- Failed in A
select compat_tools.f_unit_test('find_in_set('''', string_to_array(''a,b,c,,dx'', '',''))', '4', p_db_compat => 'B') into l_result; -- Failed in A
select compat_tools.f_unit_test('find_in_set('''', string_to_array(''a,b,c,,dx'', '',''))', '4', p_db_compat => 'PG') into l_result; -- Failed in A
-- =========================================================================
-- =========================================================================
-- field(text,VARIADIC text[])
-- field(numeric,VARIADIC numeric[])
-- =========================================================================
if compat_tools.drop_compat_function('function', 'field(text,text[])', '1.0')
then
CREATE or replace FUNCTION pg_catalog.field(str text, VARIADIC strlist text[])
RETURNS bigint IMMUTABLE AS $$
select case when str is null or strlist is null then 0
else (select coalesce(min(id), 0) from (select rownum as id, unnest(strlist) as elem) as x where elem = str)
end;
$$ LANGUAGE sql;
end if;
if compat_tools.drop_compat_function('function', 'field(numeric,numeric[])', '1.0')
then
CREATE or replace FUNCTION pg_catalog.field(str numeric, VARIADIC strlist numeric[])
RETURNS bigint IMMUTABLE AS $$
select case when str is null or strlist is null then 0
else (select coalesce(min(id), 0) from (select rownum as id, unnest(strlist) as elem) as x where elem = str)
end;
$$ LANGUAGE sql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
select compat_tools.f_unit_test('field(''Bb'', ''Aa'', ''Bb'', ''Cc'', ''Dd'', ''Ff'')', '2') into l_result;
select compat_tools.f_unit_test('field(''Gg'', ''Aa'', ''Bb'', ''Cc'', ''Dd'', ''Ff'')', '0') into l_result;
select compat_tools.f_unit_test('field(123, 1.23, 12.3, 123, 1234, 0.12)', '3') into l_result;
select compat_tools.f_unit_test('field(123, 1.23, 12.3, 23, 1234, 0.12)', '0') into l_result;
-- =========================================================================
-- =========================================================================
-- elt(int4,VARIADIC text[])
-- =========================================================================
if compat_tools.drop_compat_function('function', 'elt(int4,text[])', '1.0')
then
CREATE or replace FUNCTION pg_catalog.elt(str_pos int, VARIADIC strlist text[])
RETURNS text IMMUTABLE AS $$
select min(elem) from (select rownum as id, unnest(strlist) as elem) as x where id = str_pos;
$$ LANGUAGE sql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
select compat_tools.f_unit_test('elt( 2, ''Aa'', ''Bb'', ''Cc'', ''Dd'', ''Ff'')', '''Bb''') into l_result;
select compat_tools.f_unit_test('elt(1.2, ''Aa'', ''Bb'', ''Cc'', ''Dd'', ''Ff'')', '''Aa''') into l_result;
select compat_tools.f_unit_test('elt( 0, ''Aa'', ''Bb'', ''Cc'', ''Dd'', ''Ff'')', 'NULL', 'IS') into l_result;
select compat_tools.f_unit_test('elt( 10, ''Aa'', ''Bb'', ''Cc'', ''Dd'', ''Ff'')', 'NULL', 'IS') into l_result;
-- =========================================================================
-- =========================================================================
-- if(bool,bool,bool)
-- if(bool,text,text)
-- if(bool,numeric,numeric)
-- if(bool,timestamptz,timestamptz)
-- =========================================================================
if compat_tools.drop_compat_function('function', 'if(bool,bool,bool)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.if(check_condition boolean, true_expr bool, false_expr bool)
RETURNS bool IMMUTABLE AS $$
select case when check_condition then true_expr else false_expr end;
$$ LANGUAGE sql;
end if;
if compat_tools.drop_compat_function('function', 'if(bool,text,text)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.if(check_condition boolean, true_expr text, false_expr text)
RETURNS text IMMUTABLE AS $$
select case when check_condition then true_expr else false_expr end;
$$ LANGUAGE sql;
end if;
if compat_tools.drop_compat_function('function', 'if(bool,numeric,numeric)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.if(check_condition boolean, true_expr numeric, false_expr numeric)
RETURNS numeric IMMUTABLE AS $$
select case when check_condition then true_expr else false_expr end;
$$ LANGUAGE sql;
end if;
if compat_tools.drop_compat_function('function', 'if(bool,timestamptz,timestamptz)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.if(check_condition boolean, true_expr timestamptz, false_expr timestamptz)
RETURNS timestamptz IMMUTABLE AS $$
select case when check_condition then true_expr else false_expr end;
$$ LANGUAGE sql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
if f_version_compare((regexp_split_to_array(substr(version(), instr(version(), '(') + 1), '\s+'))[2], '3.1.0') = 1 then
select compat_tools.f_unit_test('if(1=1, ''yes''::bool, ''no''::bool)::text', '''true''',p_db_compat =>'A') into l_result;
select compat_tools.f_unit_test('if(1=1, ''yes''::bool, ''no''::bool)::text', '''true''',p_db_compat =>'PG') into l_result;
select compat_tools.f_unit_test('if(1=1, ''yes''::bool, ''no''::bool)::text', '''1''',p_db_compat =>'B') into l_result;
select compat_tools.f_unit_test('pg_typeof(if(''hongye''!=''debug'', 1, 2))', '''numeric''',p_db_compat =>'A') into l_result;
select compat_tools.f_unit_test('pg_typeof(if(''hongye''!=''debug'', 1, 2))', '''numeric''',p_db_compat =>'PG') into l_result;
select compat_tools.f_unit_test('pg_typeof(if(''hongye''!=''debug'', 1, 2))', '''integer''',p_db_compat =>'B') into l_result;
else
select compat_tools.f_unit_test('if(1=1, ''yes''::bool, ''no''::bool)::text', '''true''') into l_result;
select compat_tools.f_unit_test('pg_typeof(if(''hongye''!=''debug'', 1, 2))', '''numeric''') into l_result;
end if;
select compat_tools.f_unit_test('pg_typeof(if(1=1, ''yes''::bool, ''no''::bool))', '''boolean''') into l_result;
select compat_tools.f_unit_test('pg_typeof(if(1<2, ''yes'', ''no''))', '''text''') into l_result;
select compat_tools.f_unit_test('pg_typeof(if(instr(''hongye'', ''x''), ''1212-12-12''::timestamp, ''1111-11-11''::timestamp))', '''timestamp with time zone''') into l_result;
select compat_tools.f_unit_test('if(1<2, ''yes'', ''no'')', '''yes''') into l_result;
select compat_tools.f_unit_test('if(''hongye''!=''debug'', 1, 2)', '1') into l_result;
select compat_tools.f_unit_test('if(instr(''hongye'', ''x''), ''1212-12-12''::timestamp, ''1111-11-11''::timestamp)::timestamp', '''1111-11-11 00:00:00''') into l_result;
-- =========================================================================
-- =========================================================================
-- strcmp(text,text)
-- =========================================================================
if compat_tools.drop_compat_function('function', 'strcmp(text,text)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.strcmp(p1 text, p2 text)
RETURNS int IMMUTABLE AS $$
select case when p1 > p2 then 1 when p1 = p2 then 0 else -1 end;
$$ LANGUAGE sql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
select compat_tools.f_unit_test('strcmp(''text'', ''text2'')', '-1') into l_result;
select compat_tools.f_unit_test('strcmp(''text2'', ''text'')', '1') into l_result;
select compat_tools.f_unit_test('strcmp(''text'', ''text'')', '0') into l_result;
-- =========================================================================
-- =========================================================================
-- log10(numeric)
-- log10(float8)
-- =========================================================================
if compat_tools.drop_compat_function('function', 'log10(numeric)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.log10(p1 numeric)
RETURNS numeric IMMUTABLE AS $$
select case when p1 <= 0 then null else pg_catalog.log(p1) end;
$$ LANGUAGE sql;
end if;
if compat_tools.drop_compat_function('function', 'log10(float8)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.log10(p1 double precision)
RETURNS double precision IMMUTABLE AS $$
select case when p1 <= 0 then null else pg_catalog.log(p1) end;
$$ LANGUAGE sql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
select compat_tools.f_unit_test('log10(2)', '0.301029995663981') into l_result;
select compat_tools.f_unit_test('log10(100)', '2') into l_result;
select compat_tools.f_unit_test('log10(-100)', 'NULL', 'IS') into l_result;
-- =========================================================================
-- =========================================================================
-- insert(text,int8,int8,text)
-- =========================================================================
if compat_tools.drop_compat_function('function', 'insert(text,int8,int8,text)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.insert(p_source text, p_pos bigint, p_len bigint, p_replacement text)
RETURNS text IMMUTABLE AS $$
select case when p_source is null or p_pos is null or p_len is null or p_replacement is null then null
when p_pos <= 0 or p_pos > length(p_source) then p_source
else pg_catalog.substr(p_source, 1, p_pos - 1)||p_replacement||pg_catalog.substr(p_source, p_pos + p_len)
end;
$$ LANGUAGE sql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
select compat_tools.f_unit_test('insert(''Quadratic'', 3, 4, ''What'')', '''QuWhattic''') into l_result;
select compat_tools.f_unit_test('insert(''Quadratic'', -1, 4, ''What'')', '''Quadratic''') into l_result;
select compat_tools.f_unit_test('insert(''Quadratic'', 0, 2, ''What'')', '''Quadratic''') into l_result;
select compat_tools.f_unit_test('insert(''Quadratic'', 1, 2, ''What'')', '''Whatadratic''') into l_result;
select compat_tools.f_unit_test('insert(''Quadratic'', 9, 12, ''What'')', '''QuadratiWhat''') into l_result;
select compat_tools.f_unit_test('insert(''Quadratic'', 3, 100, ''What'')', '''QuWhat''') into l_result;
select compat_tools.f_unit_test('insert(''Quadratic'', 3, 100, null)', 'NULL', 'IS') into l_result;
select compat_tools.f_unit_test('insert(''Quadratic'', null, 100, ''What'')', 'NULL', 'IS') into l_result;
-- =========================================================================
-- =========================================================================
-- lcase(text)
-- =========================================================================
if compat_tools.drop_compat_function('function', 'lcase(text)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.lcase(p_source text)
RETURNS text IMMUTABLE AS $$
select pg_catalog.lower(p_source);
$$ LANGUAGE sql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
select compat_tools.f_unit_test('lcase(''QuadRatic'')', '''quadratic''') into l_result;
-- =========================================================================
-- =========================================================================
-- ucase(text)
-- =========================================================================
if compat_tools.drop_compat_function('function', 'ucase(text)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.ucase(p_source text)
RETURNS text IMMUTABLE AS $$
select pg_catalog.upper(p_source);
$$ LANGUAGE sql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
select compat_tools.f_unit_test('ucase(''QuadRatic'')', '''QUADRATIC''') into l_result;
-- =========================================================================
-- =========================================================================
-- space(int4)
-- =========================================================================
if compat_tools.drop_compat_function('function', 'space(int4)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.space(p_num int)
RETURNS text IMMUTABLE AS $$
select pg_catalog.repeat(' ', p_num);
$$ LANGUAGE sql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
select compat_tools.f_unit_test('concat(''|'', space(11), ''|'')', '''| |''') into l_result;
select compat_tools.f_unit_test('concat(''|'', space(-11), ''|'')', '''||''') into l_result;
select compat_tools.f_unit_test('concat(''|'', space(0), ''|'')', '''||''') into l_result;
-- =========================================================================
-- =========================================================================
-- mid(text,int8,int8)
-- =========================================================================
if compat_tools.drop_compat_function('function', 'mid(text,int8,int8)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.mid(p_source text, p_pos bigint, p_len bigint)
RETURNS text IMMUTABLE AS $$
select pg_catalog.substr(p_source, p_pos, p_len);
$$ LANGUAGE sql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
select compat_tools.f_unit_test('mid(''Hongye'', 2, 4)', '''ongy''') into l_result;
select compat_tools.f_unit_test('mid(''Hongye'', -2, 4)', '''ye''') into l_result;
select compat_tools.f_unit_test('coalesce(mid(''Hongye'', 12, 4), ''NULL'')', 'coalesce('''', ''NULL'')') into l_result; -- 数据库兼容模式 A/B
select compat_tools.f_unit_test('coalesce(mid(''Hongye'', 2, -4), ''NULL'')', 'coalesce('''', ''NULL'')') into l_result; -- 数据库兼容模式 A/B
-- =========================================================================
-- =========================================================================
-- locate(text,text,int4)
-- locate(text,text,int4,text)
-- =========================================================================
if compat_tools.drop_compat_function('function', 'locate(text,text,int4)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.locate( p_sub text
, p_source text
, p_pos int default 1)
RETURNS int IMMUTABLE strict AS $$
select pg_catalog.instr(p_source, p_sub, p_pos);
$$ LANGUAGE sql;
end if;
if compat_tools.drop_compat_function('function', 'locate(text,text,int4,text)', '2.0')
then
CREATE OR REPLACE FUNCTION pg_catalog.locate( p_sub text ,
p_source text ,
p_pos INT ,
p_charset text ) RETURNS INT IMMUTABLE strict
AS
$$
declare l_return INT;
BEGIN
IF p_charset is null or p_charset='' or p_charset='CODEUNITS32' THEN
l_return:= pg_catalog.instr(p_source, p_sub, p_pos);
ELSIF p_charset='OCTETS' THEN
l_return:= pg_catalog.instrb(p_source, p_sub, p_pos);
ELSEIF p_charset='CODEUNITS16' THEN
raise 'CODEUNITS16 isn''t unsupport!';
else
raise 'parameter p_charset error!';
END IF;
RETURN l_return;
END;
$$ LANGUAGE plpgsql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
select compat_tools.f_unit_test('locate(''bar'', ''foobarbar'')', '4') into l_result;
select compat_tools.f_unit_test('locate(''xbar'', ''foobar'')', '0') into l_result;
select compat_tools.f_unit_test('locate(''bar'', ''foobarbar'', 5)', '7') into l_result;
select compat_tools.f_unit_test('locate(''bar'', ''foobarbar'', 7)', '7') into l_result;
select compat_tools.f_unit_test('locate(null, ''foobarbar'', 7)', 'NULL', 'IS') into l_result;
select compat_tools.f_unit_test('locate(''ba'', ''foobarbar'', null)', 'NULL', 'IS') into l_result;
-- =========================================================================
-- =========================================================================
-- unix_timestamp(timestamp)
-- unix_timestamp(timestamptz)
--
-- =========================================================================
select count(1) into l_cnt from pg_proc where proname='unix_timestamp'
and prosrc in ('unix_timestamp_no_args','unix_timestamp');
if l_cnt<2 then
if compat_tools.drop_compat_function('function', 'unix_timestamp(timestamp)', '2.1')
then
CREATE or replace FUNCTION pg_catalog.unix_timestamp(p_date timestamp without time zone default date_trunc('second', now()))
RETURNS double precision IMMUTABLE AS $$
select greatest(extract(epoch from p_date),0)::float8;
$$ LANGUAGE sql;
end if;
if compat_tools.drop_compat_function('function', 'unix_timestamp(timestamptz)', '2.1')
then
CREATE or replace FUNCTION pg_catalog.unix_timestamp(p_date timestamptz)
RETURNS double precision IMMUTABLE AS $$
select greatest(extract(epoch from p_date),0)::float8;
$$ LANGUAGE sql;
end if;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
select compat_tools.f_unit_test('unix_timestamp()', '0', '>') into l_result;
if f_version_compare((regexp_split_to_array(substr(version(), instr(version(), '(') + 1), '\s+'))[2], '3.1.0') = 1 then
select compat_tools.f_unit_test('unix_timestamp(''1111-11-11 11:11:11''::timestamp)', '0',p_db_compat =>'A') into l_result;
select compat_tools.f_unit_test('unix_timestamp(''1111-11-11 11:11:11''::timestamp)', '0',p_db_compat =>'PG') into l_result;
select compat_tools.f_unit_test('unix_timestamp(''1111-11-11 11:11:11''::timestamp)', '0',p_db_compat =>'B') into l_result;
select compat_tools.f_unit_test('unix_timestamp(''1212-12-12 12:12:12.123456''::timestamp)', '0',p_db_compat =>'A') into l_result;
select compat_tools.f_unit_test('unix_timestamp(''1212-12-12 12:12:12.123456''::timestamp)', '0',p_db_compat =>'PG') into l_result;
select compat_tools.f_unit_test('unix_timestamp(''1212-12-12 12:12:12.123456''::timestamp)', '0',p_db_compat =>'B') into l_result;
else
select compat_tools.f_unit_test('unix_timestamp(''1111-11-11 11:11:11''::timestamp)', '0') into l_result;
select compat_tools.f_unit_test('unix_timestamp(''1212-12-12 12:12:12.123456''::timestamp)', '0') into l_result;
end if;
-- =========================================================================
-- =========================================================================
-- to_days(timestamp)
-- to_days(timestamptz)
-- to_days(text)
-- to_days(text,text)
-- to_days(int8)
-- =========================================================================
if compat_tools.drop_compat_function('function', 'to_days(timestamp)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.to_days(p_date timestamp without time zone)
RETURNS bigint IMMUTABLE AS $$
SELECT floor(extract(epoch from p_date)/86400)::bigint + 719528;
$$ LANGUAGE sql;
end if;
if compat_tools.drop_compat_function('function', 'to_days(timestamptz)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.to_days(p_date timestamp with time zone)
RETURNS bigint IMMUTABLE AS $$
SELECT floor(extract(epoch from p_date::timestamp without time zone)/86400)::bigint + 719528;
$$ LANGUAGE sql;
end if;
if compat_tools.drop_compat_function('function', 'to_days(text)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.to_days( p_date text)
RETURNS bigint IMMUTABLE AS $$
SELECT floor(extract(epoch from p_date::timestamp)/86400)::bigint + 719528;
$$ LANGUAGE sql;
end if;
if compat_tools.drop_compat_function('function', 'to_days(text,text)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.to_days( p_date text
, p_format text)
RETURNS bigint IMMUTABLE AS $$
SELECT floor(extract(epoch from to_timestamp(p_date, p_format))/86400)::bigint + 719528;
$$ LANGUAGE sql;
end if;
if compat_tools.drop_compat_function('function', 'to_days(int8)', '1.0', 'plpgsql')
then
CREATE or replace FUNCTION pg_catalog.to_days(p_date bigint)
RETURNS bigint IMMUTABLE AS $$
begin
if p_date <= 100
then
return null;
elsif p_date < 1000
then
-- 3位数字,年份部分暂时补充 2000,至少能保证短期结果正确
return floor(extract(epoch from ('20000'||p_date)::timestamp)/86400)::bigint + 719528;
-- return floor(extract(epoch from to_timestamp('20000'||p_date::text, 'YYYYMMDD'))/86400)::bigint + 719528;
elsif p_date < 10000
then
-- 4位数字,年份部分暂时补充 2000,至少能保证短期结果正确
return floor(extract(epoch from ('2000'||p_date)::timestamp)/86400)::bigint + 719528;
-- return floor(extract(epoch from to_timestamp('2000'||p_date::text, 'YYYYMMDD'))/86400)::bigint + 719528;
elsif p_date < 100000
then
-- 5 位数,使用格式 YYMMDD 格式化
return floor(extract(epoch from ('0'||p_date)::timestamp)/86400)::bigint + 719528;
-- return floor(extract(epoch from to_timestamp('0'||p_date::text, 'YYMMDD'))/86400)::bigint + 719528;
elsif p_date < 1000000
then
-- 6 位数,使用格式 YYMMDD 格式化
return floor(extract(epoch from p_date::text::timestamp)/86400)::bigint + 719528;
-- return floor(extract(epoch from to_timestamp(p_date::text, 'YYMMDD'))/86400)::bigint + 719528;
elsif p_date < 10000000
then
-- 7 位数,直接返回 NULL
return null;
elsif p_date > 99991231
then
-- 超过支持的最大值 99991231 直接返回 NULL
return null;
else
-- 8 位数,使用格式 YYYYMMDD 格式化
return floor(extract(epoch from p_date::text::timestamp)/86400)::bigint + 719528;
-- return floor(extract(epoch from to_timestamp(p_date::text, 'YYYYMMDD'))/86400)::bigint + 719528;
end if;
exception
when others then
return null;
end
$$ LANGUAGE plpgsql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
select compat_tools.f_unit_test('to_days(''1111-11-11'')', '406098') into l_result;
select compat_tools.f_unit_test('to_days(''1111-11-11''::timestamp without time zone)', '406098') into l_result;
select compat_tools.f_unit_test('to_days(''1111-11-11''::timestamptz)', '406098') into l_result;
select compat_tools.f_unit_test('to_days(to_date(''2020-02-02'', ''YYYY-MM-DD''))', '737822') into l_result;
select compat_tools.f_unit_test('to_days(''2020-02-02'', ''YYYY-MM-DD'')', '737822') into l_result;
select compat_tools.f_unit_test('to_days(12340501)', '450830') into l_result;
select compat_tools.f_unit_test('to_days(950501)', '728779') into l_result;
select compat_tools.f_unit_test('to_days(090501)', '733893') into l_result;
select compat_tools.f_unit_test('to_days(50501)', '732432') into l_result;
select compat_tools.f_unit_test('to_days(1101)', '730790') into l_result;
select compat_tools.f_unit_test('to_days(501)', '730606') into l_result;
select compat_tools.f_unit_test('to_days(101)', '730485') into l_result;
select compat_tools.f_unit_test('to_days(100)', 'NULL', 'IS') into l_result;
select compat_tools.f_unit_test('to_days(51)', 'NULL', 'IS') into l_result;
select compat_tools.f_unit_test('to_days(1)', 'NULL', 'IS') into l_result;
select compat_tools.f_unit_test('to_days(950551)', 'NULL', 'IS') into l_result;
select compat_tools.f_unit_test('to_days(51501)', 'NULL', 'IS') into l_result;
-- =========================================================================
-- =========================================================================
-- to_seconds(timestamp)
-- to_seconds(timestamptz)
-- =========================================================================
if compat_tools.drop_compat_function('function', 'to_seconds(timestamp)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.to_seconds(p_date timestamp)
RETURNS bigint IMMUTABLE AS $$
SELECT floor(extract(epoch from p_date))::bigint + 62167219200;
$$ LANGUAGE sql;
end if;
if compat_tools.drop_compat_function('function', 'to_seconds(timestamptz)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.to_seconds(p_date timestamptz)
RETURNS bigint IMMUTABLE AS $$
SELECT floor(extract(epoch from p_date))::bigint + 62167219200;
$$ LANGUAGE sql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
-- select to_seconds(950501); -- 62966505600 (暂时不支持)
select compat_tools.f_unit_test('to_seconds(''2009-11-29''::timestamp)', '63426672000') into l_result;
select compat_tools.f_unit_test('to_seconds(''2009-11-29 13:43:32''::timestamptz) - to_seconds(''1999-11-29 11:22:33''::timestamptz)', '315627659') into l_result;
-- =========================================================================
-- =========================================================================
-- timediff(timestamptz,timestamptz)
-- =========================================================================
if compat_tools.drop_compat_function('function', 'timediff(timestamptz,timestamptz)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.timediff(p_date1 timestamptz, p_date2 timestamptz)
RETURNS interval IMMUTABLE AS $$
SELECT p_date1 - p_date2;
$$ LANGUAGE sql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
select compat_tools.f_unit_test('timediff(''2000-01-01 00:00:00'', ''2000-01-01 00:00:00.000001'')', '''-00:00:00.000001''') into l_result;
select compat_tools.f_unit_test('timediff(''2008-12-31 23:59:59.000001'', ''2008-12-30 01:01:01.000002'')', '''1 day 22:58:57.999999''') into l_result;
-- =========================================================================
-- =========================================================================
-- time_to_sec(time)
-- =========================================================================
if compat_tools.drop_compat_function('function', 'time_to_sec(time)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.time_to_sec(p_time time)
RETURNS int IMMUTABLE AS $$
select extract(epoch from p_time::time)::int;
$$ LANGUAGE sql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
select compat_tools.f_unit_test('time_to_sec(''22:23:00'')', '80580') into l_result;
select compat_tools.f_unit_test('time_to_sec(''00:39:38'')', '2378') into l_result;
-- =========================================================================
-- =========================================================================
-- date_format(timestamp,text)
-- date_format(timestamptz,text)
-- 测试备注:
-- select t
-- , to_char(t, 'D') as d
-- , to_char(t + interval '1 day', 'IDDD') as iddd_1
-- , to_char(t, 'DDD') as ddd
-- , to_char(t, 'Day') as week
-- , to_char(t, 'DDD')::int monday
-- , (select case when c_first = 1 -- 元旦是周日
-- then ceil(c_day/7)
-- when c_day <= (8 - c_first) -- 去年的周
-- then case p_first
-- when 1 then ceil(p_last/7)
-- -- when 2 then ceil((p_last - 6)/7)
-- -- when 3 then ceil((p_last - 5)/7)
-- -- when 4 then ceil((p_last - 4)/7)
-- -- when 5 then ceil((p_last - 3)/7)
-- -- when 6 then ceil((p_last - 2)/7)
-- -- else ceil((p_last - 1)/7)
-- else ceil((p_last - (8 - p_first))/7)
-- end
-- else ceil((c_day - (8 - c_first)) / 7) -- 今年的周
-- -- else case c_first -- 今年的周
-- -- when 2 then ceil((c_day - 6)/7)
-- -- when 3 then ceil((c_day - 5)/7)
-- -- when 4 then ceil((c_day - 4)/7)
-- -- when 5 then ceil((c_day - 3)/7)
-- -- when 6 then ceil((c_day - 2)/7)
-- -- else ceil((c_day - 1)/7)
-- -- end
-- end
-- from (select to_char(t, 'DDD')::int as c_day
-- , to_char(date_trunc('year', t), 'D')::int as c_first
-- , to_char(date_trunc('year', t) - interval '1 year', 'D')::int as p_first
-- , to_char(date_trunc('year', t) - interval '1 day', 'DDD')::int as p_last
-- )
-- ) as result
-- from (select '1996-01-01'::timestamp + (interval '1 day' * d) as t from generate_series(0, 368) as d) as x;
-- =========================================================================
-- 变更记录:
-- v1.1 => 解决不同兼容模式下 NULL 与空格导致的部分测试用例失败的问题(A/B)
-- =========================================================================
if compat_tools.drop_compat_function('function', 'date_format(timestamp,text)', '1.1')
then
CREATE or replace FUNCTION pg_catalog.date_format( p_ts timestamp
, p_fmt text)
RETURNS text IMMUTABLE AS $$
select to_char( p_ts
, string_agg(case
when fmt is null or fmt = '' then case when id = 1 then '' else '%' end
else case substr(fmt, 1, 1)
when 'I' then 'HH12'
when 'l' then 'FMHH12'
when 'h' then 'HH12'
when 'H' then 'HH24'
when 'k' then 'FMHH24'
when 'i' then 'MI'
when 'S' then 'SS'
when 's' then 'SS'
when 'f' then 'US'
when 'p' then 'PM'
when 'Y' then 'YYYY'
when 'y' then 'YY'
when 'M' then 'FMMonth'
when 'b' then 'Mon'
when 'c' then 'FMMM'
when 'm' then 'MM'
when 'a' then 'Dy'
when 'W' then 'FMDay'
when 'j' then 'DDD'
when 'd' then 'DD'
when 'e' then 'FMDD'
when 'w' then (to_char(p_ts, 'D')::int - 1)::text
when 'D' then 'FMDDth'
when 'U' then lpad((select case when c_first = 1 -- 元旦是周日
then ceil(c_day/7)
when c_day <= (8 - c_first) -- 去年的周
then 0
else ceil((c_day - (8 - c_first)) / 7) -- 今年的周
end
from (select to_char(p_ts, 'DDD')::int as c_day
, to_char(date_trunc('year', p_ts), 'D')::int as c_first
)
)::text, 2, '0') -- Mode 0
when 'u' then case when to_char(p_ts, 'DDD') <= 7 and to_char(p_ts, 'IW') > 50 then '00' else 'IW' end -- Mode 1
when 'V' then lpad((select case when c_first = 1 -- 元旦是周日
then ceil(c_day/7)
when c_day <= (8 - c_first) -- 去年的周
then ceil((p_last - (case p_first when 1 then 0 else 8 - p_first end))/7)
else ceil((c_day - (8 - c_first)) / 7) -- 今年的周
end
from (select to_char(p_ts, 'DDD')::int as c_day
, to_char(date_trunc('year', p_ts), 'D')::int as c_first
, to_char(date_trunc('year', p_ts) - interval '1 year', 'D')::int as p_first
, to_char(date_trunc('year', p_ts) - interval '1 day', 'DDD')::int as p_last
)
)::text, 2, '0') -- Mode 2
when 'v' then 'IW' -- Mode 3
when 'X' then case when to_char(date_trunc('year', p_ts), 'D')::int > 1 and to_char(p_ts, 'DDD')::int <= 8 - to_char(date_trunc('year', p_ts), 'D')::int
then lpad((to_char(p_ts, 'YYYY')::int - 1)::text, 4, '0')
else 'YYYY' end -- Mode 2
when 'x' then 'IYYY' -- Mode 3
when 'r' then 'HH12:MI:SS AM'
when 'T' then 'HH24:MI:SS'
when chr(31) then '%'
else '"' || substr(fmt, 1, 1) || '"' -- 预防存在其他 MogDB 中存在的额外格式值
end || case when substr(fmt, 2) >= ' ' then '"' || substr(fmt, 2) || '"' else '' end -- 预防存在其他 MogDB 中存在的额外格式值
end, ''))
from (select rownum as id, regexp_split_to_table(replace(p_fmt, '%%', '%'||chr(31)), '%') as fmt);
$$ LANGUAGE sql;
end if;
if compat_tools.drop_compat_function('function', 'date_format(timestamptz,text)', '1.1')
then
CREATE or replace FUNCTION pg_catalog.date_format( p_ts timestamptz
, p_fmt text)
RETURNS text IMMUTABLE AS $$
select to_char( p_ts
, string_agg(case
when fmt is null or fmt = '' then case when id = 1 then '' else '%' end
else case substr(fmt, 1, 1)
when 'I' then 'HH12'
when 'l' then 'FMHH12'
when 'h' then 'HH12'
when 'H' then 'HH24'
when 'k' then 'FMHH24'
when 'i' then 'MI'
when 'S' then 'SS'
when 's' then 'SS'
when 'f' then 'US'
when 'p' then 'PM'
when 'Y' then 'YYYY'
when 'y' then 'YY'
when 'M' then 'FMMonth'
when 'b' then 'Mon'
when 'c' then 'FMMM'
when 'm' then 'MM'
when 'a' then 'Dy'
when 'W' then 'FMDay'
when 'j' then 'DDD'
when 'd' then 'DD'
when 'e' then 'FMDD'
when 'w' then (to_char(p_ts, 'D')::int - 1)::text
when 'D' then 'FMDDth'
when 'U' then lpad((select case when c_first = 1 -- 元旦是周日
then ceil(c_day/7)
when c_day <= (8 - c_first) -- 去年的周
then 0
else ceil((c_day - (8 - c_first)) / 7) -- 今年的周
end
from (select to_char(p_ts, 'DDD')::int as c_day
, to_char(date_trunc('year', p_ts), 'D')::int as c_first
)
)::text, 2, '0') -- Mode 0
when 'u' then case when to_char(p_ts, 'DDD') <= 7 and to_char(p_ts, 'IW') > 50 then '00' else 'IW' end -- Mode 1
when 'V' then lpad((select case when c_first = 1 -- 元旦是周日
then ceil(c_day/7)
when c_day <= (8 - c_first) -- 去年的周
then ceil((p_last - (case p_first when 1 then 0 else 8 - p_first end))/7)
else ceil((c_day - (8 - c_first)) / 7) -- 今年的周
end
from (select to_char(p_ts, 'DDD')::int as c_day
, to_char(date_trunc('year', p_ts), 'D')::int as c_first
, to_char(date_trunc('year', p_ts) - interval '1 year', 'D')::int as p_first
, to_char(date_trunc('year', p_ts) - interval '1 day', 'DDD')::int as p_last
)
)::text, 2, '0') -- Mode 2
when 'v' then 'IW' -- Mode 3
when 'X' then case when to_char(date_trunc('year', p_ts), 'D')::int > 1 and to_char(p_ts, 'DDD')::int <= 8 - to_char(date_trunc('year', p_ts), 'D')::int
then lpad((to_char(p_ts, 'YYYY')::int - 1)::text, 4, '0')
else 'YYYY' end -- Mode 2
when 'x' then 'IYYY' -- Mode 3
when 'r' then 'HH12:MI:SS AM'
when 'T' then 'HH24:MI:SS'
when chr(31) then '%'
else '"' || substr(fmt, 1, 1) || '"' -- 预防存在其他 MogDB 中存在的额外格式值
end || case when substr(fmt, 2) >= ' ' then '"' || substr(fmt, 2) || '"' else '' end -- 预防存在其他 MogDB 中存在的额外格式值
end, ''))
from (select rownum as id, regexp_split_to_table(replace(p_fmt, '%%', '%'||chr(31)), '%') as fmt);
$$ LANGUAGE sql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
select compat_tools.f_unit_test('date_format(''2009-10-04 22:23:00'', ''%W %M %Y'')', '''Sunday October 2009''') into l_result;
select compat_tools.f_unit_test('date_format(''2007-10-04 22:23:00'', ''%% %H:%i:%s%'')', '''% 22:23:00%''') into l_result;
select compat_tools.f_unit_test('date_format(''1900-10-04 22:23:00'', ''%D %y %a %d %m %b %j'')', '''4th 00 Thu 04 10 Oct 277''') into l_result;
select compat_tools.f_unit_test('date_format(''1997-10-04 22:23:00'', ''%H %k %I %r %T %S %w'')', '''22 22 10 10:23:00 PM 22:23:00 00 6''') into l_result;
select compat_tools.f_unit_test('date_format(''1999-01-01'', ''Q %qQ %J'')', '''Q qQ J''') into l_result;
select compat_tools.f_unit_test('date_format(''2006-01-01'', ''%X %x %V %v %U %u'')', '''2006 2005 01 52 01 00''') into l_result;
select compat_tools.f_unit_test('date_format(''1999-01-02'', ''%X %x %V %v %U %u'')', '''1998 1998 52 53 00 00''') into l_result;
select compat_tools.f_unit_test('date_format(''1999-01-03'', ''%X %x %V %v %U %u'')', '''1999 1998 01 53 01 00''') into l_result;
select compat_tools.f_unit_test('date_format(''1999-01-04'', ''%X %x %V %v %U %u'')', '''1999 1999 01 01 01 01''') into l_result;
-- select compat_tools.f_unit_test('date_format(''2006-06-00'', ''%d'')', '00') into l_result; -- 不支持
-- =========================================================================
-- =========================================================================
-- from_unixtime(int8)
-- from_unixtime(numeric)
-- from_unixtime(numeric,text)
-- =========================================================================
if compat_tools.drop_compat_function('function', 'from_unixtime(int8)', '1.1')
then
CREATE or replace FUNCTION pg_catalog.from_unixtime(p_ts bigint)
RETURNS timestamp without time zone IMMUTABLE AS $$
select to_date('1970-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS') + interval '1 seconds' * p_ts;
$$ LANGUAGE sql;
end if;
if compat_tools.drop_compat_function('function', 'from_unixtime(numeric)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.from_unixtime(p_ts numeric)
RETURNS timestamp without time zone IMMUTABLE AS $$
select to_timestamp('1970-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS') + interval '1 seconds' * p_ts;
$$ LANGUAGE sql;
end if;
if compat_tools.drop_compat_function('function', 'from_unixtime(numeric,text)', '2.0')
then
CREATE or replace FUNCTION pg_catalog.from_unixtime(p_ts numeric, p_format text)
RETURNS text IMMUTABLE AS $$
select date_format(to_timestamp('1970-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS') + interval '1 seconds' * p_ts, p_format);
$$ LANGUAGE sql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
select compat_tools.f_unit_test('from_unixtime(123456789)', '''1973-11-29 21:33:09''') into l_result;
select compat_tools.f_unit_test('from_unixtime(123456789.123456)', '''1973-11-29 21:33:09.123456''') into l_result;
select compat_tools.f_unit_test('from_unixtime(123456789.123456, ''%Y.%m.%d %H.%i.%S'')', '''1973.11.29 21.33.09''') into l_result;
-- =========================================================================
-- =========================================================================
-- sec_to_time(int4)
-- =========================================================================
if compat_tools.drop_compat_function('function', 'sec_to_time(int4)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.sec_to_time(p_secs int)
RETURNS interval IMMUTABLE AS $$
select justify_interval(numtodsinterval(p_secs, 'second'));
$$ LANGUAGE sql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
select compat_tools.f_unit_test('sec_to_time(80580)', '''22:23:00''') into l_result;
select compat_tools.f_unit_test('sec_to_time(2378)', '''00:39:38''') into l_result;
select compat_tools.f_unit_test('sec_to_time(805801)', '''9 days 07:50:01''') into l_result;
select compat_tools.f_unit_test('sec_to_time(8058011)', '''3 mons 3 days 06:20:11''') into l_result; -- MySQL (34 days, 22:59:59) 达到上限了
-- =========================================================================
-- =========================================================================
-- to_base64(text)
-- =========================================================================
if compat_tools.drop_compat_function('function', 'to_base64(text)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.to_base64(p_str text)
RETURNS text IMMUTABLE AS $$
select encode(p_str::bytea, 'base64'::text);
$$ LANGUAGE sql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
select compat_tools.f_unit_test('to_base64(''abc'')', '''YWJj''') into l_result;
select compat_tools.f_unit_test('to_base64(''Hongye'')', '''SG9uZ3ll''') into l_result;
-- =========================================================================
-- =========================================================================
-- from_base64(text)
-- =========================================================================
if compat_tools.drop_compat_function('function', 'from_base64(text)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.from_base64(p_str text)
RETURNS text IMMUTABLE AS $$
select convert_from(decode(p_str, 'base64'), 'UTF8');
$$ LANGUAGE sql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
select compat_tools.f_unit_test('from_base64(''YWJj'')', '''abc''') into l_result;
select compat_tools.f_unit_test('from_base64(''SG9uZ3ll'')', '''Hongye''') into l_result;
-- =========================================================================
-- =========================================================================
-- truncate(numeric,int4)
-- =========================================================================
if compat_tools.drop_compat_function('function', 'truncate(numeric,int4)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.truncate(p_num numeric, p_prec int4)
RETURNS numeric IMMUTABLE AS $$
select trunc(p_num, p_prec);
$$ LANGUAGE sql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
select compat_tools.f_unit_test('truncate(1.223,1)', '1.2') into l_result;
select compat_tools.f_unit_test('truncate(1.999, 1)', '1.9') into l_result;
select compat_tools.f_unit_test('truncate(1.999, 0)', '1') into l_result;
select compat_tools.f_unit_test('truncate(1.999, -1)', '0') into l_result;
select compat_tools.f_unit_test('truncate(121.999, -1)', '120') into l_result;
-- =========================================================================
-- =========================================================================
-- rand_setseed(int4)
-- rand(int4)
-- =========================================================================
if compat_tools.drop_compat_function('function', 'rand_setseed(int4)', '1.0', 'plpgsql')
then
CREATE or replace FUNCTION pg_catalog.rand_setseed(p_seed int)
RETURNS double precision IMMUTABLE AS $$
DECLARE
l_result text;
begin
select setseed(p_seed/4294967296::float8) into l_result;
return 0;
end;
$$ LANGUAGE plpgsql;
end if;
if compat_tools.drop_compat_function('function', 'rand()', '1.0')
then
CREATE or replace FUNCTION pg_catalog.rand()
RETURNS double precision AS $$
select random() ;
$$ LANGUAGE sql;
end if;
if compat_tools.drop_compat_function('function', 'rand(int4)', '2.0')
then
CREATE or replace FUNCTION pg_catalog.rand(p_seed int)
RETURNS double precision AS $$
select case when p_seed is null then random() else rand_setseed(p_seed) + random() end;
$$ LANGUAGE sql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
select compat_tools.f_unit_test('rand()', '0.0', '>') into l_result;
select compat_tools.f_unit_test('rand(123)', '0.0', '>') into l_result;
-- =========================================================================
-- =========================================================================
-- log2(numeric)
-- =========================================================================
if compat_tools.drop_compat_function('function', 'log2(numeric)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.log2(p_num numeric)
RETURNS numeric IMMUTABLE AS $$
select case when p_num <= 0 then null else log(2, p_num) end;
$$ LANGUAGE sql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
select compat_tools.f_unit_test('log2(64)', '6.0') into l_result;
select compat_tools.f_unit_test('log2(123)::float8', '6.9425145053392399::float8') into l_result;
select compat_tools.f_unit_test('log2(0)', 'NULL', 'IS') into l_result;
select compat_tools.f_unit_test('log2(-12)', 'NULL', 'IS') into l_result;
-- =========================================================================
-- =========================================================================
-- uuid()
-- =========================================================================
if compat_tools.drop_compat_function('function', 'uuid()', '1.0')
then
CREATE or replace FUNCTION pg_catalog.uuid()
RETURNS uuid VOLATILE AS $$
select md5(random()::text || clock_timestamp()::text)::uuid;
$$ LANGUAGE sql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
select compat_tools.f_unit_test('length(uuid()::text)', '36') into l_result;
-- =========================================================================
-- =========================================================================
-- uuid_to_bin(uuid,int4)
-- swap_flag 参数暂不处理,由于生成的 uuid 是纯随机的,暂时做不到顺序处理
-- =========================================================================
if compat_tools.drop_compat_function('function', 'uuid_to_bin(uuid,int4)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.uuid_to_bin(p_uuid uuid, swap_flag int4 default 0)
RETURNS bytea IMMUTABLE AS $$
select ('\x'||replace(p_uuid::text, '-', ''))::bytea;
$$ LANGUAGE sql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
select compat_tools.f_unit_test('uuid_to_bin(''0768a47d-d355-372b-4926-ee668b6cb443''::uuid)::text', '''\x0768a47dd355372b4926ee668b6cb443''') into l_result;
-- =========================================================================
-- =========================================================================
-- bin_to_uuid(bytea,int4)
-- swap_flag 参数暂不处理,由于生成的 uuid 是纯随机的,暂时做不到顺序处理
-- =========================================================================
if compat_tools.drop_compat_function('function', 'bin_to_uuid(bytea,int4)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.bin_to_uuid(p_uuid bytea, swap_flag int4 default 0)
RETURNS uuid IMMUTABLE AS $$
select (replace(p_uuid::text, '\x', ''))::uuid;
$$ LANGUAGE sql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
select compat_tools.f_unit_test('bin_to_uuid(''\x0768a47dd355372b4926ee668b6cb443'')', '''0768a47d-d355-372b-4926-ee668b6cb443''') into l_result;
-- =========================================================================
-- =========================================================================
-- timestampdiff(text,timestamptz,timestamptz)
-- 本兼容函数用法与 MySQL 有区别:
-- 1. 必须指定 pg_catalog Schema,否则会报错 timestampdiff syntax is not supported.
-- 2. 第一个参数(时间单位),必须使用单引号包裹,但可以不区分大小写
-- =========================================================================
if compat_tools.drop_compat_function('function', 'timestampdiff(text,timestamptz,timestamptz)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.timestampdiff( p_unit text
, p_ts1 timestamptz
, p_ts2 timestamptz)
RETURNS bigint IMMUTABLE AS $$
select (case upper(p_unit)
when 'MICROSECOND' then extract(epoch from p_ts2) * 1000000 - extract(epoch from p_ts1) * 1000000
when 'SECOND' then extract(epoch from p_ts2) - extract(epoch from p_ts1)
when 'MINUTE' then trunc((extract(epoch from p_ts2) - extract(epoch from p_ts1))/60)
when 'HOUR' then trunc((extract(epoch from p_ts2) - extract(epoch from p_ts1))/3600)
when 'DAY' then extract(DAY from p_ts2 - p_ts1)
when 'WEEK' then trunc((extract(DAY from p_ts2 - p_ts1))/7)
when 'MONTH' then (select (extract(YEAR from t) * 12 + extract(MONTH from t)) from (SELECT age(p_ts2, p_ts1) as t) as x)
when 'QUARTER' then (select trunc((extract(YEAR from t) * 12 + extract(MONTH from t))/3) from (SELECT age(p_ts2, p_ts1) as t) as x)
when 'YEAR' then extract(YEAR from age(p_ts2, p_ts1))
else null
end)::bigint;
$$ LANGUAGE sql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
select compat_tools.f_unit_test('pg_catalog.timestampdiff (''MICROSECOND'', ''1911-11-11 11:23:45.123456''::timestamp without time zone, ''2021-12-12 12:12:12.654321''::timestamp without time zone)', 3474060507530865) into l_result;
select compat_tools.f_unit_test('pg_catalog.timestampdiff (''SECOND'', ''1911-11-11 11:23:45''::timestamp without time zone, ''2021-12-12 12:12:12''::timestamp without time zone)', 3474060507) into l_result;
select compat_tools.f_unit_test('pg_catalog.timestampdiff (''MINUTE'', ''1911-11-11 11:23:45''::timestamp without time zone, ''2021-12-12 12:12:12''::timestamp without time zone)', 57901008) into l_result;
select compat_tools.f_unit_test('pg_catalog.timestampdiff (''HOUR'', ''1911-11-11 11:23:45''::timestamp without time zone, ''2021-12-12 12:12:12''::timestamp without time zone)', 965016) into l_result;
select compat_tools.f_unit_test('pg_catalog.timestampdiff (''DAY'', ''1911-11-11 11:23:45''::timestamp without time zone, ''2021-12-12 12:12:12''::timestamp without time zone)', 40209) into l_result;
select compat_tools.f_unit_test('pg_catalog.timestampdiff (''WEEK'', ''1911-11-11 11:23:45''::timestamp without time zone, ''2021-12-12 12:12:12''::timestamp without time zone)', 5744) into l_result;
select compat_tools.f_unit_test('pg_catalog.timestampdiff (''MONTH'', ''1911-11-11 11:23:45''::timestamp without time zone, ''2021-12-12 12:12:12''::timestamp without time zone)', 1321) into l_result;
select compat_tools.f_unit_test('pg_catalog.timestampdiff (''QUARTER'', ''1911-11-11 11:23:45''::timestamp without time zone, ''2021-12-12 12:12:12''::timestamp without time zone)', 440) into l_result;
select compat_tools.f_unit_test('pg_catalog.timestampdiff (''YEAR'', ''1911-11-11 11:23:45''::timestamp without time zone, ''2021-12-12 12:12:12''::timestamp without time zone)', 110) into l_result;
select compat_tools.f_unit_test('pg_catalog.timestampdiff (''day'', ''2021-12-12 12:12:12''::timestamp without time zone, ''1911-11-11 11:23:45''::timestamp without time zone)', -40209) into l_result;
select compat_tools.f_unit_test('pg_catalog.timestampdiff (''year'',''2002-01-01''::timestamp without time zone, ''2001-01-01''::timestamp without time zone)', -1) into l_result;
select compat_tools.f_unit_test('pg_catalog.timestampdiff (''year'',''2002-01-01''::timestamp without time zone, ''2001-01-02''::timestamp without time zone)', 0) into l_result;
-- =========================================================================
-- =========================================================================
-- isnull(text)
-- isnull(numeric)
-- isnull(timestamptz)
-- =========================================================================
if compat_tools.drop_compat_function('function', 'isnull(text)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.isnull(text)
RETURNS bool IMMUTABLE AS $$
select (case when $1 is null then 'true' else 'false' end)::bool;
$$ LANGUAGE sql;
end if;
if compat_tools.drop_compat_function('function', 'isnull(numeric)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.isnull(numeric)
RETURNS bool IMMUTABLE AS $$
select (case when $1 is null then 'true' else 'false' end)::bool;
$$ LANGUAGE sql;
end if;
if compat_tools.drop_compat_function('function', 'isnull(timestamptz)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.isnull(timestamptz)
RETURNS bool IMMUTABLE AS $$
select (case when $1 is null then 'true' else 'false' end)::bool;
$$ LANGUAGE sql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
if f_version_compare((regexp_split_to_array(substr(version(), instr(version(), '(') + 1), '\s+'))[2], '5.0.0') = -1 then
select compat_tools.f_unit_test('isnull(0)::text', '''false''') into l_result;
select compat_tools.f_unit_test('isnull(1)::text', '''false''') into l_result;
select compat_tools.f_unit_test('isnull(11)::text', '''false''') into l_result;
select compat_tools.f_unit_test('isnull('''')::text', '''false''', p_db_compat => 'B') into l_result; -- Failed in A
select compat_tools.f_unit_test('isnull('''')::text', '''false''', p_db_compat => 'PG') into l_result; -- Failed in A
select compat_tools.f_unit_test('isnull(''x'')::text', '''false''') into l_result;
select compat_tools.f_unit_test('isnull(null)::text', '''true''') into l_result;
select compat_tools.f_unit_test('isnull(now())::text', '''false''') into l_result;
select compat_tools.f_unit_test('isnull(''2012-12-12 12:34:56''::timestamp)::text', '''false''') into l_result;
else
select compat_tools.f_unit_test('isnull(0)::text', '''0''', p_db_compat => 'B') into l_result;
select compat_tools.f_unit_test('isnull(1)::text', '''0''', p_db_compat => 'B') into l_result;
select compat_tools.f_unit_test('isnull(11)::text', '''0''', p_db_compat => 'B') into l_result;
select compat_tools.f_unit_test('isnull('''')::text', '''0''', p_db_compat => 'B') into l_result;
select compat_tools.f_unit_test('isnull(''x'')::text', '''0''', p_db_compat => 'B') into l_result;
select compat_tools.f_unit_test('isnull(null)::text', '''1''', p_db_compat => 'B') into l_result;
select compat_tools.f_unit_test('isnull(now())::text', '''0''', p_db_compat => 'B') into l_result;
select compat_tools.f_unit_test('isnull(''2012-12-12 12:34:56''::timestamp)::text', '''0''', p_db_compat => 'B') into l_result;
select compat_tools.f_unit_test('isnull(0)::text', '''false''', p_db_compat => 'A') into l_result;
select compat_tools.f_unit_test('isnull(1)::text', '''false''', p_db_compat => 'A') into l_result;
select compat_tools.f_unit_test('isnull(11)::text', '''false''', p_db_compat => 'A') into l_result;
select compat_tools.f_unit_test('isnull(''x'')::text', '''false''', p_db_compat => 'A') into l_result;
select compat_tools.f_unit_test('isnull(null)::text', '''true''', p_db_compat => 'A') into l_result;
select compat_tools.f_unit_test('isnull(now())::text', '''false''', p_db_compat => 'A') into l_result;
select compat_tools.f_unit_test('isnull(''2012-12-12 12:34:56''::timestamp)::text', '''false''', p_db_compat => 'A') into l_result;
select compat_tools.f_unit_test('isnull(0)::text', '''false''', p_db_compat => 'PG') into l_result;
select compat_tools.f_unit_test('isnull(1)::text', '''false''', p_db_compat => 'PG') into l_result;
select compat_tools.f_unit_test('isnull(11)::text', '''false''', p_db_compat => 'PG') into l_result;
select compat_tools.f_unit_test('isnull('''')::text', '''false''', p_db_compat => 'PG') into l_result; -- Failed in A
select compat_tools.f_unit_test('isnull(''x'')::text', '''false''', p_db_compat => 'PG') into l_result;
select compat_tools.f_unit_test('isnull(null)::text', '''true''', p_db_compat => 'PG') into l_result;
select compat_tools.f_unit_test('isnull(now())::text', '''false''', p_db_compat => 'PG') into l_result;
select compat_tools.f_unit_test('isnull(''2012-12-12 12:34:56''::timestamp)::text', '''false''', p_db_compat => 'PG') into l_result;
end if;
-- =========================================================================
-- =========================================================================
-- str_to_date(text,text)
-- =========================================================================
if compat_tools.drop_compat_function('function', 'str_to_date(text,text)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.str_to_date( p_ts text
, p_fmt text)
RETURNS timestamp IMMUTABLE AS $$
select to_timestamp( p_ts
, string_agg(case
when fmt is null then (case when id = 1 then '' else '%' end)
else case substr(fmt, 1, 1)
when 'I' then 'HH12'
when 'l' then 'FMHH12'
when 'h' then 'HH12'
when 'H' then 'HH24'
when 'k' then 'FMHH24'
when 'i' then 'MI'
when 'S' then 'SS'
when 's' then 'SS'
when 'f' then 'US'
when 'p' then 'PM'
when 'Y' then 'YYYY'
when 'y' then 'YY'
when 'M' then 'FMMonth'
when 'b' then 'Mon'
when 'c' then 'FMMM'
when 'm' then 'MM'
when 'a' then 'Dy'
when 'W' then 'FMDay'
when 'j' then 'DDD'
when 'd' then 'DD'
when 'e' then 'FMDD'
when 'D' then 'FMDDth'
when 'x' then 'IYYY'
when 'r' then 'HH12:MI:SS AM'
when 'T' then 'HH24:MI:SS'
when chr(31) then '%'
else '"' || substr(fmt, 1, 1) || '"' -- 预防存在其他 MogDB 中存在的额外格式值
end || case when substr(fmt, 2) is null then '' else '"' || substr(fmt, 2) || '"' end -- 预防存在其他 MogDB 中存在的额外格式值
end, ''))
from (select rownum as id, regexp_split_to_table(replace(p_fmt, '%%', '%'||chr(31)), '%') as fmt);
$$ LANGUAGE sql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
-- 注意: MySQL 和 openGauss 中的起始时间不一样
-- MySQL 起始于 0000-00-00
-- openGauss 起始于 0001-01-01
select compat_tools.f_unit_test('str_to_date(''01,5,2013'',''%d,%m,%Y'')::text', '''2013-05-01 00:00:00''') into l_result; --> ''2013-05-01''
select compat_tools.f_unit_test('str_to_date(''May 1, 2013'',''%M %d,%Y'')::text', '''2013-05-01 00:00:00''') into l_result; --> ''2013-05-01''
select compat_tools.f_unit_test('str_to_date(''9'',''%m'')::text', '''0001-09-01 00:00:00 BC''') into l_result; --> ''0000-09-00''
select compat_tools.f_unit_test('str_to_date(''9'',''%s'')::text', '''0001-01-01 00:00:09 BC''') into l_result; --> ''00:00:09''
select compat_tools.f_unit_test('str_to_date(null, ''%m/%d/%Y'')', 'NULL', 'IS') into l_result; --> null
select compat_tools.f_unit_test('str_to_date(''04/31/2004'', null)', 'NULL', 'IS') into l_result; --> null
-- MySQL 中的以下场景不被支持:
-- 1. 时间与格式串中存在某种不能识别的字符
-- select str_to_date('a09:30:17','a%h:%i:%s'); --> '09:30:17'
-- select str_to_date('a09:30:17','%h:%i:%s'); --> NULL
-- select str_to_date('09:30:17a','%h:%i:%s'); --> '09:30:17'
-- select str_to_date('abc','abc'); --> '0000-00-00'
-- 2. 全 0 时间(年、月、日任意部分在 MogDB 中都不能为全零)
-- select str_to_date('00/00/0000', '%m/%d/%Y'); --> '0000-00-00'
-- 3. 其他不合法的时间,例如: 4月31(4月没有31)
-- select str_to_date('04/31/2004', '%m/%d/%Y'); --> '2004-04-31'
-- =========================================================================
-- =========================================================================
-- conv(text,int4,int4)
-- 注意: 目前只支持 2, 10, 16 进制之间的互相转换
-- =========================================================================
if compat_tools.drop_compat_function('function', 'conv(text,int4,int4)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.conv( p_num text
, p_from_base int4
, p_to_base int4)
RETURNS text IMMUTABLE AS $$
select case when p_from_base = 10 and p_to_base = 16 then upper(to_hex(p_num::bigint)::text)
when p_from_base = 10 and p_to_base = 2 then ltrim(p_num::bigint::bit(128)::text, '0')
when p_from_base = 16 and p_to_base = 10 then (select sum(n)::text
from (select case substr(lower(p_num), n, 1)
when 'a' then 10
when 'b' then 11
when 'c' then 12
when 'd' then 13
when 'e' then 14
when 'f' then 15
else substr(lower(p_num), n, 1)::int
end * (16 ^ (max(n) over () - n)) as n
from generate_series(1, length(p_num)) as n))
when p_from_base = 16 and p_to_base = 2 then ltrim(('x'||p_num)::varbit(128)::text, '0')
when p_from_base = 2 and p_to_base = 10 then (select sum(n)::text
from (select substr(lower(p_num), n, 1)::int
* (2 ^ (max(n) over () - n)) as n
from generate_series(1, length(p_num)) as n))
when p_from_base = 2 and p_to_base = 16 then (select string_agg(hex_data, '' order by id desc)
from (select rownum as id
, case substr('000'||p_num, l - rownum * 4 + 4, 4)
-- 首部补 3 个零,避免高位不足 4 个,同时截取起始位置从 l - rownum * 4 + 1 变为 l - rownum * 4 + 4
when '0000' then '0'
when '0001' then '1'
when '0010' then '2'
when '0011' then '3'
when '0100' then '4'
when '0101' then '5'
when '0110' then '6'
when '0111' then '7'
when '1000' then '8'
when '1001' then '9'
when '1010' then 'A'
when '1011' then 'B'
when '1100' then 'C'
when '1101' then 'D'
when '1110' then 'E'
when '1111' then 'F'
end as hex_data
from (select generate_series(1, ceil(length(p_num) / 4)) as n, length(p_num) as l)
order by id desc)) -- 取值是从右往左取,拼接的时候从左往右
else null
end;
$$ LANGUAGE sql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
select compat_tools.f_unit_test('conv(''123456'', 10, 16)', '''1E240''') into l_result;
select compat_tools.f_unit_test('conv(''123456'', 10, 2)', '''11110001001000000''') into l_result;
select compat_tools.f_unit_test('conv(''1E240'', 16, 10)', '''123456''') into l_result;
select compat_tools.f_unit_test('conv(''1E240'', 16, 2)', '''11110001001000000''') into l_result;
select compat_tools.f_unit_test('conv(''11110001001000000'', 2, 10)', '''123456''') into l_result;
select compat_tools.f_unit_test('conv(''11110001001000000'', 2, 16)', '''1E240''') into l_result;
select compat_tools.f_unit_test('conv(''a'',16, 2)', '''1010''') into l_result;
select compat_tools.f_unit_test('conv(''6e'',16, 10)', '''110''') into l_result;
-- =========================================================================
-- =========================================================================
-- curdate()
-- 注意: A模式和B模式,此函数输出格式不一样
-- =========================================================================
if compat_tools.drop_compat_function('function', 'curdate()', '1.0')
then
CREATE or replace FUNCTION pg_catalog.curdate()
RETURNS date IMMUTABLE AS $$
select current_date::date;
$$ LANGUAGE sql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
select compat_tools.f_unit_test('curdate()', 'current_date', '=') into l_result; --> null
-- =========================================================================
-- =========================================================================
-- yearweek(timestamp,int4)
-- yearweek(timestamptz,int4)
-- yearweek(text,int4)
-- 注意: openGauss输出结果与mysql第二个参数为3时输出一致
-- =========================================================================
if compat_tools.drop_compat_function('function', 'yearweek(timestamp,int4)', '1.0')
then
CREATE OR REPLACE FUNCTION pg_catalog.yearweek(timestamp,int4 default 3)
RETURNS text
LANGUAGE plpgsql
IMMUTABLE NOT FENCED NOT SHIPPABLE
AS $$
declare
begin
/*第二个参数mode,强制为3*/
return EXTRACT(isoyear FROM $1)||
lpad(EXTRACT(WEEK FROM $1),2,'0');
end;
$$;
end if;
if compat_tools.drop_compat_function('function', 'yearweek(timestamptz,int4)', '1.0')
then
CREATE OR REPLACE FUNCTION pg_catalog.yearweek(timestamptz,int4 default 3)
RETURNS text
LANGUAGE plpgsql
IMMUTABLE NOT FENCED NOT SHIPPABLE
AS $$
declare
begin
/*第二个参数mode,强制为3*/
return EXTRACT(isoyear FROM $1)||
lpad(EXTRACT(WEEK FROM $1),2,'0');
end;
$$;
end if;
if compat_tools.drop_compat_function('function', 'yearweek(text,int4)', '1.0')
then
CREATE OR REPLACE FUNCTION pg_catalog.yearweek(text,int4 default 3)
RETURNS text
LANGUAGE plpgsql
IMMUTABLE NOT FENCED NOT SHIPPABLE
AS $$
declare
begin
/*第二个参数mode,强制为3*/
return EXTRACT(isoyear FROM $1)||
lpad(EXTRACT(WEEK FROM $1),2,'0');
end;
$$;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
select compat_tools.f_unit_test('yearweek(''20220102'',3)', '''202152''', '=','B') into l_result;
select compat_tools.f_unit_test('yearweek(20220102,3)', '''202152''', '=','B') into l_result;
select compat_tools.f_unit_test('yearweek(''20220103'',3)', '''202201''', '=','B') into l_result;
select compat_tools.f_unit_test('yearweek(date''2022-01-03'',3)', '''202201''', '=','B') into l_result;
select compat_tools.f_unit_test('yearweek(20220103,3)', '''202201''', '=','B') into l_result;
-- =========================================================================
-- =========================================================================
-- date_add(TIMESTAMP,interval)
-- 注意: 第二个参数,数字要用单引号包裹
-- =========================================================================
if compat_tools.drop_compat_function('function', 'date_add(timestamp,interval)', '1.0')
then
create or replace function pg_catalog.date_add(timestamp,interval) RETURNS timestamp
LANGUAGE sql
IMMUTABLE NOT FENCED NOT SHIPPABLE
AS $$
select $1+$2;
$$;
end if;
if compat_tools.drop_compat_function('function', 'date_add(timestamptz,interval)', '1.0')
then
create or replace function pg_catalog.date_add(timestamptz,interval) RETURNS timestamptz
LANGUAGE sql
IMMUTABLE NOT FENCED NOT SHIPPABLE
AS $$
select $1+$2;
$$;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
select compat_tools.f_unit_test('date_add(to_timestamp(''20180501'',''yyyymmdd''),INTERVAL ''1'' DAY)', '''2018-05-02 00:00:00.000''::timestamp', '=') into l_result; --> null
select compat_tools.f_unit_test('date_add(''2020-12-31 23:59:59'',INTERVAL ''1'' SECOND)', '''2021-01-01 00:00:00.000''::timestamp', '=') into l_result; --> null
-- =========================================================================
-- =========================================================================
-- json_extract(json,text)
-- json_extract(json,VARIADIC text[])
-- 注:仅3.0版本数据库可用
-- select
-- json_extract('{"name":"mogdb","tel":"13888888888"}','$.name'),
-- json_extract('{"name":"mogdb","tel":"13888888888","c":{"d":"3"}}','$.c.d'),
-- json_extract('[10, 20, [30, 40]]', '$[2][*]') ,
-- json_extract('[10, 20, [30, 40]]', '$[2][1]') ,
-- json_extract('[{"f2":{"f3":1},"f4":{"f5":99,"f6":[0,1,2]}},{"f4":"abc"}]','$[0].f4.f6[2]'),
-- json_extract('[10, 20, [30, 40]]', '$[1]', '$[0]');
-- =========================================================================
if f_version_compare((regexp_split_to_array(substr(version(), instr(version(), '(') + 1), '\s+'))[2], '2.0.0') = 1 and f_version_compare((regexp_split_to_array(substr(version(), instr(version(), '(') + 1), '\s+'))[2], '5.0.0') = -1
then
if compat_tools.drop_compat_function('function', 'json_extract(json,text)', '1.0')
then
CREATE or replace FUNCTION pg_catalog.json_extract (json,text)
RETURNS setof json
IMMUTABLE
AS $$
select $1 #> ('{'||substr(translate(replace($2,'[*]',''),'.[]$',',,'),2)||'}')::_text;
$$ LANGUAGE sql;
end if;
if compat_tools.drop_compat_function('function', 'json_extract(json,text[])', '1.0')
then
CREATE or replace FUNCTION pg_catalog.json_extract (json,VARIADIC text[])
RETURNS setof json
IMMUTABLE
AS $$
select to_json(array_agg($1 #> ('{'||substr(translate(replace(s,'[*]',''),'.[]$',',,'),2)||'}')::_text))
from unnest($2) s;
$$ LANGUAGE sql;
end if;
-- =========================================================================
-- 测试用例:
-- ----------
select compat_tools.f_unit_test('json_extract(''{"name":"mogdb","tel":"13888888888"}'',''$.name'')', '''"mogdb"''', '=') into l_result;
select compat_tools.f_unit_test('json_extract(''{"name":"mogdb","tel":"13888888888","c":{"d":"3"}}'',''$.c.d'')', '''"3"''', '=') into l_result;
select compat_tools.f_unit_test('json_extract(''[10, 20, [30, 40]]'', ''$[2][*]'')', '''[30, 40]''', '=') into l_result;
select compat_tools.f_unit_test('json_extract(''[10, 20, [30, 40]]'', ''$[2][1]'')', '40', '=') into l_result;
select compat_tools.f_unit_test('json_extract(''[{"f2":{"f3":1},"f4":{"f5":99,"f6":[0,1,2]}},{"f4":"abc"}]'',''$[0].f4.f6[2]'')', '2', '=') into l_result;
select compat_tools.f_unit_test('json_extract(''[10, 20, [30, 40]]'', ''$[1]'', ''$[0]'')', '''[20,10]''', '=') into l_result;
-- =========================================================================
end if;
end;
$VIEW_CREATION$ language plpgsql;
-- Show result & Exit
do $RESULT_SUMMARY$
declare
l_app_name text := current_setting('application_name');
l_failed_cnt bigint;
begin
set client_min_messages='notice';
if l_app_name not in ('runMe', 'checkMe')
then
raise notice '';
raise notice '-- =====================================================================';
raise notice '-- Compat Object List: ';
raise notice '-- =====================================================================';
for l_app_name in select ' |' || pad_char
|| rpad(coalesce(object_type, ' '), max_object_type, pad_char) || pad_char || '|' || pad_char
|| rpad(coalesce(object_name, ' '), max_object_name, pad_char) || pad_char || '|' || pad_char
|| rpad(coalesce(object_version, ' '), max_object_version, pad_char) || pad_char || '|' || pad_char
|| rpad(coalesce(object_language, ' '), max_object_language, pad_char) || pad_char || '|' || pad_char
|| rpad(coalesce(operation, ' '), max_operation, pad_char) || pad_char || '|' as result_data
from (select greatest(max(length(object_type)), 5) max_object_type
, greatest(max(length(object_name)), 6) max_object_name
, greatest(max(length(case when local_version = script_version then local_version else local_version || ' => ' || script_version end)), 7) max_object_version
, greatest(max(length(case when local_language = script_language then local_language else local_language || ' => ' || script_language end)), 8) max_object_language
, greatest(max(length(operation)), 9) max_operation
from temp_result) l
join (select 'type' as object_type
, 'name' as object_name
, 'version' as object_version
, 'language' as object_language
, 'operation' as operation
, ' ' as pad_char
union all
select '-' as object_type
, '-' as object_name
, '-' as object_version
, '-' as object_language
, '-' as operation
, '-' as pad_char
union all
select object_type, object_name
, case when local_version = script_version then local_version else local_version || ' => ' || script_version end as object_version
, case when local_language = script_language then local_language else local_language || ' => ' || script_language end as object_language
, operation, ' ' from temp_result) r on 1 = 1
loop
raise notice '%', l_app_name;
end loop;
raise notice '';
raise notice '-- =====================================================================';
raise notice '-- Test Summary: ';
raise notice '-- =====================================================================';
for l_app_name in select ' | result_type | case_count | start_time | complete_time |'
union all
select ' |-------------|------------|---------------------|---------------------|'
union all
select ' | '
|| rpad((case when test_ok then 'PASSED' when not test_ok then 'FAILED' else 'NULL' end)::text, 11)
|| ' | '
|| lpad(count(*)::text, 10)
|| ' | '
|| to_char(min(test_timestamp), 'YYYY-MM-DD HH24:MI:SS')
|| ' | '
|| to_char(max(test_timestamp), 'YYYY-MM-DD HH24:MI:SS')
|| ' |' as result_data
from compat_tools.compat_testing
group by case when test_ok then 'PASSED' when not test_ok then 'FAILED' else 'NULL' end
loop
raise notice '%', l_app_name;
end loop;
raise notice '';
raise notice '-- =====================================================================';
raise notice '-- Test Detail (Failed or Null): ';
raise notice '-- =====================================================================';
select count(*) into l_failed_cnt
from compat_tools.compat_testing
where test_ok is null or (not test_ok);
if l_failed_cnt = 0
then
raise notice '-- <<< ALL SUCCEED >>>';
else
for l_app_name in select ' | test_expression | result | expect | complete_time |'
union all
select ' |----------------------------------------------|-----------------|-----------------|---------------------|'
union all
select ' | '
|| case when length(test_expr) > 44 then substr(test_expr, 1, 40)||' ...' else rpad(test_expr, 44) end
|| ' | '
|| lpad(coalesce(test_result, ' '), 15)
|| ' | '
|| rpad(coalesce(expect_result, ' '), 15)
|| ' | '
|| to_char(test_timestamp, 'YYYY-MM-DD HH24:MI:SS')
|| ' |' as result_data
from compat_tools.compat_testing
where test_ok is null or (not test_ok)
loop
raise notice '%', l_app_name;
end loop;
end if;
end if;
end;
$RESULT_SUMMARY$ language plpgsql;
reset behavior_compat_options;
\q
SQL
1
https://gitee.com/enmotech/compat-tools.git
git@gitee.com:enmotech/compat-tools.git
enmotech
compat-tools
compat-tools
master

搜索帮助