先日、ブログ移行時に下書き状態にしていた記事を復元しました。その中の一つ。
PostgreSQLのdate型に挿入できるフォーマット - Log
2020/02//03
がエラーにならなかった。試しに2020/02/////////////////03
とかやってもいけた。気になる。
なんとこれが記事の全文です。Twitterでやれ。
さて、この結果だけを見ると区切り文字はなんでもいいのかと思えます。ちょっと試してみる。
2023$03$18
: OK2023||||||||||03|18
: OK2023a03a18
: NG2023🥺03🥺18
: NG
それらしき文字で区切られていればいいみたいですね。
それらしき文字?ふわふわなのでソースを取得して真相を確かめます。*1
wget https://ftp.postgresql.org/pub/source/v15.2/postgresql-15.2.tar.gz
gitリポジトリを含めると時間がかかるためソースのみ取得します。Chromiumをビルドをしたときから進歩しました。その際に、私のPCではデカいプロジェクトのビルドに耐えられないことに気付いたので今回はビルドしません。手元でコード見るだけ。不要なビルドを減らしてSDGs。
src/backend/utils/adt/datetime.cのParseDateTime
あたりがそれっぽい。
/* ParseDateTime() * Break string into tokens based on a date/time context. * Returns 0 if successful, DTERR code if bogus input detected.
これは解説記事ではないので処理が気になれば自分で読んでください。
処理を読み進めていきます。
/* Ignore spaces between fields */ if (isspace((unsigned char) *cp)) { cp++; continue; }
/* date field? allow embedded text month */ else if (*cp == '-' || *cp == '/' || *cp == '.') { /* save delimiting character to use later */ char delim = *cp;
/* ignore other punctuation but use as delimiter */ else if (ispunct((unsigned char) *cp)) { cp++; continue; }
ispunct()
〜〜。彼が区切り文字の番人のようでした。*2
ispunct | Programming Place Plus C言語編 標準ライブラリのリファレンス
実はPostgreSQLの正規表現でpunt
という文字クラスを利用できます。
SELECT '$' ~ '[[:punct:]]'; -- TRUE SELECT 'a' ~ '[[:punct:]]'; -- FALSE SELECT '🥺' ~ '[[:punct:]]'; -- FALSE
いつでもSQLでpunct
な文字を確認できますね。
ParseDateTime()
の処理に話を戻します。
punct
以外にも空白はスキップすること、-
/
.
などの真っ当なdate型の区切り文字は特別であることも分かります。後者はこんな簡単な話ではありませんが、要は$
などとは処理が異なってややこしいということです。これらを除けばpunct
である文字はスキップしているだけなので、異なる文字でも問題ないことが分かります。
2023|||||||03$18
: OK} 2023 |^|%| || 03$||18
: OK
3年前より理解は進んでいたのでここらで引き上げます。C言語を読めるとQOL爆増するだろうなと思いました。SQL生活のビタミンC。