目录结构
注:提前言明 本文借鉴了以下博主、书籍或网站的内容,其列表如下:
PostgreSQL数据库 psql获取环境变量的元命令\getenv

文章快速说明索引
学习目标:
做数据库内核开发久了就会有一种 少年得志,年少轻狂 的错觉,然鹅细细一品觉得自己其实不算特别优秀 远远没有达到自己想要的。也许光鲜的表面掩盖了空洞的内在,每每想到于此,皆有夜半临渊如履薄冰之感。为了睡上几个踏实觉,即日起 暂缓其他基于PostgreSQL数据库的兼容功能开发,近段时间 将着重于学习分享Postgres的基础知识和实践内幕。
备注1:
遇一本好书,很难得
读一本好书,很重要
我给大家推荐一本书:《PostgreSQL指南:内幕探索》,点击前往
学习内容:(详见目录)
1、PostgreSQL数据库 psql获取环境变量的元命令\getenv
的实现
学习时间:
2022年03月20日 16:46:28
学习产出:
1、PostgreSQL数据库基础知识回顾 1个
2、CSDN 技术博客 1篇
3、PostgreSQL数据库内核深入学习
注:下面我们所有的学习环境是Centos7+PostgreSQL14.2+Oracle11g+MySQL8.0
postgres=# select version();
version
-----------------------------------------------------------------------------
PostgreSQL 14.2 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 7.1.0, 64-bit
(1 row)
postgres=#
#-----------------------------------------------------------------------------#
SQL> select * from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
CORE 11.2.0.1.0 Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production
SQL>
#-----------------------------------------------------------------------------#
mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.27 |
+-----------+
1 row in set (0.06 sec)
mysql>
问题描述背景说明
在开始之前,先来看一下现在的PostgreSQL数据库里面 psql 工具所支持的元命令:
postgres=# select version();
version
--------------------------------------------------------------------------------------------------------
PostgreSQL 14.2 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 8.5.0 20210514 (Red Hat 8.5.0-4), 64-bit
(1 row)
postgres=# \?
General
\copyright show PostgreSQL usage and distribution terms
\crosstabview [COLUMNS] execute query and display results in crosstab
\errverbose show most recent error message at maximum verbosity
\g [(OPTIONS)] [FILE] execute query (and send results to file or |pipe);
\g with no arguments is equivalent to a semicolon
\gdesc describe result of query, without executing it
\gexec execute query, then execute each value in its result
\gset [PREFIX] execute query and store results in psql variables
\gx [(OPTIONS)] [FILE] as \g, but forces expanded output mode
\q quit psql
\watch [SEC] execute query every SEC seconds
Help
\? [commands] show help on backslash commands
\? options show help on psql command-line options
\? variables show help on special variables
\h [NAME] help on syntax of SQL commands, * for all commands
Query Buffer
\e [FILE] [LINE] edit the query buffer (or file) with external editor
\ef [FUNCNAME [LINE]] edit function definition with external editor
\ev [VIEWNAME [LINE]] edit view definition with external editor
\p show the contents of the query buffer
\r reset (clear) the query buffer
\s [FILE] display history or save it to file
\w FILE write query buffer to file
Input/Output
\copy ... perform SQL COPY with data stream to the client host
\echo [-n] [STRING] write string to standard output (-n for no newline)
\i FILE execute commands from file
\ir FILE as \i, but relative to location of current script
\o [FILE] send all query results to file or |pipe
\qecho [-n] [STRING] write string to \o output stream (-n for no newline)
\warn [-n] [STRING] write string to standard error (-n for no newline)
Conditional
\if EXPR begin conditional block
\elif EXPR alternative within current conditional block
\else final alternative within current conditional block
\endif end conditional block
Informational
(options: S = show system objects, + = additional detail)
\d[S+] list tables, views, and sequences
\d[S+] NAME describe table, view, sequence, or index
\da[S] [PATTERN] list aggregates
\dA[+] [PATTERN] list access methods
\dAc[+] [AMPTRN [TYPEPTRN]] list operator classes
\dAf[+] [AMPTRN [TYPEPTRN]] list operator families
\dAo[+] [AMPTRN [OPFPTRN]] list operators of operator families
\dAp[+] [AMPTRN [OPFPTRN]] list support functions of operator families
\db[+] [PATTERN] list tablespaces
\dc[S+] [PATTERN] list conversions
\dC[+] [PATTERN] list casts
\dd[S] [PATTERN] show object descriptions not displayed elsewhere
\dD[S+] [PATTERN] list domains
\ddp [PATTERN] list default privileges
\dE[S+] [PATTERN] list foreign tables
\des[+] [PATTERN] list foreign servers
\det[+] [PATTERN] list foreign tables
\deu[+] [PATTERN] list user mappings
\dew[+] [PATTERN] list foreign-data wrappers
\df[anptw][S+] [FUNCPTRN [TYPEPTRN ...]]
list [only agg/normal/procedure/trigger/window] functions
\dF[+] [PATTERN] list text search configurations
\dFd[+] [PATTERN] list text search dictionaries
\dFp[+] [PATTERN] list text search parsers
\dFt[+] [PATTERN] list text search templates
\dg[S+] [PATTERN] list roles
\di[S+] [PATTERN] list indexes
\dl list large objects, same as \lo_list
\dL[S+] [PATTERN] list procedural languages
\dm[S+] [PATTERN] list materialized views
\dn[S+] [PATTERN] list schemas
\do[S+] [OPPTRN [TYPEPTRN [TYPEPTRN]]]
list operators
\dO[S+] [PATTERN] list collations
\dp [PATTERN] list table, view, and sequence access privileges
\dP[itn+] [PATTERN] list [only index/table] partitioned relations [n=nested]
\drds [ROLEPTRN [DBPTRN]] list per-database role settings
\dRp[+] [PATTERN] list replication publications
\dRs[+] [PATTERN] list replication subscriptions
\ds[S+] [PATTERN] list sequences
\dt[S+] [PATTERN] list tables
\dT[S+] [PATTERN] list data types
\du[S+] [PATTERN] list roles
\dv[S+] [PATTERN] list views
\dx[+] [PATTERN] list extensions
\dX [PATTERN] list extended statistics
\dy[+] [PATTERN] list event triggers
\l[+] [PATTERN] list databases
\sf[+] FUNCNAME show a function's definition
\sv[+] VIEWNAME show a view's definition
\z [PATTERN] same as \dp
Formatting
\a toggle between unaligned and aligned output mode
\C [STRING] set table title, or unset if none
\f [STRING] show or set field separator for unaligned query output
\H toggle HTML output mode (currently off)
\pset [NAME [VALUE]] set table output option
(border|columns|csv_fieldsep|expanded|fieldsep|
fieldsep_zero|footer|format|linestyle|null|
numericlocale|pager|pager_min_lines|recordsep|
recordsep_zero|tableattr|title|tuples_only|
unicode_border_linestyle|unicode_column_linestyle|
unicode_header_linestyle)
\t [on|off] show only rows (currently off)
\T [STRING] set HTML <table> tag attributes, or unset if none
\x [on|off|auto] toggle expanded output (currently off)
Connection
\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}
connect to new database (currently "postgres")
\conninfo display information about current connection
\encoding [ENCODING] show or set client encoding
\password [USERNAME] securely change the password for a user
Operating System
\cd [DIR] change the current working directory
\setenv NAME [VALUE] set or unset environment variable
\timing [on|off] toggle timing of commands (currently off)
\! [COMMAND] execute command in shell or start interactive shell
Variables
\prompt [TEXT] NAME prompt user to set internal variable
\set [NAME [VALUE]] set internal variable, or list all if no parameters
\unset NAME unset (delete) internal variable
Large Objects
\lo_export LOBOID FILE
\lo_import FILE [COMMENT]
\lo_list
\lo_unlink LOBOID large object operations
postgres=#
OK,我们这里着重看一下这一行:
\setenv NAME [VALUE] set or unset environment variable
使用如下:
postgres=#
postgres=# \setenv ONE 1
postgres=#
那怎么看一下 当前操作系统的环境变量 和 \setenv
设置的环境变量呢?
暂时并没有什么好的办法可以直接去查看,其实 这里也很奇怪,既然有 \setenv
,怎么没有元命令: \getenv
?
设计实现思路说明
我们此次的开发需求,大致如下:
- 实现
\getenv
元命令 - 可以获取 当前操作系统的环境变量 和
\setenv
设置的环境变量 - 直接打印在 bash 端即可
- 完善 psql 工具的相关汉化
- …
稍微分析一下,元命令调用如下:
// src/bin/psql/command.c
HandleSlashCmds
|
exec_command
|
exec_command_setenv
/*
* \setenv -- set environment variable
*/
static backslashResult
exec_command_setenv(PsqlScanState scan_state, bool active_branch,
const char *cmd)
{
bool success = true;
if (active_branch)
{
char *envvar = psql_scan_slash_option(scan_state,
OT_NORMAL, NULL, false);
char *envval = psql_scan_slash_option(scan_state,
OT_NORMAL, NULL, false);
if (!envvar)
{
pg_log_error("\\%s: missing required argument", cmd);
success = false;
}
else if (strchr(envvar, '=') != NULL)
{
pg_log_error("\\%s: environment variable name must not contain \"=\"",
cmd);
success = false;
}
else if (!envval)
{
/* No argument - unset the environment variable */
unsetenv(envvar);
success = true;
}
else
{
/* Set variable to the value of the next argument */
setenv(envvar, envval, 1);
success = true;
}
free(envvar);
free(envval);
}
else
ignore_slash_options(scan_state);
return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
}
内部再行调用的是下面这两个函数:
而最后实际工作的函数为系统库函数:
// /usr/include/stdlib.h
#if defined __USE_SVID || defined __USE_XOPEN
/* The SVID says this is in <stdio.h>, but this seems a better place. */
/* Put STRING, which is of the form "NAME=VALUE", in the environment.
If there is no `=', remove NAME from the environment. */
extern int putenv (char *__string) __THROW __nonnull ((1));
#endif
因为同时存在库函数getenv
,如下:
__BEGIN_NAMESPACE_STD
/* Return the value of envariable NAME, or NULL if it doesn't exist. */
extern char *getenv (const char *__name) __THROW __nonnull ((1)) __wur;
__END_NAMESPACE_STD
因此我们就可以直接利用该函数进行开发元命令!
注:这个做起来实在是太过简单,具体实现思路就不再说了!有兴趣的小伙伴们可以自行前去开发!
功能实现结果测试
postgres=# select version();
version
-----------------------------------------------------------------------------
PostgreSQL 14.2 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 7.1.0, 64-bit
(1 row)
postgres=# \getenv LANG
en_US.UTF-8
postgres=#
postgres=# \getenv LC_ALL
postgres=#
postgres=# \setenv ONE 1
postgres=#
postgres=# \getenv ONE
1
postgres=#
postgres=# \setenv ONE
postgres=#
postgres=# \getenv ONE
postgres=#
postgres=#
注:这一块内容可以参见我的好哥们的博客:PostgreSQL数据库之国际化语言支持学习总结,点击前往 和 我之前的博客:PostgreSQL的学习心得和知识总结(十三)|数据库配置参数说明,点击前往
第一步,重新进行configure,如下:
[postgres@localhost postgres]$ ./configure --prefix=/home/postgres/test --enable-debug --enable-nls="zh_CN"
第二步,翻译并重新编译
第三步,配置中文环境 并重新初始化,如下:
[postgres@localhost bin]$ echo $LANG
zh_CN.UTF-8
[postgres@localhost bin]$ echo $LC_ALL
zh_CN.UTF-8
[postgres@localhost bin]$
注:后面 我会上传资源patch,有兴趣的小伙伴们可以自行前去开发!