From 3f334a5bb8f65f25544e16eaac8562dd0c8b6882 Mon Sep 17 00:00:00 2001 From: qianxue Date: Tue, 8 Apr 2025 02:29:45 -0400 Subject: [PATCH] sql_variant --- contrib/shark/CMakeLists.txt | 1 + contrib/shark/Makefile | 2 +- contrib/shark/input/test_sqlvariant.source | 351 ++++++ contrib/shark/output/test_sqlvariant.source | 1235 +++++++++++++++++++ contrib/shark/parallel_schedule | 2 +- contrib/shark/shark--1.0.sql | 391 ++++++ contrib/shark/sqlvariant.cpp | 703 +++++++++++ src/common/backend/parser/parse_coerce.cpp | 45 +- src/include/parser/parse_coerce.h | 1 + 9 files changed, 2715 insertions(+), 16 deletions(-) create mode 100644 contrib/shark/input/test_sqlvariant.source create mode 100644 contrib/shark/output/test_sqlvariant.source create mode 100644 contrib/shark/sqlvariant.cpp diff --git a/contrib/shark/CMakeLists.txt b/contrib/shark/CMakeLists.txt index 32f375d6ad..bab71ad4e9 100644 --- a/contrib/shark/CMakeLists.txt +++ b/contrib/shark/CMakeLists.txt @@ -100,6 +100,7 @@ add_cmd_gen_when_configure(flex_target shark_parser_cmd_src) set(TGT_shark_SRC ${CMAKE_CURRENT_SOURCE_DIR}/shark.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/sqlvariant.cpp ${CMAKE_CURRENT_SOURCE_DIR}/${BEPARSERDIR}/gram-backend.cpp ${CMAKE_CURRENT_SOURCE_DIR}/${BEPARSERDIR}/keywords.cpp ${CMAKE_CURRENT_SOURCE_DIR}/${BEPARSERDIR}/parser.cpp diff --git a/contrib/shark/Makefile b/contrib/shark/Makefile index f8aef5c7f5..9adee1f968 100644 --- a/contrib/shark/Makefile +++ b/contrib/shark/Makefile @@ -6,7 +6,7 @@ PLDIR=src/pltsql DATA = shark--1.0.sql REGRESS = dummy -OBJS = shark.o dbcc.o varlena.o +OBJS = shark.o dbcc.o varlena.o sqlvariant.o OBJS += $(BEPARSERDIR)/parser.o OBJS += $(BEPARSERDIR)/gram-backend.o OBJS += $(BEPARSERDIR)/keywords.o diff --git a/contrib/shark/input/test_sqlvariant.source b/contrib/shark/input/test_sqlvariant.source new file mode 100644 index 0000000000..279cf3d6a0 --- /dev/null +++ b/contrib/shark/input/test_sqlvariant.source @@ -0,0 +1,351 @@ +drop database if exists db_mssql_sqlvariant; +create database db_mssql_sqlvariant dbcompatibility 'd'; +\c db_mssql_sqlvariant +create extension shark; +-- 表存储 +create table t (a sql_variant); +create index idx1 on t(a); +select pg_get_tabledef('t'); + +-- 这里都是隐式转换 +insert into t values(1::int); +insert into t values(1::int8); +insert into t values(2::numeric); +insert into t values('3'::varchar); +insert into t values(1::varchar); +insert into t values(1::varchar); +insert into t values(1::varchar); +insert into t values('1234567890'::varchar(10)); +insert into t values('1234567890'::nchar(10)); +insert into t values(NULL::numeric); +insert into t values(4); +insert into t values(4.1); +insert into t values('5'); +insert into t values(true); +insert into t values(null); +insert into t values(2::money); + +select * from t order by a; +explain select * from t order by a; +select * from t where a=1; +select * from t where a=1::varchar; + +create table tt (a sql_variant, b text); +insert into tt values(1::int,1); +insert into tt values(2::numeric,2); +insert into tt values('3'::varchar,3); +insert into tt values('1234567890'::varchar(10),'1234567890'); +insert into tt values('1234567890'::nchar(10),'1234567890'); +insert into tt values(NULL::numeric,null::numeric); +insert into tt values(4,4); +insert into tt values(4.1,4.1); +insert into tt values('5','5'); +insert into tt values(true,true); +insert into tt values(null,null); +select * from tt join t on t.a=tt.a; + +-- 视图 +CREATE VIEW t_v AS SELECT * FROM t AS t_a; +select * from t_v; + +-- 函数 +CREATE OR REPLACE FUNCTION test_sql_variant(sql_variant, sql_variant) +RETURNS BOOL +AS $$ select $1 > $2 $$ +LANGUAGE SQL STRICT IMMUTABLE NOT FENCED; +select test_sql_variant(1::numeric, 2::numeric); + +-- 比较运算符 +-- 有比较运算符 +select 1::int::sql_variant > 3::int::sql_variant; +select 1::int::sql_variant >= 3::int::sql_variant; +select 1::int::sql_variant < 3::int::sql_variant; +select 1::int::sql_variant <= 3::int::sql_variant; +select 1::int::sql_variant = 3::int::sql_variant; +select 1::int::sql_variant <> 3::int::sql_variant; + +-- 有比较运算符, 不同类型 +select 1::int::sql_variant > 1::int8::sql_variant; +select 1::int::sql_variant >= 1::int8::sql_variant; +select 1::int::sql_variant < 1::int8::sql_variant; +select 1::int::sql_variant <= 1::int8::sql_variant; +select 1::int::sql_variant = 1::int8::sql_variant; +select 1::int::sql_variant <> 1::int8::sql_variant; + +-- 没有比较运算符, 不同类型, 不同catalogy +select '1'::int::sql_variant = '1'::varchar::sql_variant; +select '1'::int::sql_variant <> '1'::varchar::sql_variant; +select '1'::int::sql_variant > '1'::varchar::sql_variant; +select '1'::int::sql_variant >= '1'::varchar::sql_variant; +select '1'::int::sql_variant < '1'::varchar::sql_variant; +select '1'::int::sql_variant <= '1'::varchar::sql_variant; + +-- 没有比较运算符, 不同类型, 相同catalogy +select '1'::char::sql_variant = '1'::varchar::sql_variant; +select '1'::char::sql_variant <> '1'::varchar::sql_variant; +select '1'::char::sql_variant > '1'::varchar::sql_variant; +select '1'::char::sql_variant >= '1'::varchar::sql_variant; +select '1'::char::sql_variant < '1'::varchar::sql_variant; +select '1'::char::sql_variant <= '1'::varchar::sql_variant; + +-- 没有比较运算符,且类型相同 +select '1'::varchar::sql_variant = '1'::varchar::sql_variant; +select '1'::varchar::sql_variant <> '1'::varchar::sql_variant; +select '1'::varchar::sql_variant > '1'::varchar::sql_variant; +select '1'::varchar::sql_variant >= '1'::varchar::sql_variant; +select '1'::varchar::sql_variant < '1'::varchar::sql_variant; +select '1'::varchar::sql_variant <= '1'::varchar::sql_variant; + +-- 字符串类型有特殊规则 +select '111' = '111'::varchar::sql_variant; +select '111' = '111'::char(3)::sql_variant; +select '111' = '111'::nvarchar::sql_variant; +select '111' = '111'::nchar(3)::sql_variant; +select '1111' = '111'::varchar::sql_variant; +select '1111' = '111'::char(3)::sql_variant; +select '1111' = '111'::nvarchar::sql_variant; +select '1111' = '111'::nchar(3)::sql_variant; +select '1111' > '111'::varchar::sql_variant; +select '1111' > '111'::char(3)::sql_variant; +select '1111' > '111'::nvarchar::sql_variant; +select '1111' > '111'::nchar(3)::sql_variant; +select '1111' < '111'::varchar::sql_variant; +select '1111' < '111'::char(3)::sql_variant; +select '1111' < '111'::nvarchar::sql_variant; +select '1111' < '111'::nchar(3)::sql_variant; +select '111'::varchar::sql_variant = '111'::varchar::sql_variant; +select '111'::varchar::sql_variant = '111'::char(3)::sql_variant; +select '111'::varchar::sql_variant = '111'::nvarchar::sql_variant; +select '111'::varchar::sql_variant = '111'::nchar(3)::sql_variant; +select '111'::char(3)::sql_variant = '111'::varchar::sql_variant; +select '111'::char(3)::sql_variant = '111'::char(3)::sql_variant; +select '111'::char(3)::sql_variant = '111'::nvarchar::sql_variant; +select '111'::char(3)::sql_variant = '111'::nchar(3)::sql_variant; +select '111'::char(4)::sql_variant = '111'::varchar::sql_variant; +select '111'::char(4)::sql_variant = '111'::char(3)::sql_variant; +select '111'::char(4)::sql_variant = '111'::nvarchar::sql_variant; +select '111'::char(4)::sql_variant = '111'::nchar(3)::sql_variant; +select '111'::nvarchar::sql_variant = '111'::varchar::sql_variant; +select '111'::nvarchar::sql_variant = '111'::char(3)::sql_variant; +select '111'::nvarchar::sql_variant = '111'::nvarchar::sql_variant; +select '111'::nvarchar::sql_variant = '111'::nchar(3)::sql_variant; +select '111'::nchar(3)::sql_variant = '111'::varchar::sql_variant; +select '111'::nchar(3)::sql_variant = '111'::char(3)::sql_variant; +select '111'::nchar(3)::sql_variant = '111'::nvarchar::sql_variant; +select '111'::nchar(3)::sql_variant = '111'::nchar(3)::sql_variant; +select '111'::nchar(8)::sql_variant = '111'::varchar::sql_variant; +select '111'::nchar(8)::sql_variant = '111'::char(3)::sql_variant; +select '111'::nchar(8)::sql_variant = '111'::nvarchar::sql_variant; +select '111'::nchar(8)::sql_variant = '111'::nchar(3)::sql_variant; + +select '111 '::varchar::sql_variant = '111'::varchar::sql_variant; +select '111 '::char(6)::sql_variant = '111'::varchar::sql_variant; +select '111 '::nvarchar::sql_variant = '111'::varchar::sql_variant; +select '111 '::nchar(6)::sql_variant = '111'::varchar::sql_variant; +select '111 '::sql_variant = '111'::varchar::sql_variant; + +-- 类型转换 +-- 测试几种,理论上大部分都要支持的 +select 1::int::sql_variant; +select 1::numeric::sql_variant; +select 1::varchar::sql_variant; +select '111111'::varchar::sql_variant; +select NULL::int::sql_variant; + +-- 转换原类型 +select 1::int::sql_variant::int; +select 1::numeric::sql_variant::numeric; +select 1::varchar::sql_variant::varchar; +select '111111'::varchar::sql_variant::varchar; +select NULL::int::sql_variant::int; +select '2020-01-01 10:10:10'::smalldatetime::sql_variant::smalldatetime; +select '2020-01-01'::date::sql_variant::date; +select '10:10:10'::time::sql_variant::time; +select 1.23::float::sql_variant::float; +select 1.23::float4::sql_variant::float4; +select 1.23::money::sql_variant::money; +select 1::bigint::sql_variant::bigint; +select 1::smallint::sql_variant::smallint; +select 1::tinyint::sql_variant::tinyint; +select '1'::bit::sql_variant::bit; +select 'a'::char::sql_variant::char; +select 1::nvarchar::sql_variant::nvarchar; + +-- 转到其他类型 +select 1::int::numeric; +select 1::int::sql_variant::numeric; +select 1::int::varchar; +select 1::int::sql_variant::varchar; +select NULL::int::sql_variant::numeric; +select '2020-01-01 10:10:10'::datetime::sql_variant::date; +select '2020-01-01'::date::sql_variant::datetime; +select '10:10:10'::time::sql_variant::datetime; +select 1.23::float::sql_variant::numeric; +select 1.23::float4::sql_variant::numeric; +select 1.23::money::sql_variant::varchar; +select 1::bigint::sql_variant::numeric; +select 1::smallint::sql_variant::int; +select 1::tinyint::sql_variant::int; +select '1'::bit::sql_variant::varchar; +select 'a'::char::sql_variant::varchar; +select 1::nvarchar::sql_variant::varchar; + +-- falied +select 1::int::time; +select 1::int::sql_variant::time; +select '10:10:10'::time::int; +select '10:10:10'::time::sql_variant::int; + +select '0x123456'::text::sql_variant; +select ''::xml::sql_variant; +select 1::numeric::sql_variant::sql_variant; + +select null::text::sql_variant; +select null::xml::sql_variant; +select ''::text::sql_variant; +select ''::xml::sql_variant; +select 1::sql_variant::bytea; +select '{"a": 1}'::jsonb::sql_variant::json; +select '{"a": 1}'::jsonb::sql_variant::json; + +-- 长度限制 +select '111112333'::char(8001)::sql_variant; +select '111112333'::char(8000)::sql_variant; +select '111112333'::char(10)::sql_variant; + +-- 类似sql_variant直接输入 +select true::sql_variant; +select false::sql_variant; +select true::sql_variant::boolean; +select false::sql_variant::boolean; +select 1::sql_variant; +select 1::sql_variant::int; +select 1::sql_variant::numeric; +select 1.111::sql_variant; +select 1.111::sql_variant::numeric; +select 1.111::sql_variant::int; +select 'hello'::sql_variant; +select 'sss'::sql_variant; +select null::sql_variant; +select null::sql_variant is null; +select null::int::sql_variant is null; +select ''::sql_variant; + +create table t1 (a char(8)); +insert into t1 values('sss'::char(8)::sql_variant); +create table t2 (a sql_variant not null); +insert into t2 values(null); +insert into t2 values(null::int); + +declare + res sql_variant; + res1 int; + res2 varchar; +begin + res := '1.2333'::float; + res1 := res::int; + res2 := res; + raise notice '%', res; + raise notice '%', res::float; + raise notice '%', res1; + raise notice '%', res2; +end; +/ +create domain tp1 as sql_variant; +create domain tp2 as int; +select 1::int::tp1; +select 1::sql_variant::tp2; +select 1::tp2::sql_variant; +select 1::tp2::tp1::tp2; +select 1::tp1::tp1; +select 1::tp1::sql_variant; +select 'ssss'::sql_variant = 'ssss'; +drop domain tp1; +drop domain tp2; + +select ''::sql_variant = ''::sql_variant; +select ''::sql_variant = ''; + +DECLARE + p varchar; +BEGIN + raise notice '%', 1::sql_variant; + p := 1::sql_variant; + raise notice '%', p; +END; +/ + +drop type if exists tp1; +create type tp1 as (a1 int, a2 sql_variant); +create table t_tp (c tp1); +insert into t_tp values((1, 'sddd')); +select * from t_tp; +drop table t_tp; +drop type if exists tp1; + +--建外表 +create table tt_1130316(a1 sql_variant PRIMARY KEY); +insert into tt_1130316 values(2::int),('ff'::char(4)),('!'::varchar(3)),('li'::char(6)),('good'::varchar2(8)); + +create table tab_1130316( +a1 int not null, +a2 sql_variant unique, +a3 sql_variant PRIMARY KEY, +a4 sql_variant default 'good'::char(8), +a5 sql_variant check(a5 is not null), +a6 sql_variant REFERENCES tt_1130316(a1)) +partition by range(a1) +( +PARTITION P1 VALUES LESS THAN(100), +PARTITION P2 VALUES LESS THAN(200), +PARTITION P3 VALUES LESS THAN(MAXVALUE) +); + +insert into tab_1130316 values(1,'bb'::char(4),'cc'::varchar(3),'dd'::varchar2(8),'ee'::varchar,'ff'::char(8));--成功 +insert into tab_1130316 values(null,'hi'::char(4),'how'::char(4),'are'::char(4),'you'::char(4),'!'::char(4));--触发约束,报错 +insert into tab_1130316 values(2,'bb'::char(4),'how'::char(4),'are'::char(4),'you'::char(4),'!'::char(4));--触发约束,报错 +insert into tab_1130316 values(3,'name'::char(8),'cc'::varchar(4),'is'::char(4),'li'::char(4),'li'::char(4));--触发约束,报错 +insert into tab_1130316(a1,a2,a3,a5,a6) values(4,'english'::char(16),'is'::char(4),'very'::char(4),'good'::varchar(4));--触发约束,成功 +insert into tab_1130316 values(5,'is'::char(4),'null'::char(4),'?'::char(4),null,'yes'::char(4));--触发约束,报错 +insert into tab_1130316 values(6,'外键'::char(8),'约束'::char(8),'是'::char(4),'1'::char(4),'2'::char(4));--触发约束,报错 + +MERGE INTO tab_1130316 p +USING tt_1130316 np +ON (p.a6=np.a1) +WHEN MATCHED THEN +UPDATE SET p.a4 = 'bad'::char(4) where p.a2='wzr'::char(4) +WHEN NOT MATCHED THEN +INSERT VALUES (8, np.a1,np.a1,np.a1,np.a1,np.a1); + +\c contrib_regression +drop database db_mssql_sqlvariant; + +-- dump +create database dump_database with dbcompatibility 'D'; +create database restore_database with dbcompatibility 'D'; +\c dump_database +create extension shark; +create table t (a sql_variant); +insert into t values(1::int); +insert into t values(2::numeric); +insert into t values('3'::varchar); +insert into t values('1234567890'::varchar(10)); +insert into t values('1234567890'::nchar(10)); +insert into t values(NULL::numeric); +insert into t values(4); +insert into t values(4.1); +insert into t values('5'); +insert into t values(null); +select * from t order by a; + +\c restore_database +create extension shark; + +\! @abs_bindir@/gs_dump dump_database -p @portstring@ -f @abs_bindir@/dump_sqlvariant.tar -F t >/dev/null 2>&1; echo $? +\! @abs_bindir@/gs_restore -d restore_database -p @portstring@ @abs_bindir@/dump_sqlvariant.tar >/dev/null 2>&1; echo $? +\c restore_database +select * from t order by a; + +\c contrib_regression +drop database dump_database; +drop database restore_database; diff --git a/contrib/shark/output/test_sqlvariant.source b/contrib/shark/output/test_sqlvariant.source new file mode 100644 index 0000000000..1f511a75f1 --- /dev/null +++ b/contrib/shark/output/test_sqlvariant.source @@ -0,0 +1,1235 @@ +drop database if exists db_mssql_sqlvariant; +NOTICE: database "db_mssql_sqlvariant" does not exist, skipping +create database db_mssql_sqlvariant dbcompatibility 'd'; +\c db_mssql_sqlvariant +create extension shark; +-- 表存储 +create table t (a sql_variant); +create index idx1 on t(a); +select pg_get_tabledef('t'); + pg_get_tabledef +--------------------------------------------------------------- + SET search_path = public; + + CREATE TABLE t ( + + a sql_variant + + ) + + WITH (orientation=row, compression=no); + + CREATE INDEX idx1 ON t USING btree (a) TABLESPACE pg_default; +(1 row) + +-- 这里都是隐式转换 +insert into t values(1::int); +insert into t values(1::int8); +insert into t values(2::numeric); +insert into t values('3'::varchar); +insert into t values(1::varchar); +insert into t values(1::varchar); +insert into t values(1::varchar); +insert into t values('1234567890'::varchar(10)); +insert into t values('1234567890'::nchar(10)); +insert into t values(NULL::numeric); +insert into t values(4); +insert into t values(4.1); +insert into t values('5'); +insert into t values(true); +ERROR: column "a" is of type sql_variant but expression is of type boolean +LINE 1: insert into t values(true); + ^ +HINT: You will need to rewrite or cast the expression. +CONTEXT: referenced column: a +insert into t values(null); +insert into t values(2::money); +ERROR: operator does not exist: integer < money +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +select * from t order by a; + a +------------ + 1 + 1 + 1 + 1234567890 + 1234567890 + 3 + 5 + 1 + 1 + 2 + 4 + 4.1 + + +(14 rows) + +explain select * from t order by a; + QUERY PLAN +------------------------------------------------------------------------ + [Bypass] + Index Only Scan using idx1 on t (cost=0.00..68.00 rows=1317 width=32) +(2 rows) + +select * from t where a=1; + a +--- + 1 + 1 +(2 rows) + +select * from t where a=1::varchar; + a +--- + 1 + 1 + 1 +(3 rows) + +create table tt (a sql_variant, b text); +insert into tt values(1::int,1); +insert into tt values(2::numeric,2); +insert into tt values('3'::varchar,3); +insert into tt values('1234567890'::varchar(10),'1234567890'); +insert into tt values('1234567890'::nchar(10),'1234567890'); +insert into tt values(NULL::numeric,null::numeric); +insert into tt values(4,4); +insert into tt values(4.1,4.1); +insert into tt values('5','5'); +insert into tt values(true,true); +ERROR: column "a" is of type sql_variant but expression is of type boolean +LINE 1: insert into tt values(true,true); + ^ +HINT: You will need to rewrite or cast the expression. +CONTEXT: referenced column: a +insert into tt values(null,null); +select * from tt join t on t.a=tt.a; + a | b | a +------------+------------+------------ + 1234567890 | 1234567890 | 1234567890 + 1234567890 | 1234567890 | 1234567890 + 1234567890 | 1234567890 | 1234567890 + 1234567890 | 1234567890 | 1234567890 + 3 | 3 | 3 + 5 | 5 | 5 + 1 | 1 | 1 + 1 | 1 | 1 + 2 | 2 | 2 + 4 | 4 | 4 + 4.1 | 4.1 | 4.1 +(11 rows) + +-- 视图 +CREATE VIEW t_v AS SELECT * FROM t AS t_a; +select * from t_v; + a +------------ + 1 + 1 + 2 + 3 + 1 + 1 + 1 + 1234567890 + 1234567890 + + 4 + 4.1 + 5 + +(14 rows) + +-- 函数 +CREATE OR REPLACE FUNCTION test_sql_variant(sql_variant, sql_variant) +RETURNS BOOL +AS $$ select $1 > $2 $$ +LANGUAGE SQL STRICT IMMUTABLE NOT FENCED; +select test_sql_variant(1::numeric, 2::numeric); + test_sql_variant +------------------ + f +(1 row) + +-- 比较运算符 +-- 有比较运算符 +select 1::int::sql_variant > 3::int::sql_variant; + ?column? +---------- + f +(1 row) + +select 1::int::sql_variant >= 3::int::sql_variant; + ?column? +---------- + f +(1 row) + +select 1::int::sql_variant < 3::int::sql_variant; + ?column? +---------- + t +(1 row) + +select 1::int::sql_variant <= 3::int::sql_variant; + ?column? +---------- + t +(1 row) + +select 1::int::sql_variant = 3::int::sql_variant; + ?column? +---------- + f +(1 row) + +select 1::int::sql_variant <> 3::int::sql_variant; + ?column? +---------- + t +(1 row) + +-- 有比较运算符, 不同类型 +select 1::int::sql_variant > 1::int8::sql_variant; + ?column? +---------- + f +(1 row) + +select 1::int::sql_variant >= 1::int8::sql_variant; + ?column? +---------- + t +(1 row) + +select 1::int::sql_variant < 1::int8::sql_variant; + ?column? +---------- + f +(1 row) + +select 1::int::sql_variant <= 1::int8::sql_variant; + ?column? +---------- + t +(1 row) + +select 1::int::sql_variant = 1::int8::sql_variant; + ?column? +---------- + t +(1 row) + +select 1::int::sql_variant <> 1::int8::sql_variant; + ?column? +---------- + f +(1 row) + +-- 没有比较运算符, 不同类型, 不同catalogy +select '1'::int::sql_variant = '1'::varchar::sql_variant; + ?column? +---------- + f +(1 row) + +select '1'::int::sql_variant <> '1'::varchar::sql_variant; + ?column? +---------- + t +(1 row) + +select '1'::int::sql_variant > '1'::varchar::sql_variant; + ?column? +---------- + t +(1 row) + +select '1'::int::sql_variant >= '1'::varchar::sql_variant; + ?column? +---------- + t +(1 row) + +select '1'::int::sql_variant < '1'::varchar::sql_variant; + ?column? +---------- + f +(1 row) + +select '1'::int::sql_variant <= '1'::varchar::sql_variant; + ?column? +---------- + f +(1 row) + +-- 没有比较运算符, 不同类型, 相同catalogy +select '1'::char::sql_variant = '1'::varchar::sql_variant; + ?column? +---------- + t +(1 row) + +select '1'::char::sql_variant <> '1'::varchar::sql_variant; + ?column? +---------- + f +(1 row) + +select '1'::char::sql_variant > '1'::varchar::sql_variant; + ?column? +---------- + f +(1 row) + +select '1'::char::sql_variant >= '1'::varchar::sql_variant; + ?column? +---------- + t +(1 row) + +select '1'::char::sql_variant < '1'::varchar::sql_variant; + ?column? +---------- + f +(1 row) + +select '1'::char::sql_variant <= '1'::varchar::sql_variant; + ?column? +---------- + t +(1 row) + +-- 没有比较运算符,且类型相同 +select '1'::varchar::sql_variant = '1'::varchar::sql_variant; + ?column? +---------- + t +(1 row) + +select '1'::varchar::sql_variant <> '1'::varchar::sql_variant; + ?column? +---------- + f +(1 row) + +select '1'::varchar::sql_variant > '1'::varchar::sql_variant; + ?column? +---------- + f +(1 row) + +select '1'::varchar::sql_variant >= '1'::varchar::sql_variant; + ?column? +---------- + t +(1 row) + +select '1'::varchar::sql_variant < '1'::varchar::sql_variant; + ?column? +---------- + f +(1 row) + +select '1'::varchar::sql_variant <= '1'::varchar::sql_variant; + ?column? +---------- + t +(1 row) + +-- 字符串类型有特殊规则 +select '111' = '111'::varchar::sql_variant; + ?column? +---------- + t +(1 row) + +select '111' = '111'::char(3)::sql_variant; + ?column? +---------- + t +(1 row) + +select '111' = '111'::nvarchar::sql_variant; + ?column? +---------- + t +(1 row) + +select '111' = '111'::nchar(3)::sql_variant; + ?column? +---------- + t +(1 row) + +select '1111' = '111'::varchar::sql_variant; + ?column? +---------- + f +(1 row) + +select '1111' = '111'::char(3)::sql_variant; + ?column? +---------- + f +(1 row) + +select '1111' = '111'::nvarchar::sql_variant; + ?column? +---------- + f +(1 row) + +select '1111' = '111'::nchar(3)::sql_variant; + ?column? +---------- + f +(1 row) + +select '1111' > '111'::varchar::sql_variant; + ?column? +---------- + t +(1 row) + +select '1111' > '111'::char(3)::sql_variant; + ?column? +---------- + t +(1 row) + +select '1111' > '111'::nvarchar::sql_variant; + ?column? +---------- + t +(1 row) + +select '1111' > '111'::nchar(3)::sql_variant; + ?column? +---------- + t +(1 row) + +select '1111' < '111'::varchar::sql_variant; + ?column? +---------- + f +(1 row) + +select '1111' < '111'::char(3)::sql_variant; + ?column? +---------- + f +(1 row) + +select '1111' < '111'::nvarchar::sql_variant; + ?column? +---------- + f +(1 row) + +select '1111' < '111'::nchar(3)::sql_variant; + ?column? +---------- + f +(1 row) + +select '111'::varchar::sql_variant = '111'::varchar::sql_variant; + ?column? +---------- + t +(1 row) + +select '111'::varchar::sql_variant = '111'::char(3)::sql_variant; + ?column? +---------- + t +(1 row) + +select '111'::varchar::sql_variant = '111'::nvarchar::sql_variant; + ?column? +---------- + t +(1 row) + +select '111'::varchar::sql_variant = '111'::nchar(3)::sql_variant; + ?column? +---------- + t +(1 row) + +select '111'::char(3)::sql_variant = '111'::varchar::sql_variant; + ?column? +---------- + t +(1 row) + +select '111'::char(3)::sql_variant = '111'::char(3)::sql_variant; + ?column? +---------- + t +(1 row) + +select '111'::char(3)::sql_variant = '111'::nvarchar::sql_variant; + ?column? +---------- + t +(1 row) + +select '111'::char(3)::sql_variant = '111'::nchar(3)::sql_variant; + ?column? +---------- + t +(1 row) + +select '111'::char(4)::sql_variant = '111'::varchar::sql_variant; + ?column? +---------- + t +(1 row) + +select '111'::char(4)::sql_variant = '111'::char(3)::sql_variant; + ?column? +---------- + t +(1 row) + +select '111'::char(4)::sql_variant = '111'::nvarchar::sql_variant; + ?column? +---------- + t +(1 row) + +select '111'::char(4)::sql_variant = '111'::nchar(3)::sql_variant; + ?column? +---------- + t +(1 row) + +select '111'::nvarchar::sql_variant = '111'::varchar::sql_variant; + ?column? +---------- + t +(1 row) + +select '111'::nvarchar::sql_variant = '111'::char(3)::sql_variant; + ?column? +---------- + t +(1 row) + +select '111'::nvarchar::sql_variant = '111'::nvarchar::sql_variant; + ?column? +---------- + t +(1 row) + +select '111'::nvarchar::sql_variant = '111'::nchar(3)::sql_variant; + ?column? +---------- + t +(1 row) + +select '111'::nchar(3)::sql_variant = '111'::varchar::sql_variant; + ?column? +---------- + t +(1 row) + +select '111'::nchar(3)::sql_variant = '111'::char(3)::sql_variant; + ?column? +---------- + t +(1 row) + +select '111'::nchar(3)::sql_variant = '111'::nvarchar::sql_variant; + ?column? +---------- + t +(1 row) + +select '111'::nchar(3)::sql_variant = '111'::nchar(3)::sql_variant; + ?column? +---------- + t +(1 row) + +select '111'::nchar(8)::sql_variant = '111'::varchar::sql_variant; + ?column? +---------- + t +(1 row) + +select '111'::nchar(8)::sql_variant = '111'::char(3)::sql_variant; + ?column? +---------- + t +(1 row) + +select '111'::nchar(8)::sql_variant = '111'::nvarchar::sql_variant; + ?column? +---------- + t +(1 row) + +select '111'::nchar(8)::sql_variant = '111'::nchar(3)::sql_variant; + ?column? +---------- + t +(1 row) + +select '111 '::varchar::sql_variant = '111'::varchar::sql_variant; + ?column? +---------- + f +(1 row) + +select '111 '::char(6)::sql_variant = '111'::varchar::sql_variant; + ?column? +---------- + t +(1 row) + +select '111 '::nvarchar::sql_variant = '111'::varchar::sql_variant; + ?column? +---------- + f +(1 row) + +select '111 '::nchar(6)::sql_variant = '111'::varchar::sql_variant; + ?column? +---------- + t +(1 row) + +select '111 '::sql_variant = '111'::varchar::sql_variant; + ?column? +---------- + f +(1 row) + +-- 类型转换 +-- 测试几种,理论上大部分都要支持的 +select 1::int::sql_variant; + sql_variant +------------- + 1 +(1 row) + +select 1::numeric::sql_variant; + sql_variant +------------- + 1 +(1 row) + +select 1::varchar::sql_variant; + sql_variant +------------- + 1 +(1 row) + +select '111111'::varchar::sql_variant; + sql_variant +------------- + 111111 +(1 row) + +select NULL::int::sql_variant; + sql_variant +------------- + +(1 row) + +-- 转换原类型 +select 1::int::sql_variant::int; + int4 +------ + 1 +(1 row) + +select 1::numeric::sql_variant::numeric; + numeric +--------- + 1 +(1 row) + +select 1::varchar::sql_variant::varchar; + varchar +--------- + 1 +(1 row) + +select '111111'::varchar::sql_variant::varchar; + varchar +--------- + 111111 +(1 row) + +select NULL::int::sql_variant::int; + int4 +------ + +(1 row) + +select '2020-01-01 10:10:10'::smalldatetime::sql_variant::smalldatetime; + smalldatetime +-------------------------- + Wed Jan 01 10:10:00 2020 +(1 row) + +select '2020-01-01'::date::sql_variant::date; + date +------------ + 01-01-2020 +(1 row) + +select '10:10:10'::time::sql_variant::time; + time +---------- + 10:10:10 +(1 row) + +select 1.23::float::sql_variant::float; + float8 +-------- + 1.23 +(1 row) + +select 1.23::float4::sql_variant::float4; + float4 +-------- + 1.23 +(1 row) + +select 1.23::money::sql_variant::money; + money +------- + $1.23 +(1 row) + +select 1::bigint::sql_variant::bigint; + int8 +------ + 1 +(1 row) + +select 1::smallint::sql_variant::smallint; + int2 +------ + 1 +(1 row) + +select 1::tinyint::sql_variant::tinyint; + int1 +------ + 1 +(1 row) + +select '1'::bit::sql_variant::bit; + bit +----- + 1 +(1 row) + +select 'a'::char::sql_variant::char; + bpchar +-------- + a +(1 row) + +select 1::nvarchar::sql_variant::nvarchar; + nvarchar2 +----------- + 1 +(1 row) + +-- 转到其他类型 +select 1::int::numeric; + numeric +--------- + 1 +(1 row) + +select 1::int::sql_variant::numeric; + numeric +--------- + 1 +(1 row) + +select 1::int::varchar; + varchar +--------- + 1 +(1 row) + +select 1::int::sql_variant::varchar; + varchar +--------- + 1 +(1 row) + +select NULL::int::sql_variant::numeric; + numeric +--------- + +(1 row) + +select '2020-01-01 10:10:10'::datetime::sql_variant::date; +ERROR: type "datetime" does not exist +LINE 1: select '2020-01-01 10:10:10'::datetime::sql_variant::date; + ^ +CONTEXT: referenced column: date +select '2020-01-01'::date::sql_variant::datetime; +ERROR: type "datetime" does not exist +LINE 1: select '2020-01-01'::date::sql_variant::datetime; + ^ +CONTEXT: referenced column: datetime +select '10:10:10'::time::sql_variant::datetime; +ERROR: type "datetime" does not exist +LINE 1: select '10:10:10'::time::sql_variant::datetime; + ^ +CONTEXT: referenced column: datetime +select 1.23::float::sql_variant::numeric; + numeric +--------- + 1.23 +(1 row) + +select 1.23::float4::sql_variant::numeric; + numeric +--------- + 1.23 +(1 row) + +select 1.23::money::sql_variant::varchar; + varchar +--------- + $1.23 +(1 row) + +select 1::bigint::sql_variant::numeric; + numeric +--------- + 1 +(1 row) + +select 1::smallint::sql_variant::int; + int4 +------ + 1 +(1 row) + +select 1::tinyint::sql_variant::int; + int4 +------ + 1 +(1 row) + +select '1'::bit::sql_variant::varchar; + varchar +--------- + 1 +(1 row) + +select 'a'::char::sql_variant::varchar; + varchar +--------- + a +(1 row) + +select 1::nvarchar::sql_variant::varchar; + varchar +--------- + 1 +(1 row) + +-- falied +select 1::int::time; +ERROR: cannot cast type integer to time without time zone +LINE 1: select 1::int::time; + ^ +CONTEXT: referenced column: time +select 1::int::sql_variant::time; +ERROR: cannot cast type integer to time without time zone +CONTEXT: referenced column: time +select '10:10:10'::time::int; +ERROR: cannot cast type time without time zone to integer +LINE 1: select '10:10:10'::time::int; + ^ +CONTEXT: referenced column: int4 +select '10:10:10'::time::sql_variant::int; +ERROR: cannot cast type time without time zone to integer +CONTEXT: referenced column: int4 +select '0x123456'::text::sql_variant; + sql_variant +------------- + 0x123456 +(1 row) + +select ''::xml::sql_variant; +ERROR: invalid XML content +LINE 1: select ''::xml::sql_variant; + ^ +CONTEXT: referenced column: sql_variant +select 1::numeric::sql_variant::sql_variant; + sql_variant +------------- + 1 +(1 row) + +select null::text::sql_variant; + sql_variant +------------- + +(1 row) + +select null::xml::sql_variant; +ERROR: cannot cast type xml to sql_variant +LINE 1: select null::xml::sql_variant; + ^ +CONTEXT: referenced column: sql_variant +select ''::text::sql_variant; + sql_variant +------------- + +(1 row) + +select ''::xml::sql_variant; +ERROR: invalid XML content +LINE 1: select ''::xml::sql_variant; + ^ +CONTEXT: referenced column: sql_variant +select 1::sql_variant::bytea; +ERROR: cannot cast type sql_variant to bytea +LINE 1: select 1::sql_variant::bytea; + ^ +CONTEXT: referenced column: bytea +select '{"a": 1}'::jsonb::sql_variant::json; +ERROR: cannot cast type jsonb to sql_variant +LINE 1: select '{"a": 1}'::jsonb::sql_variant::json; + ^ +CONTEXT: referenced column: json +select '{"a": 1}'::jsonb::sql_variant::json; +ERROR: cannot cast type jsonb to sql_variant +LINE 1: select '{"a": 1}'::jsonb::sql_variant::json; + ^ +CONTEXT: referenced column: json +-- 长度限制 +select '111112333'::char(8001)::sql_variant; +ERROR: value of basic type must be a binary length <= 8000 byte +CONTEXT: referenced column: sql_variant +select '111112333'::char(8000)::sql_variant; + sql_variant +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 111112333 +(1 row) + +select '111112333'::char(10)::sql_variant; + sql_variant +------------- + 111112333 +(1 row) + +-- 类似sql_variant直接输入 +select true::sql_variant; +ERROR: cannot cast type boolean to sql_variant +LINE 1: select true::sql_variant; + ^ +CONTEXT: referenced column: sql_variant +select false::sql_variant; +ERROR: cannot cast type boolean to sql_variant +LINE 1: select false::sql_variant; + ^ +CONTEXT: referenced column: sql_variant +select true::sql_variant::boolean; +ERROR: cannot cast type boolean to sql_variant +LINE 1: select true::sql_variant::boolean; + ^ +CONTEXT: referenced column: bool +select false::sql_variant::boolean; +ERROR: cannot cast type boolean to sql_variant +LINE 1: select false::sql_variant::boolean; + ^ +CONTEXT: referenced column: bool +select 1::sql_variant; + sql_variant +------------- + 1 +(1 row) + +select 1::sql_variant::int; + int4 +------ + 1 +(1 row) + +select 1::sql_variant::numeric; + numeric +--------- + 1 +(1 row) + +select 1.111::sql_variant; + sql_variant +------------- + 1.111 +(1 row) + +select 1.111::sql_variant::numeric; + numeric +--------- + 1.111 +(1 row) + +select 1.111::sql_variant::int; + int4 +------ + 1 +(1 row) + +select 'hello'::sql_variant; + sql_variant +------------- + hello +(1 row) + +select 'sss'::sql_variant; + sql_variant +------------- + sss +(1 row) + +select null::sql_variant; + sql_variant +------------- + +(1 row) + +select null::sql_variant is null; + ?column? +---------- + t +(1 row) + +select null::int::sql_variant is null; + ?column? +---------- + t +(1 row) + +select ''::sql_variant; + sql_variant +------------- + +(1 row) + +create table t1 (a char(8)); +insert into t1 values('sss'::char(8)::sql_variant); +ERROR: column "a" is of type character but expression is of type sql_variant +LINE 1: insert into t1 values('sss'::char(8)::sql_variant); + ^ +HINT: You will need to rewrite or cast the expression. +CONTEXT: referenced column: a +create table t2 (a sql_variant not null); +insert into t2 values(null); +ERROR: null value in column "a" violates not-null constraint +DETAIL: Failing row contains (null). +insert into t2 values(null::int); +ERROR: null value in column "a" violates not-null constraint +DETAIL: Failing row contains (null). +declare + res sql_variant; + res1 int; + res2 varchar; +begin + res := '1.2333'::float; + res1 := res::int; + res2 := res; + raise notice '%', res; + raise notice '%', res::float; + raise notice '%', res1; + raise notice '%', res2; +end; +/ +NOTICE: 1.2333 +NOTICE: 1.2333 +NOTICE: 1 +NOTICE: 1.2333 +create domain tp1 as sql_variant; +create domain tp2 as int; +select 1::int::tp1; + tp1 +----- + 1 +(1 row) + +select 1::sql_variant::tp2; + tp2 +----- + 1 +(1 row) + +select 1::tp2::sql_variant; + sql_variant +------------- + 1 +(1 row) + +select 1::tp2::tp1::tp2; + tp2 +----- + 1 +(1 row) + +select 1::tp1::tp1; + tp1 +----- + 1 +(1 row) + +select 1::tp1::sql_variant; + sql_variant +------------- + 1 +(1 row) + +select 'ssss'::sql_variant = 'ssss'; + ?column? +---------- + t +(1 row) + +drop domain tp1; +drop domain tp2; +select ''::sql_variant = ''::sql_variant; + ?column? +---------- + t +(1 row) + +select ''::sql_variant = ''; + ?column? +---------- + t +(1 row) + +DECLARE + p varchar; +BEGIN + raise notice '%', 1::sql_variant; + p := 1::sql_variant; + raise notice '%', p; +END; +/ +NOTICE: 1 +NOTICE: 1 +drop type if exists tp1; +NOTICE: type "tp1" does not exist, skipping +create type tp1 as (a1 int, a2 sql_variant); +create table t_tp (c tp1); +insert into t_tp values((1, 'sddd')); +select * from t_tp; + c +---------- + (1,sddd) +(1 row) + +drop table t_tp; +drop type if exists tp1; +--建外表 +create table tt_1130316(a1 sql_variant PRIMARY KEY); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "tt_1130316_pkey" for table "tt_1130316" +insert into tt_1130316 values(2::int),('ff'::char(4)),('!'::varchar(3)),('li'::char(6)),('good'::varchar2(8)); +create table tab_1130316( +a1 int not null, +a2 sql_variant unique, +a3 sql_variant PRIMARY KEY, +a4 sql_variant default 'good'::char(8), +a5 sql_variant check(a5 is not null), +a6 sql_variant REFERENCES tt_1130316(a1)) +partition by range(a1) +( +PARTITION P1 VALUES LESS THAN(100), +PARTITION P2 VALUES LESS THAN(200), +PARTITION P3 VALUES LESS THAN(MAXVALUE) +); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "tab_1130316_pkey" for table "tab_1130316" +NOTICE: CREATE TABLE / UNIQUE will create implicit index "tab_1130316_a2_tableoid_key" for table "tab_1130316" +insert into tab_1130316 values(1,'bb'::char(4),'cc'::varchar(3),'dd'::varchar2(8),'ee'::varchar,'ff'::char(8));--成功 +insert into tab_1130316 values(null,'hi'::char(4),'how'::char(4),'are'::char(4),'you'::char(4),'!'::char(4));--触发约束,报错 +ERROR: null value in column "a1" violates not-null constraint +DETAIL: Failing row contains (null, hi , how , are , you , ! ). +insert into tab_1130316 values(2,'bb'::char(4),'how'::char(4),'are'::char(4),'you'::char(4),'!'::char(4));--触发约束,报错 +ERROR: duplicate key value violates unique constraint "tab_1130316_a2_tableoid_key" +DETAIL: Key (a2)=(bb ) already exists. +insert into tab_1130316 values(3,'name'::char(8),'cc'::varchar(4),'is'::char(4),'li'::char(4),'li'::char(4));--触发约束,报错 +ERROR: duplicate key value violates unique constraint "tab_1130316_pkey" +DETAIL: Key (a3)=(cc) already exists. +insert into tab_1130316(a1,a2,a3,a5,a6) values(4,'english'::char(16),'is'::char(4),'very'::char(4),'good'::varchar(4));--触发约束,成功 +insert into tab_1130316 values(5,'is'::char(4),'null'::char(4),'?'::char(4),null,'yes'::char(4));--触发约束,报错 +ERROR: new row for relation "tab_1130316" violates check constraint "tab_1130316_a5_check" +DETAIL: N/A +insert into tab_1130316 values(6,'外键'::char(8),'约束'::char(8),'是'::char(4),'1'::char(4),'2'::char(4));--触发约束,报错 +ERROR: insert or update on table "tab_1130316" violates foreign key constraint "tab_1130316_a6_fkey" +DETAIL: Key (a6)=(2 ) is not present in table "tt_1130316". +MERGE INTO tab_1130316 p +USING tt_1130316 np +ON (p.a6=np.a1) +WHEN MATCHED THEN +UPDATE SET p.a4 = 'bad'::char(4) where p.a2='wzr'::char(4) +WHEN NOT MATCHED THEN +INSERT VALUES (8, np.a1,np.a1,np.a1,np.a1,np.a1); +\c contrib_regression +drop database db_mssql_sqlvariant; +-- dump +create database dump_database with dbcompatibility 'D'; +create database restore_database with dbcompatibility 'D'; +\c dump_database +create extension shark; +create table t (a sql_variant); +insert into t values(1::int); +insert into t values(2::numeric); +insert into t values('3'::varchar); +insert into t values('1234567890'::varchar(10)); +insert into t values('1234567890'::nchar(10)); +insert into t values(NULL::numeric); +insert into t values(4); +insert into t values(4.1); +insert into t values('5'); +insert into t values(null); +select * from t order by a; + a +------------ + 1234567890 + 1234567890 + 3 + 5 + 1 + 2 + 4 + 4.1 + + +(10 rows) + +\c restore_database +create extension shark; +\! @abs_bindir@/gs_dump dump_database -p @portstring@ -f @abs_bindir@/dump_sqlvariant.tar -F t >/dev/null 2>&1; echo $? +0 +\! @abs_bindir@/gs_restore -d restore_database -p @portstring@ @abs_bindir@/dump_sqlvariant.tar >/dev/null 2>&1; echo $? +0 +\c restore_database +select * from t order by a; + a +------------ + 1 + 1234567890 + 1234567890 + 2 + 3 + 4 + 4.1 + 5 + + +(10 rows) + +\c contrib_regression +drop database dump_database; +drop database restore_database; diff --git a/contrib/shark/parallel_schedule b/contrib/shark/parallel_schedule index 23bb475c99..e0aac5d0a6 100644 --- a/contrib/shark/parallel_schedule +++ b/contrib/shark/parallel_schedule @@ -10,4 +10,4 @@ test: functions test: test_dbcc test_dbcc_case_sen test: test_sysviews test: gs_dump_d_format rotate_part2_dump - +test: test_sqlvariant diff --git a/contrib/shark/shark--1.0.sql b/contrib/shark/shark--1.0.sql index d1651bd592..bfdb339943 100644 --- a/contrib/shark/shark--1.0.sql +++ b/contrib/shark/shark--1.0.sql @@ -556,4 +556,395 @@ lateral ( where has_table_privilege(quote_ident(s.nspname) ||'.'||quote_ident(c_tab.relname), 'SELECT'); grant select on sys.sysindexkeys to public; +create type sql_variant; +CREATE OR REPLACE FUNCTION sys.sql_variantin(cstring) + RETURNS sql_variant + LANGUAGE C + IMMUTABLE STRICT NOT FENCED NOT SHIPPABLE +as '$libdir/shark', 'sql_variantin'; + +CREATE OR REPLACE FUNCTION sys.sql_variantout(sql_variant) + RETURNS cstring + LANGUAGE C + IMMUTABLE STRICT NOT FENCED NOT SHIPPABLE +as '$libdir/shark', 'sql_variantout'; + +CREATE OR REPLACE FUNCTION sys.sql_variantsend(sql_variant) + RETURNS bytea + LANGUAGE C + IMMUTABLE STRICT NOT FENCED NOT SHIPPABLE +as '$libdir/shark', 'sql_variantsend'; + +CREATE OR REPLACE FUNCTION sys.sql_variantrecv(internal) + RETURNS sql_variant + LANGUAGE C + IMMUTABLE STRICT NOT FENCED NOT SHIPPABLE +as '$libdir/shark', 'sql_variantrecv'; + +CREATE TYPE sys.SQL_VARIANT ( + INPUT = sys.sql_variantin, + OUTPUT = sys.sql_variantout, + RECEIVE = sys.sql_variantrecv, + SEND = sys.sql_variantsend, + INTERNALLENGTH = VARIABLE, + ALIGNMENT = 'int4', + STORAGE = 'extended', + CATEGORY = 'U', + PREFERRED = false, + COLLATABLE = true +); + +CREATE OR REPLACE FUNCTION sys.sql_variantcmp(sql_variant, sql_variant) + RETURNS integer + LANGUAGE C + IMMUTABLE STRICT NOT FENCED NOT SHIPPABLE +as '$libdir/shark', 'sql_variantcmp'; + +CREATE OR REPLACE FUNCTION sys.sql_varianteq(sql_variant, sql_variant) + RETURNS boolean + LANGUAGE C + IMMUTABLE STRICT LEAKPROOF NOT FENCED NOT SHIPPABLE +as '$libdir/shark', 'sql_varianteq'; + +CREATE OR REPLACE FUNCTION sys.sql_variantge(sql_variant, sql_variant) + RETURNS boolean + LANGUAGE C + IMMUTABLE STRICT LEAKPROOF NOT FENCED NOT SHIPPABLE +as '$libdir/shark', 'sql_variantge'; + +CREATE OR REPLACE FUNCTION sys.sql_variantgt(sql_variant, sql_variant) + RETURNS boolean + LANGUAGE C + IMMUTABLE STRICT LEAKPROOF NOT FENCED NOT SHIPPABLE +as '$libdir/shark', 'sql_variantgt'; + +CREATE OR REPLACE FUNCTION sys.sql_variantle(sql_variant, sql_variant) + RETURNS boolean + LANGUAGE C + IMMUTABLE STRICT LEAKPROOF NOT FENCED NOT SHIPPABLE +as '$libdir/shark', 'sql_variantle'; + +CREATE OR REPLACE FUNCTION sys.sql_variantlt(sql_variant, sql_variant) + RETURNS boolean + LANGUAGE C + IMMUTABLE STRICT LEAKPROOF NOT FENCED NOT SHIPPABLE +as '$libdir/shark', 'sql_variantlt'; + +CREATE OR REPLACE FUNCTION sys.sql_variantne(sql_variant, sql_variant) + RETURNS boolean + LANGUAGE C + IMMUTABLE STRICT LEAKPROOF NOT FENCED NOT SHIPPABLE +as '$libdir/shark', 'sql_variantne'; + +CREATE OPERATOR sys.= ( + LEFTARG = sys.SQL_VARIANT, + RIGHTARG = sys.SQL_VARIANT, + COMMUTATOR = =, + NEGATOR = <>, + PROCEDURE = sys.sql_varianteq, + RESTRICT = eqsel, + JOIN = eqjoinsel, + MERGES +); + +CREATE OPERATOR sys.<> ( + LEFTARG = sys.SQL_VARIANT, + RIGHTARG = sys.SQL_VARIANT, + NEGATOR = =, + COMMUTATOR = <>, + PROCEDURE = sys.sql_variantne, + RESTRICT = neqsel, + JOIN = neqjoinsel +); + +CREATE OPERATOR sys.< ( + LEFTARG = sys.SQL_VARIANT, + RIGHTARG = sys.SQL_VARIANT, + NEGATOR = >=, + COMMUTATOR = >, + PROCEDURE = sys.sql_variantlt, + RESTRICT = scalarltsel, + JOIN = scalarltjoinsel +); + +CREATE OPERATOR sys.<= ( + LEFTARG = sys.SQL_VARIANT, + RIGHTARG = sys.SQL_VARIANT, + NEGATOR = >, + COMMUTATOR = >=, + PROCEDURE = sys.sql_variantle, + RESTRICT = scalarltsel, + JOIN = scalarltjoinsel +); + +CREATE OPERATOR sys.> ( + LEFTARG = sys.SQL_VARIANT, + RIGHTARG = sys.SQL_VARIANT, + NEGATOR = <=, + COMMUTATOR = <, + PROCEDURE = sys.sql_variantgt, + RESTRICT = scalargtsel, + JOIN = scalargtjoinsel +); + +CREATE OPERATOR sys.>= ( + LEFTARG = sys.SQL_VARIANT, + RIGHTARG = sys.SQL_VARIANT, + NEGATOR = <, + COMMUTATOR = <=, + PROCEDURE = sys.sql_variantge, + RESTRICT = scalargtsel, + JOIN = scalargtjoinsel +); + +CREATE OPERATOR CLASS sys.sqlvariant_ops +DEFAULT FOR TYPE sys.SQL_VARIANT USING btree AS + OPERATOR 1 < (sys.SQL_VARIANT, sys.SQL_VARIANT), + OPERATOR 2 <= (sys.SQL_VARIANT, sys.SQL_VARIANT), + OPERATOR 3 = (sys.SQL_VARIANT, sys.SQL_VARIANT), + OPERATOR 4 >= (sys.SQL_VARIANT, sys.SQL_VARIANT), + OPERATOR 5 > (sys.SQL_VARIANT, sys.SQL_VARIANT), + FUNCTION 1 sql_variantcmp(sys.SQL_VARIANT, sys.SQL_VARIANT); + +-- CAST FUNCTIONS to SQL_VARIANT +CREATE OR REPLACE FUNCTION sys.smalldatetime_sqlvariant(SMALLDATETIME, int) +RETURNS sys.SQL_VARIANT +AS '$libdir/shark', 'smalldatetime2sqlvariant' +LANGUAGE C VOLATILE STRICT ; + +CREATE CAST (SMALLDATETIME AS sys.SQL_VARIANT) +WITH FUNCTION sys.smalldatetime_sqlvariant (SMALLDATETIME, int) AS IMPLICIT; + +CREATE OR REPLACE FUNCTION sys.date_sqlvariant(DATE, int) +RETURNS sys.SQL_VARIANT +AS '$libdir/shark', 'date2sqlvariant' +LANGUAGE C IMMUTABLE STRICT ; + +CREATE CAST (DATE AS sys.SQL_VARIANT) +WITH FUNCTION sys.date_sqlvariant (DATE, int) AS IMPLICIT; + +CREATE OR REPLACE FUNCTION sys.time_sqlvariant(TIME, int) +RETURNS sys.SQL_VARIANT +AS '$libdir/shark', 'time2sqlvariant' +LANGUAGE C IMMUTABLE STRICT ; + +CREATE CAST (TIME AS sys.SQL_VARIANT) +WITH FUNCTION sys.time_sqlvariant (TIME, int) AS IMPLICIT; + +CREATE OR REPLACE FUNCTION sys.float_sqlvariant(FLOAT, int) +RETURNS sys.SQL_VARIANT +AS '$libdir/shark', 'float2sqlvariant' +LANGUAGE C IMMUTABLE STRICT ; + +CREATE CAST (FLOAT AS sys.SQL_VARIANT) +WITH FUNCTION sys.float_sqlvariant (FLOAT, int) AS IMPLICIT; + +CREATE OR REPLACE FUNCTION sys.real_sqlvariant(REAL, int) +RETURNS sys.SQL_VARIANT +AS '$libdir/shark', 'real2sqlvariant' +LANGUAGE C IMMUTABLE STRICT ; + +CREATE CAST (REAL AS sys.SQL_VARIANT) +WITH FUNCTION sys.real_sqlvariant (REAL, int) AS IMPLICIT; + +CREATE OR REPLACE FUNCTION sys.numeric_sqlvariant(NUMERIC, int) +RETURNS sys.SQL_VARIANT +AS '$libdir/shark', 'numeric2sqlvariant' +LANGUAGE C IMMUTABLE STRICT ; + +CREATE CAST (NUMERIC AS sys.SQL_VARIANT) +WITH FUNCTION sys.numeric_sqlvariant (NUMERIC, int) AS IMPLICIT; + +CREATE OR REPLACE FUNCTION sys.money_sqlvariant(money, int) +RETURNS sys.SQL_VARIANT +AS '$libdir/shark', 'money2sqlvariant' +LANGUAGE C IMMUTABLE STRICT ; + +CREATE CAST (money AS sys.SQL_VARIANT) +WITH FUNCTION sys.money_sqlvariant (money, int) AS IMPLICIT; + +CREATE OR REPLACE FUNCTION sys.bigint_sqlvariant(BIGINT, int) +RETURNS sys.SQL_VARIANT +AS '$libdir/shark', 'bigint2sqlvariant' +LANGUAGE C IMMUTABLE STRICT ; + +CREATE CAST (BIGINT AS sys.SQL_VARIANT) +WITH FUNCTION sys.bigint_sqlvariant (BIGINT, int) AS IMPLICIT; + +CREATE OR REPLACE FUNCTION sys.int_sqlvariant(INT, int) +RETURNS sys.SQL_VARIANT +AS '$libdir/shark', 'int2sqlvariant' +LANGUAGE C IMMUTABLE STRICT ; + +CREATE CAST (INT AS sys.SQL_VARIANT) +WITH FUNCTION sys.int_sqlvariant (INT, int) AS IMPLICIT; + +CREATE OR REPLACE FUNCTION sys.smallint_sqlvariant(smallint, int) +RETURNS sys.SQL_VARIANT +AS '$libdir/shark', 'smallint2sqlvariant' +LANGUAGE C IMMUTABLE STRICT ; + +CREATE CAST (smallint AS sys.SQL_VARIANT) +WITH FUNCTION sys.smallint_sqlvariant (smallint, int) AS IMPLICIT; + +CREATE OR REPLACE FUNCTION sys.tinyint_sqlvariant(tinyint, int) +RETURNS sys.SQL_VARIANT +AS '$libdir/shark', 'tinyint2sqlvariant' +LANGUAGE C IMMUTABLE STRICT ; + +CREATE CAST (tinyint AS sys.SQL_VARIANT) +WITH FUNCTION sys.tinyint_sqlvariant (tinyint, int) AS IMPLICIT; + +CREATE OR REPLACE FUNCTION sys.bit_sqlvariant(BIT, int) +RETURNS sys.SQL_VARIANT +AS '$libdir/shark', 'bit2sqlvariant' +LANGUAGE C IMMUTABLE STRICT ; + +CREATE CAST (BIT AS sys.SQL_VARIANT) +WITH FUNCTION sys.bit_sqlvariant (BIT, int) AS IMPLICIT; + +CREATE OR REPLACE FUNCTION sys.varchar_sqlvariant(varchar, int) +RETURNS sys.SQL_VARIANT +AS '$libdir/shark', 'varchar2sqlvariant' +LANGUAGE C IMMUTABLE STRICT ; + +CREATE CAST (VARCHAR AS sys.SQL_VARIANT) +WITH FUNCTION sys.varchar_sqlvariant (VARCHAR, int) AS IMPLICIT; + +CREATE OR REPLACE FUNCTION sys.nvarchar_sqlvariant(nvarchar, int) +RETURNS sys.SQL_VARIANT +AS '$libdir/shark', 'nvarchar2sqlvariant' +LANGUAGE C IMMUTABLE STRICT ; + +CREATE CAST (NVARCHAR AS sys.SQL_VARIANT) +WITH FUNCTION sys.nvarchar_sqlvariant (NVARCHAR, int) AS IMPLICIT; + +CREATE OR REPLACE FUNCTION sys.char_sqlvariant(CHAR, int) +RETURNS sys.SQL_VARIANT +AS '$libdir/shark', 'char2sqlvariant' +LANGUAGE C IMMUTABLE STRICT ; + +CREATE CAST (CHAR AS sys.SQL_VARIANT) +WITH FUNCTION sys.char_sqlvariant (CHAR, int) AS IMPLICIT; + +-- CAST functions from SQL_VARIANT +CREATE OR REPLACE FUNCTION sys.sqlvariant_smalldatetime(sys.SQL_VARIANT) +RETURNS SMALLDATETIME +AS '$libdir/shark', 'sqlvariant2smalldatetime' +LANGUAGE C VOLATILE STRICT ; + +CREATE CAST (sys.SQL_VARIANT AS SMALLDATETIME) +WITH FUNCTION sys.sqlvariant_smalldatetime (sys.SQL_VARIANT); + +CREATE OR REPLACE FUNCTION sys.sqlvariant_date(sys.SQL_VARIANT) +RETURNS DATE +AS '$libdir/shark', 'sqlvariant2date' +LANGUAGE C VOLATILE STRICT ; + +CREATE CAST (sys.SQL_VARIANT AS DATE) +WITH FUNCTION sys.sqlvariant_date (sys.SQL_VARIANT); + +CREATE OR REPLACE FUNCTION sys.sqlvariant_time(sys.SQL_VARIANT) +RETURNS TIME +AS '$libdir/shark', 'sqlvariant2time' +LANGUAGE C VOLATILE STRICT ; + +CREATE CAST (sys.SQL_VARIANT AS TIME) +WITH FUNCTION sys.sqlvariant_time (sys.SQL_VARIANT); + +CREATE OR REPLACE FUNCTION sys.sqlvariant_float(sys.SQL_VARIANT) +RETURNS FLOAT +AS '$libdir/shark', 'sqlvariant2float' +LANGUAGE C VOLATILE STRICT ; + +CREATE CAST (sys.SQL_VARIANT AS FLOAT) +WITH FUNCTION sys.sqlvariant_float (sys.SQL_VARIANT); + +CREATE OR REPLACE FUNCTION sys.sqlvariant_real(sys.SQL_VARIANT) +RETURNS REAL +AS '$libdir/shark', 'sqlvariant2real' +LANGUAGE C VOLATILE STRICT ; + +CREATE CAST (sys.SQL_VARIANT AS REAL) +WITH FUNCTION sys.sqlvariant_real (sys.SQL_VARIANT); + +CREATE OR REPLACE FUNCTION sys.sqlvariant_numeric(sys.SQL_VARIANT) +RETURNS NUMERIC +AS '$libdir/shark', 'sqlvariant2numeric' +LANGUAGE C VOLATILE STRICT ; + +CREATE CAST (sys.SQL_VARIANT AS NUMERIC) +WITH FUNCTION sys.sqlvariant_numeric (sys.SQL_VARIANT); + +CREATE OR REPLACE FUNCTION sys.sqlvariant_money(sys.SQL_VARIANT) +RETURNS MONEY +AS '$libdir/shark', 'sqlvariant2money' +LANGUAGE C VOLATILE STRICT ; + +CREATE CAST (sys.SQL_VARIANT AS MONEY) +WITH FUNCTION sys.sqlvariant_money (sys.SQL_VARIANT); + +CREATE OR REPLACE FUNCTION sys.sqlvariant_bigint(sys.SQL_VARIANT) +RETURNS BIGINT +AS '$libdir/shark', 'sqlvariant2bigint' +LANGUAGE C VOLATILE STRICT ; + +CREATE CAST (sys.SQL_VARIANT AS BIGINT) +WITH FUNCTION sys.sqlvariant_bigint (sys.SQL_VARIANT); + +CREATE OR REPLACE FUNCTION sys.sqlvariant_int(sys.SQL_VARIANT) +RETURNS INT +AS '$libdir/shark', 'sqlvariant2int' +LANGUAGE C VOLATILE STRICT ; + +CREATE CAST (sys.SQL_VARIANT AS INT) +WITH FUNCTION sys.sqlvariant_int (sys.SQL_VARIANT); + +CREATE OR REPLACE FUNCTION sys.sqlvariant_smallint(sys.SQL_VARIANT) +RETURNS SMALLINT +AS '$libdir/shark', 'sqlvariant2smallint' +LANGUAGE C VOLATILE STRICT ; + +CREATE CAST (sys.SQL_VARIANT AS SMALLINT) +WITH FUNCTION sys.sqlvariant_smallint (sys.SQL_VARIANT); + +CREATE OR REPLACE FUNCTION sys.sqlvariant_tinyint(sys.SQL_VARIANT) +RETURNS TINYINT +AS '$libdir/shark', 'sqlvariant2smallint' +LANGUAGE C VOLATILE STRICT ; + +CREATE CAST (sys.SQL_VARIANT AS TINYINT) +WITH FUNCTION sys.sqlvariant_tinyint (sys.SQL_VARIANT); + +CREATE OR REPLACE FUNCTION sys.sqlvariant_bit(sys.SQL_VARIANT) +RETURNS BIT +AS '$libdir/shark', 'sqlvariant2bit' +LANGUAGE C VOLATILE STRICT ; + +CREATE CAST (sys.SQL_VARIANT AS BIT) +WITH FUNCTION sys.sqlvariant_bit (sys.SQL_VARIANT); + +CREATE OR REPLACE FUNCTION sys.sqlvariant_sysvarchar(sys.SQL_VARIANT) +RETURNS VARCHAR +AS '$libdir/shark', 'sqlvariant2varchar' +LANGUAGE C VOLATILE STRICT ; + +CREATE CAST (sys.SQL_VARIANT AS VARCHAR) +WITH FUNCTION sys.sqlvariant_sysvarchar (sys.SQL_VARIANT); + +CREATE OR REPLACE FUNCTION sys.sqlvariant_nvarchar(sys.SQL_VARIANT) +RETURNS NVARCHAR +AS '$libdir/shark', 'sqlvariant2varchar' +LANGUAGE C VOLATILE STRICT ; + +CREATE CAST (sys.SQL_VARIANT AS NVARCHAR) +WITH FUNCTION sys.sqlvariant_sysvarchar (sys.SQL_VARIANT); + +CREATE OR REPLACE FUNCTION sys.sqlvariant_char(sys.SQL_VARIANT) +RETURNS CHAR +AS '$libdir/shark', 'sqlvariant2char' +LANGUAGE C VOLATILE STRICT ; + +CREATE CAST (sys.SQL_VARIANT AS CHAR) +WITH FUNCTION sys.sqlvariant_char (sys.SQL_VARIANT); reset search_path; diff --git a/contrib/shark/sqlvariant.cpp b/contrib/shark/sqlvariant.cpp new file mode 100644 index 0000000000..728de7aff0 --- /dev/null +++ b/contrib/shark/sqlvariant.cpp @@ -0,0 +1,703 @@ +#include "knl/knl_variable.h" + +#include "postgres.h" +#include "miscadmin.h" +#include "knl/knl_instance.h" +#include +#include + +#include "access/sysattr.h" +#include "knl/knl_variable.h" +#include "commands/extension.h" +#include "commands/dbcommands.h" +#include "nodes/execnodes.h" +#include "utils/builtins.h" +#include "utils/cash.h" +#include "utils/date.h" +#include "utils/numeric.h" +#include "utils/numeric_gs.h" +#include "utils/varbit.h" +#include "utils/lsyscache.h" +#include "utils/fmgroids.h" +#include "parser/scansup.h" +#include "parser/parse_coerce.h" +#include "parser/parse_oper.h" +#include "tcop/ddldeparse.h" +#include "catalog/pg_depend.h" +#include "catalog/pg_attrdef.h" +#include "catalog/indexing.h" +#include "catalog/pg_constraint.h" +#include "catalog/pg_operator.h" +#include "catalog/pg_trigger.h" +#include "libpq/pqformat.h" + +/* limit for sql_variant */ +#define MaxSqlVariantSize 8016 +#define MaxBasicValueSize 8000 + +static Datum do_cast(Oid source_type, Oid target_type, Datum value, int32_t typmod, Oid coll, CoercionContext cc); +Datum do_compare(char *oprname, Datum basic_value1, Datum basic_value2, Oid type_oid1, Oid type_oid2, int typeprio1, int typeprio2, Oid fncollation); +Datum comp_time(char *oprname, uint16_t t1, uint16_t t2); + +typedef struct +{ + Oid typoid; /* oid is only retrievable during runtime, so + * we have to init to 0 */ + const char *typname; + int family_prio; +} type_prio; + +#define TOTAL_TYPECODE_COUNT 16 +type_prio type_prios[TOTAL_TYPECODE_COUNT] = +{ + {SMALLDATETIMEOID, "smalldatetime", 1}, + {DATEOID, "date", 1}, + {TIMEOID, "time", 1}, + {FLOAT8OID, "float8", 2}, + {FLOAT4OID, "float4", 2}, + {NUMERICOID, "numeric", 3}, + {CASHOID, "money", 3}, + {INT8OID, "int8", 3}, + {INT4OID, "int4", 3}, + {INT2OID, "int2", 3}, + {INT1OID, "tinyint", 3}, + {BITOID, "bit", 3}, + {NVARCHAR2OID, "nvarchar", 4}, + {VARCHAROID, "varchar", 4}, + {BPCHAROID, "bpchar", 4}, + {TEXTOID, "text", 4}, +}; + +static int get_typeprio(Oid typoid, TYPCATEGORY tcategory) +{ + int result = 0; + for (int i = 0; i < TOTAL_TYPECODE_COUNT; i++) { + if (type_prios[i].typoid == typoid) { + return type_prios[i].family_prio; + } + } + + switch (tcategory) { + case ('D'): /*Datetime*/ + result = 1; + break; + case ('N'): /*Numeric*/ + result = 3; + break; + case ('S'): /*String*/ + result = 4; + break; + default: + result = 0; + break; + } + return result; +} + +extern "C" Datum sql_variantin(PG_FUNCTION_ARGS); +extern "C" Datum sql_variantout(PG_FUNCTION_ARGS); +extern "C" Datum sql_variantrecv(PG_FUNCTION_ARGS); +extern "C" Datum sql_variantsend(PG_FUNCTION_ARGS); +PG_FUNCTION_INFO_V1(sql_variantin); +PG_FUNCTION_INFO_V1(sql_variantout); +PG_FUNCTION_INFO_V1(sql_variantrecv); +PG_FUNCTION_INFO_V1(sql_variantsend); + + +static Datum from_sql_variant(bytea* valena, Oid* typeoid, int32* typmod) +{ + char* data = VARDATA_ANY(valena); + StringInfoData buf; + Oid typreceive, typioparam; + Datum result; + *typeoid = *(Oid*)data; + *typmod = *(int32*)(data + sizeof(Oid)); + bytea* basic_value_b = (bytea*) (data + sizeof(Oid) + VARHDRSZ); + initStringInfo(&buf); + pq_sendbytes(&buf, VARDATA_ANY(basic_value_b), VARSIZE_ANY_EXHDR(basic_value_b)); + getTypeBinaryInputInfo(*typeoid, &typreceive, &typioparam); + result = OidReceiveFunctionCall(typreceive, &buf, typioparam, *typmod); + pfree(buf.data); + PG_RETURN_DATUM(result); +} + +Datum to_sql_variant_internal(Datum value, Oid basic_type, int32 typmod) +{ + Oid typsend, typreceive, typioparam; + bool typisvarlena; + bytea *result, *val; + int32 len; + char* data; + errno_t ss_rc = 0; + + /* 只是检查类型是否有二进制输入函数 */ + getTypeBinaryInputInfo(basic_type, &typreceive, &typioparam); + getTypeBinaryOutputInfo(basic_type, &typsend, &typisvarlena); + + val = OidSendFunctionCall(typsend, value); + /* vastbase 可能发生原始类型值大小超过8000字节 */ + if (VARSIZE_ANY_EXHDR(val) > MaxBasicValueSize) { + ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("value of basic type must be a binary length <= 8000 byte"))); + } + + len = VARHDRSZ + sizeof(Oid) + VARHDRSZ + VARSIZE_ANY(val); + result = (bytea*)palloc0(len); + SET_VARSIZE(result, len); + data = VARDATA_ANY(result); + *(Oid*)data = basic_type; /* basictype, typmod, isnull and basictypevalue*/ + data += sizeof(Oid); + *(int32*)data = typmod; + data += VARHDRSZ; + ss_rc = memcpy_s(data, VARSIZE_ANY(val), val, VARSIZE_ANY(val)); + securec_check(ss_rc, "\0", "\0"); + + PG_RETURN_BYTEA_P(result); +} + +Datum sql_variantin(PG_FUNCTION_ARGS) +{ + char* inputText = PG_GETARG_CSTRING(0); + Datum result = DirectFunctionCall3(varcharin, CStringGetDatum(inputText), ObjectIdGetDatum(InvalidOid), Int32GetDatum(-1)); + return to_sql_variant_internal(result, VARCHAROID, -1); +} + +/* sql_variant将内部存储格式转换为字符串形式 */ +Datum sql_variantout(PG_FUNCTION_ARGS) +{ + bytea* vlena = PG_GETARG_BYTEA_PP(0); + bool typIsVarlena; + Oid typeoid, typOutput; + int32 typemod; + Datum basic_value; + + basic_value = from_sql_variant(vlena, &typeoid, &typemod); + getTypeOutputInfo(typeoid, &typOutput, &typIsVarlena); + PG_RETURN_CSTRING(OidOutputFunctionCall(typOutput, basic_value)); +} + +Datum sql_variantrecv(PG_FUNCTION_ARGS) +{ + StringInfo buf = (StringInfo)PG_GETARG_POINTER(0); + bytea* result = NULL; + int nbytes; + + nbytes = buf->len - buf->cursor; + + /* size of sql_variant is limit to 8016 */ + if (nbytes + VARHDRSZ > MaxSqlVariantSize) { + ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("size of sql_variant type must be <= 8016 byte"))); + } + result = (bytea*)palloc(nbytes + VARHDRSZ); + SET_VARSIZE(result, nbytes + VARHDRSZ); + pq_copymsgbytes(buf, VARDATA(result), nbytes); + PG_RETURN_BYTEA_P(result); +} + +Datum sql_variantsend(PG_FUNCTION_ARGS) +{ + bytea* vlena = PG_GETARG_BYTEA_P_COPY(0); + + PG_RETURN_BYTEA_P(vlena); +} + +extern "C" Datum sql_variantcmp(PG_FUNCTION_ARGS); +PG_FUNCTION_INFO_V1(sql_variantcmp); + +Datum sql_variantcmp(PG_FUNCTION_ARGS) +{ + bytea* vlena1 = PG_GETARG_BYTEA_PP(0); + bytea* vlena2 = PG_GETARG_BYTEA_PP(1); + + Oid typeoid1, typeoid2; + int32 typemod1, typemod2; + int typeprio1, typeprio2; + Datum basic_value1, basic_value2; + TYPCATEGORY tcategory1, tcategory2; + bool typispreferred1 = false; + bool typispreferred2 = false; + int result = 0; + + basic_value1 = from_sql_variant(vlena1, &typeoid1, &typemod1); + basic_value2 = from_sql_variant(vlena2, &typeoid2, &typemod2); + + /* 必须保证比较运算符的传递性 */ + get_type_category_preferred(typeoid1, &tcategory1, &typispreferred1); + get_type_category_preferred(typeoid2, &tcategory2, &typispreferred2); + + typeprio1 = get_typeprio(typeoid1, tcategory1); + typeprio2 = get_typeprio(typeoid2, tcategory2); + if (typeprio1 == typeprio2) { + char *opeq = "="; + char *oplt = "<"; + Datum is_eq; + Datum is_lt; + + is_lt = do_compare(oplt, basic_value1, basic_value2, typeoid1, typeoid2, typeprio1, typeprio2, PG_GET_COLLATION()); + if (DatumGetBool(is_lt)) { + result = Int32GetDatum(-1); + } else { + is_eq = do_compare(opeq, basic_value1, basic_value2, typeoid1, typeoid2, typeprio1, typeprio2, PG_GET_COLLATION()); + result = DatumGetBool(is_eq) ? Int32GetDatum(0) : Int32GetDatum(1); + } + } else { + result = (typeprio1 > typeprio2) ? Int32GetDatum(-1) : Int32GetDatum(1); + } + PG_RETURN_INT32(result); +} + +Datum +do_cast(Oid source_type, Oid target_type, Datum value, int32_t typmod, Oid coll, CoercionContext ccontext) +{ + Oid funcid; + CoercionPathType path; + Oid typioparam; + bool isVarlena; + int nargs; + + path = find_coercion_pathway(target_type, source_type, ccontext, &funcid); + + + switch (path) { + case COERCION_PATH_FUNC: + nargs = get_func_nargs(funcid); + switch (nargs) { + case 1: + return OidFunctionCall1Coll(funcid, coll, value); + case 2: + return OidFunctionCall2Coll(funcid, coll, value, (Datum) typmod); + case 3: + return OidFunctionCall3Coll(funcid, coll, value, (Datum) typmod, (Datum) (ccontext == COERCION_EXPLICIT)); + default: + elog(ERROR, "Unsupported number of arguments (%d) for function %u", nargs, funcid); + } + break; + case COERCION_PATH_COERCEVIAIO: + if (TypeCategory(source_type) == TYPCATEGORY_STRING) { + getTypeInputInfo(target_type, &funcid, &typioparam); + return OidInputFunctionCall(funcid, TextDatumGetCString(value), typioparam, typmod); + } else { + getTypeOutputInfo(source_type, &funcid, &isVarlena); + return CStringGetTextDatum(OidOutputFunctionCall(funcid, value)); + } + break; + case COERCION_PATH_RELABELTYPE: + return value; + break; + default: + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("unable to cast from internal type %s to %s", + format_type_be(source_type), format_type_be(target_type)))); + } + return value; +} + +Datum +comp_time(char *oprname, Oid t1, Oid t2) +{ + /* + * Notice: THIS IS NOT A GENERATL COMPARISON FUNCTION Assumption : 1 and + * ONLY 1 of t1,t2 is of TIME_T + */ + if (pg_strncasecmp(oprname, "<>", 2) == 0) { + PG_RETURN_BOOL(true); + } else if (pg_strncasecmp(oprname, ">", 1) == 0) { /* including >= */ + PG_RETURN_BOOL(t1 != TIMEOID && t2 == TIMEOID); + } else if (pg_strncasecmp(oprname, "<", 1) == 0) { /* including <= */ + PG_RETURN_BOOL(t1 == TIMEOID && t2 != TIMEOID); + } else { /* (pg_strncasecmp(oprname, "=", 2) == 0) */ + PG_RETURN_BOOL(false); + } + +} + +Datum +do_compare(char *oprname, Datum basic_value1, Datum basic_value2, Oid type_oid1, Oid type_oid2, int typeprio1, int typeprio2, Oid fncollation) +{ + Operator operator_cmp; + Form_pg_operator opform; + Oid oprcode; + + /* handle sql_variant specific cases */ + if (type_oid1 != type_oid2 && (type_oid1 == TIMEOID || type_oid2 == TIMEOID)) { + return comp_time(oprname, type_oid1, type_oid2); + } + + /* find direct comparisions without casting */ + operator_cmp = oper(NULL, list_make1(makeString(oprname)), + type_oid1, type_oid2, false, -1); + opform = (Form_pg_operator)GETSTRUCT(operator_cmp); + oprcode = opform->oprcode; + ReleaseSysCache(operator_cmp); + + if (targetissqlvariant(opform->oprleft) || targetissqlvariant(opform->oprright)) { + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_FUNCTION), + errmsg("operator does not exist: %s %s %s", format_type_be(type_oid1), oprname, format_type_be(type_oid2)), + errhint("No operator matches the given name and argument type(s). " + "You might need to add explicit type casts."), + parser_errposition(NULL, -1))); + } + + if (type_oid1 != opform->oprleft) { + basic_value1 = do_cast(type_oid1, opform->oprleft, basic_value1, -1, fncollation, COERCION_IMPLICIT); + } + + if (type_oid2 != opform->oprright) { + basic_value2 = do_cast(type_oid2, opform->oprright, basic_value2, -1, fncollation, COERCION_IMPLICIT); + } + return OidFunctionCall2Coll(oprcode, fncollation, basic_value1, basic_value2); +} +extern "C" Datum sql_varianteq(PG_FUNCTION_ARGS); +extern "C" Datum sql_variantne(PG_FUNCTION_ARGS); +extern "C" Datum sql_variantlt(PG_FUNCTION_ARGS); +extern "C" Datum sql_variantle(PG_FUNCTION_ARGS); +extern "C" Datum sql_variantgt(PG_FUNCTION_ARGS); +extern "C" Datum sql_variantge(PG_FUNCTION_ARGS); +PG_FUNCTION_INFO_V1(sql_varianteq); +PG_FUNCTION_INFO_V1(sql_variantne); +PG_FUNCTION_INFO_V1(sql_variantlt); +PG_FUNCTION_INFO_V1(sql_variantle); +PG_FUNCTION_INFO_V1(sql_variantgt); +PG_FUNCTION_INFO_V1(sql_variantge); + +Datum sql_varianteq(PG_FUNCTION_ARGS) +{ + int ret = DatumGetInt32(sql_variantcmp(fcinfo)); + PG_RETURN_BOOL(ret == 0); +} + +Datum sql_variantne(PG_FUNCTION_ARGS) +{ + int ret = DatumGetInt32(sql_variantcmp(fcinfo)); + PG_RETURN_BOOL(ret != 0); +} + +Datum sql_variantlt(PG_FUNCTION_ARGS) +{ + int ret = DatumGetInt32(sql_variantcmp(fcinfo)); + PG_RETURN_BOOL(ret < 0); +} + +Datum sql_variantle(PG_FUNCTION_ARGS) +{ + int ret = DatumGetInt32(sql_variantcmp(fcinfo)); + PG_RETURN_BOOL(ret <= 0 ); +} + +Datum sql_variantgt(PG_FUNCTION_ARGS) +{ + int ret = DatumGetInt32(sql_variantcmp(fcinfo)); + PG_RETURN_BOOL(ret > 0); +} + +Datum sql_variantge(PG_FUNCTION_ARGS) +{ + int ret = DatumGetInt32(sql_variantcmp(fcinfo)); + PG_RETURN_BOOL(ret >= 0); +} + +/* + * CAST functions to SQL_VARIANT + */ +extern "C" Datum smalldatetime2sqlvariant(PG_FUNCTION_ARGS); +extern "C" Datum date2sqlvariant(PG_FUNCTION_ARGS); +extern "C" Datum time2sqlvariant(PG_FUNCTION_ARGS); +extern "C" Datum float2sqlvariant(PG_FUNCTION_ARGS); +extern "C" Datum real2sqlvariant(PG_FUNCTION_ARGS); +extern "C" Datum numeric2sqlvariant(PG_FUNCTION_ARGS); +extern "C" Datum money2sqlvariant(PG_FUNCTION_ARGS); +extern "C" Datum bigint2sqlvariant(PG_FUNCTION_ARGS); +extern "C" Datum int2sqlvariant(PG_FUNCTION_ARGS); +extern "C" Datum smallint2sqlvariant(PG_FUNCTION_ARGS); +extern "C" Datum tinyint2sqlvariant(PG_FUNCTION_ARGS); +extern "C" Datum bit2sqlvariant(PG_FUNCTION_ARGS); +extern "C" Datum varchar2sqlvariant(PG_FUNCTION_ARGS); +extern "C" Datum nvarchar2sqlvariant(PG_FUNCTION_ARGS); +extern "C" Datum char2sqlvariant(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(smalldatetime2sqlvariant); +PG_FUNCTION_INFO_V1(date2sqlvariant); +PG_FUNCTION_INFO_V1(time2sqlvariant); +PG_FUNCTION_INFO_V1(float2sqlvariant); +PG_FUNCTION_INFO_V1(real2sqlvariant); +PG_FUNCTION_INFO_V1(numeric2sqlvariant); +PG_FUNCTION_INFO_V1(money2sqlvariant); +PG_FUNCTION_INFO_V1(bigint2sqlvariant); +PG_FUNCTION_INFO_V1(int2sqlvariant); +PG_FUNCTION_INFO_V1(smallint2sqlvariant); +PG_FUNCTION_INFO_V1(tinyint2sqlvariant); +PG_FUNCTION_INFO_V1(bit2sqlvariant); +PG_FUNCTION_INFO_V1(varchar2sqlvariant); +PG_FUNCTION_INFO_V1(nvarchar2sqlvariant); +PG_FUNCTION_INFO_V1(char2sqlvariant); + +Datum +smalldatetime2sqlvariant(PG_FUNCTION_ARGS) +{ + return to_sql_variant_internal(PG_GETARG_DATUM(0), SMALLDATETIMEOID, PG_GETARG_INT32(1)); +} + +Datum +date2sqlvariant(PG_FUNCTION_ARGS) +{ + return to_sql_variant_internal(PG_GETARG_DATUM(0), DATEOID, PG_GETARG_INT32(1)); +} + +Datum +time2sqlvariant(PG_FUNCTION_ARGS) +{ + return to_sql_variant_internal(PG_GETARG_DATUM(0), TIMEOID, PG_GETARG_INT32(1)); +} + +/* Approximate numerics */ +Datum +float2sqlvariant(PG_FUNCTION_ARGS) +{ + return to_sql_variant_internal(PG_GETARG_DATUM(0), FLOAT8OID, PG_GETARG_INT32(1)); +} + +Datum +real2sqlvariant(PG_FUNCTION_ARGS) +{ + return to_sql_variant_internal(PG_GETARG_DATUM(0), FLOAT4OID, PG_GETARG_INT32(1)); +} + +Datum +numeric2sqlvariant(PG_FUNCTION_ARGS) +{ + return to_sql_variant_internal(PG_GETARG_DATUM(0), NUMERICOID, PG_GETARG_INT32(1)); +} + +Datum +money2sqlvariant(PG_FUNCTION_ARGS) +{ + return to_sql_variant_internal(PG_GETARG_DATUM(0), CASHOID, PG_GETARG_INT32(1)); +} + +Datum +bigint2sqlvariant(PG_FUNCTION_ARGS) +{ + return to_sql_variant_internal(PG_GETARG_DATUM(0), INT8OID, PG_GETARG_INT32(1)); +} + +Datum +int2sqlvariant(PG_FUNCTION_ARGS) +{ + return to_sql_variant_internal(PG_GETARG_DATUM(0), INT4OID, PG_GETARG_INT32(1)); +} + +Datum +smallint2sqlvariant(PG_FUNCTION_ARGS) +{ + return to_sql_variant_internal(PG_GETARG_DATUM(0), INT2OID, PG_GETARG_INT32(1)); +} + +Datum +tinyint2sqlvariant(PG_FUNCTION_ARGS) +{ + return to_sql_variant_internal(PG_GETARG_DATUM(0), INT1OID, PG_GETARG_INT32(1)); +} + +Datum +bit2sqlvariant(PG_FUNCTION_ARGS) +{ + return to_sql_variant_internal(PG_GETARG_DATUM(0), BITOID, PG_GETARG_INT32(1)); +} + +/* Character strings */ +Datum +varchar2sqlvariant(PG_FUNCTION_ARGS) +{ + return to_sql_variant_internal(PG_GETARG_DATUM(0), VARCHAROID, PG_GETARG_INT32(1)); +} + +Datum +nvarchar2sqlvariant(PG_FUNCTION_ARGS) +{ + return to_sql_variant_internal(PG_GETARG_DATUM(0), NVARCHAR2OID, PG_GETARG_INT32(1)); +} + +Datum +char2sqlvariant(PG_FUNCTION_ARGS) +{ + return to_sql_variant_internal(PG_GETARG_DATUM(0), BPCHAROID, PG_GETARG_INT32(1)); +} + +/* copy from pl_exec.cpp:exec_simple_cast_datum but change a lot */ +static Datum cast_value(Datum value, Oid valtype, Oid reqtype, CoercionContext context) +{ + Oid funcid = InvalidOid; + CoercionPathType result = COERCION_PATH_NONE; + + if (valtype == reqtype) { + return value; + } + if (valtype == UNKNOWNOID) { + valtype = TEXTOID; + value = DirectFunctionCall1(textin, value); + } + + result = find_coercion_pathway(reqtype, valtype, context, &funcid); + if (result == COERCION_PATH_NONE || result == COERCION_PATH_ARRAYCOERCE) { + ereport(ERROR, + (errcode(ERRCODE_CANNOT_COERCE), + errmsg("cannot cast type %s to %s", format_type_be(valtype), format_type_be(reqtype)))); + } + if (result == COERCION_PATH_FUNC) { + value = OidFunctionCall1(funcid, value); + } else if (result == COERCION_PATH_COERCEVIAIO) { + Oid typoutput, typinput, typioparam; + char* extval = NULL; + bool typIsVarlena = false; + getTypeInputInfo(reqtype, &typinput, &typioparam); + getTypeOutputInfo(valtype, &typoutput, &typIsVarlena); + extval = OidOutputFunctionCall(typoutput, value); + value = OidInputFunctionCall(typinput, extval, typioparam, -1); + } + return value; +} + +Datum cast_from_sql_variant(bytea* valena, Oid targettype) +{ + Oid srctype; + int32 srctypemod; + Datum basic_value = from_sql_variant(valena, &srctype, &srctypemod); + + return cast_value(basic_value, srctype, targettype, COERCION_EXPLICIT); +} + +extern "C" Datum sqlvariant2smalldatetime(PG_FUNCTION_ARGS); +extern "C" Datum sqlvariant2date(PG_FUNCTION_ARGS); +extern "C" Datum sqlvariant2time(PG_FUNCTION_ARGS); +extern "C" Datum sqlvariant2float(PG_FUNCTION_ARGS); +extern "C" Datum sqlvariant2real(PG_FUNCTION_ARGS); +extern "C" Datum sqlvariant2numeric(PG_FUNCTION_ARGS); +extern "C" Datum sqlvariant2money(PG_FUNCTION_ARGS); +extern "C" Datum sqlvariant2bigint(PG_FUNCTION_ARGS); +extern "C" Datum sqlvariant2int(PG_FUNCTION_ARGS); +extern "C" Datum sqlvariant2smallint(PG_FUNCTION_ARGS); +extern "C" Datum sqlvariant2bit(PG_FUNCTION_ARGS); +extern "C" Datum sqlvariant2varchar(PG_FUNCTION_ARGS); +extern "C" Datum sqlvariant2char(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(sqlvariant2smalldatetime); +PG_FUNCTION_INFO_V1(sqlvariant2date); +PG_FUNCTION_INFO_V1(sqlvariant2time); +PG_FUNCTION_INFO_V1(sqlvariant2float); +PG_FUNCTION_INFO_V1(sqlvariant2real); +PG_FUNCTION_INFO_V1(sqlvariant2numeric); +PG_FUNCTION_INFO_V1(sqlvariant2money); +PG_FUNCTION_INFO_V1(sqlvariant2bigint); +PG_FUNCTION_INFO_V1(sqlvariant2int); +PG_FUNCTION_INFO_V1(sqlvariant2smallint); +PG_FUNCTION_INFO_V1(sqlvariant2bit); +PG_FUNCTION_INFO_V1(sqlvariant2varchar); +PG_FUNCTION_INFO_V1(sqlvariant2char); + +Datum +sqlvariant2smalldatetime(PG_FUNCTION_ARGS) +{ + bytea *sv = PG_GETARG_BYTEA_PP(0); + Datum result = cast_from_sql_variant(sv, SMALLDATETIMEOID); + PG_RETURN_TIMESTAMP(DatumGetTimestamp(result)); +} + +Datum +sqlvariant2date(PG_FUNCTION_ARGS) +{ + bytea *sv = PG_GETARG_BYTEA_PP(0); + Datum result = cast_from_sql_variant(sv, DATEOID); + PG_RETURN_DATEADT(DatumGetDateADT(result)); +} + +Datum +sqlvariant2time(PG_FUNCTION_ARGS) +{ + bytea *sv = PG_GETARG_BYTEA_PP(0); + Datum result = cast_from_sql_variant(sv, TIMEOID); + PG_RETURN_TIMEADT(DatumGetTimeADT(result)); +} + +Datum +sqlvariant2float(PG_FUNCTION_ARGS) +{ + bytea *sv = PG_GETARG_BYTEA_PP(0); + Datum result = cast_from_sql_variant(sv, FLOAT8OID); + PG_RETURN_FLOAT8(DatumGetFloat8(result)); +} + +Datum +sqlvariant2real(PG_FUNCTION_ARGS) +{ + bytea *sv = PG_GETARG_BYTEA_PP(0); + Datum result = cast_from_sql_variant(sv, FLOAT4OID); + PG_RETURN_FLOAT4(DatumGetFloat4(result)); +} + +Datum +sqlvariant2numeric(PG_FUNCTION_ARGS) +{ + bytea *sv = PG_GETARG_BYTEA_PP(0); + Datum result = cast_from_sql_variant(sv, NUMERICOID); + PG_RETURN_NUMERIC(DatumGetNumeric(result)); +} + +Datum +sqlvariant2money(PG_FUNCTION_ARGS) +{ + bytea *sv = PG_GETARG_BYTEA_PP(0); + Datum result = cast_from_sql_variant(sv, CASHOID); + PG_RETURN_CASH(DatumGetInt64(result)); +} + +Datum +sqlvariant2bigint(PG_FUNCTION_ARGS) +{ + bytea *sv = PG_GETARG_BYTEA_PP(0); + Datum result = cast_from_sql_variant(sv, INT8OID); + PG_RETURN_INT64(DatumGetInt64(result)); +} + +Datum +sqlvariant2int(PG_FUNCTION_ARGS) +{ + bytea *sv = PG_GETARG_BYTEA_PP(0); + Datum result = cast_from_sql_variant(sv, INT4OID); + PG_RETURN_INT32(DatumGetInt32(result)); +} + +Datum +sqlvariant2smallint(PG_FUNCTION_ARGS) +{ + bytea *sv = PG_GETARG_BYTEA_PP(0); + Datum result = cast_from_sql_variant(sv, INT2OID); + PG_RETURN_INT16(DatumGetInt16(result)); +} + +Datum +sqlvariant2bit(PG_FUNCTION_ARGS) +{ + bytea *sv = PG_GETARG_BYTEA_PP(0); + Datum result = cast_from_sql_variant(sv, BITOID); + PG_RETURN_VARBIT_P(result); +} + +Datum +sqlvariant2varchar(PG_FUNCTION_ARGS) +{ + bytea *sv = PG_GETARG_BYTEA_PP(0); + Datum result = cast_from_sql_variant(sv, VARCHAROID); + PG_RETURN_VARCHAR_P(DatumGetVarCharP(result)); +} + +Datum +sqlvariant2char(PG_FUNCTION_ARGS) +{ + bytea *sv = PG_GETARG_BYTEA_PP(0); + Datum result = cast_from_sql_variant(sv, BPCHAROID); + PG_RETURN_BPCHAR_P(DatumGetBpCharP(result)); +} + diff --git a/src/common/backend/parser/parse_coerce.cpp b/src/common/backend/parser/parse_coerce.cpp index 67607a67dd..ce2563c69b 100644 --- a/src/common/backend/parser/parse_coerce.cpp +++ b/src/common/backend/parser/parse_coerce.cpp @@ -398,6 +398,17 @@ static Datum stringTypeDatum_with_collation(Type tp, char* string, char*fmtstr, return result; } +bool targetissqlvariant(Oid targetOid) +{ + if (!DB_IS_CMPT(D_FORMAT)) { + return false; + } + + Oid SvOid = get_typeoid(get_namespace_oid(SYS_NAMESPACE_NAME, true), "sql_variant"); + + return OidIsValid(SvOid) && targetOid == SvOid; +} + /* * coerce_type() * Convert an expression to a different type. @@ -1224,23 +1235,29 @@ static Node* build_coercion_expression(Node* node, CoercionPathType pathtype, Oi args = list_make1(node); - if (nargs >= 2) { - if (type_is_set(targetTypeId)) { - /* Pass actual set id as Oid type */ - cons = makeConst(OIDOID, -1, InvalidOid, sizeof(Oid), ObjectIdGetDatum(targetTypeId), false, true); - } else { - /* Pass target typmod as an int4 constant */ - cons = makeConst(INT4OID, -1, InvalidOid, sizeof(int32), Int32GetDatum(targetTypMod), false, true); - } - + if (DB_IS_CMPT(D_FORMAT) && (targetissqlvariant(targetTypeId))) { + /* convert to sql_variant */ + cons = makeConst(INT4OID, -1, InvalidOid, sizeof(int32), Int32GetDatum(exprTypmod(node)), false, true); args = lappend(args, cons); - } + } else { + if (nargs >= 2) { + if (type_is_set(targetTypeId)) { + /* Pass actual set id as Oid type */ + cons = makeConst(OIDOID, -1, InvalidOid, sizeof(Oid), ObjectIdGetDatum(targetTypeId), false, true); + } else { + /* Pass target typmod as an int4 constant */ + cons = makeConst(INT4OID, -1, InvalidOid, sizeof(int32), Int32GetDatum(targetTypMod), false, true); + } - if (nargs == 3) { - /* Pass it a boolean isExplicit parameter, too */ - cons = makeConst(BOOLOID, -1, InvalidOid, sizeof(bool), BoolGetDatum(isExplicit), false, true); + args = lappend(args, cons); + } - args = lappend(args, cons); + if (nargs == 3) { + /* Pass it a boolean isExplicit parameter, too */ + cons = makeConst(BOOLOID, -1, InvalidOid, sizeof(bool), BoolGetDatum(isExplicit), false, true); + + args = lappend(args, cons); + } } fexpr = makeFuncExpr(funcId, targetTypeId, args, InvalidOid, InvalidOid, cformat); diff --git a/src/include/parser/parse_coerce.h b/src/include/parser/parse_coerce.h index 8e5204bbce..6f588f77f2 100644 --- a/src/include/parser/parse_coerce.h +++ b/src/include/parser/parse_coerce.h @@ -84,6 +84,7 @@ extern Node* coerce_to_target_charset(Node* expr, int target_charset, Oid target extern Node *transferConstToAconst(Node *node); extern Const* setValueToConstExpr(SetVariableExpr* set); +extern bool targetissqlvariant(Oid targetOid); #ifdef USE_SPQ extern bool get_cast_func(Oid oidSrc, Oid oidDest, bool *is_binary_coercible, Oid *oidCastFunc, CoercionPathType *pathtype); #endif -- Gitee