有人从MySQL改用PG,用户表大概这么个结构
CREATE TABLE "user"(
userid int,
username text,
...
)
不加双引号是不可以的,USER是保留关键字。
猜测建表用的是某种GUI工具,自动给表名加双引号,所以创建是没有问题的。
通过JDBC运行SQL:SELECT * FROM user;
然后 rs.getString(2) 试图取出用户名,被告知超过列数范围。直到注意到这个表名叫user,问题才得以解决。
我们来试试,两种方式都是可以的
flying=# select user;
user
--------
quanzl
(1 row)
flying=# select * from user;
user
--------
quanzl
(1 row)
user是个什么语法元素?既能出现在target列表看起来是个伪列,又能出现在FROM列表看起来是个返回结果集的伪表(这个词我自己发明的)。前者容易理解,我们看看后者。
from_clause:
FROM from_list { $$ = $2; }
| /*EMPTY*/ { $$ = NIL; }
;
from_list:
table_ref { $$ = list_make1($1); }
| from_list ',' table_ref { $$ = lappend($1, $3); }
;
这是FROM子句的语法定义,其中 table_ref 的部分定义
| func_table func_alias_clause
{
RangeFunction *n = (RangeFunction *) $1;
n->alias = linitial($2);
n->coldeflist = lsecond($2);
$$ = (Node *) n;
}
func_table定义
func_table: func_expr_windowless opt_ordinality
func_expr_windowless定义
func_expr_windowless:
func_application { $$ = $1; }
| func_expr_common_subexpr { $$ = $1; }
;
在func_expr_common_subexpr语法结构里
| USER
{
$$ = makeSQLValueFunction(SVFOP_USER, -1, @1);
}
FROM user 就是这么来的。
这里能看到的只是语法部分,后续语法还要翻译为词法,又是一番操作,有哪天兴趣来了继续翻代码。