SSブログ

Firebird 3.0 の統計処理用の集約関数 [Firebird]

この記事は Firebird Advent Calendar 2016 http://qiita.com/advent-calendar/2016/firebird 13日目のエントリーです

Firebird 3.0 で相関係数・標準偏差とその関連の値を求める関数が実装されました。
公式なドキュメントしては、 Firebird3.0 のリリースノートに説明があるので読んでください。
http://firebirdsql.org/file/documentation/release_notes/html/en/3_0/bk01ch09s05.html#rnfb30-dml-statistical

(PostgreSQLでは歴史的理由で残されている stddev, variance は、Firebird では実装されていませんが)PostgreSQL の統計処理用の集約関数に相当するので、日本語で読みたい場合は、PostgreSQL のリファレンスマニュアルを見るのが良いと思います。
https://www.postgresql.jp/document/9.6/html/functions-aggregate.html#functions-aggregate-statistics-table
ぶっちゃけ、私も、この PostgreSQL の表を参考に実装しました。

今年の Firebird Advent Calendar では、 meijik さんが、
「使い慣れたSQLに潜む実装依存: Firebirdの場合」
というテーマで連続して書かれてますが、標準偏差、分散に関連する関数についても、PostgreSQL で、戻り値の型が
「浮動小数点型の引数ではdouble precision。それ以外ではnumeric 」
となっているところは、Firebird では常に double precision が返ります。

関数の詳細について、日本語で書かれた良いドキュメントないかなーと探したのですが、
標準偏差と分散については Redshift のマニュアルがわかりやすいと思いました。
- http://docs.aws.amazon.com/ja_jp/redshift/latest/dg/r_STDDEV_functions.html
- http://docs.aws.amazon.com/ja_jp/redshift/latest/dg/r_VARIANCE_functions.html
残念ながら、そのほかの関数は Redshift では実装されてないようです
- http://docs.aws.amazon.com/ja_jp/redshift/latest/dg/c_unsupported-postgresql-functions.html

これらの関数について pull request を送ってマージされた話は昨年の Firebird Advent Calendar 2015
http://nakagami.blog.so-net.ne.jp/2015-12-22 に書きました
コメント(0)  トラックバック(0) 
共通テーマ:日記・雑感

Firebird のイベント機能の使い方 [Firebird]

この記事は Firebird Advent Calendar 2016 http://qiita.com/advent-calendar/2016/firebird 9日目のエントリーです

Firebird には Interbase の頃から、「イベント」という機能があります。
トリガーの中で post_event 'イベント名' とすると、
クライアントに、そのイベントが発生したことを通知できる機能です。

もちろん、クライアントライブラリがその機能を持っていなければ
使うことはできませんが、 pyfirebirdsql には、その機能があります。

例えば、 test_table のレコードが削除された時に 'event_d' という
イベントを発生させるトリガーを
CREATE TRIGGER trig_test_delete_event
    FOR test_table AFTER DELETE
AS BEGIN
    post_event 'event_d';
END
のように書きます。

pyfirebirdsql では一度に複数のイベントを待ち受けることができます
例えば、以下の例では event_a, event_b, event_d を待ち受けます

    conn = firebirdsql.connect('server', 'database', 'user', 'password')
    conduit = conn.event_conduit(['event_a', 'event_b', 'event_d'])
    result = conduit.wait()
    print(result)


そして、例えば test_table のデータを2レコード削除するようなクエリーを
delete from test_table; (←2レコードデータ削除されるとすると・・・)

他のクライアント(isqlなど)から実行すると

{'event_b': 0, 'event_a': 0, 'event_d': 2}

と print されます。
つまり、待ち受けていたイベントのどれかがポストされた時
{'イベント名': 発生回数} の辞書形式でデータを受け取ることができます
コメント(0)  トラックバック(0) 
共通テーマ:日記・雑感

pyfirebirdsql 1.0 リリース [Firebird]

この記事は Firebird Advent Calendar 2016 http://qiita.com/advent-calendar/2016/firebird 6日目のエントリーです

私が書き起こしてメンテナンスを続けている pure python の Firebird データーベースドライバー pyfirebirdsql については、一昨年と昨年の Advent Calendar でも言及していました

- http://nakagami.blog.so-net.ne.jp/2014-12-20
- http://nakagami.blog.so-net.ne.jp/2015-12-05

Firebird 3.0 の対応はベータリリースの頃にはできており、もう長いこと機能追加しないままバージョン番号が 0.9.12 になってしまったので思い切って 1.0.0 としてリリースしました。

検索してみたところ、Python mini Hack-a-thon #1 https://atnd.org/events/7474 の時に私が Github & pypi デビューした時がリリースの始まりだったようで http://nakagami.blog.so-net.ne.jp/2010-09-26-1 (ソースの Copyright を見ると、その前年あたりから開発してたっぽい)
version 1.0 のリリースというより、ここまで続けてこれたことと、この時参加した人の何人かが、いま同じ会社にいることが感慨深いです。
コメント(0)  トラックバック(0) 
共通テーマ:日記・雑感

Firebird3.0 の firebird.conf の記述 [Firebird]

この記事は Firebird Advent Calendar 2016 http://qiita.com/advent-calendar/2016/firebird 2日目のエントリーです

Firebird サーバーの設定については、 firebird.conf に記述するようになっていて

- 最初は全部コメントになっていて決まったデフォルト値が有効になっている
- 記述の仕方は firebird.conf にコメントとして記述されている
- Firebird3.0 では、データーベース(ファイル)毎に設定できる項目もできた

となっています。

Firebird 3.0 の Wireprotocol version 13 というバージョンに対応したデーターベースドライバー(クライアントライブラリ)を使えば、デフォルトの(全てコメント状態の) firebird.conf のままで使えますが firebird.conf の設定を適切にすれば、古いドライバーのクライアントアプリケーションから Firebird 3.0 のサーバーに接続することも可能です。

Firebird 3.0 は、以前のバージョンからパフォーマンスダウンにならないように慎重に開発されたようなので、サーバーリプレースの際には Firebird 3.0 にバージョンアップすることを考慮して良いと思います。

以下、古いデーターベースドライバー(アプリケーション)から Firebird3.0 に接続するための設定項目について解説します

[AuthServer]
認証方法。デフォルトでは、 Srp という、サーバーとクライアントが公開鍵を交換しあうことで秘密のセッションキーを取得するプロトコルで認証するようになっています古いクライアントから接続するためには、 Legacy_Auth を設定します

AuthServer = Srp, Legacy_Auth

と記述しておくと、サーバーはまず最初に Srp での認証を試み、クライアントが Srp認証に対応していないと Legacy_Auth で認証するようになります。

[UserManager]
ユーザー管理のデータベースにどの形式を使うかを指定します。
Firebird2.5 までの、セキュリティデーターベース(ログイン情報)をそのまま使う場合、
UserManager=Legacy_UserManager
と設定するようです。
Firebird3.0 のサーバーを新たに立てるなどした場合で、Firebird のデーターベースユーザーをその時新規に作るような場合は特に設定しないで良いと思います
(UserManager=Srp と同等になる)

- 新しいサーバーに Firebird 3.0 をインストールしユーザーを追加
- 古いサーバーから gbak でバックアップして新しいサーバーでリストア

の手順を踏めば UserManage の設定はしなくて良いはずです

[WireCrypt]
通信路を暗号化するかどうかデフォルトでは WireCrypt=Required となっていますが古いドライバーを使うアプリケーションの場合には
WireCrypt=Enable
もしくは
WireCrypt=Disable
とします。
WireCrypt=Enable は、通信経路の暗号化のネゴシエーションがうまくいけば暗号化し、ダメなら平文で通信します。
WireCrypt=Disable ならクライアントが通信経路を暗号化する機能を持っていても常に平文で通信します

[ServerMode]
Firebird2.1 まででは、Super Server と Classic Server が、 Firebird2.5 では、それに加えて SuperClassic というアーキテクチャーの
サーバーがそれぞれ別のバイナリとして提供されていましたが Firebird3.0 からはバイナリは一つになって、 firebird.conf の設定で切り替えるようになりました
Super/SuperClassic/Classic のいずれかを設定できるようです。
「あれ? 前にそうだったんで、 ClassicServer が使いたいんだけど、どこにいったの?」
というような場合に設定してください

ちなみに、古いドライバーだと firebird.conf に AuthServer, WireCrypt あたりを設定すると使えるようになりますが、Firebird 3.0 で実装された boolean 型のデータを select しようとすると(当然ならが)動作しないので、気をつけてください。

2014年の AdventCalendar に書いたエントリーも参考にしてください
http://nakagami.blog.so-net.ne.jp/2014-12-16
コメント(0)  トラックバック(0) 
共通テーマ:日記・雑感

Firebird 3.0 リリース [Firebird]

Firebird 3.0 がついにリリースされた
http://www.firebirdsql.org/en/news/firebird-3-0-is-released/
http://www.firebirdnews.org/firebird-3-is-released/

確か Jim Sterkey が MySQL AB に移籍した時に Firebird プロジェクトに
置き土産として残していったコードが Firebird 3.0 の始まりだったんだと思う。
http://www.itmedia.co.jp/enterprise/articles/0602/24/news031.html
http://www.firebirdnews.org/jim-starkey-joined-mysql-ab/
その時は、(Jim Sterkey がいなくなって先行きは不安だけど) 3.0 はすぐに出るだろうと思っていた。
Jim Sterkey が費やした時間を無視しても、もうあの時からリリースまでに10年以上かかったことになる。

途中、あまりにも時間が空いてしまったので、ということでポイントリリースした 2.5 が出たのですら 2010年10月なので、最後のメジャーリリースから5年半も経ってしまっている。

正直、もう 3.0 は出ないのかもしれないと思った時期もあった。
とにかく 3.0がリリースできたことで、Firebird の開発が盛り返すだろう。
実際、3.0のリリース前に 4.0 の Planning Board が公開されている。
http://www.firebirdsql.org/en/planning-board/
とても、予定通りの Time Schedule で進むとは思えないが、そうは言っても、あと5年も待つということはないだろう(と思いたい)。

3.0は、個人的にも、とても嬉しいリリースになった。
リリースまでに、あまりにも時間がかかり過ぎたおかげで、僕が統計関数の一部のコードを書いて、Release Notes に名前を刻むことができた
http://www.firebirdsql.org/file/documentation/release_notes/html/en/3_0/bk01ch09s05.html#rnfb30-dml-statistical
10年前には、まさか自分が Firebird のコードに Contribute することになろうとは想像すらしなかった。
コメント(0)  トラックバック(0) 
共通テーマ:日記・雑感

Firebird 3.0 の統計関数 [Firebird]

これは Firebird Advent Calendar 2015 の http://qiita.com/advent-calendar/2015/firebird 22 日目の記事です

Firebird3.0 beta2 から統計算数が使えるようになりました。
ここで、統計関数と言っているのはこの表↓の中の stddev, variance 以外の関数のことです。
https://www.postgresql.jp/document/9.4/html/functions-aggregate.html#FUNCTIONS-AGGREGATE-STATISTICS-TABLE
SQL標準で定義されているものですので、当然 Firebird にも必要とされていた機能だと思っていました。
3.0 の alpha1 リリースあたりで、一部の Window 関数は実装されていましたが、上記の統計関数はまだ実装されていませんでした。
「Window 関数の処理を真似をすれば、一連の統計関数も実装できるんじゃね?」
ということを考えていました。

最新の状況を追いかけるために、Firebird をソースからコンパイルするようになって
http://nakagami.blog.so-net.ne.jp/2014-12-17
(Firebird のリポジトリは sourceforge の subversion のものが本物で JIRA で Issue を管理しているのですが)
GitHub のミラーリポジトリにダメもとで初期実装のプルリクエストを送ったらコメントのやりとりの末マージされました。
というわけで残りも段階的にプルリクエストを送って、無事マージされました。
ここらへん↓
https://github.com/FirebirdSQL/core/pull/2
https://github.com/FirebirdSQL/core/pull/3
https://github.com/FirebirdSQL/core/pull/4
初期実装を私がして(pull request して) Adriano dos Santos Fernandes さんが、コードレビュー、マージ、リファクタリングをしました。
リファクタリングによって、内部で管理している blob_id という数値を無駄遣いしなくなったので、良い形になったと思います。
beta2 で、この統計関数がマージされたものがリリースされました。
beta2 → RC1 の間には新機能は追加されていないので、3.0 にギリギリ間に合ったのかな、と思っています。

計算方法は、ここらへんに書いてあるんですが↓
https://github.com/FirebirdSQL/core/blob/master/doc/sql.extensions/README.statistical_functions.txt
https://github.com/FirebirdSQL/core/blob/master/doc/sql.extensions/README.regr_functions.txt
ぶっちゃけ PostgreSQL のドキュメント(もしくは Redshift のドキュメント)を読んだほうがいいです。
これらのなかで、戻り値について、PostgreSQLのドキュメントで
「浮動小数点型の引数ではdouble precision。それ以外ではnumeric」
となっているところは、 Firebird では double precision が返ってくる点が違います。
PostgreSQL の人は標準偏差が decimal で返ってきたら困らないんでしょうか?

Firebird3.0 は(まだ出てないけど)個人的に特別のリリースになりました。
コメント(0)  トラックバック(0) 
共通テーマ:日記・雑感

Jaybird (JDBC ドライバー)の Firebird 3.0 対応 [Firebird]

これは Firebird Advent Calendar 2015 の http://qiita.com/advent-calendar/2015/firebird 20 日目の記事です

Firebird の JDBC ドライバー jaybird の歴史は長く、継続してリリースされていて安定して使えているというイメージです。

ある日、現在 jaybird の開発とメンテナンスをメインでしている Mark Rotteveel さんが firebird-devel の Mailing list で Firebird3 の protocol 13 の変更の詳細について質問していたのを見かけて
http://sourceforge.net/p/firebird/mailman/message/34316685/
「あれ? protocol13 の実装していなかったの?プロトコルの詳細の説明は(英語で)できないけど、実装ならできるかも」
と思いました。

幸い、その頃ソースコードリポジトリが sourceforge の subversion からGitHub に移っていたので
https://github.com/FirebirdSQL/jaybird
(subversion だと使い方も忘れたし、どこにパッチ送っていいかわからないけど、GitHub で pull request なら送れるぞ)
段階を追って pull request 送り、無事マージされました。
https://github.com/FirebirdSQL/jaybird/pull/3
https://github.com/FirebirdSQL/jaybird/pull/4
https://github.com/FirebirdSQL/jaybird/pull/5
https://github.com/FirebirdSQL/jaybird/pull/6

コードを書くことよりも、英語でコードレビューにコメントすることのほうがだいぶ大変でした。
あと、マージする前に
「Software License Agreement のレターにサインして送ってくれ」
と言われ、規定フォーマットのレターにサインしてスキャンしてメールで送り返しました。
そういう、ソースコードに関係ないところのやりとりが英語できない僕には大変でした。

現在は
「master にマージされたけど、そのコードが含まれたバージョンはリリースされていない」
という状態です。
Firebird 3.0 が出た直後ぐらいにはリリースされるかなー、と楽しみにしています。
コメント(0)  トラックバック(0) 
共通テーマ:日記・雑感

私の Firebird 情報源 [Firebird]

これは Firebird Advent Calendar 2015 の http://qiita.com/advent-calendar/2015/firebird 17 日目の記事です

Firebird News http://www.firebirdnews.org
ここは、公式ではないのですが、もう何年もコンスタントに Firebird とその関連情報が更新されていて、私の情報の入手元のほとんどはここです。
Firebird 公式サイト http://www.firebirdsql.org の News も、ほとんどが、この Firebird News で紹介されているので、公式サイトは興味があったニュースの時だけ見たりします。

Mailing List は、この↓リストの中にいろいろあります。
http://www.firebirdsql.org/en/mailing-lists/

その中で Firebird Developpers' Lab は、全部は(英語的にも、内容の難しさ的にも)読めませんが Subject に興味を持った時にスレッドを読んでいます。
流量はそんなに多くないし、Jim Starkey や Dmitry Yemanov が投稿してるのでミーハー気分で subscribe しても良いと思います。
それ以外の Mailing LIst は購読してないのですが、良さそうなのがあったら教えてください。

最近気づいたのですが、
- IBPhoenix の Howto のページ http://www.ibphoenix.com/resources/documents/how_to
- IBSurgeon の記事 http://www.ibsurgeon.com/en/articles/
あたりを読むと役に立ちそうです

一般に知られていませんが、 Firebird のソースコードリポジトリの中の doc ディレクトリの下は、開発に合わせてきちんとメンテナンスされています。
https://github.com/FirebirdSQL/core/tree/master/doc
トピック毎にテキストに分割されているので、いささか読みづらいですが、 BNF のシンタックスと使用例が書かれているので、慣れると読めます。例えば昨日のエントリの説明はこれ↓
https://github.com/FirebirdSQL/core/blob/master/doc/sql.extensions/README.identity_columns.txt

正直あまり Firebird 固有の情報源は少ないんですが、 Firebird は SQL標準に近いので SQL を書く範囲ではあまり困らないんではないかと思います。

・・・が、いい情報源があったら教えてください
コメント(0)  トラックバック(0) 
共通テーマ:日記・雑感

Firebird3 の新しい Identity カラム [Firebird]

これは Firebird Advent Calendar 2015 の http://qiita.com/advent-calendar/2015/firebird 16 日目の記事で、昨日の木村さんのエントリー http://blog.kimuradb.com/?eid=877448 の続きです

Interbase/Firebird を開発していた人たちは、オートインクリメントする型というのは、リレーショナルデーターベースの理論から外れるからということからか、導入に消極的だったように思います。

Firebird 1.x(Interbase 6.0)では、generator という整数列を生成するオブジェクトから trigger で値を設定するのが一般的でした。
http://firebirdfaq.sourceforge.net/faq29/

Firebird 2.0 SEQUENCE が作られ、値の取得に NEXT VALUE FOR UPDATE という構文が導入されました
http://www.firebirdsql.org/refdocs/langrefupd20-create-seq.html
http://www.firebirdsql.org/refdocs/langrefupd20-nextvaluefor.html
insert into employee (id, name) values (next value for a_seq, 'Alice')
とすると、ID 列に値がインクリメント入りますが、ID列を指定しないで値を入れたい場合は、トリガーで設定することになります。
http://symfoware.blog68.fc2.com/blog-entry-929.html
次の値を取ってくる構文がちょっと違いますが、Generator の例と同じですね
この機能は、 SQL標準で定義されているため、それに合わせるために導入されたもののようです。

Firebird 3.0 からは Identity というものが用意されました
https://github.com/FirebirdSQL/core/blob/master/doc/sql.extensions/README.identity_columns.txt

create table employee (
id integer generated by default as identity primary key,
name varchar(15)
);

と定義できるようになりました。このテーブルで

insert into employee (name) values ('Alice')

とすると id 列を指定しなくても、値がオートインクリメントで入ります。

id 列の開始値を変更するのは

alter table employee alter id restart withe 1000;

とするようです。(次に insert した時には1001 が入る)

テーブルに ID 列があることを想定している O/R マッパーが一般的になってきたので、ようやくか、という感じです。
コメント(0)  トラックバック(0) 
共通テーマ:日記・雑感

Firebird の思い出(後半) [Firebird]

これは Firebird Advent Calendar 2015 の http://qiita.com/advent-calendar/2015/firebird 13 日目の記事で、 http://nakagami.blog.so-net.ne.jp/2015-12-11 の続きです

2008年になって、 python の Firebird データーベースドライバー
KInterbaseDB のメンテナンスが危機的状況ということを知って、ずっと気になっていました。
そして、2008年12月に Python3.0 が出て、今後、データーベースドライバーを
Python3 対応にしていかないといけないであろうに、その目処が全く立っていない
という状況になってしまいました。

2008年後半から2010年前半のどこかのタイミングで、このドキュメント(当時は Githubでないどこかにあった)を発見しました。
https://github.com/cincuranet/FirebirdSql.Data.FirebirdClient/tree/master/Documentation
このドキュメントを見ただけではわかりませんでしたが、
isql とサーバーの間で、どんなデータをやり取りしているか調べるスクリプトを書いて、
実際にやり取りされるデータと上記のプロトコルドキュメントを見比べると、
うっすらと、データーベースドライバーが書けそうな気がしてきました。
現実的な路線として
- 不具合があっても、機能的に KInterbasDB に劣っていてもよいので、とにかく動くもの
- C 拡張は難しいので、 pure python のもの
- Python2 で動かなくてよいので、Python3 で動くもの
を目標にしました。

2010-09-26 に Protocol Version 10 (Interbase6.0相当)で
Python3 で動作する最低限のものができて、 PyPI にリリースできました。
https://pypi.python.org/pypi/firebirdsql/0.1.0
Python2 で Firebird に接続したい人は、KInterbasDB を使ったほうが
安定して速いので、pure python のドライバー使わないだろうと思ったのですが、
リリース直後の反応は、「Python2 では動かないのか?」という問い合わせが多くて、
ほどなく Python2 でも動くようになりました(しました)。

最初のリリース後、Firebird 公式の python 用ドライバー FDB の開発が始まりリリースされました。
もし、FDB があったら、python のドライバーを書こうと思わなかったでしょう。
僕がリリースするまで、誰も python のドライバーを書き直そう(もしくは KInterbaseDB を Python3 で動くようにしよう)
と思わなかったことは、結果として僕にとってラッキーなことでした。
・・・と書くと、すんなりと完成したようにも見えるかもしれませんが、
完成するかどうかわからない状態で試行錯誤している時には、
「ここまで時間をかけて完成しなかったら、今までの労力が無駄になってしまう」
というあせりはありました。完成して本当に良かったと思っています。

あらためて見直してみると、2008年から2010年中頃まで2年半は、断続的にではありますが
プロトコルの資料探したり、Interbase6 の Developper's Guide を読んだり、
あーでもないこーでもないとパケット観察しながら思考錯誤してたりしてたようです。
思うに、これだけ長く挫折せずに続けられたのは、代わりになる Python のドライバーが
出現できなかったことと、Firebird 本体の開発が停滞していて「まだ追いつける」という
気がしてたからだと思います。停滞万歳。

その後、2013年の8月頃に GO言語の勉強をしてみたら、思いのほか書ける気がしました。
http://nakagami.blog.so-net.ne.jp/2013-08-24
サンプルコードは書いたので、次は習作として何か使える(使われる)ものを書きたいと思いました。
そして書いたのが、Firebird のデーターベースドライバーでした。
(GO言語のよいドライバーがなかったので)
この時は、 プロトコルの理解も進んでいて Python の動く実装もあったので、思ったよりすぐ動くようになりました。
ちゃんとした記録がなくてよくわからないのですが、2014-04-14 の頃には一般に知られるようになったようです
http://www.firebirdnews.org/another-firebirdsql-driver-for-go-golang/

仕事でちょっと使って、いつかまた役に立つだろうと Firebird の開発状況のウォッチを続け、
気がつくと、Firebird を使わずに、 Firebird のドライバーを書いてばかりいて、
(しかも、仕事には関係なく)なんだか不思議なことです。
コメント(0)  トラックバック(0) 
共通テーマ:日記・雑感