1/26 (木)
[MyWeb][PostgreSQL] PostgreSQL のコーディングスタイル
PostgreSQL のコーディングスタイルの記事を書いた。 PostgreSQL エクステンションを作成する上でのコーディングスタイルをメモして置く。
1/21 (土)
[Movie] 沈黙 -サイレンス-
6 ポイント溜まって無料鑑賞が可能になったので川崎 TOHO シネマズで『沈黙 - サイレンス -』を観る。
[Movie] 君の名は。の IMAX
109 シネマズで『君の名は。』の IMAX 上映を観る。
通常版と比べると、確かに細部がくっきりしているような気がするが、極端に印象が違うシーンはなかった。
[Food] Eggs'n Things@ラゾーナ川崎
ラゾーナ川崎の Eggs'n Thinks でご飯を食べる。 前回(2016年2月13日)はガーリックシュリンプを頼んで後悔したので、今回はオムレツとアサイーボールを食べてみる。
1/17 (火)
[PostgreSQL] 2つのテーブルの比較
PostgreSQL でプランの最適化ルーチンを書いていると、最適化前と最適化後の結果が等しいことを確認したいことがある。
その場合、SELECT INTO
で結果を一時テーブルに書き込んでおいて後で比較したいが、これが結構難しい。
仮に最適化前と最適化後の結果をそれぞれ T1 と T2 という一時テーブルに格納したとすると、T1 と T2 のどちらかにしかない行を表示できるようにしたい。 最適化によってテーブル内の行の並び順を変えるのはありなので、テーブルを最初から最後まで逐次検査することはできないし、同じ内容の行が複数あったとしても何行あるかが異なればそれは違う結果となる。
とりあえず適当なテーブルを作ってみる。
CREATE TABLE T1 (C1 TEXT, C2 CHAR(10), C3 VARCHAR, C4 VARCHAR(10)); CREATE TABLE T2 (C1 TEXT, C2 CHAR(10), C3 VARCHAR, C4 VARCHAR(10)); INSERT INTO T1 (C1, C2, C3, C4) VALUES ('D', 'C', 'B', 'A'), ('a', 'b', 'c', 'd'), ('A', 'B', 'C', 'D'); INSERT INTO T2 (C1, C2, C3, C4) VALUES ('a', 'b', 'c', 'd'), ('d', 'c', 'b', 'a'), ('D', 'C', 'B', 'A');
まず比較用 SQL クエリーとして以下のような奴を考えてみる。 T1 テーブルの各行を読み込みそれを ROW 演算子でまとめ +1 の列を付加する。 T2 テーブルは同様に -1 する。 ROW 演算子でまとめたテーブルの行を GROUP BY し、+1 と -1 の SUM で集約する。 もし SUM の結果が 0 以外であれば結果は異なっていることになる。
SELECT K, SUM(V) FROM (SELECT +1 AS V, ROW(T1.*) AS K FROM T1 UNION ALL SELECT -1 AS V, ROW(T2.*) AS K FROM T2) AS T GROUP BY K HAVING SUM(V) >< 0;
結果行は見辛いが重複行のカウントができる。
k | sum ----------------------+----- (A,"B ",C,D) | 1 (d,"c ",b,a) | -1 (2 rows)
もっと簡単なのは EXCEPT ALL と UNION ALL を使って、T1 にあって T2 にない行と、T2 にあて T1 にない行をまとめる方法か。
SELECT T1.*, 'only T1' AS x FROM T1 EXCEPT ALL SELECT T2.*, 'only T1' AS x FROM T2 UNION ALL SELECT T2.*, 'only T2' AS x FROM T2 EXCEPT ALL SELECT T1.*, 'only T2' AS x FROM T1;
結果行はこちらの方が見易いが、重複行 2 行以上あると行数分表示されることになる。
c1 | c2 | c3 | c4 | x ----+------------+----+----+--------- A | B | C | D | only T1 d | c | b | a | only T2 (2 rows)
1/7 (土)
[Movie] 傷物語
『傷物語』の3部作の最後の冷血篇が封切られた。 川崎はTOHOシネマズでのみ上映なのでTOHOで観る。 1作目の熱血篇は2016年1月10日、2作目の鉄血篇は2016年8月20日に観た。
[PostgreSQL] PostgreSQL の bool 型と stdbool.h のヘッダーとの bool 型が衝突
PostgreSQL の C 言語で書かれているが、C89 の標準で利用可能な言語機能のみを使うことという制限がある。 これは PostgreSQL のエクステンション作成する場合も同様で、例えばブロックの真ん中で変数を定義すると ISO C90 forbids mixed declarations and code の警告をとられたりする。
一方、PostgreSQL は typedef char bool;
と定義しているので、C++ のように bool 型と true/false を使うことができる。
ところがこの PostgreSQL とMongoDB を混ぜたエクステンションを作成しようとしたら問題が発生。
Linux + gcc 環境でコンパイルすると passing argument 2 of ‘expression_tree_walker’ from incompatible pointer type /home/nminoru/pgsql-9.5.4/include/server/nodes/nodeFuncs.h:43: note: expected ‘bool (*)()’ but argument is of type ‘_Bool (*)(struct Node *, void *)’ のような警告が大量に発生する。
MongoDB へのアクセスを行うため MongoDB C Driver のインクルードファイルを取り込んだのだが、その中でさらに stdbool.h がインクルードされている。
stdbool.h は、その中で #define bool _Bool
を定義しているので、bool が上書きされたのだ。
コンパイラの警告があまりに大量に出すぎて、他の警告が埋もれて見つけることができない。
トホホ。
結局、これはヘッダーの順番を変えることで干渉を避けるようにできた。 PostgreSQL のルールでは、バックエンドモジュール(.c ファイル)の先頭に postgres.h をインクルードすることになっている。 しかしこのルールを破り、先に MongoDB C Driver のヘッダーを読み込むことにする。
/* PostgreSQL ヘッダーを読み込む前に MongoDB C Driver のヘッダーをインクルードする */ #include <bson.h> #include <mongoc.h> #include "postgres.h" #include "catalog/pg_type.h" ...
あるいは stdbool.h を先に読み込む。
/* PostgreSQL ヘッダーを読み込む前に stdbool.h をインクルードする */ #include <stdbool.h> #include "postgres.h" #include "catalog/pg_type.h" ... #include <bson.h> #include <mongoc.h>
実際は bool が char ではなく _Bool になるので、PostgreSQL のライブラリのビルド時の型と別の型でリンクすることになる。 ただし C 言語はリンク情報にデータ型を持っていないし、char と _Bool は同じバイト数で不整合なく読み書きできるので動いている。 C 言語が大雑把な扱いで助かった例だ。 他のプログラミング言語ではこうはいかない。
1/2 (月)
渋谷で買い物
お正月の渋谷を散策。 ビックカメラでノートパソコン用のケースを、サカゼンでブルゾンを購入する。
年賀状を書いた
筆王ZEROを使っていたのだが、自宅パソコンを一時的に Windows 10 にした前後から動作しなくなった。 しょうがないので筆王 Ver.21 を購入して年賀状を書いてネットプリンティングする。
1/1 (日)
謹賀新年
明けましておめでとうございます。 今年もよろしくおねがいします。
閏秒が挿入
Linux カーネルのログに閏秒の跡が残っていた。
Dec 31 09:52:13 centos7 chronyd[724]: System clock status set to insert leap second Jan 1 08:59:59 centos7 kernel: Clock: inserting leap second 23:59:60 UTC Jan 1 09:00:01 centos7 chronyd[724]: System clock status set to not insert/delete leap second