psqlコマンドのEast Asian Ambiguous Width文字の幅を全角にする

# はじめに

筆者の環境は

- macOS Ventura 13.3.1
- psql 15.3
- iTerm2
    - 設定で `Ambiguous characters are double-width` にチェック

であり、psqlコマンドの出力中に `◯` `★` `→` といったEast Asian Ambiguous Width文字があると表示がずれていた。

[Macのターミナルで全角記号を綺麗に表示したかった - Qiita](https://qiita.com/seto-r/items/706d2c4d795dba7d42ed)
によると、

- 解決策2: Ambiguous の適応範囲を強引に書き換えて全角表記にする
- 解決策3: Ambiguous 文字を半角で表示するフォントを使う

という解決策があるようだが、2はSIPを無効にしてもファイルシステムがread onlyのため断念。3は、やはり本当は全角で表示したいのと、フォントを変えるのにも軽い抵抗があって見送り。

まあ、大した問題でもないので放置しても良いのだが、技術的興味からpsqlコマンドのソースコードをいじって対応できないか調べてみた。

これが正しい方法なのか分からないが、今のところちゃんと動いている。本記事はその記録である。

before:
![スクリーンショット 2023-06-05 21.34.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79394/7504a02b-2573-d29f-189d-8b0eb552cf20.png)

after:
![スクリーンショット 2023-06-05 21.34.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79394/f67c4b93-984c-2ca4-a0a0-3f6cdcaa8dbe.png)

# 修正方法

https://www.postgresql.org/ftp/source/v15.3/ から `postgresql-15.3.tar.bz2` をダウンロード。
（https://github.com/postgres/postgres にgitリポジトリがあるが、`INSTALL` ファイルが入っていなかったり、 `./configure` が通らなかったので配布版をダウンロード）

```console
$ tar xf postgresql-15.3.tar.bz2
$ cd postgresql-15.3
$ ./configure --prefix=/usr/local/pgsql
$ vi src/common/unicode/generate-unicode_east_asian_fw_table.pl
# ここで上記ファイルを下記diffのように変更
```

`A` （曖昧）の文字幅を `F` や `W` と同じく2にする。

```diff
--- generate-unicode_east_asian_fw_table.pl.orig    2023-06-05 21:25:10.121372085 +0900
+++ generate-unicode_east_asian_fw_table.pl 2023-06-05 21:25:21.141461036 +0900
@@ -36,7 +36,7 @@

    ($first, $last) = map(hex, ($first, $last));

-   if ($width eq 'F' || $width eq 'W')
+   if ($width eq 'F' || $width eq 'W' || $width eq 'A')
    {
        # fullwidth/wide characters
        if (!defined($range_start))
```

続けて下記実行。

```console
$ make -C src/common/unicode/ unicode_east_asian_fw_table.h
$ cp ./src/common/unicode/unicode_east_asian_fw_table.h ./src/include/common/unicode_east_asian_fw_table.h
$ make
$ sudo make install
```

インストールされたpsqlを実行：

```console
$ /usr/local/pgsql/bin/psql
```

曖昧幅文字が表示されるようなクエリを実行して確認:
```
postgres=# WITH t (name, age) AS (VALUES ('◯yamda', 1), ('tan', 2))  SELECT * FROM t;
```

# おわりに
psqlはlibcの `wcwidth` を使わず、独自に文字幅テーブルを持っていたようだ。
これでは「解決策2」のシステムロケールを書き換える方法では対応できないはず。
また、本記事の方法はLinuxでも有効なはずである。

# 追記： PostgreSQL 16.0対応

`postgresql-16.0.tar.bz2` を同様にビルドしようとしたところ、configureが下記エラーとなった。

```
checking for pkg-config... /usr/local/bin/pkg-config
checking pkg-config is at least version 0.9.0... yes
checking allow thread-safe client libraries... yes
checking whether to build with ICU support... yes
checking for icu-uc icu-i18n... no
configure: error: ICU library not found
If you have ICU already installed, see config.log for details on the
failure.  It is possible the compiler isn't looking in the proper directory.
Use --without-icu to disable ICU support.
```

homebrewでicu4cは入っているはずだったので、INSTALLの通り下記のように指定したら成功した。
```console
$ ICU_CFLAGS='-I/usr/local/opt/icu4c/include' ICU_LIBS='-L/usr/local/opt/icu4c/lib -licui18n -licuuc -licudata' ./configure --prefix=/usr/local/pgsql && make
```

その後`brew info icu4c`を見たら
```
For pkg-config to find icu4c you may need to set:
  export PKG_CONFIG_PATH="/usr/local/opt/icu4c/lib/pkgconfig"
```
と出てきたので、これでも良かったかもしれない。