谓词下推引起的查询报错

问题现象

计划中出现谓词下推时,按照SQL标准中的查询执行顺序本不应该报错,结果执行出错。

openGauss=# select * from tba;
 a 
---
 -1
  2
(2 rows)

openGauss=# select * from tbb;
 b 
---
 -1
  1
(2 rows)

openGauss=# select * from tba join tbb on a > b where b > 0 and sqrt(a) > 1;
ERROR: cannot table square root of a negative number

按照SQL执行标准流程: 1、执行FROM子句,能够保证所有数据满足a > b。 2、执行WHERE子句中b > 0,若结果为true则能够推导出a > 0,并继续执行;若false则结束,后面的条件被短路,不会执行。 3、执行WHERE子句中sqrt(a) > 1

但是实际却报错入参为负值。

原因分析

openGauss=# explain (costs off) select * from tba join tbb on a > b where b > 0 and sqrt(a) > 1;
            QUERY PLAN            
----------------------------------
Nest loop
  Join Filter: (a > b)
  -> Seq Scan on public.tba
       Filter: (sqrt(a) > 1)
  -> Materialize
       -> Seq Scan on public.tbb
            Filter: (b > 0)
(7 rows)

分析计划可知,原本a > b, b > 0, sqrt(a) > 1的三个条件,被拆分下推到了不同的算子之中,从而并非按顺序执行. 且当前的等价类推理仅支持等号推理,因此无法自动推理补充出a > 0。 最终查询报错。

处理办法

谓词下推可以极大的提升查询性能,且此种短路、推导的特殊场景,在大多数数据库优化器下都没有过多考虑,因此建议修改查询语句,在相关的条件下手动添加a > 0

openGauss=# select * from tba join tbb on a > b where b > 0 and a > 0 and sqrt(a) > 1;
 a | b 
---+---
 2 | 1 
(1 row)

openGauss=# explain (costs off) select * from tba join tbb on a > b where b > 0 and a > 0 and sqrt(a) > 1;
              QUERY PLAN              
--------------------------------------
Nest loop
  Join Filter: (a > b)
  -> Seq Scan on public.tba
       Filter: (a > 0 and sqrt(a) > 1)
  -> Materialize
       -> Seq Scan on public.tbb
            Filter: (b > 0)
(7 rows)