この記事はマニア向けの補足記事です。
psql service=prod
みたいな接続先の指定方法があるという話を書きました。
ところでこれこれどう実装されているんでしょう。psqlのコードの中に、service=prod
みたいなコマンドライン引数を解釈するコードがあるんだろうかと思ったけど全然そんなのは見当たらないのです。
psqlのヘルプを見てみましょう。
Usage: psql [OPTION]... [DBNAME [USERNAME]]
もし、psqlに適当な引数を渡すと、それはDBNAME
として解釈されます。
$ psql hello psql: FATAL: database "hello" does not exist
同様に、service=prod
のような文字列をコマンドライン引数として渡した場合も、psql的にはDBNAME
として扱われます。そしてこれを解釈するのはlibpqです。libpqにはデータベースに接続するための関数がいくつかありますが、psqlでは8.3の頃はPQsetdbLogin()
を使っていました(今はPQconnectdbParams()
を使っていますが大体似たような話なので省略します)。
https://www.postgresql.jp/document/11/html/libpq-connect.html#LIBPQ-PQSETDBLOGIN
PGconn *PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions, const char *pgtty, const char *dbName, const char *login, const char *pwd);
dbName内に=記号が含まれる場合、または有効な接続URI接頭辞を持つ場合、PQconnectdbに渡された場合とまったく同じ扱いでconninfo文字列として扱われます。 その後残りのパラメータがPQconnectdbParamsの指定のように適用されます。
つまり、PQsetdbLogin()
の第五引数dbnameにservice=prod
みたいな文字列をわたすことができるということです。そして8.3.0のリリースノートにはこの変更について、psqlの変更としてではなくlibpqの変更として以下のように書いてあります。
E.147.3.16. libpq
Interpret the dbName parameter of PQsetdbLogin() as a conninfo string if it contains an equals sign (Andrew)
- This allows use of conninfo strings in client programs that still use PQsetdbLogin().
いかがでしたか?
今回は8.3.0からpsqlのコマンドのコマンドライン引数にconninfo文字列を渡すことができるようになった変更について調べてみました。そしてその変更はpsqlではなくlibpq側で行われたものだということがわかりました。
最後までお読みいただきありがとうございました!もし気に入っていただけたら5000兆円ください!(テンプレあまりよくわかってない)