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
注释来设置优先级。
productions expression
c_expr
是a_expr
和b_expr
所共有的规则,递归引用a_expr
或b_expr
的productions通常不能出现在c_expr
规则中。但是,可以引用出现在括号内的a_exprs
,例如函数参数;这不会给b_expr
语法带来歧义。productions that refer recursively to a_expr or b_expr mostly cannot appear here. However, it’s OK to refer to a_exprs that occur inside parentheses, such as function arguments; that cannot introduce ambiguity to the b_expr syntax.
规则五:SQL-style CASE子句,两种形式:Full specification(CASE WHEN a = b THEN c ... ELSE d END
)和 Implicit argument(CASE a WHEN b THEN c ... ELSE d END
)。
在第二种形式种,WHEN子句的条件表达式是comparison values比较值。解析分析器将其转换为CaseTestExpr '=' comexpr形式的合法布尔表达式。CaseTestExpr节点是placeholder,在运行时返回正确的值。该结构为例能使testexpr执行一次而引入。在解析分期之后,条件表达式永远返回布尔值。
transformCaseExpr
定义在src/backend/parser/parser_expr.c文件中的Node *transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)函数用于分析和转换表达式,包含类型检查和类型转换的工作。该函数将原始语法输出转换为具有完全确定语义的表达式树(Type checking and type casting is done here. This processing converts the raw grammar output into expression trees with fully determined semantics)。
static Node *transformExprRecurse(ParseState *pstate, Node *expr)函数用于递归处理表达式,其整体代码框架如下所示。
static Node *transformExprRecurse(ParseState *pstate, Node *expr){
Node *result;
if (expr == NULL) return NULL;
check_stack_depth(); /* Guard against stack overflow due to overly complex expressions */
switch (nodeTag(expr)){
case T_ColumnRef:
case T_ParamRef:
case T_A_Const:
case T_A_Indirection:
case T_A_ArrayExpr:
case T_TypeCast:
case T_CollateClause:
case T_A_Expr:
case T_BoolExpr:
case T_FuncCall:
case T_MultiAssignRef:
case T_GroupingFunc:
case T_NamedArgExpr:
case T_SubLink:
case T_CaseExpr:
result = transformCaseExpr(pstate, (CaseExpr *) expr);
break;
case T_RowExpr:
case T_CoalesceExpr:
case T_MinMaxExpr:
case T_SQLValueFunction:
case T_XmlExpr:
case T_XmlSerialize:
case T_NullTest:
case T_BooleanTest:
case T_CurrentOfExpr:
case T_SetToDefault:
case T_CaseTestExpr:
case T_Var:
default:
/* should not reach here */
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr));
result = NULL; /* keep compiler quiet */ break;
}
return result;
}
复制
T_CaseExpr
static Node *transformCaseExpr(ParseState *pstate, CaseExpr *c)函数定义在src/backend/parser/parse_expr.c文件中,用于处理T_CaseExpr节点,其主要执行流程如下:(从中可以看出transformExprRecurse函数遇到General Expressions就会被调用,也即是递归处理的含义)
首先处理testexpr(test expression)子句,也就是CaseExpr.arg成员,递归调用transformExprRecurse处理a_expr表达式,并将其设置到transform流程中新的CaseExpr.arg成员中。如果式第二种CASE语法,则需要创建CaseTestExpr节点类型的placeholder,用于实现后续WHEN子句的CaseTestExpr = complexpr A_Expr节点。
处理WHEN子句的CaseWhen节点,首先处理CaseExpr中的args元素CaseWhen节点的expr和result成员,其中要注意上一步中生成的placeholder,需要将CaseWhen.expr转为A_Expr节点,实现CaseTestExpr = complexpr 转变,然后调用transformExprRecurse处理。
最后处理CaseExpr中的defresult表达式,也就是default分支子句,如果为空,需要添加A_Const值为Null的几点,然后调用transformExprRecurse处理。
T_CaseTestExpr
CaseTestExpr不需要任何处理,仅仅用于插入parse trees。CaseTestExpr dosen't require any processing; it is only injected into parse trees in a fully-formed state.
欢迎关注微信公众号肥叔菌PostgreSQL数据库专栏:
PostgreSQL数据库守护进程——Postmaster总体流程
PostgreSQL数据库守护进程——读取控制文件
PostgreSQL数据库守护进程——RemovePgTempFiles删除临时文件
PostgreSQL数据库守护进程——RemovePromoteSignalFiles
PostgreSQL数据库信号处理——kill backend
PostgreSQL数据库PMsignal——后端进程\Postmaster信号通信
PostgreSQL数据库后端进程——inter-process latch
PostgreSQL数据库后端进程——监视postmaster death
PostgreSQL数据库后台进程——一等公民
PostgreSQL数据库后台进程——后台一等公民进程保活
PostgreSQL数据库头胎——后台一等公民进程StartupDataBase启动
PostgreSQL数据库头胎——后台一等公民进程StartupDataBase信号通知
PostgreSQL数据库头胎——StarupXLOG函数恢复模式和目标
PostgreSQL数据库状态pmState——PM_STARTUP状态
PostgreSQL数据库复制——Setting Up Asynchronous Replication
PostgreSQL数据库复制——后台一等公民进程WalReceiver启动函数
PostgreSQL数据库复制——后台一等公民进程WalReceiver获知连接
PostgreSQL数据库复制——后台一等公民进程WalReceiver&startup交互
PostgreSQL数据库复制——后台一等公民进程WalReceiver ready_to_display
PostgreSQL数据库复制——后台一等公民进程WalReceiver提取信息
PostgreSQL数据库复制——后台一等公民进程WalReceiver收发逻辑
PostgreSQL数据库复制——后台一等公民进程WalReceiver pg_stat_wal_receiver视图
PostgreSQL数据库复制——walsender后端启动
PostgreSQL数据库守护进程——后台二等公民进程第一波启动maybe_start_bgworkers
PostgreSQL数据库参数——简述GUC
PostgreSQL数据库网络层——libpq连接参数
PostgreSQL数据库动态共享内存管理器——dynamic shared memory segment
PostgreSQL数据库WAL——资源管理器RMGR
PostgreSQL数据库WAL——备机回放checkpoint WAL
PostgreSQL数据库事务系统——phenomena
PostgreSQL数据库统计信息——analyze命令
PostgreSQL数据库统计信息——analyze大致流程
PostgreSQL数据库统计信息——analyze执行函数
PostgreSQL数据库统计信息——查找继承子表find_all_inheritors
PostgreSQL数据库统计信息——analyze流程对不同表的处理
PostgreSQL数据库统计信息——examine_attribute单列预分析
PostgreSQL数据库统计信息——acquire_sample_rows采样函数
PostgreSQL数据库统计信息——acquire_inherited_sample_rows采样函数
PostgreSQL数据库统计信息——计算统计数据
PostgreSQL数据库统计信息——compute_scalar_stats计算统计数
PostgreSQL数据库统计信息——analyze统计信息收集
PostgreSQL数据库统计信息——统计信息系统表
PostgreSQL守护进程(Postmaster)——辅助进程PgStat主流程
PostgreSQL守护进程(Postmaster)——辅助进程PgStat统计消息
PostgreSQL数据库查询监控技术——pg_stat_activity简介
PostgreSQL查询引擎——编译调试
PostgreSQL查询引擎——select * from where = transform流程
PostgreSQL查询引擎——General Expressions Grammar之columnref
PostgreSQL查询引擎——Transform Expressions之columnref
PostgreSQL查询引擎——General Expressions Grammar之CaseExpr
PostgreSQL查询引擎——General Expressions Grammar之AexprConst
PostgreSQL查询引擎——Transform Expressions之const
PostgreSQL查询引擎——create table xxx(...)基础建表流程
PostgreSQL查询引擎——create table xxx(...)基础建表transformCreateStmt
PostgreSQL数据库查询执行——T_VariableSetStmt
PostgreSQL数据库查询执行——T_TransactionStmt
PostgreSQL数据库查询执行——Parallel Query
PostgreSQL数据库查询执行——SeqScan节点执行
PostgreSQL数据库查询执行——Using GDB To Trace Into a Parallel Worker Spawned By Postmaster During a Large Query
PostgreSQL数据库查询执行——Parallel SeqScan节点执行
PostgreSQL数据库可插拔存储引擎——pg_am系统表
PostgreSQL数据库可插拔存储引擎——Table Access Manager
PostgreSQL数据库可插拔存储引擎——GetTableAmRoutine函数
PostgreSQL数据库可插拔存储引擎——Table scan callbacks
PostgreSQL数据库HeapAM——TupleTableSlot类型
PostgreSQL数据库HeapAM——HeapAM Scan
PostgreSQL数据库HeapAM——HeapAM Parallel table scan
PostgreSQL数据库HeapAM——synchronized scan machinery
PostgreSQL数据库缓冲区管理器——概述
PostgreSQL数据库缓冲区管理器——本地缓冲区管理
PostgreSQL数据库缓冲区管理器——Shared Buffer Pool初始化
PostgreSQL数据库存储介质管理器——SMGR
PostgreSQL数据库存储介质管理器——磁盘管理器
PostgreSQL数据库目录——目录操作封装
PostgreSQL虚拟文件描述符VFD机制——FD LRU池
PostgreSQL虚拟文件描述符VFD机制——FD LRU池其他函数
PostgreSQL数据库FDW——The Internals of PostgreSQL
PostgreSQL数据库FDW——WIP PostgreSQL Sharding
PostgreSQL数据库FDW——Parquet S3 Foreign Data Wrapper
PostgreSQL数据库FDW——Parquet S3 ParquetReader类
PostgreSQL数据库FDW——Parquet S3 ReaderCacheEntry
PostgreSQL数据库FDW——Parquet S3 ParallelCoordinator
PostgreSQL数据库FDW——Parquet S3 DefaultParquetReader类
PostgreSQL数据库FDW——Parquet S3 CachingParquetReader类
PostgreSQL数据库FDW——Parquet S3 ParquetS3FdwExecutionState类
PostgreSQL数据库FDW——Parquet S3 MultifileMergeExecutionStateBaseS3类
PostgreSQL数据库FDW——Parquet S3 读取parquet文件用例
PostgreSQL数据库使用——between and以及日期的使用
PostgreSQL数据库使用——iRedMail定时备份数据库脚本
PostgreSQL数据库使用——iRedMail初始化数据库脚本
PostgreSQL数据库使用——iRedMail创建用户脚本
PostgreSQL数据库插件——定时任务pg_cron
PostgreSQL数据库故障分析——invalid byte sequence for encoding
ETCD、Zookeeper和Consul 分布式数据库的魔法银弹
PostgreSQL数据库高可用——patroni介绍[翻译]
PostgreSQL数据库高可用——patroni配置[翻译]
PostgreSQL数据库高可用——patroni REST API[翻译]
PostgreSQL数据库高可用——将独立集群转换为Patroni集群[翻译]
PostgreSQL数据库高可用——patroni源码学习
PostgreSQL数据库高可用——patroni源码学习——abstract_main
PostgreSQL数据库高可用——patroni源码AbstractPatroniDaemon类
PostgreSQL数据库高可用——patroni源码Patroni子类简介
PostgreSQL数据库高可用——patroni源码PatroniLogger类
PostgreSQL数据库高可用——patroni RestApiServer
PostgreSQL数据库高可用——patroni源码DCS类
PostgreSQL数据库高可用——patroni源码AbstractEtcd类
PostgreSQL数据库高可用——patroni源码EtcdClient类
PostgreSQL数据库高可用——patroni源码Etcd
PostgreSQL数据库高可用——patroni源码学习——Ha类概述
PostgreSQL数据库高可用——Patroni AsyncExecutor类
PostgreSQL数据库高可用——Patroni PostmasterProcess类
PostgreSQL数据库备份恢复迁移——Barman Before you start[翻译]
PostgreSQL数据库备份恢复迁移——Barman Introduction[翻译]
Postgres-XL数据库GTM——概念
Postgres-XL数据库GTM——事务管理
Postgres-XL数据库GTM——GTM and Global Transaction Management[翻译]
Postgres-XL数据库GTM——Master & Standby启动流程
Postgres-XL数据库GTM——Master & Standby子线程
Postgres-XL数据库GTM——Node管理器
Greenplum数据库统计信息——analyze命令 Greenplum数据库统计信息——分布式采样 Greenplum数据库统计信息——auto-analyze特性 Greenplum数据库Hash分布——计算哈希值和映射segment Greenplum数据库Hash分布——GUC gp_use_legacy_hashops Greenplum数据库数据分片策略Hash分布——执行器行为 Greenplum数据库过滤投影——ExecScan执行逻辑 Greenplum数据库外部表——Scan执行节点 Greenplum数据库外部表——fileam封装 Greenplum数据库外部表——external_getnext获取元组 Greenplum数据库外部表——url_curl创建销毁 Greenplum数据库外部协议——Define EXTPROTOCOL Greenplum数据库外部协议——GPHDFS实现协议 Greenplum数据库外部协议——GPHDFS gphdfs_fopen HashData数据库外部表——GPHDFS实现简介 Greenplum数据库高可用——FTS进程 Greenplum数据库高可用——FTS进程ftsConnect Greenplum数据库高可用——FTS进程触发轮询 Greenplum数据库高可用——FTS进程ftsPoll\Send\Receive Greenplum数据库高可用——FTS Pull模型 Greenplum数据库高可用——FTS HandleFtsWalRepProbe函数 Greenplum数据库高可用——FTS HandleFtsWalRepSyncRepOff函数 Greenplum数据库高可用——FTS HandleFtsWalRepPromote函数 Greenplum数据库高可用——FTS processRetry函数 Greenplum数据库高可用——FTS processResponse函数 Greenplum数据库高可用——FTS updateConfiguration更新系统表 Greenplum Python专用库gppylib学习——logging模块 Greenplum Python专用库gppylib学习——GpArray
Greenplum Python专用库gppylib学习——base.py
Greenplum Python工具库gpload学习——gpload类
Greenplum数据库源码分析——Standby Master操作工具分析
Greenplum数据库故障分析——利用GDB调试多线程core文件
Greenplum数据库故障分析——semop(id=,num=11) failed:invalid argument
Greenplum数据库故障分析——能对数据库base文件夹进行软连接嘛
Greenplum数据库故障分析——UDP Packet Lost(packet reassembles failed)
Greenplum数据库故障分析——版本升级后gpstart -a为何返回失败
Greenplum数据库故障分析——can not listen port
HAWQ数据库技术解析——内部架构
HAWQ数据库技术解析——filesystem interface
HAWQ数据库技术解析——HDFS filesystem
HAWQ数据库技术解析(一)——HAWQ简介[转载]