PostgreSQL子查询别名改造(兼容Oracle)

在PostgreSQL中子查询必须得加上别名,即使我们在其它地方不会再引用到这个别名。
否则便会报以下错误:

postgres=# select * from (select * from t1 limit 5);
ERROR:  subquery in FROM must have an alias
LINE 1: select * from (select * from t1 limit 5);
                      ^
HINT:  For example, FROM (SELECT ...) [AS] foo.

而在Oracle中是可以不加别名的,例如:

SQL> select * from (select * from t1);

        ID
----------
         1

当然并不是说这样不好,因为PG中的这种语法是SQL标准语法,但对于某些从Oracle迁移的用户而言,可能会存在一些困扰,那么我们来看看如何从内核层面去实现兼容呢?

首先需要知道,我们输入的SQL语句是作为字符串传递给查询分析器,然后数据库对其进行词法分析和语法分析生成分析树。
而在PG中,词法分析和语法分析依赖的文件是scan.l和gram.y中。通过scan.l进行词法分析,将sql中的关键字识别,作为token传递给语法分析器,而gram.y对传入的token定义语法,并进行语法分析,从而生成parsetree。

我们根据前面的报错,找到gram.y中对应的部分:

| select_with_parens opt_alias_clause
	{
   
		RangeSubselect *n = makeNode(RangeSubselect);
		n->lateral = false;
		n->subquery = $1;
		n->alias = $2;
		/*
		 * The SQL spec does not permit a subselect
		 * (<derived_table>) without an alias clause,
		 * so we don't either.  This avoids the problem
		 * of needing to invent a unique refname for it.
		 * That could be surmounted if there's sufficient
		 * popular demand, but for now let's just implement
		 * the spec and see if anyone complains.
		 * However, it does seem like a good idea to emit
		 * an error message that's better than "syntax error".
		 */
		
		if ($2 == NULL)
		{
   
			if (IsA($1, SelectStmt) &&
				((SelectStmt *) $1)->valuesLists)
				ereport(ERROR,
						(errcode
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值