NAKAMURA Minoru の日記 (2020年02月)

先月の日記(2020年01月) 今月の日記(2020年02月)
2002 | 10 | 11 | 12
2003 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2004 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2005 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2006 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2007 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2008 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2009 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2010 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2011 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2012 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2013 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2014 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2015 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2016 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2017 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2018 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2019 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2020 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2021 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2022 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2023 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2024 | 1 | 2 | 3 | 4
ホームページ | 最新のコメント50
インデックス: 食べ歩き | Java | プログラム | UNIX | 画像
最新の日記へのリンク | この日記ページをはてなアンテナに追加 この日記ページをはてなブックマークに追加
はてな ダイアリー アンテナ ブックマーク ブログ
Twitter | mixi | Facebook | slideshare | github | Qiita



2/24 (月)

PostgreSQL JDBC で復号型の配列を扱いたいのだが…

PostgreSQL JDBC のドライバーにはいろいろ癖があり、JDBC で定義されている機能の一部をサポートしていない。 ユーザー定義タイプ(User-Defined Type)を扱う java.sql.SQLData がサポートされておらず、PostgreQL の複合型(composite type)を扱うのが非常に難しい。

例えば entity_struct という複合型があるとする。 この配列を作って entity_table テーブルに一度に複数行を挿入することを考える。

CREATE TABLE entity_table (
    guid     uuid      NOT NULL,
    version  bigint    NOT NULL,
    message  text      NOT NULL,
    creation timestamp NOT NULL
);

CREATE TYPE entity_struct AS (
    guid     uuid,
    version  bigint,
    message  text,
    creation timestamp
);

一応、org.postgresql.util.PGobject を介して複合型のオブジェクトを作ることはできるが、その setValue メソッドの値に PostgreSQL のネイティブの複合型のリテラル表現 を入れることになる。 例えば "(9107ffb3-2457-4dc9-8f20-12c645c288fd, 123, 'abc', '2018-03-21 16:00:45.0')" みたいに。

これは全体が文字リテラルの上に、その中の構成要素も型に応じた文字列化が必要なので書くのが非常に複雑だ。 uuid 型や数値型はまだよいが文字列型を入れるにはエスケープシーケンスを二重にかけることになる。 より書きやすい ROW(9107ffb3-2457-4dc9-8f20-12c645c288fd, 123, 'abc', '2018-03-21 16:00:45.0') はここには書けないようだ。

Class.forName("org.postgresql.Driver");

Properties info = new Properties();
info.setProperty("user",     "<user>");
info.setProperty("password", "<password>");

Connection connection;
connection = DriverManager.getConnection("jdbc:postgresql://127.0.0.1:5432/<db>", info);
connection.setAutoCommit(true);

Object[] in = new Object[SIZE];

for (int i = 0 ; i < SIZE ; i++) {
    PGobject cc = new PGobject();

    UUID      uuid      = UUID.randomUUID();
    long      version   = i;
    String    message   = "abc";
    Timestamp timestamp = new Timestamp(new Date().getTime());

    cc.setType("entity_struct");
    cc.setValue(uuid.toString() + "," + String.valeOf(version) + ",'" + message + "','" + timestamp.toString() + "')");

    in[i] = cc;
}

try (PreparedStatement pstmt = connection.prepareStatement(
         "INSERT INTO entity_table (guid, version, message, creation) " +
         "SELECT E.guid, E.version, E.message, E.creation FROM unnest(?::entity_struct[]) E";")) {
    pstmt.setArray(1, connection.createArrayOf("entity_struct", in));

    pstmt.executeUpdate();
}

いろいろ困っていたのだが、無理に JDBC のレベルで複合型にする必要はないと気づいた。 PostgreSQL の場合、SELECT リストに unnest 関数を並べると、配列のインデックスの番号が一致する要素を集めて新しい行を作ることができるので、JDBC 側では複合型の列を別々の配列にして渡せばよい。 単一型の配列ならば通常通りの変換がでできるので、Java の String 型を java.sql.String の配列にする場合、エスケープシーケンスなどは JDBC ドライバー側に任せることができるようになる。

Object[] in1 = new Object[SIZE];
Object[] in2 = new Object[SIZE];
Object[] in3 = new Object[SIZE];
Object[] in4 = new Object[SIZE];

for (int i = 0 ; i < SIZE ; i++) {
    in1[i] = UUID.randomUUID();
    in2[i] = new Long(i);
    in3[i] = "abc";
    in4[i] = new Timestamp(new Date().getTime());
}

try (PreparedStatement pstmt = connection.prepareStatement(
         "INSERT INTO entity_table (guid, version, message, creation) " +
         "SELECT unnest(?::uuid[]), unnest(?::int8[]), unnest(?::text[]), unnest(?::timestamp[])));
    pstmt.setArray(1, connection.createArrayOf("uuid", in1));
    pstmt.setArray(2, connection.createArrayOf("int8", in2));
    pstmt.setArray(3, connection.createArrayOf("message", in3));
    pstmt.setArray(4, connection.createArrayOf("timestamp", in4));

    pstmt.executeUpdate();
}

非常にかっこが悪いが実用的なやり方だ。


2/14 (金)

GitLab CI で Docker で

GitLab CI のジョブコンテナの中から GitLab CI サーバーの Docker デーモンにアクセスする、それも Docker デーモンが TCP ソケットで待ち受けしている所にアクセスしようとする。 この場合、GitLab CI のジョブコンテナから GitLab CI サーバー(ホスト)にアクセスする場合、ホスト側のファイヤーウォールの制限を受けるようだ。

ホストとコンテナは docker0 のネットワークでつながっているので、ここにホストの Docker デーモンのアクセスポートを書く必要がある。

firewall-cmd --permanent --zone=trusted --change-interface=docker0
firewall-cmd --permanent --zone=trusted --add-port=(ポート)/tcp
firewall-cmd --reload

2/9 (日)

通勤中に見かけた変なもの

新丸子駅のプラットフォームには輪切りの羊の銅像がある。 何なのかは全く不明。


2/6 (木)

DNS リゾルバーを設定しないホストでは Kong が異常動作する

Kong を動かすサーバーは DNS リゾルバーを設定していないと動作しない。 127.0.0.1 経由でも Admin API を実行できなくなるためだ。

Kong が DNS を使ってロードバランシングをする機能があり、DNS リゾルバーが設定されていないと異常を検出されてしまうためで、どこにもつながらないローカルに閉じた DNS サーバーであっても、指定されてさいいれば動くようだ。


2/5 (水)

Open Container Initiative コンテナの仕様

Open Container Initiative(OCI) コンテナの仕様を読む。


2/4 (火)

[Java] IOException のメッセージ

Java の IOException クラスの getMessagegetLocalizedMessage が両方とも日本語になることがあるので、気になっていたのだが、これは OS 側の errno のエラー番号とエラーメッセージがそのまま入っていたためだったのね…


先月の日記(2020年01月) 今月の日記(2020年02月)
2002 | 10 | 11 | 12
2003 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2004 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2005 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2006 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2007 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2008 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2009 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2010 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2011 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2012 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2013 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2014 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2015 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2016 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2017 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2018 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2019 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2020 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2021 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2022 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2023 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2024 | 1 | 2 | 3 | 4
ホームページ | 最新のコメント50
インデックス: 食べ歩き | Java | プログラム | UNIX | 画像
最新の日記へのリンク | この日記ページをはてなアンテナに追加 この日記ページをはてなブックマークに追加
はてな ダイアリー アンテナ ブックマーク ブログ
Twitter | mixi | Facebook | slideshare | github | Qiita


Written by NAKAMURA Minoru, Email: nminoru atmark nminoru dot jp, Twitter:@nminoru_jp