KingbaseES避免表的重写与数据类型二进制兼容

发布时间 2023-04-17 10:05:17作者: nwwhile

KingbaseES避免表的重写与数据类型二进制兼容

一、关于KingbaseES变更表结构表的重写:

1.修改表结构可能会导致表进行重写(表OID发生变化)。

2.修改表结构带有索引或者字段类型长度或者精度操作时,会触发索引重建。

3.不修改列内容且旧类型与新类型二进制兼容(binary coercible),不需要重写表。

4.数据表字段类型长度或者精度由小变大的操作,不需要rewrite重写表。

5.数字类型int4到int8这种更改,需要重写数据表,主要是由于底层存储不一样。

详细实践过程参考:KingbaseES变更表结构表重写问题

二、避免表重写修改字段类型方法:

2.1 通过修改系统表避免表发生重写:

2.1.1 准备环境:

test=# create table t01(id numeric(6));
CREATE TABLE
test=# select sys_relation_filenode('t01');
 SYS_RELATION_FILENODE 
-----------------------
                206188
(1 row)

test=# alter table t01 alter COLUMN id type numeric(9,3);
ALTER TABLE
test=# select sys_relation_filenode('t01');              
 SYS_RELATION_FILENODE 
-----------------------
                206191
(1 row)

2.1.2 由于numeric的类型在sys_attribute里面没有具体精度:

计算numeric类型精度:

test=# \d sys_attribute 
              View "sys_catalog.sys_attribute"
    Column     |   Type    | Collation | Nullable | Default 
---------------+-----------+-----------+----------+---------
 attrelid      | oid       |           |          | 
 attname       | name      |           |          | 
 atttypid      | oid       |           |          | 
 attstattarget | integer   |           |          | 
 attlen        | smallint  |           |          | 
 attnum        | smallint  |           |          | 
 attndims      | integer   |           |          | 
 attcacheoff   | integer   |           |          | 
 atttypmod     | integer   |           |          | 
 attbyval      | boolean   |           |          | 
 attstorage    | "char"    |           |          | 
 attalign      | "char"    |           |          | 
 attnotnull    | boolean   |           |          | 
 atthasdef     | boolean   |           |          | 
 atthasmissing | boolean   |           |          | 
 attidentity   | "char"    |           |          | 
 attgenerated  | "char"    |           |          | 
 attisdropped  | boolean   |           |          | 
 attislocal    | boolean   |           |          | 
 attinhcount   | integer   |           |          | 
 attcollation  | oid       |           |          | 
 attacl        | aclitem[] |           |          | 
 attoptions    | text[]    | c         |          | 
 attfdwoptions | text[]    | c         |          | 
 attmissingval | anyarray  |           |          | 

test=# select attname,atttypmod from sys_attribute where attrelid='t01'::regclass and attname='id';
 ATTNAME | ATTTYPMOD 
---------+-----------
 id      |    589831
(1 row)

# 使用以下SQL查看numeric类型的精度:
SELECT
  CASE atttypid
         WHEN 21 /*int2*/ THEN 16
         WHEN 23 /*int4*/ THEN 32
         WHEN 20 /*int8*/ THEN 64
         WHEN 1700 /*numeric*/ THEN
              CASE WHEN atttypmod = -1
                   THEN null
                   ELSE ((atttypmod - 4) >> 16) & 65535     -- 计算精度
                   END
         WHEN 700 /*float4*/ THEN 24 /*FLT_MANT_DIG*/
         WHEN 701 /*float8*/ THEN 53 /*DBL_MANT_DIG*/
         ELSE null
  END   AS numeric_precision,
  CASE 
    WHEN atttypid IN (21, 23, 20) THEN 0
    WHEN atttypid IN (1700) THEN            
        CASE 
            WHEN atttypmod = -1 THEN null       
            ELSE (atttypmod - 4) & 65535            -- 计算标度  
        END
       ELSE null
  END AS numeric_scale
FROM sys_attribute
 where attrelid = 't01'::regclass and attname = 'id';
 
test=#  where attrelid = 't01'::regclass and attname = 'id';
 NUMERIC_PRECISION | NUMERIC_SCALE 
-------------------+---------------
                 9 |             3 

attname:列名

atttypmod:记录了在表创建时提供的类型相关数据(例如一 个 varchar列的最大长度)。它会被传递给类型相关的输入函数和长度强制函数。对于那些不需要 atttypmod的类型,这个值通常总是为-1。

2.1.3 通过修改系统表数据实现字段类型的修改:

在kingbase.cong添加allow_system_table_dml=on参数,重启数据库

test=# select attname,atttypmod from sys_attribute where attrelid='t01'::regclass;
 ATTNAME  | ATTTYPMOD 
----------+-----------
 tableoid |        -1
 cmax     |        -1
 xmax     |        -1
 cmin     |        -1
 xmin     |        -1
 ctid     |        -1
 id       |    589831
(7 rows)

test=# select attname,atttypmod from sys_attribute where attrelid='t01'::regclass and attname='id';
 ATTNAME | ATTTYPMOD 
---------+-----------
 id      |    589831
(1 row)

# 计算字段ID的atttypmod值
589831 = 9*65,536+3+4

atttypmod值计算公式:atttypmod = precision * 65,536 + scale + 4

如果要修改为numeric(10,3),计算一下:atttypmod = precision * 65,536 + scale + 4 = 655360 + 3 + 4 = 655367

2.1.3.1 无数据场景的修改:
# 修改t01表id字段数据类型为numeric(10,3)
test=# \d t01
                   Table "public.t01"
 Column |     Type     | Collation | Nullable | Default 
--------+--------------+-----------+----------+---------
 id     | numeric(9,3) |           |          | 

test=# UPDATE sys_attribute SET atttypmod = 655367 WHERE attrelid = 't01'::regclass AND attname = 'id';
UPDATE 1
test=# \d t01
                   Table "public.t01"
 Column |     Type      | Collation | Nullable | Default 
--------+---------------+-----------+----------+---------
 id     | numeric(10,3) |           |          | 
 
test=# select sys_relation_filenode('t01');   
 SYS_RELATION_FILENODE 
-----------------------
                206191
(1 row)
# 修改t01表id字段数据类型为numeric(6,5)

test=# \d t01                                                                                          
                   Table "public.t01"
 Column |     Type      | Collation | Nullable | Default 
--------+---------------+-----------+----------+---------
 id     | numeric(10,3) |           |          | 
 
test=# UPDATE sys_attribute SET atttypmod = 393225 WHERE attrelid = 't01'::regclass AND attname = 'id';
UPDATE 1
test=# \d t01                                                                                          
                   Table "public.t01"
 Column |     Type     | Collation | Nullable | Default 
--------+--------------+-----------+----------+---------
 id     | numeric(6,5) |           |          | 
 
test=# select sys_relation_filenode('t01');   
 SYS_RELATION_FILENODE 
-----------------------
                206191
(1 row)

通过测试可以发现,修改系统表更改数据类型,表oid不会发生改变,也就是表不会发生重写。

2.1.3.2 表有数据场景的修改:
test=# \d t01                                                                                          
                   Table "public.t01"
 Column |     Type     | Collation | Nullable | Default 
--------+--------------+-----------+----------+---------
 id     | numeric(6,5) |           |          | 

test=# insert into t01 select generate_series(1,5) from dual;
INSERT 0 5
test=# select * from t01;
   ID    
---------
 1.00000
 2.00000
 3.00000
 4.00000
 5.00000
(5 rows)

# 修改t01表id字段数据类型为numeric(8,3)
test=# UPDATE sys_attribute SET atttypmod = 524295 WHERE attrelid = 't01'::regclass AND attname = 'id';
UPDATE 1
test=# \d t01
                   Table "public.t01"
 Column |     Type     | Collation | Nullable | Default 
--------+--------------+-----------+----------+---------
 id     | numeric(8,3) |           |          | 

test=# select * from t01;                                                                              
   ID    
---------
 1.00000
 2.00000
 3.00000
 4.00000
 5.00000
(5 rows)

test=# insert into t01 values(6);
INSERT 0 1
test=# select * from t01;        
   ID    
---------
 1.00000
 2.00000
 3.00000
 4.00000
 5.00000
   6.000
(6 rows)

test=# select sys_relation_filenode('t01');   
 SYS_RELATION_FILENODE 
-----------------------
                206191
(1 row)

通过测试可以发现,修改系统表更改数据类型,表oid不会发生改变并且已存在的数据数据类型不会发生变化,只有新插入的数据才可以使用修改后的数据类型。

注意:

不推荐在生产系统使用这种方式进行表结构的修改,本文只做研究学习使用。

三、数据类型的二进制兼容:

二进制可兼容表示该转换可以被“免费”执行而不用调用任何函数。相应的数据类型值使用同样的内部表示。

KingbaseES内置转换函数,Function列有binary coercible信息说明是二进制兼容的:

test=# \dC varchar
                                 List of casts
 Source type |         Target type         |      Function      |   Implicit?   
-------------+-----------------------------+--------------------+---------------
 boolean     | varchar                     | text               | in assignment
 bpchar      | varchar                     | text               | yes
 bpcharbyte  | varchar                     | (binary coercible) | yes
 "char"      | varchar                     | text               | in assignment
 cidr        | varchar                     | text               | in assignment
 dsinterval  | varchar                     | dsinterval_text    | in assignment
 inet        | varchar                     | text               | in assignment
 name        | varchar                     | varchar            | in assignment
 text        | varchar                     | (binary coercible) | yes
 tinyint     | varchar                     | text               | in assignment
 varchar     | bigint                      | int8               | yes
 varchar     | bpchar                      | (binary coercible) | in assignment
 varchar     | bpcharbyte                  | (binary coercible) | in assignment
 varchar     | bytea                       | (with inout)       | yes
 varchar     | "char"                      | char               | in assignment
 varchar     | date                        | text_date          | yes
 varchar     | double precision            | float8             | yes
 varchar     | dsinterval                  | to_dsinterval      | in assignment
 varchar     | integer                     | int4               | yes
 varchar     | name                        | name               | yes
 varchar     | numeric                     | text_numeric       | yes
 varchar     | real                        | float4             | yes
 varchar     | regclass                    | regclass           | yes
 varchar     | smallint                    | int2               | yes
 varchar     | text                        | (binary coercible) | yes
 varchar     | timestamp without time zone | text_timestamp     | yes
 varchar     | timestamp with time zone    | timestamptz        | yes
 varchar     | time without time zone      | text_time          | yes
 varchar     | time with time zone         | text_timetz        | yes
 varchar     | tinyint                     | tinyint            | yes
 varchar     | varchar                     | varchar            | yes
 varchar     | varcharbyte                 | (binary coercible) | yes
 varchar     | xml                         | xml                | in assignment
 varchar     | yminterval                  | to_yminterval      | in assignment
 varcharbyte | varchar                     | (binary coercible) | in assignment
 xml         | varchar                     | (binary coercible) | in assignment
 yminterval  | varchar                     | yminterval_text    | in assignment
(37 rows)

# 也可以使用以下语句查询
SELECT format_type(castsource, NULL) AS "Source type",
       format_type(casttarget, NULL) AS "Target type",
       CASE WHEN c.castmethod = 'b' THEN '(binary coercible)'
            WHEN c.castmethod = 'i' THEN '(with inout)'
            ELSE p.proname
       END AS "Function",
       CASE WHEN c.castcontext = 'e' THEN 'no'
            WHEN c.castcontext = 'a' THEN 'in assignment'
            ELSE 'yes'
       END AS "Implicit?",
       d.description AS "Description"
FROM sys_cast c LEFT JOIN sys_proc p
     ON c.castfunc = p.oid
     LEFT JOIN sys_type ts
     ON c.castsource = ts.oid
     LEFT JOIN sys_namespace ns
     ON ns.oid = ts.typnamespace
     LEFT JOIN sys_type tt
     ON c.casttarget = tt.oid
     LEFT JOIN sys_namespace nt
     ON nt.oid = tt.typnamespace
     LEFT JOIN sys_description d
     ON d.classoid = c.oid AND d.objoid = c.oid AND d.objsubid = 0
WHERE ( (true  AND sys_type_is_visible(ts.oid)
) OR (true  AND sys_type_is_visible(tt.oid)
) ) ORDER BY 1, 2;

列Source type:表示源数据类型。

列Target type:表示目标数据类型。

列Function(根据 sys_cast表castmethod字段得到):表示如何进行类型转换。

sys_cast.castmethod字段说明:

说明
f 表明使用castfunc中指定的函数
i 表明使用输入/输出函数
b 表明该类型是二进制兼容的,因此不需要转换

列Implicit(根据sys_cast表castcontext字段得到):有以下三种情况

sys_cast.castcontext 字段说明:

说明
assignment castcontext = a,表示在赋值给目标列时隐式调用, 和显式调用一样。也就是说在赋值时自动对类型进行转换
no pg_cast.castcontext = e,表示仅能作为一个显式转换(使用CAST或::语法)
yes pg_cast.castcontext = i,表示在表达式中隐式调用,和其他转换一样

2.1 测试过程:

2.1.1 使用cast强制转换数据类型:

"char"转化为integer,castcontext为e,表示不会隐式调用,不能对类型进行自动转换。

test=# select castsource::regtype,casttarget::regtype,castfunc::regproc,castcontext,castmethod from sys_cast where  castsource= '"char"'::regtype and casttarget = 'integer'::regtype;
 CASTSOURCE | CASTTARGET |    CASTFUNC     | CASTCONTEXT | CASTMETHOD 
------------+------------+-----------------+-------------+------------
 "char"     | integer    | pg_catalog.int4 | e           | f
(1 row)

test=# 
test=#  select castsource::regtype,casttarget::regtype,castfunc::regproc,castcontext,castmethod from sys_cast where CASTCONTEXT='e';
     CASTSOURCE      |    CASTTARGET    |       CASTFUNC       | CASTCONTEXT | CASTMETHOD 
---------------------+------------------+----------------------+-------------+------------
 "char"              | integer          | pg_catalog.int4      | e           | f
 integer             | "char"           | pg_catalog."char"    | e           | f
 lseg                | point            | pg_catalog.point     | e           | f
 path                | point            | pg_catalog.point     | e           | f
 box                 | point            | pg_catalog.point     | e           | f
 box                 | lseg             | pg_catalog.lseg      | e           | f
 box                 | circle           | pg_catalog.circle    | e           | f
 polygon             | point            | pg_catalog.point     | e           | f
 polygon             | box              | pg_catalog.box       | e           | f
 polygon             | circle           | pg_catalog.circle    | e           | f
 circle              | point            | pg_catalog.point     | e           | f
 circle              | box              | pg_catalog.box       | e           | f
 circle              | polygon          | pg_catalog.polygon   | e           | f
 bigint              | bit              | pg_catalog."bit"     | e           | f
 integer             | bit              | pg_catalog."bit"     | e           | f
 bit                 | bigint           | pg_catalog.int8      | e           | f
 bit                 | integer          | pg_catalog.int4      | e           | f
 jsonb               | boolean          | pg_catalog.bool      | e           | f
 jsonb               | numeric          | pg_catalog."numeric" | e           | f
 jsonb               | smallint         | pg_catalog.int2      | e           | f
 jsonb               | integer          | pg_catalog.int4      | e           | f
 jsonb               | bigint           | pg_catalog.int8      | e           | f
 jsonb               | real             | pg_catalog.float4    | e           | f
 jsonb               | double precision | pg_catalog.float8    | e           | f
 pg_catalog.interval | dsinterval       | interval_dsinterval  | e           | f
(25 rows)

# 创建测试表并插入数据
test=# create table t01(id "char",i_id integer );
CREATE TABLE
test=# insert into t01 values('1',"char" '1');
ERROR:  column "i_id" is of type integer but expression is of type "char"
LINE 1: insert into t01 values('1',"char" '1');
                                          ^
HINT:  You will need to rewrite or cast the expression.

# 使用cast强制转换
test=# insert into t01 values('1',cast(("char" '1') as integer));
INSERT 0 1

2.1.2 修改系统表自动转换数据类型:

"char"转换为integer,修改castcontext为a,表示在赋值给目标列时隐式调用,自动对类型进行转换。

test=# begin;
BEGIN
test=# update sys_cast set castcontext = 'a' where castsource= '"char"'::regtype and casttarget = 'integer'::regtype;
UPDATE 1
test=# insert into t01 values('1',"char" '1');
INSERT 0 1
test=# rollback;
ROLLBACK
test=# insert into t01 values('1',"char" '1');
ERROR:  column "i_id" is of type integer but expression is of type "char"
LINE 1: insert into t01 values('1',"char" '1');
                                          ^
HINT:  You will need to rewrite or cast the expression.
test=# 

修改系统表之后,就可以正常插入数据不报错。

2.1.3 不在系统表显示的内置转换:

需要注意的是,sys_cast并不表示系统知道如何执行的所有类型转换,它只包括哪些不能从某些普通规则推导出的转换。

例如,一个域及其基类型之间的转换并未显式地在pg_cast中展示。

另一个重要的例外是"自动 I/O转换造型",它们通过数据类型自己的I/O函数来转换成(或者转换自)text或其他字符串类型,这些转换也没有显式地在sys_cast中表示。

例如:date、timestamp转换为varchar

test=# \dC date
                                List of casts
         Source type         | Target type |      Function       | Implicit? 
-----------------------------+-------------+---------------------+-----------
 bpchar                      | date        | text_date           | yes
 text                        | date        | text_date           | yes
 timestamp without time zone | date        | timestamp_to_date   | yes
 timestamp with time zone    | date        | timestamptz_to_date | yes
 varchar                     | date        | text_date           | yes
(5 rows)

test=# \dC timestamp
                                           List of casts
         Source type         |         Target type         |       Function        |   Implicit?   
-----------------------------+-----------------------------+-----------------------+---------------
 bpchar                      | timestamp without time zone | text_timestamp        | yes
 bpcharbyte                  | timestamp without time zone | text_timestamp        | yes
 integer                     | timestamp without time zone | cast_int_to_timestamp | in assignment
 pg_catalog.date             | timestamp without time zone | timestamp             | yes
 text                        | timestamp without time zone | text_timestamp        | yes
 timestamp without time zone | date                        | timestamp_to_date     | yes
 timestamp without time zone | pg_catalog.date             | date                  | in assignment
 timestamp without time zone | text                        | text                  | yes
 timestamp without time zone | timestamp without time zone | timestamp             | yes
 timestamp without time zone | timestamp with time zone    | timestamptz           | yes
 timestamp without time zone | time without time zone      | time                  | in assignment
 timestamp with time zone    | timestamp without time zone | timestamp             | in assignment
 varchar                     | timestamp without time zone | text_timestamp        | yes
 varcharbyte                 | timestamp without time zone | text_timestamp        | yes
(14 rows)

test=# select castsource::regtype,casttarget::regtype,castfunc::regproc,castcontext,castmethod from sys_cast where castsource= 'date'::regtype and casttarget ='varchar'::regtype;
 CASTSOURCE | CASTTARGET | CASTFUNC | CASTCONTEXT | CASTMETHOD 
------------+------------+----------+-------------+------------
(0 rows)

test=# select castsource::regtype,casttarget::regtype,castfunc::regproc,castcontext,castmethod from sys_cast where castsource= 'timestamp(0)'::regtype and casttarget ='varchar'::regtype;
 CASTSOURCE | CASTTARGET | CASTFUNC | CASTCONTEXT | CASTMETHOD 
------------+------------+----------+-------------+------------
(0 rows)

test=# select castsource::regtype,casttarget::regtype,castfunc::regproc,castcontext,castmethod from sys_cast where castsource= 'timestamp'::regtype and casttarget ='varchar'::regtype;   
 CASTSOURCE | CASTTARGET | CASTFUNC | CASTCONTEXT | CASTMETHOD 
------------+------------+----------+-------------+------------
(0 rows)

test=# create table t01(dat varchar(20));                                                                                                                                         
CREATE TABLE
test=# insert into t01 values(date '2023-04-11');                                                                                                                                 
INSERT 0 1
test=# insert into t01 values(timestamp(0) '2023-04-11');
INSERT 0 1
test=# insert into t01 values(timestamp '2023-04-11');   
INSERT 0 1

虽然date、timestamp转换为varchar在sys_cast系统表查询不到,但是测试过程种并不需要使用cast进行数据类型的强制转换。数据类型通过自己的I/O函数来进行转换。

2.1.4 使用内置的IO函数自定义数据类型转换:

语法:

test=# \h create cast
Command:     CREATE CAST
Description: define a new cast
Syntax:
CREATE CAST (source_type AS target_type)
    WITH FUNCTION function_name [ (argument_type [, ...]) ]
    [ AS ASSIGNMENT | AS IMPLICIT ]

CREATE CAST (source_type AS target_type)
    WITHOUT FUNCTION
    [ AS ASSIGNMENT | AS IMPLICIT ]

CREATE CAST (source_type AS target_type)
    WITH INOUT
    [ AS ASSIGNMENT | AS IMPLICIT ]

创建自定义类型转换函数:

test=# select castsource::regtype,casttarget::regtype,castfunc::regproc,castcontext,castmethod from pg_cast where castsource= '"char"'::regtype and casttarget = 'bigint'::regtype;
 CASTSOURCE | CASTTARGET | CASTFUNC | CASTCONTEXT | CASTMETHOD 
------------+------------+----------+-------------+------------
(0 rows)

test=# create cast ("char" as bigint) with inout as assignment;                                                                                                                    
CREATE CAST
test=# select castsource::regtype,casttarget::regtype,castfunc::regproc,castcontext,castmethod from pg_cast where castsource= '"char"'::regtype and casttarget = 'bigint'::regtype;
 CASTSOURCE | CASTTARGET | CASTFUNC | CASTCONTEXT | CASTMETHOD 
------------+------------+----------+-------------+------------
 "char"     | bigint     | -        | a           | i
(1 row)

test=# create table t01(id bigint);
CREATE TABLE
test=# insert into t01 values ("char" '123');
INSERT 0 1
test=# insert into t01 values ("char" '1234');
INSERT 0 1
test=# drop cast("char" as bigint);                                                                                                                                                
DROP CAST
test=# insert into t01 values ("char" '12345');
ERROR:  column "id" is of type bigint but expression is of type "char"
LINE 1: insert into t01 values ("char" '12345');
                                       ^
HINT:  You will need to rewrite or cast the expression.

通过使用WITH INOUT语法来定义一个I/O转换映射。一个I/O转换是通过调用源数据类型的输出函数,并将结果字符串传递给目标数据类型的输入函数来执行的。在常用的场景下,这个功能避免了为数据类型转换编写一个单独的转换函数。I/O转换的行为与基于常规函数的转换相同,只是实现方式不同。

每个数据类型都有一个内置的I/O转换函数,如varchar、text..

test=# \df textin
                          List of functions
   Schema   |  Name  | Result data type | Argument data types | Type 
------------+--------+------------------+---------------------+------
 pg_catalog | textin | text             | cstring             | func
(1 row)

test=# \df textout
                          List of functions
   Schema   |  Name   | Result data type | Argument data types | Type 
------------+---------+------------------+---------------------+------
 pg_catalog | textout | cstring          | text                | func
(1 row)

test=# \df varcharin
                            List of functions
   Schema   |   Name    | Result data type |  Argument data types  | Type 
------------+-----------+------------------+-----------------------+------
 pg_catalog | varcharin | varchar          | cstring, oid, integer | func
(1 row)

test=# \df varcharout
                            List of functions
   Schema   |    Name    | Result data type | Argument data types | Type 
------------+------------+------------------+---------------------+------
 pg_catalog | varcharout | cstring          | varchar             | func
(1 row)

varcharin表示用于转化为内部的表示格式,varcharout表示用于将内部格式转化为想要的格式。

2.1.5 二进制兼容数据类型简单整理:

数据类型转换重写与不重写:

  • varchar(x) 转换到 varchar(y) 当 y>=x,不需要重写。
  • numeric(x,z) 转换到 numeric(y,z) 当 y>=x,或者不指定精度类型,不需要重写。
  • numeric(x,c) 转换到 numeric(y,z) 当 y=x c>z,当numeric数据类型标度不一致时,需要重写。
  • varbit(x) 转换到 varbit(y) 当 y>=x,不需要重写。
  • timestamp(x) 转换到 timestamp(y) 当 y>=x,或者转换为timestamp,不需要重写。
  • timestamptz(x) 转换到 timestamptz(y) 当 y>=x,或者转换为timestamptz,不需要重写。
  • interval(x) 转换到 interval(y) 当 y>=x ,或者转换为interval,不需要重写。
  • timestamp 转换到 text、varchar、varchar(n),char(n),需要重写。
  • timestamp(x)转换到 text、varchar、varchar(n)、char(n),n>=x,需要重写。
  • text 转换到 char、char(x)、varchar(n),需要重写。
  • text 转换到 varchar,不需要重写。
  • numeric(x) 转换到 numeric(y),y>=x,不需要重写。
  • numeric(x) 转换到 numeric,不需要重写
  • numeric(x,y) 转换到 numeric,不需要重写

KingbaseES全部的二进制兼容类型:

test=# select castsource::regtype,casttarget::regtype,castfunc::regproc,castcontext,castmethod from sys_cast where castmethod='b';                                                    
   CASTSOURCE    |     CASTTARGET      | CASTFUNC | CASTCONTEXT | CASTMETHOD 
-----------------+---------------------+----------+-------------+------------
 integer         | oid                 | -        | i           | b
 integer         | regconfig           | -        | i           | b
 integer         | regoperator         | -        | i           | b
 integer         | regtype             | -        | i           | b
 integer         | regclass            | -        | i           | b
 integer         | regprocedure        | -        | i           | b
 integer         | regproc             | -        | i           | b
 integer         | regoper             | -        | i           | b
 integer         | regnamespace        | -        | i           | b
 integer         | regrole             | -        | i           | b
 integer         | regdictionary       | -        | i           | b
 regproc         | oid                 | -        | i           | b
 regproc         | regprocedure        | -        | i           | b
 regproc         | integer             | -        | a           | b
 text            | bpchar              | -        | i           | b
 text            | varcharbyte         | -        | i           | b
 text            | varchar             | -        | i           | b
 text            | bpcharbyte          | -        | i           | b
 oid             | regoperator         | -        | i           | b
 oid             | integer             | -        | a           | b
 oid             | regproc             | -        | i           | b
 oid             | regprocedure        | -        | i           | b
 oid             | regoper             | -        | i           | b
 oid             | regclass            | -        | i           | b
 oid             | regtype             | -        | i           | b
 oid             | regconfig           | -        | i           | b
 oid             | regdictionary       | -        | i           | b
 oid             | regrole             | -        | i           | b
 oid             | regnamespace        | -        | i           | b
 xml             | text                | -        | a           | b
 xml             | varchar             | -        | a           | b
 xml             | bpchar              | -        | a           | b
 pg_node_tree    | text                | -        | i           | b
 cidr            | inet                | -        | i           | b
 bpchar          | text                | -        | i           | b
 bpchar          | varcharbyte         | -        | i           | b
 bpchar          | bpcharbyte          | -        | i           | b
 varchar         | text                | -        | i           | b
 varchar         | bpcharbyte          | -        | a           | b
 varchar         | varcharbyte         | -        | i           | b
 varchar         | bpchar              | -        | a           | b
 bit             | bit varying         | -        | i           | b
 bit varying     | bit                 | -        | i           | b
 regprocedure    | regproc             | -        | i           | b
 regprocedure    | integer             | -        | a           | b
 regprocedure    | oid                 | -        | i           | b
 regoper         | integer             | -        | a           | b
 regoper         | regoperator         | -        | i           | b
 regoper         | oid                 | -        | i           | b
 regoperator     | integer             | -        | a           | b
 regoperator     | oid                 | -        | i           | b
 regoperator     | regoper             | -        | i           | b
 regclass        | oid                 | -        | i           | b
 regclass        | integer             | -        | a           | b
 regtype         | integer             | -        | a           | b
 regtype         | oid                 | -        | i           | b
 pg_ndistinct    | bytea               | -        | i           | b
 pg_dependencies | bytea               | -        | i           | b
 regconfig       | oid                 | -        | i           | b
 regconfig       | integer             | -        | a           | b
 regdictionary   | oid                 | -        | i           | b
 regdictionary   | integer             | -        | a           | b
 regnamespace    | integer             | -        | a           | b
 regnamespace    | oid                 | -        | i           | b
 regrole         | integer             | -        | a           | b
 regrole         | oid                 | -        | i           | b
 pg_mcv_list     | bytea               | -        | i           | b
 yminterval      | pg_catalog.interval | -        | a           | b
 bpcharbyte      | bpchar              | -        | a           | b
 bpcharbyte      | varchar             | -        | i           | b
 bpcharbyte      | text                | -        | i           | b
 bpcharbyte      | varcharbyte         | -        | i           | b
 varcharbyte     | bpchar              | -        | a           | b
 varcharbyte     | bpcharbyte          | -        | a           | b
 varcharbyte     | varchar             | -        | a           | b
 varcharbyte     | text                | -        | i           | b
(76 rows)

在KingbaseES变更表结构可以参考以上内容。