PostgreSQL查询引擎——General Expressions Grammar之restricted expression
General expressions语法规则定义在src/backend/parser/gram.y文件中,其是表达式语法的核心。有两种表达式类型:a_expr是不受限制的类型,b_expr是必须在某些地方使用的子集,以避免移位/减少冲突。例如,我们不能将BETWEEN作为BETWEEN a_expr AND a_exp,因为AND的使用与AND作为布尔运算符冲突。因此,b_expr在BETWEEN中使用,我们从b_expr中删除布尔关键字。请注意,( a_expr )是b_expr,因此始终可以使用无限制表达式,方法是用括号将其括起来。c_expr是a_expr和b_expr共同的所有乘积;它被分解出来只是为了消除冗余编码。注意涉及多个terminal token的产出productions。默认情况下,bison将为此类productions分配其最后一个terminal的优先级,但在几乎所有情况下,您都希望它是第一个terminal的优先权;否则你不会得到你期望的行为!因此,我们可以自由使用%prec注释来设置优先级。

b_expr代表Restricted expressions,它是复杂表达式a_expr的子集,AND, NOT, IS, and IN是a_expr的关键字,这些关键字在b_expr使用会存在歧义。b_expr is a subset of the complete expression syntax defined by a_expr. Presently, AND, NOT, IS, and IN are the a_expr keywords that would cause trouble in the places where b_expr is used. For simplicity, we just eliminate all the boolean-keyword-operator productions from b_expr.
b_expr: c_expr{ $$ = $1; }| b_expr TYPECAST Typename{ $$ = makeTypeCast($1, $3, @2); }| '+' b_expr %prec UMINUS{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", NULL, $2, @1); }| '-' b_expr %prec UMINUS{ $$ = doNegate($2, @1); }| b_expr '+' b_expr{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", $1, $3, @2); }| b_expr '-' b_expr{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "-", $1, $3, @2); }| b_expr '*' b_expr{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "*", $1, $3, @2); }| b_expr '/' b_expr{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "/", $1, $3, @2); }| b_expr '%' b_expr{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "%", $1, $3, @2); }| b_expr '^' b_expr{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "^", $1, $3, @2); }| b_expr '<' b_expr{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $3, @2); }| b_expr '>' b_expr{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $3, @2); }| b_expr '=' b_expr{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", $1, $3, @2); }| b_expr LESS_EQUALS b_expr{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "<=", $1, $3, @2); }| b_expr GREATER_EQUALS b_expr{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, ">=", $1, $3, @2); }| b_expr NOT_EQUALS b_expr{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "<>", $1, $3, @2); }| b_expr qual_Op b_expr %prec Op{ $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, $3, @2); }| qual_Op b_expr %prec Op{ $$ = (Node *) makeA_Expr(AEXPR_OP, $1, NULL, $2, @1); }| b_expr qual_Op %prec POSTFIXOP{ $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, NULL, @2); }| b_expr IS DISTINCT FROM b_expr %prec IS{ $$ = (Node *) makeSimpleA_Expr(AEXPR_DISTINCT, "=", $1, $5, @2); }| b_expr IS NOT DISTINCT FROM b_expr %prec IS{ $$ = (Node *) makeSimpleA_Expr(AEXPR_NOT_DISTINCT, "=", $1, $6, @2); }| b_expr IS OF '(' type_list ')' %prec IS{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "=", $1, (Node *) $5, @2); }| b_expr IS NOT OF '(' type_list ')' %prec IS{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "<>", $1, (Node *) $6, @2); }| b_expr IS DOCUMENT_P %prec IS{ $$ = makeXmlExpr(IS_DOCUMENT, NULL, NIL, list_make1($1), @2); }| b_expr IS NOT DOCUMENT_P %prec IS{ $$ = makeNotExpr(makeXmlExpr(IS_DOCUMENT, NULL, NIL, list_make1($1), @2), @2); }
表达式强转

b_expr TYPECAST Typename是表达式强转的规则,其中主要关注SimpleTypename所代表的规则。除了GenericType之外的规则和PostgreSQL查询引擎——General Expressions Grammar之AexprConst中介绍的常量类型强转类似,这里仅仅关注GenericType。
SimpleTypename:GenericType { $$ = $1; }| Numeric { $$ = $1; }| Bit { $$ = $1; }| Character { $$ = $1; }| ConstDatetime { $$ = $1; }| ConstInterval opt_interval{ $$ = $1; $$->typmods = $2; }| ConstInterval '(' Iconst ')'{ $$ = $1; $$->typmods = list_make2(makeIntConst(INTERVAL_FULL_RANGE, -1), makeIntConst($3, @3)); };
GenericType涵盖所有没有标准规定的特殊语法的类型名称,包括限定名称。我们还允许类型修饰符。为了避免对函数调用的解析冲突,这里必须将修饰符显示为expr_list,但解析分析只接受它们的常量。GenericType covers all type names that don’t have special syntax mandated by the standard, including qualified names. We also allow type modifiers. To avoid parsing conflicts against function invocations, the modifiers have to be shown as expr_list here, but parse analysis will only accept constants for them.
GenericType:type_function_name opt_type_modifiers{ $$ = makeTypeName($1); $$->typmods = $2; $$->location = @1; }| type_function_name attrs opt_type_modifiers{ $$ = makeTypeNameFromNameList(lcons(makeString($1), $2)); $$->typmods = $3; $$->location = @1; }
opt_type_modifiers: '(' expr_list ')' { $$ = $2; }| /* EMPTY */ { $$ = NIL; }
表达式强转的规则不同之处在于opt_array_bounds和ARRAY对于arrayBounds成员取值的影响,以及使用SETOF需要将setof成员设置为true。
Typename: SimpleTypename opt_array_bounds{ $$ = $1; $$->arrayBounds = $2; }| SETOF SimpleTypename opt_array_bounds{ $$ = $2; $$->arrayBounds = $3; $$->setof = true; }/* SQL standard syntax, currently only one-dimensional */| SimpleTypename ARRAY '[' Iconst ']'{ $$ = $1; $$->arrayBounds = list_make1(makeInteger($4)); }| SETOF SimpleTypename ARRAY '[' Iconst ']'{ $$ = $2; $$->arrayBounds = list_make1(makeInteger($5)); $$->setof = true; }| SimpleTypename ARRAY{ $$ = $1; $$->arrayBounds = list_make1(makeInteger(-1)); }| SETOF SimpleTypename ARRAY{ $$ = $2; $$->arrayBounds = list_make1(makeInteger(-1)); $$->setof = true; }
opt_array_bounds:opt_array_bounds '[' ']'{ $$ = lappend($1, makeInteger(-1)); }| opt_array_bounds '[' Iconst ']'{ $$ = lappend($1, makeInteger($3)); }| /*EMPTY*/{ $$ = NIL; }
运算符

| '+' b_expr %prec UMINUS{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", NULL, $2, @1); }| '-' b_expr %prec UMINUS{ $$ = doNegate($2, @1); }| b_expr '+' b_expr{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", $1, $3, @2); }| b_expr '-' b_expr{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "-", $1, $3, @2); }| b_expr '*' b_expr{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "*", $1, $3, @2); }| b_expr '/' b_expr{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "/", $1, $3, @2); }| b_expr '%' b_expr{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "%", $1, $3, @2); }| b_expr '^' b_expr{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "^", $1, $3, @2); }| b_expr '<' b_expr{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $3, @2); }| b_expr '>' b_expr{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $3, @2); }| b_expr '=' b_expr{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", $1, $3, @2); }| b_expr LESS_EQUALS b_expr{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "<=", $1, $3, @2); }| b_expr GREATER_EQUALS b_expr{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, ">=", $1, $3, @2); }| b_expr NOT_EQUALS b_expr{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "<>", $1, $3, @2); }| b_expr qual_Op b_expr %prec Op{ $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, $3, @2); }| qual_Op b_expr %prec Op{ $$ = (Node *) makeA_Expr(AEXPR_OP, $1, NULL, $2, @1); }| b_expr qual_Op %prec POSTFIXOP{ $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, NULL, @2); }| b_expr IS DISTINCT FROM b_expr %prec IS{ $$ = (Node *) makeSimpleA_Expr(AEXPR_DISTINCT, "=", $1, $5, @2); }| b_expr IS NOT DISTINCT FROM b_expr %prec IS{ $$ = (Node *) makeSimpleA_Expr(AEXPR_NOT_DISTINCT, "=", $1, $6, @2); }| b_expr IS OF '(' type_list ')' %prec IS{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "=", $1, (Node *) $5, @2); }| b_expr IS NOT OF '(' type_list ')' %prec IS{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "<>", $1, (Node *) $6, @2); }| b_expr IS DOCUMENT_P %prec IS{ $$ = makeXmlExpr(IS_DOCUMENT, NULL, NIL, list_make1($1), @2); }| b_expr IS NOT DOCUMENT_P %prec IS{ $$ = makeNotExpr(makeXmlExpr(IS_DOCUMENT, NULL, NIL, list_make1($1), @2), @2); }
https://www.developerastrid.com/sql/sql-predicates/
相关文章:
PostgreSQL查询引擎——General Expressions Grammar之restricted expression
General expressions语法规则定义在src/backend/parser/gram.y文件中,其是表达式语法的核心。有两种表达式类型:a_expr是不受限制的类型,b_expr是必须在某些地方使用的子集,以避免移位/减少冲突。例如,我们不能将BETWE…...
从某种程度上来看,产业互联网是一次对于互联网的弥补和修正
如果对当下我们正在经历的这样一个时代进行一次定义的话,我更加愿意将其划归到产业互联网的范畴里。可能有人会说,这与产业互联网并无联系,因为从本质上来看,当下我们所经历的这样一个时代,其实是与互联网并没有太多联…...
【C#Unity题】1.委托和事件在使用上的区别是什么?2.C#中 == 和 Equals 的区别是什么?
1.委托和事件在使用上的区别是什么? 委托和事件是C#中的重要概念,通俗来讲,委托是一个可以指向特定方法的指针,可以将委托分配给不同的脚本,使它们能够完成不同的任务。而事件则是一种使用委托实现的通知机制ÿ…...
FFmpeg5.0源码阅读——内存池AVBufferPool
摘要:FFmpeg中大多数数据存储比如AVFrame,AVPacket都是通过AVBufferRef管理的,而承载数据的结构为AVBuffer。本文主要通过FFmpeg源码来分析下FFmpeg中AVBuffer相关的实现。 关键字:AVBuffer、AVBufferPool、AVBufferPool 1. AVBufferRef 1.…...
Python学习------起步7(字符串的连接、删除、修改、查询与统计、类型判断及字符串字母大小写转换)
目录 前言: 1.字符串的连接 join() 函数 2.字符串的删除&取代 replace()函数 3.字符串的修改&切割 (1)strip() 函数 (2)lstrip()函数 和 rstrip()函数 (3)split()函数-->…...
雪花算法snowflake
snowflake中文的意思是 雪花,雪片,所以翻译成雪花算法。它最早是twitter内部使用的分布式环境下的唯一ID生成算法。在2014年开源。雪花算法产生的背景当然是twitter高并发环境下对唯一ID生成的需求,得益于twitter内部高超的技术,雪…...
Part 4 描述性统计分析(占比 10%)——上
文章目录【后续会持续更新CDA Level I&II备考相关内容,敬请期待】【考试大纲】【考试内容】【备考资料】1、统计基本概念1.1、统计学的含义及应用1.1.1、统计学的含义1.2.1、统计学的应用1.2、统计学的基本概念1.2.1、数据及数据的分类1.2.2、总体和样本1.2.3、…...
Linux系统安全:安全技术和防火墙
目录 一、安全技术 1、安全技术 2、防火墙分类 二、防火墙 1、iptables五表五链 2、黑白名单 3、iptables基本语法 4、iptables选项 5、控制类型 6、隐藏扩展模块 7、显示扩展模块 8、iptables规则保存 9、自定义链使用 一、安全技术 1、安全技术 ①入侵检测系统…...
【干货】Python:turtle库的用法
【干货】Python:turtle库的用法1. turtle库概述2. turtle库与基本绘图2.1 导入库的三种方式2.1.12.1.22.1.32.2 窗体函数2.2 画笔状态函数2.2.1 seed(s)2.2.2 random()2.2.3 randint(a, b)2.2.4 getrandbits(k)2.2.5 randrange(start, stop[ , step])2.2.6 uniform(…...
信息安全与网络安全有什么区别?
生活中我们经常会听到要保障自己的或者企业的信息安全。那到底什么是信息安全呢?信息安全包含哪些内容?与网络安全又有什么区别呢?今天我们就一起来详细了解一下。什么叫做信息安全?信息安全定义如下:为数据处理系统建…...
花了5年时间,用过市面上95%的工具,终于找到这款万能报表工具
经常有粉丝问我有“哪个报表工具好用易上手?”或者是“有哪些适合绝大多数普通职场人的万能报表工具?” 从这里我大概总结出了大家选择报表工具最期望满足的3点: (1)简单易上手:也就是所谓的学习门槛要低…...
ESP32S3系列--SPI主机驱动详解(一)
一、目的SPI是一种串行同步接口,可用于与外围设备进行通信。ESP32S3自带4个SPI控制器外设,其中SPI0/SPI1内部专用,共用一组信号线,通过一个仲裁器访问外部Flash和PSRAM;SPI2/3各自使用一组信号线;开发者可以使用SPI2/3控制外部SPI…...
2023开工开学火热!远行的人们,把淘特箱包送上顶流
春暖花开,被疫情偷走的三年在今年开学季找补回来了。多个数据反馈,居民消费意愿大幅提升。在淘特上,开工开学节点就很是明显:1月30日以来,淘特箱包品类甚至远超2022年双11,成为开年“第一爆品”。与此同时&…...
Intel x86_64 PMU简介
文章目录前言一、性能监控概述二、CPUID information三、架构性能监控3.1 架构性能监控 Version 13.1.1 架构性能监控 Version 1 Facilities3.1.2 预定义的体系结构性能事件3.1.3 cmask demo测试参考资料前言 Intel 64 和 IA-32 架构提供了 PMU(Performance Monito…...
Vue (2)
文章目录1. 模板语法1.1 插值语法1.2 指令语法2. 数据绑定3. 穿插 el 和 data 的两种写法4. MVVM 模型1. 模板语法 root 容器中的代码称为 vue 模板 1.1 插值语法 1.2 指令语法 图一 : 简写 : v-bind: 是可以简写成 : 的 总结 : …...
ESP8266 + STC15基于AT指令通过TCP通讯协议获取时间
ESP8266 + STC15基于AT指令通过TCP通讯协议获取时间 如果纯粹拿32位的ESP8266模块给8位的单片机仅供授时工具使用,有点大材小用了。这里不讨论这个拿esp8266来单独开发使用。本案例只是通过学习esp8266 AT指令功能来验证方案的可行性。 🔖STC15 单片机采用的是:STC15F2K60S…...
谈谈Spring中Bean的生命周期?(让你瞬间通透~)
目录 1.Bean的生命周期 1.1、概括 1.2、图解 2、代码示例 2.1、初始化代码 2.2、初始化的前置方法和后置方法(重写) 2.3、Spring启动类 2.4、执行结果 2.5、经典面试问题 3.总结 1.Bean的生命周期 1.1、概括 Spring中Bean的生命周期就是Bean在…...
如何将VirtualBox虚拟机转换到VMware中
转换前的准备 首先需要你找到你的virtualbox以及VM安装到哪个文件夹里了,需要将这两个文件夹添加进环境变量Path中。 如果你记不清了,可以用everything全局搜索一下“VBoxManage.exe’以及“vmware-vdiskmanager.exe”,看一眼这个程序放到哪…...
洞庭龙梦(开发技巧和结构理论集)
1、经验来源,单一获取方式。进行形态等级展示。唯一游戏系统经验来源。无主线和支线剧情。2、玩家使用流通货币(充值货币),到玩家空间商城充值游戏,两人以上玩家进行游戏,掉落道具。交易系统游戏玩法&#…...
【23种设计模式】创建型模式详细介绍
前言 本文为 【23种设计模式】创建型模式详细介绍 相关内容介绍,下边具体将对单例模式,工厂方法模式,抽象工厂模式,建造者模式,原型模式,具体包括它们的特点与实现等进行详尽介绍~ 📌博主主页&…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...
ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...
MySQL 主从同步异常处理
阅读原文:https://www.xiaozaoshu.top/articles/mysql-m-s-update-pk MySQL 做双主,遇到的这个错误: Could not execute Update_rows event on table ... Error_code: 1032是 MySQL 主从复制时的经典错误之一,通常表示ÿ…...
0x-3-Oracle 23 ai-sqlcl 25.1 集成安装-配置和优化
是不是受够了安装了oracle database之后sqlplus的简陋,无法删除无法上下翻页的苦恼。 可以安装readline和rlwrap插件的话,配置.bahs_profile后也能解决上下翻页这些,但是很多生产环境无法安装rpm包。 oracle提供了sqlcl免费许可,…...
【UE5 C++】通过文件对话框获取选择文件的路径
目录 效果 步骤 源码 效果 步骤 1. 在“xxx.Build.cs”中添加需要使用的模块 ,这里主要使用“DesktopPlatform”模块 2. 添加后闭UE编辑器,右键点击 .uproject 文件,选择 "Generate Visual Studio project files",重…...
Python训练营-Day26-函数专题1:函数定义与参数
题目1:计算圆的面积 任务: 编写一个名为 calculate_circle_area 的函数,该函数接收圆的半径 radius 作为参数,并返回圆的面积。圆的面积 π * radius (可以使用 math.pi 作为 π 的值)要求:函数接收一个位置参数 radi…...
