polar_sql_inception(SQL审核)

更新时间:
复制为 MD 格式

在团队协作或自动化发布流程中,不一致的SQL规范和未经审核的变更操作可能引入数据错误、性能瓶颈甚至生产环境故障。polar_sql_inception插件通过提供一个集审核与执行于一体的自动化SQL审核引擎,解决了这一痛点。您可以通过自定义规则,在开发、测试及发布阶段自动检查SQL,强制执行编码标准,拦截高风险操作,从而保障数据库变更的质量与安全。

适用范围

支持的PolarDB PostgreSQL的版本如下:

  • PostgreSQL 16(内核小版本2.0.16.9.9.0及以上)

  • PostgreSQL 15(内核小版本2.0.15.15.7.0及以上)

  • PostgreSQL 14(内核小版本2.0.14.19.38.0及以上)

说明

您可在控制台查看内核小版本号,也可以通过SHOW polardb_version;语句查看。如未满足内核小版本要求,请升级内核小版本

快速入门

本节将通过一个简单的示例,快速展示polar_sql_inception的核心功能:在3分钟内拦截一条不符合规范的建表语句。

  1. 安装polar_sql_inception插件:在您的数据库中执行以下命令。

    CREATE EXTENSION polar_sql_inception;
  2. 设置一条审核规则,强制所有新建的表都必须包含主键。执行SET命令,在当前会话中开启该规则。

    SET polar_sql_inception.table_rule_check_primary_key = ON;
  3. 调用审核函数,检查一条不含主键的建表语句。 执行以下查询。将execute参数设置为FALSE,表示只审核,不执行。

    SELECT * FROM polar_sql_inception(
        sql_statements := 'CREATE TABLE users (id INT, name TEXT);',
        execute := FALSE
    );
  4. 预期结果:审核不通过,并返回明确的错误信息。 error_level字段为errorerror_message字段清晰地指出了set a primary key的违规原因。这表明该插件已成功拦截了不合规的SQL。

     sql_id |             sql_statement              |  stage  | error_level |   error_message   | affected_rows 
    --------+----------------------------------------+---------+-------------+-------------------+---------------
          1 | CREATE TABLE users (id INT, name TEXT) | checked | warning     | set a primary key+|             0
            |                                        |         |             |                   | 

工作原理

配置模式

您可以根据需求选择不同的方式来配置审核规则。

  • 通过SET命令在当前数据库中设置参数。此方式灵活便捷,无需重启集群,配置仅对应用范围生效。

    • 会话级配置:

      -- 仅在当前会话生效
      SET polar_sql_inception.dml_rule_check_dml_where = ON;
    • 用户级别:

      -- 仅在当前用户生效
      ALTER username SET polar_sql_inception.dml_rule_check_dml_where = ON;
    • DATABASE级别

      -- 仅在当前数据库生效
      ALTER databasename SET polar_sql_inception.dml_rule_check_dml_where = ON;

执行模型

当您调用polar_sql_inception函数并传入多条SQL语句时,它遵循以下处理流程:

  1. 串行处理:插件按顺序逐条处理SQL语句,流程为:审核语句A -> (若通过且executeTRUE)执行语句A -> 审核语句B -> (若通过且executeTRUE)执行语句B -> ...。

  2. 错误中断:在审核或执行过程中,一旦某条语句触发了error级别的错误,或者触发了warning级别错误且未设置忽略警告(ignore_warning_when_executing = OFF),后续所有语句的执行流程都将被中断。但插件会继续完成对剩余所有语句的审核,并返回完整的审核结果。

执行SQL审核与变更

本节介绍如何通过polar_sql_inception函数执行SQL审核,并根据需要执行变更。

函数定义

polar_sql_inception(
    sql_statements TEXT,
    execute BOOLEAN DEFAULT FALSE,
    schema TEXT DEFAULT NULL
)

参数说明

参数

说明

适用范围

sql_statements

需要审核的一条或多条SQL语句。

同功能适用范围。

execute

是否在审核通过后执行SQL语句。默认为FALSE,表示只审核不执行。

  • 集群版本:

    • PostgreSQL 16(内核小版本2.0.16.10.11.0及以上)

    • PostgreSQL 15(内核小版本2.0.15.15.7.0及以上)

    • PostgreSQL 14(内核小版本2.0.14.19.40.0及以上)

  • 支持执行的SQL语句:

    • INSERTUPDATEDELETE

    • CREATE TABLEALTER TABLEDROP TABLETRUNCATE TABLE

    • CREATE INDEXALTER INDEXDROP INDEX

    • CREATE VIEWDROP VIEW

    • COMMENT

schema

指定SQL语句执行时依赖的默认Schema。

说明

此参数效果等同于在本次审核执行的内部临时执行SET search_path TO 'your_schema',执行完毕后会自动恢复,不影响您当前会话的search_path设置。如果为NULL(默认值),则依赖当前会话的search_path

  • PostgreSQL 16(内核小版本2.0.16.10.12.0及以上)

  • PostgreSQL 14(内核小版本2.0.14.20.41.0及以上)

操作示例

场景一:仅审核多条SQL语句

检查两句CREATE TABLE语句是否符合必须有主键的规则,但不实际创建表。

-- 开启“表必须有主键”的规则
SET polar_sql_inception.table_rule_check_primary_key = ON;

-- 调用函数进行审核
SELECT * FROM polar_sql_inception(
    sql_statements := $$
        -- 错误示例:没有主键
        CREATE TABLE t1 (id INT);

        -- 正确示例:有主键
        CREATE TABLE t2 (id INT PRIMARY KEY);
    $$,
    execute := FALSE
);

返回结果:第一条SQL因违反规则而报错,第二条SQL审核通过。

 sql_id |                sql_statement                 |  stage  | error_level |    error_message    | affected_rows 
--------+----------------------------------------------+---------+-------------+---------------------+---------------
      1 |                                             +| checked | warning     | set a primary key  +|             0
        |         -- 错误示例:没有主键                  +|         |             |                     | 
        |         CREATE TABLE t1 (id INT)             |         |             |                     | 
      2 |                                             +| checked | success     | no violations found |             0
        |                                             +|         |             |                     | 
        |         -- 正确示例:有主键                    +|         |             |                     | 
        |         CREATE TABLE t2 (id INT PRIMARY KEY) |         |             |                     | 

场景二:审核并通过后执行

审核一条UPDATE语句是否符合DML必须带WHERE子句的规则,如果符合则执行它。

-- 准备测试数据
CREATE TABLE products (id INT, stock INT);
INSERT INTO products VALUES (1, 100);

-- 开启“DML必须带WHERE”的规则
SET polar_sql_inception.dml_rule_check_dml_where = ON;

-- 调用函数,审核并执行
SELECT * FROM polar_sql_inception(
    sql_statements := 'UPDATE products SET stock = 99 WHERE id = 1;',
    execute := TRUE
);

返回结果:SQL语句审核通过并成功执行(stage: executederror_level: success),affected_rows字段显示有1行数据被更新。

 sql_id |                sql_statement                |  stage   | error_level |    error_message    | affected_rows 
--------+---------------------------------------------+----------+-------------+---------------------+---------------
      1 | UPDATE products SET stock = 99 WHERE id = 1 | executed | success     | no violations found |             1

结果集详解

polar_sql_inception函数返回一个结果集,每一行对应您输入的一条SQL语句的审核与执行结果。

字段

说明

sql_id

SQL语句的序号,从1开始。

sql_statement

当前处理的SQL语句原文。

stage

表示当前SQL语句的处理阶段:

  • none:未做任何处理,通常因为前面的语句存在语法错误导致解析提前终止。

  • checked:已完成审核,但未执行。

  • executed:已执行。无论执行成功或失败,都为此状态。

error_level

表示结果的严重级别:

  • checked阶段:

    • success:审核通过。

    • warning:违反了配置的规则,不影响执行。

    • error:违反了默认规则,影响执行。

  • executed阶段:

    • success:执行成功。

    • warning:一般情况不存在,除非您配置了ignore_warning_when_executing运行参数,忽略了checked阶段的warning报错进行执行,执行成功。

    • error:执行失败。

error_message

详细的审核意见或错误信息。如果有多条违规,信息会用换行符分隔。审核通过时,返回no violations found

affected_rows

受影响的行数。

  • checked阶段:默认返回优化器预估的影响行数。如果开启了get_real_affected_rows,会将UPDATEDELETEINSERT语句转化为对应的SELECT语句并执行,以获取实际影响行数。如果执行失败,也会抛出ERROR级错误。

  • executed阶段:返回SQL执行后真实影响的行数。

配置模板

为帮助您批量设置规则参数,PolarDB提供以下设置模板。您可以根据实际业务需求,设置对应的规则。

-- 运行配置
SET polar_sql_inception.get_real_affected_rows = OFF;
SET polar_sql_inception.enable_utility_parse_analysis = ON;
SET polar_sql_inception.ignore_warning_when_executing = OFF;

-- 表相关规则
SET polar_sql_inception.table_rule_enable_partition = ON;
SET polar_sql_inception.table_rule_check_primary_key = OFF;
SET polar_sql_inception.table_rule_enable_foreign_key = ON;
SET polar_sql_inception.table_rule_merge_alter_table = OFF;
SET polar_sql_inception.table_rule_must_have_columns ='column1,column2,column3';

-- 列相关规则
SET polar_sql_inception.column_rule_max_char_length = 0;
SET polar_sql_inception.column_rule_enable_text_type = ON;
SET polar_sql_inception.column_rule_enable_json_type = ON;
SET polar_sql_inception.column_rule_check_not_null = OFF;
SET polar_sql_inception.column_rule_enable_timestamp_type = ON;
SET polar_sql_inception.column_rule_check_timestamp_default = OFF;
SET polar_sql_inception.column_rule_check_timestamp_count = OFF;
SET polar_sql_inception.column_rule_check_default_value = OFF;

-- 索引相关规则
SET polar_sql_inception.index_rule_enable_null_index_name = ON;
SET polar_sql_inception.index_rule_max_key_parts = 0;
SET polar_sql_inception.index_rule_max_primary_key_parts = 0;
SET polar_sql_inception.index_rule_check_pk_columns_only_int = OFF;
SET polar_sql_inception.index_rule_max_keys = 0;

-- 命名相关规则
SET polar_sql_inception.naming_rule_check_char = OFF;
SET polar_sql_inception.naming_rule_check_keyword = OFF;

-- DML 相关规则
SET polar_sql_inception.dml_rule_check_insert_field = OFF;
SET polar_sql_inception.dml_rule_check_dml_where = OFF;
SET polar_sql_inception.dml_rule_enable_select_star = ON;
SET polar_sql_inception.dml_rule_enable_orderby_rand = ON;
SET polar_sql_inception.dml_rule_max_update_rows = 0;
SET polar_sql_inception.dml_rule_max_insert_rows = 0;
SET polar_sql_inception.dml_rule_max_delete_rows = 0;

-- 其他规则
SET polar_sql_inception.check_schema_consistency = OFF;

配置项参考

运行配置

参数

默认值

说明

polar_sql_inception.get_real_affected_rows

FALSE

checked阶段,当配置polar_sql_inception.get_real_affected_rows时,会将UPDATEDELETEINSERT语句转化为对应的SELECT语句并执行,以获取实际影响行数,而非优化器的估算值。

polar_sql_inception.enable_utility_parse_analysis

TRUE

checked阶段,检查SQL语句的语义错误。目前支持的语句:DML语句、DDL语句、CREATE TABLEALTER TABLECREATE INDEXALTER INDEXCOMMENT

说明

支持的集群版本如下:

  • PostgreSQL 16(内核小版本2.0.16.10.10.0及以上)

  • PostgreSQL 15(内核小版本2.0.15.15.7.0及以上)

  • PostgreSQL 14(内核小版本2.0.14.19.38.0及以上)

polar_sql_inception.ignore_warning_when_executing

FALSE

executed阶段,将忽略check阶段的warning报错进行执行。

说明

支持的集群版本如下:

  • PostgreSQL 16(内核小版本2.0.16.10.11.11及以上)

  • PostgreSQL 15(内核小版本2.0.15.15.7.0及以上)

  • PostgreSQL 14(内核小版本2.0.14.19.40.0及以上)

规则配置

表相关规则

规则名称

参数

默认值

触发场景

表必须包含主键

polar_sql_inception.table_rule_check_primary_key

FALSE

  • CREATE TABLE没有主键。

  • ALTER TABLE删除主键约束。

  • ALTER TABLE删除主键列。

禁止创建分区表

polar_sql_inception.table_rule_enable_partition

TRUE

  • CREATE TABLE创建分区表。

禁止使用外键

polar_sql_inception.table_rule_enable_foreign_key

TRUE

  • CREATE TABLE有外键约束。

  • ALTER TABLE新增外键约束。

表必须包含指定列

polar_sql_inception.table_rule_must_have_columns

"",即不检查

  • CREATE TABLE必须包含某些列。

  • ALTER TABLE删除这些列。

合并多个ALTER TABLE

polar_sql_inception.table_rule_merge_alter_table

FALSE

  • 多个连续的针对同一个表的ALTER TABLE

创建的表不存在

默认规则

-

  • CREATE TABLE表不存在。

只能有一个主键

默认规则

-

  • CREATE TABLE有多个主键。

  • ALTER TABLE在已有主键的情况下新建主键索引,或者新建两个及以上的主键索引。

LIKE的表不存在

默认规则

-

  • CREATE TABLE LIKE的表不存在。

用户必须有权限

默认规则

-

  • CREATE TABLE所在Schema没有权限。

  • CREATE TABLE LIKE的表没有权限。

  • ALTER TABLE的表没有权限。

列相关规则

规则名称

参数

默认值

触发场景

CHAR长度限制

polar_sql_inception.column_rule_max_char_length

0,即不检查

  • CREATE TABLE创建列为CHAR类型。

  • ALTER TABLE修改列为CHAR类型。

  • ALTER TABLE新增列为CHAR类型。

禁止使用TEXT类型

polar_sql_inception.column_rule_enable_text_type

TRUE

  • CREATE TABLE创建列为TEXT类型。

  • ALTER TABLE修改列为TEXT类型。

  • ALTER TABLE新增列为TEXT类型。

禁止使用JSON类型

polar_sql_inception.column_rule_enable_json_type

TRUE

  • CREATE TABLE创建列为JSON类型。

  • ALTER TABLE修改列为JSON类型。

  • ALTER TABLE新增列为JSON类型。

列必须有NOT NULL约束

polar_sql_inception.column_rule_check_not_null

FALSE

  • CREATE TABLE创建列为NOT NULL类型。

  • ALTER TABLE修改列为NOT NULL类型。

  • ALTER TABLE新增列为NOT NULL类型。

禁止使用TIMESTAMP类型

polar_sql_inception.column_rule_enable_timestamp_type

TRUE

  • CREATE TABLE创建列为TIMESTAMP类型。

  • ALTER TABLE修改列为TIMESTAMP类型。

  • ALTER TABLE新增列为TIMESTAMP类型。

TIMESTAMP列必须有默认值

polar_sql_inception.column_rule_check_timestamp_default

FALSE

  • CREATE TABLE创建TIMESTAMP类型列没有默认值。

  • ALTER TABLE修改TIMESTAMP类型列没有默认值。

  • ALTER TABLE新增TIMESTAMP类型列没有默认值。

只能有一个 TIMESTAMP字段在DEFAULT指定 CURRENT_TIMESTAMP

polar_sql_inception.column_rule_check_timestamp_count

FALSE

  • CREATE TABLE创建两个TIMESTAMP类型的列,默认值为CURRENT_TIMESTAMP

每个列都需要定义默认值,除了 TIMESTAMP/自增列/主键/JSON/计算列/以及BYTEA列以外

polar_sql_inception.column_rule_check_default_value

FALSE

  • CREATE TABLE创建列没有默认值。

  • ALTER TABLE新增列没有默认值。

  • ALTER TABLE删除列的默认值。

不能有重复的列名

默认规则

-

  • CREATE TABLE有重复的列名。

  • ALTER TABLE列名重命名与已有的列名重复。

  • ALTER TABLE新增列的列名与已有的列名重复。

索引相关规则

规则名称

参数

默认值

触发场景

索引必须有名称

polar_sql_inception.index_rule_enable_null_index_name

TRUE

  • CREATE INDEX索引没有名称。

普通索引的列数限制

polar_sql_inception.index_rule_max_key_parts

0

  • CREATE INDEX普通索引的列数超过max_key_parts

主键索引的列数限制

polar_sql_inception.index_rule_max_primary_key_parts

0

  • CREATE TABLE主键索引的列数超过参数指定列数。

  • ALTER TABLE创建的主键索引的列数超过参数指定列数。

主键列必须为整数类型

polar_sql_inception.index_rule_check_pk_columns_only_int

FALSE

  • CREATE TABLE主键索引所包含的列的类型不是INT类型。

  • ALTER TABLE创建主键索引所包含的列的类型不是INT类型。

单表索引总数限制

polar_sql_inception.index_rule_max_keys

0

  • CREATE TABLE索引的数量超过index_rule_max_keys

  • CREATE INDEX已存在的索引数量已经达到index_rule_max_keys

  • ALTER TABLE 创建主键/UNIQUE 索引,已存在的索引数量已经达到index_rule_max_keys

建索引时,指定的列必须存在。

默认规则

-

  • CREATE INDEX指定列不存在。

  • CREATE TABLE主键/UNIQUE 指定列不存在。

  • ALTER TABLE创建主键索引所包含的列不存在。

建索引时,指定的列必须存在。

默认规则

-

  • CREATE INDEX索引中的列重复。

  • CREATE TABLE主键/UNIQUE 指定的列存在重复。

  • ALTER TABLE创建主键索引指定的列存在重复。

索引名不能重复

默认规则

-

  • CREATE INDEX索引名与已有的索引名重复。

  • ALTER INDEX索引重命名与已有的索引名重复。

  • ALTER TABLE创建主键索引名与已有的索引名重复。

用户必须有权限

默认规则

-

  • CREATE INDEX的表没有权限。

命名相关规则

规则名称

参数

默认值

触发场景

检查名称字符集

polar_sql_inception.naming_rule_check_char

FALSE

  • CREATE TABLE表名、列名使用了[a-zA-Z0-9*]之外的字符。

  • CREATE INDEX索引名使用了[a-zA-Z0-9*]之外的字符。

  • CREATE TABLE表级主键和UNIQUE索引名使用了[a-zA-Z0-9*]之外的字符。

  • ALTER TABLE重命名表名使用了[a-zA-Z0-9*]之外的字符。

  • ALTER TABLE新增的列的使用了[a-zA-Z0-9*]之外的字符。

  • ALTER TABLE新增的主键索引使用了[a-zA-Z0-9*]之外的字符。

  • ALTER INDEX重命名索引使用了[a-zA-Z0-9_]之外的字符。

检查是否为关键字

polar_sql_inception.naming_rule_check_keyword

FALSE

  • CREATE TABLE表名、列名使用了关键字。

  • CREATE INDEX索引名使用了关键字。

  • CREATE TABLE表级主键和UNIQUE索引名使用了关键字。

  • ALTER TABLE重命名表名使用了关键字。

  • ALTER TABLE新增的列的使用了关键字。

  • ALTER TABLE新增的主键索引使用了关键字。

  • ALTER INDEX 重命名索引使用了关键字。

DML 相关规则

规则名称

参数

默认值

触发场景

必须指定插入列表

polar_sql_inception.dml_rule_check_insert_field

FALSE

INSERT/INSERT SELECT没有指定插入列表。

DML必须有WHERE条件

polar_sql_inception.dml_rule_check_dml_where

FALSE

UPDATE/DELETE/SELECT/INSERT SELECT没有WHERE条件。

禁止使用SELECT *

polar_sql_inception.dml_rule_enable_select_star

TRUE

SELECT/INSERT SELECT使用了SELECT *

禁止使用ORDER BY RAND()

polar_sql_inception.dml_rule_enable_orderby_rand

TRUE

SELECT/INSERT SELECT使用了ORDER BY RANDOM

限制UPDATE行数

polar_sql_inception.dml_rule_max_update_rows

0

UPDATE操作影响的预估行数超过dml_rule_max_update_rows

限制INSERT行数

polar_sql_inception.dml_rule_max_insert_rows

0

INSERT操作插入的预估行数超过dml_rule_max_insert_rows

限制DELETE行数

polar_sql_inception.dml_rule_max_delete_rows

0

DELETE操作影响的预估行数超过dml_rule_max_delete_rows

表、列必须存在

默认规则

-

DML语句中表、列并不存在。

用户必须有权限

默认规则

-

DML语句用户对表没有权限。

其他规则

规则名称

参数

默认值

触发场景

检查Schema一致性

polar_sql_inception.check_schema_consistency

FALSE

DMLDDL语句显式指定的Schemapolar_sql_inception函数指定的Schema参数不一致时触发。

说明

支持的集群版本如下:

  • PostgreSQL 16(内核小版本2.0.16.10.12.0及以上)

  • PostgreSQL 14(内核小版本2.0.14.20.41.0及以上)