Home

memo-space

検索

  • 2004-12-23
  • vim

大文字小文字同一視
/\chello (Hello, HELLOにもマッチ)

カーソル位置指定
/hello/e (helloにマッチして、カーソルを"o"の位置に)
/hello/e1 (helloにマッチして、カーソルを"o"の次の位置に)

コマンドラインに最後に検索したパターンを入力する
:/

correlationとプラン

pg_statsのcorrelationとは、データが物理的に格納されている順番をあらわすような値らしい。これがIndexScanのコスト計算に影響する。 次のコードは、テーブルtbl1のa,bフィールドに1〜100000の値を格納する。aには昇順に、bにはランダムな順番に格納する。で、a,bそれぞれにインデックスを作成する。
<?php

$conn = pg_connect("") or die;

pg_query($conn, "drop table tbl1");
pg_query($conn, "create table tbl1 (a serial, b int)");
pg_query($conn, "create temp table tbl2 (a int)");
$scale = 100000;
pg_query($conn, "copy tbl2 from stdin");
for ($i = 0; $i < $scale; $i++)
{
  pg_put_line("$i\n");
}
pg_put_line("\\.\n");
pg_end_copy($conn);

pg_query("insert into tbl1 (b) select a from tbl2 order by random()");
pg_query("create index tbl1_a_idx on tbl1 (a)");
pg_query("create index tbl1_b_idx on tbl1 (b)");
pg_query("analyze tbl1");
pg_close($conn);
?>
この時のcorrelationは以下のようになっている。
ishida=# SELECT tablename, attname, correlation from pg_stats where tablename
= 'tbl1';
 tablename | attname | correlation
-----------+---------+-------------
 tbl1      | a       |           1
 tbl1      | b       | 0.000599762
(2 rows)
で、explain してみると、
ishida=# EXPLAIN ANALYZE select * from tbl1 where a < 100;
                                                    QUERY PLAN                  
-------------------------------------------------------------------------------------------------------------------
 Index Scan using tbl1_a_idx on tbl1  (cost=0.00..4.17 rows=88 width=8)
(actual time=0.143..1.823 rows=99 loops=1)
   Index Cond: (a < 100)
 Total runtime: 3.349 ms
(3 rows)

ishida=# EXPLAIN ANALYZE select * from tbl1 where b < 100;
                                                      QUERY PLAN                
----------------------------------------------------------------------------------------------------------------------
 Index Scan using tbl1_b_idx on tbl1  (cost=0.00..187.01 rows=49 width=8)
(actual time=0.224..2.911 rows=100 loops=1)
   Index Cond: (b < 100)
 Total runtime: 5.614 ms
(3 rows)
同じ行数を返すクエリなのに、aのコストが4.17に対して、bのコストは187.01になっている。(しかもbはrowsの見積りが49と本来の半分なのに、、、)。 bのクエリの返す行数を増やしていくと、900あたりでSeq Scanが選択される。
ishida=# EXPLAIN ANALYZE select * from tbl1 where b < 900;
                                              QUERY PLAN                        
-------------------------------------------------------------------------------------------------------
 Seq Scan on tbl1  (cost=0.00..1743.05 rows=838 width=8) (actual
time=1.564..250.410 rows=900 loops=1)
   Filter: (b < 900)
 Total runtime: 257.991 ms
(3 rows)

ishida=# EXPLAIN ANALYZE select * from tbl1 where b < 800;
                                                       QUERY PLAN               
-------------------------------------------------------------------------------------------------------------------------
 Index Scan using tbl1_b_idx on tbl1  (cost=0.00..1699.95 rows=740 width=8)
(actual time=0.209..17.035 rows=800 loops=1)
   Index Cond: (b < 800)
 Total runtime: 26.627 ms
(3 rows)
けど、800の時に26.627msなのに、900で257.991msでは、明かに900の時もIndex Scanを使った方が速そうだ。つまり、Index Scanのコストの見積りが大きすぎる。 randome_page_costを1にしてみると、80000あたりでSeq Scanを選択するようになった。
ishida=# set random_page_cost to 1;
SET

ishida=# EXPLAIN ANALYZE select * from tbl1 where b < 70000;
                                                          QUERY PLAN            
------------------------------------------------------------------------------------------------------------------------------
 Index Scan using tbl1_b_idx on tbl1  (cost=0.00..1595.15 rows=70234 width=8)
(actual time=0.142..864.855 rows=70000 loops=1)
   Index Cond: (b < 70000)
 Total runtime: 1313.035 ms
(3 rows)

ishida=# EXPLAIN ANALYZE select * from tbl1 where b < 80000;
                                                QUERY PLAN                      
-----------------------------------------------------------------------------------------------------------
 Seq Scan on tbl1  (cost=0.00..1743.05 rows=80459 width=8) (actual
time=0.076..828.856 rows=80000 loops=1)
   Filter: (b < 80000)
 Total runtime: 1340.610 ms
(3 rows)
ちなみにその物理的な並び順は、clusterコマンドで変更することができる。
ishida=# CLUSTER tbl1_b_idx ON tbl1;
CLUSTER
ishida=# ANALYZE tbl1;
ANALYZE
ishida=# SELECT tablename, attname, correlation from pg_stats where tablename
= 'tbl1';
 tablename | attname | correlation
-----------+---------+-------------
 tbl1      | a       |  -0.0377632
 tbl1      | b       |           1
(2 rows)

psで見えるプロセスの名前

http://blade.nagaokaut.ac.jp/ruby/ruby-dev/14646

Linuxにはsetproctitle()は無かったのか、、、こんな時間に何をやってるんだろう。

Unix Programming FAQによると、argv[0]を書き換えちゃうという方法もあるらしい。 http://www.adl.nii.ac.jp/~moro/unix-programmer/faq-j_2.html#SEC22

tomcat5とdeployer package

tomcat5についてくる(正確には別にダウンロードするものだけど)client deployer packageを使ってみた。jakartaのダウンロードサイトに置いてある、5.0.28.Deployer.zipとかいうヤツです。要するにantでdeployとかreloadとかする為のセットみたいです。 まあ、eclipseのそれなりのプラグインとか、NetBeansとか使ってれば必要無いのかもしれないんですが。 フォルダ構成としては、
+-project/
  +-lib/       -- deployer package のやつをコピーする
  +-build.xml  -- 同上
  +-deployer.properties  -- 自分で作る
  +-websrc/
    +-WEB-INF/
      +-...
みたいな感じです。 なんか、antすると"Unsupported or unknown request method POST"とか出て失敗する。ググってみたら、なんかFC2のgcj版antの問題のような気がしてきたのでyum remove antして普通のantを入れなおしたら動いた。 えーっと、/context/servlet/ServletみたいなURLでサーブレットが動かないんですけど、、、と思ったらconv/web.xmlでinvokerがコメントアウトされてるじゃん!!

幸せなITパーソンになるためのいきいきする仕事とやる気のつくり方

はぶさんの本。日経BP IT Proの“心が折れるその一言”がプロジェクトを倒壊させるあたりの話らしい。

gimpで自動レベル調整

今まで色をいじったことなかったんだけど、gimpで[画像]-[色]-[レベル]-[自動調整]するだけで(ものによっては)ずいぶんちがうじゃん。真面目にTC勉強しようかなぁ。

元画像

文字コードの話

文字コードの話はしょっちゅうワケがわからなくなるのでメモ。

関数のポインタのtypedef

たまにちょっとCのソースを読もうと思うと、よくわからんことばかりだなぁ。

typedef Datum (*PGFunction) (FunctionCallInfo fcinfo);

なんですかこれ。えーっと、

Datum (*func_pointer) (FunctionCallInfo fcinfo);

と書いてやると、Datum型を返す関数へのポインタであるfunc_pointerという変数を定義する(引数はFunctionCallInfo型のものを1つとる)ということだから、さっきのは、Datum型を返す関数へのポインタをPGFunctionという名前でtypedefしてるのか。

ということはここでのfcinfoは意味無いんだな。うーん、fcinfoがどこで定義されてるか知りたかったんだけど。ん?こっちは何だろう。

/* Standard parameter list for fmgr-compatible functions */
#define PG_FUNCTION_ARGS	FunctionCallInfo fcinfo

はぅ!!func(PG_FUNCTION_ARGS)はfunc(FunctionCallInfo fcinfo)という意味だったのか。どうりでタグジャンプで見つからないわけだ。

メモリプロファイライ

メモリリークを検出するツールとして、ccmallocとかdmallocとか試す。うーん。よくわからん。

試しに作ったプログラムをccallocしてみたら、libpqの中でリークしてるように見える。追っかけてみたら、getpwduid()の中で取得しているメモリを解放していないように見える。でもそれをfree()するとcore dumpした。man getpwduidすると、

The functions getpwent(), getpwnam(), and getpwuid(), leave their results in an internal static object and return a pointer to that object. Subsequent calls to the same function will modify the same object.

何がリークなのかを判断するのもひと苦労だ。

M+ fonts / BDF M+

M+ fontsは可読性の高いビットマップフォント。フリーで日本語も表示できます。BDF M+はそれをKaoriyaのKoRoNさんがTTF化したものだそうだ。

読み易くて小さい固定ピッチフォントをお探しの方はぜひ試してみましょう。今まではコーディングにMS明朝を使っていたけど(MSゴシックは小文字のエルにヒゲが無いのが嫌い)、完全にM+にのりかえました。

複数のウィンドウでのcookieの扱い

cookieを送りつけてくるURLをブラウザで開く、で、もう一つ同じURLを別のウィンドウで開いた時、そいつはそのcookieを送信するのか、という話。これも知ってる人には今さらな話なのかもしれない。

IEだと、IEのアイコンをダブルクリックした時と、既に開いているIEのウィンドウから[新規作成]->[開く]した時とで挙動が違う。前者ではcookieは別の管理となるみたいだ。もしかしたらこの辺の挙動を制御する設定があるのかもしれないが。

FireFoxだと、New TabでもNew Windowでも、あるいはアイコンをダブルクリックして起動しても常にcookieを送信するようだ。

例えばサッカーの速報サイトがあったとしよう(あんまいい例えじゃないが)。セッション管理をcookieでやってるとして、ブラウザにはセッションIDが送られる。どの試合の速報を表示しているかという情報をセッションで管理していたとなると、複数のウィンドウで別々の試合を見ようとしても、全部同じ試合が表示されちゃうよね。

やっぱセッションIDはGETかPOSTかするべきか。

メーリングリストのsubscribe風二重投稿の防止方法

大分前に思いついたことなのだけれど。

"ユーザー登録画面"みたいなのをウェブアプリケーションで作っていると、ブラウザの"更新"ボタンを押された時などに二重投稿されてしまうのをどう防ぐか、という問題がある。これをメーリングリストシステムの講読で使われている方法を応用できないかという話。

メーリングリストを講読しようとすると、

confirm 2004041000340123580xxxxxxxx ISHIDA Akio
という一文を xxx@xxxxxx.xxx まで送り返してください。

とかいったメールが送られてくる。この"20040410......"というのを何というのか知らないが、ここではチケットと呼ぶことにしよう。

このチケットは、講読しようとしてるユーザーに送信されると同時にメーリングリストサーバー側にも保存される。ユーザーからの"confirm [チケット]"というメールを受信すると、サーバーは自分が保持しているチケットと照合してその妥当性を検証するわけだ。妥当であればユーザーを講読者として登録し、サーバーに保存したチケットは削除(消費)する。これで同じチケットはもう使えないんだ。

これと同じように、まずウェブアプリケーションはチケットを"ユーザー登録画面"のフォーム内にhiddenとして送りこみ、同時にサーバー側のセッションオブジェクトなり何なりに保存しておく。

更新のリクエストがきたら、送信されたチケットと保持しているチケットを照合する。妥当ならユーザー登録処理を行ない、セッションオブジェクトからチケットを更新(あるいは削除)する。もしこの後ブラウザ側で"更新"ボタンが押されても、送信されるチケットとサーバー側のチケットが一致しないので、二重投稿だと判断できるわけだ。

cvsメモ

cvs status すると Up-to-date / Locally Modified / Needs Patch / Needs Merge のどれかになる。

Needs Patchの時にcvs updateするとフツーにローカルファイルがリポジトリの内容で更新される。

Needs Mergeの時にcvs updateすると、コンフリクトがおこる。

Up-to-date及びLocally Modifiedの時にcvs updateしても何もおこらない。

Locally Modifiedなローカルファイルをリポジトリの状態に戻したい時はcvs update -Cとする。

もっと昔のもの(commit済のもの)に戻したければ、cvs -Q update -p filename > filename として標準出力に書き出したものをリダイレクトする。-jオプションを使う方法もある。

CVSの基礎練習 結城さん
バージョン管理システム CVS を使う 西本さん
CVS manual の日本語訳 Hayashiさん
Open Source Development with CVS 日本語訳 竹内かほりさん
入門 CVS サポートページ みかままさん

[pgsql-jp: 33190] PostgrsSQL7.4.2 ecpgのprepare,execute でnull値が渡せない

[pgsql-jp: 33190]の件を追ってみた。とりあえず*.yファイルを追うのってすごく大変。というか設計思想がわからんとツラい。なんか使ってないところもいっぱいありそうな気がするし。

src/interface/ecpg/preproc/preproc.yあたりを見る。でちょっと書き換えたりして。でもbisonが入ってなくて(あるいははいっててもバージョンが古くて)makeしてもpreproc.cに反映されてなかったとかいう失態をしながら。(PostgreSQL needs Bison version 1.875 or laterです)。

indicatorなしのホスト変数は、 stmt -> ECPGExecute -> execute_rest -> ecpg_using -> using_list -> UsingConst ->AllConst -> NumConst -> civar みたいになってる。

cvsみてたら、ここの変更以降でindicatorが使えなくなってる気がする。元々ECPGExecute ... USING ... の所にホスト変数しか使えなかったところを、constも使えるようにしたら、今度はindicatorが使えなくなっちゃったように見える。

ところでdeallocateもちゃんと動かない気がしてきた。もうちょい時間が必用か。

WingNest.COM - ごうきさんのウェブログ

【オブジェクト倶楽部:2004-07号】 の中で、 ごうきさんのウェブログ が紹介されている。空手の型についての話とソフトウェア開発の学習の話だ。 僕が好きなウェブログがオブジェクト倶楽部みたいなところで紹介されるのは嬉しい。

ごうきさんを初めて知ったのは、デスマーチ撲滅委員会MLへの投稿 「 [d-march-ml:0406] Re: 工場を作ることが上手い 」(パスワード要) だった。 同じテーマについて ウェブログにもエントリがある が、MLへの投稿の方が詳しい。

本人には失礼だが、 なんだか騙されてるんじゃないかという思うくらい、すごく好きになってしまった。 このMLへの投稿にはコメントが付かなかった。 僕も書こうかと思ったけど、ごうきさんの言っていることはたぶんちゃんと理解できていなかったし、 「よくわかんないけど感動しました」と書くわけにもいかないのでやめておいた。 こんな時にトラックバックって使うのかもしれない。

[ANNOUNCE] Slony-I goes BETA

とりあえず顔怖すぎ。トリガベースのマルチマスタレプリケーションなのかな。よくわかりません。

FreeBSD上のvimで日本語処理が変

カーソルは1byteずつ動くし、ひらがなを1文字消すのにxxって打たなきゃならない。 なんだか不便だなと思いながら使っていたらちゃんと直す方法があったじゃない。

カーソルが 1byte ずつしか移動しません(vim users guid)。

なんかFreeBSDのmblen()の挙動の問題らしい。 とりあえずsrc/mbyte.cの中でmblen()を#ifdef 0 してるところを#ifdef 1 に変更したら直った。

PostgreSQL Conference 2004

カンファレンスから帰ってきて社会復帰。うっかり4日間も出掛けてるとチェックしてたスレもDAT落ちしてる。orz

内容は書く根性ないのでメモ。

pgbenchとカーネルキャッシュ

ファイルシステムやマウントオプションがどれくらいpgbenchの結果に影響をあたえるかを調べたかったんだけど、pgbenchした後に$PGDATAをumount -> mountしてまたpgbenchをするとガクンと結果が悪くなる(tpsが半分以下になる)。

どうやら、umountしたときにカーネルのキャッシュから消えてしまうかららしい。 mountしなおした後に数回pgbenchを実行しても速くならないが、pgbench -iしなおすとグっとパフォーマンスが良くなる。

さらに、この様子をvmstat 10とかしながあ見ていると、pgbench -iした直後にpgbenchすると、全くbi(Block In)が発生していないのがわかる。で、umountするとCashが減ってFreeが増える。mountしてpgbenchするとbiがガシガシ発生する(CashとFreeはほとんど変わらない)。

なんとか無理矢理カーネルキャッシュに載せてやることは出来ないのかと思い、cat /usr/local/pgsql/data/base/xxxx/* > /dev/null みたいなことをやってみると、確かにCashは増えてFreeは減る。pgbenchするとそこそこ結果も良かった。

ふーむ。こんなにキャッシュがベンチマークの結果に影響を与えるなら、うまいことキャッシュを操作する方法が欲しいな。

さてベンチマークの結果だけど、ファイルシステム(ext2かext3か)とwal_sync_methodについて調べてみたら(今更ext2なんて使うなと言われそうですが)、ext2ではfdatasyncの方が速い、ext3のopen_syncはメチャ速いような気がしてきました。本当だろうか。あまりアテにしないでね。

ext2 ext3
fsync 39〜45tps 21〜22tps
fdatasync 68〜85tps 21〜22tps
open_sync 30〜45tps 410〜497tps

別の環境でも試してみよう。

PostgreSQL OpenOffice driver

* Assistance needed with PostgreSQL OpenOffice driver
* dba: PostgreSQL SDBC driver

OpenOffice.orgからPostgreSQLに繋ぐには、odbc / ADO / jdbc 経由といった方法があったんだけど、直接OOoから接続できるドライバを作ってるらしいです。

不要とは思うがインストール方法:

  1. http://dba.openoffice.org/drivers/postgresql/index.htmlからドライバをダウンロード
  2. OOoを終了する。クイック起動も終了。
  3. OpenOffice1.1.0/user/uno_packages/ フォルダにダウンロードした.zipファイルを(解凍せずに)置く。
  4. DOSから、OpenOffice1.1.0/program/pkgchk.exeを実行する。成功すれば何も表示されない。
  5. OOoの何かを起動し、[ツール(T)]-[データソース(D)]で「データベースの種類(T)」のドロップダウンリストに「postgresql」が追加されていることを確認。
  6. データソースのURLは"sdbc:postgresql:[name1=value1] [name2=value2] [...]"。[name1=value1]はlibpqのPQconnectdb()と一緒。("host=xxx user=xxx"等)。

PostgreSQL Users' Group sites now available

from pgsql-announce.

PostgreSQL Users Groups Siteなるものができたらしい。

pgFoundry

from pgsql-announce.

pgFoundryなるものが出来たそうだ。GBorgにかわるものなのかな。

マルチカラムインデックスで逆順ソート

冷静に考えてみればあたりまえですが、、、

テーブルtに(a, b)というフィールドでマルチカラムインデックスが張ってあったとき、

select * from t order by a, b limit 1;

みたいなのだとIndes Scanされますが、

select * from t order by a, b desc limit 1;

ではIndex Scanされません。

select * from t order by a desc, b desc limit 1;

ならIndex Scanされます。

読書会 MINI-HOWTO

読書会ってやってみたいと思っていたら、読書会 MINI-HOWTOというのがあった。ありがたい。

ふだん書籍を読む場合、すべてを熟読することはなかなか困難です。

激しく同意。最近ホントななめ読みしすぎ。本は好きなんだけど、活字をボンヤリ眺めてるのが好きなんです。

dsssl

dssslについての日本語情報源

DSSSL入門(JAGAT) Paul Prescond のIntroduction to DSSSLの和訳
DSSSLへの手引き(JAGAT)
フォーマッターJADE(JAGAT)
DSSSL研究室 (NEXT SOLUTION)
SGML/XML + DSSSL/CSS/XSL を活用する (佐藤 広生さん)
いまさらDSSSL、いまからDSSSL (Kazutoshi Kuobta さん)

テーブル定義の変更と依存関係(その2)

テーブル定義を変更したい場合、例えばフィールドの追加なんかだと、ALTER TABLE ... ADD ...; と追加すればいいわけだけど、それだと最後に追加することしかできない。"んーなもん常識だろ"といわれそうだけど、そういう保守的なのはイヤなんだ。

だとすればどうするか。

  1. まず、tbl1の依存関係を調べて、依存しているものをダンプしておく。大抵、プライマリキー制約とか外部参照制約とかだろう。但し制約だけをpg_dumpすることはできないので、pg_dump --schema-only --table=[テーブル名]で、テーブルごとダンプして必要な部分だけ切り出す必要がある。
  2. pg_dump --data-only --column-inserts --table=tbl1 する。--column-insertsを指定すると、insert into tbl1 (fld1, fld2...) values (.., ..);ってな形式でダンプされるわけだ。
  3. drop table tbl1 cascadeする。
  4. 新しいテーブル定義でcreate table tbl1...する。
  5. 1.でpg_dumpした依存しているオブジェクトを戻す。
  6. 2.でpg_dumpしたデータを流しこむ

ってな感じだ。フィールドの削除があった場合はそのままpg_dump --data-onlyすると流し込む時にエラーになるので、先にCREATE TEMP TABLE t AS SELECT fld1, ...;等と一時テーブルを作っておいてそれをpg_dumpするといいだろう。この辺を自動化するツールがあったら素敵だと思う。

っーか、色々考えてたら、pg_dumpを書き直したくなってきちゃったなぁ。

SQL覚え書き

結合する相手が0または1行を返す場合は、LEFT JOINのかわりにターゲットリストでのサブクエリーが使える(スカラー副問い合わせ)。但しサブクエリーが複数行を返すとエラーになる。結合条件がプライマリキーな場合だけ使うのが良いかもしれない。

SELECT shain.*
     , busho.busho_id
  FROM shain
       LEFT JOIN busho USING (busho_id);
       |
       V
SELECT shain.*
     ,(SELECT busho_name
         FROM busho
        WHERE shain.busho_id = busho.busho_id);

MAX()のかわりにORDER BY...LIMITが使える場合がある。インデックスがあれば速いかも。但しテーブルが空だった場合、MAX()はNullを返すがORDER BY...LIMITは行を返さない。

SELECT max(score)
  FROM score_table;
       |
       V
SELECT score
  FROM score_table
 ORDER BY score DESC
 LIMIT 1

テーブル定義の変更と依存関係

テーブル定義を変更しようとしたら依存関係でハマったので、ちょっとまとめておこう。

単純なcreate table文でも依存関係は発生する。pg_typeにテーブル名と同じ"型"を登録するからだ。依存関係の情報はpg_dependから得られる。

ishida=> CREATE TABLE tbl1 (fld1 integer);
CREATE TABLE
ishida=>
 SELECT classid::regclass, * FROM pg_depend d
  WHERE EXISTS
       (SELECT * FROM pg_class c
         WHERE c.oid = d.refobjid AND c.relname = 'tbl1');
-[ RECORD 1 ]--------------
classid     | pg_type
classid     | 1247
objid       | 4238396
objsubid    | 0
refclassid  | 1259
refobjid    | 4238395
refobjsubid | 0
deptype     | i
ishida=> ALTER TABLE tbl1
           ADD CONSTRAINT tbl1_pkey PRIMARY KEY (fld1);
(sql省略)
-[ RECORD 1 ]--------------
classid     | pg_type
classid     | 1247
objid       | 4238396
objsubid    | 0
refclassid  | 1259
refobjid    | 4238395
refobjsubid | 0
deptype     | i
-[ RECORD 2 ]--------------
classid     | pg_constraint
classid     | 16386
objid       | 4238398
objsubid    | 0
refclassid  | 1259
refobjid    | 4238395
refobjsubid | 1
deptype     | a

deptypeには、n(NORMAL), a(AUTO), i(INTERNAL), p(PIN)のいずれかが入る。NORMALな依存関係はDROP CASCADEでのみ削除できる。AUTOとINTERNALは親をDROPすると自動的に削除される。AUTOは子だけを個別に削除することも可能だ。 ここまでの例ではAUTOとINTERNALしかないので、DROP TABLE tbl1;は問題無く実行できる。 ではtbl1.fld1を外部キーとして参照する別のテーブルを作ってみよう。この場合、tbl1とtbl2の間に依存関係ができるのではなく、tbl1とtbl2の外部キー制約の間に依存関係ができる。(つまり、DROP TABLE tbl1 CASCADE;すると、tbl2が削除されるのでははく、tbl2の外部キー制約が削除される)。

ishida=> CREATE TABLE tbl1 (fld1 integer PRIMARY KEY);
ishida=> CREATE TABLE tbl2 (fld2 integer, FOREIGN KEY (fld2) 
           REFERENCES tbl1(fld1));
(sql省略)
-[ RECORD 1 ]--------------
classid     | pg_type
classid     | 1247
objid       | 4238405
objsubid    | 0
refclassid  | 1259
refobjid    | 4238404
refobjsubid | 0
deptype     | i
-[ RECORD 2 ]--------------
classid     | pg_constraint
classid     | 16386
objid       | 4238407
objsubid    | 0
refclassid  | 1259
refobjid    | 4238404
refobjsubid | 1
deptype     | a
-[ RECORD 3 ]--------------
classid     | pg_constraint
classid     | 16386
objid       | 4238410
objsubid    | 0
refclassid  | 1259
refobjid    | 4238404
refobjsubid | 1
deptype     | n

ishida=> DROP TABLE tbl1;
NOTICE:  constraint $1 on table tbl2 depends on table tbl1
ERROR:  cannot drop table tbl1 because other objects depend on it
HINT:  Use DROP ... CASCADE to drop the dependent objects too.

(続く、、、かも)

依存関係の追跡
pg_depend

StringInfoを使う

PostgreSQLのユーザー定義関数なんかを書くとき、文字列の処理にはStringInfoを使うことができる。ちなみにフロントエンド側(libpqアプリケーション)を書くときは、ほとんど同じ機能を持つPQExpBufferというのがある。

StringInfoの定義はinclude/lib/stringinfo.hに、取り扱う関数群はsrc/backend/lib/stringinfo.cにある。

初期化には、 StringInfo s = makeStringInfo(); あるいは、先に領域確保していおいて initStringInfo(s); する。StringInfo型はStringInfoDataへのポインタだ。(typedef StringInfoData *StringInfo;)

あとは、appendStringInfo(StringInfo str, const char *fmt,...)とかゴニョゴニョして、実際の文字列へのポインタが欲しくなったらs->dataする。

PostgreSQL北海道支部講演会

去る2月28日、PostgreSQL北海道支部の講演会にいってきた。

講演の間の空き時間にくわむらさんが声を掛けてくださった。僕の廻りにはPostgreSQLコミュニティに参加している人がいないので、自分のコミュニティでの知名度やコミュニティに対してしていることが本当に役に立っているのかよくわからない。なので、くわむらさんなんかに名前(だけでなく顔まで)を覚えてもらっているのは嬉しい。

個人的に面白かったのは、大垣さんと永安さんのコマだった。

大垣さんはPHPでwebアプリケーションを作る時のパフォーマンスやセキュリティに関しての注意点について。webアプリケーションというのは幅広い知識を要求される。DB、PHP、Apach、Linux、JavaScript、HTTP等々。

PostgreSQLのメリットの1つはコストパフォーマンスだ。なのでPostgreSQLでシステム構築を考えている方々の多くは、プログラマーだったりDB管理者だったりネットワーク管理者だったり、複数の仕事を一人で引き受けなければならない状況にあるのではないかと思う。

そういった人達に、PostgreSQLの良さを知ってもらうことも大切だけど、どんな難しさがあるのかということを知ってもらうことも大切だと思う。

永安さんはオープンソースソフトウェアコミュニティに参加するということについての御自身のOSDLの経験談や、華やかな面ばかり取り挙げられるが本当に"just for fun"だけでよいのか?個人に負担を強いていないだろうか、OSSコミュニィと個人と企業と学校との関係みたいな、こちらも"難しさ"についての話だった。

モチベーションというのは大切な話で、僕も含めてJPUGというのはPostgreSQLの普及と促進を目的としてるわけだが、実際そんなに流行らせたいか?という素朴な疑問もある。これは例え話だが、PostgreSQLが普及することでPostgreSQLを使った仕事が増えて、それによって良い転職先が見つかるかもしれないという個人的なメリットは考えられるだろう。まあそれだと、僕が今勤めている会社とOSSコミュニティとの間の利害関係が一致しなくなってしまうのだが。

僕個人としては、jpug-docの活動に協力しているのは"自分の勉強のため"に他ならない。仕事でPostgreSQLを使っているので、会社のためになってはいるが、会社に理解されてコミュニティに関わっているわけではない。僕がPostgreSQL関連のメールを読んでいる時は仕事をサボっている時だ。永安さんの話にはすごく共感するけれども、その観点から見れば僕のやっていることは恥かしいことなのかもしれない。

個人の意見はよしとして、一般的にOSSコミュニティに参加する意義って何なんだろう。みんな会社に理解されて参加しているのかな。っつーかまずコミュニティの目的もよくわからんし。別に、真の目的がOSSの名前を使って楽しくお酒を飲むことだというのであれば、それはそれで否定しない(が、僕は参加しないが)。

よく見たらこの人東京ではできなさそうとか言ってるし。どーでもいいけど俺、エントリ書くのに時間かかりすぎ。

/gと\G

perlの正規表現の m/../g と \G の働きがよくわからん。 m/../g はスカラコンテキストでは、 前回マッチした位置から開始して、マッチしたかどうかを返すらしい。 でも「前回マッチした結果」って何だ?

$a = 'abcde';

print "$&\n" if $a =~ m/[ace]/g;
print "$&\n" if $a =~ m/[ace]/g;
print "$&\n" if $a =~ m/[ace]/g;

$ perl x.pl
a
c
e

なるほど。これはわかる。 ではこの $a を文字列リテラルにしてみる。

print "$&\n" if 'abcde' =~ m/[ace]/g;
print "$&\n" if 'abcde' =~ m/[ace]/g;
print "$&\n" if 'abcde' =~ m/[ace]/g;

$ perl x.pl
a
a
a

この場合は「前回マッチした」とは扱われないようだ。 さっきの例の $a を途中で書き変えてみるとどうなるだろう。

$a = 'abcde';

print "$& $'\n" if $a =~ m/[ace]/g; $a = 'abeee';
print "$& $'\n" if $a =~ m/[ace]/g;
print "$& $'\n" if $a =~ m/[ace]/g;

$ perl x.pl
a
a
e

途中で書き換えると、また先頭からマッチを始めている。 さてこれをふまえて、\Gについてはまた今度 (続く)。

緯度、経度から距離を求める

MapFanやMapionのURLには緯度、経度が含まれているので、そこから距離がわかればなんとなく便利なんじゃないかと思って調べてみた。

1海里とは、、、経度1分(1852m)のことである。(へー)

1ノットとは、、、時速1海里のことである。(へー)

F U D! F U D!

FUDってのは、外から見て「アイツのココが弱い。ココが世間に理解されていない」というメッセージなんだから、それを逆に利用しない手はないんじゃないか?わざわざ自分達の弱点を調べてくれたのだから、ウダウダ言うより真摯に受けとめて自分たちもちゃんとしたメッセージを発信すればいいじゃない。って思うんです

FUD とは何ぞや?

FUD は、競合相手が自分達のものより優れていて、しかも価格も安い、つまりは自分達の製品では太刀打ちできない製品が発売されるときに利用されるマーケティングのテクニックである。

この定義を見ると、どっかのメーカーとかがPostgreSQLに対してFUDという戦略を使うという(フィクション)のはちょっとPostgreSQLをかいかぶりすぎだけどね。

暇なら読むぞメモ

TODO

時間ができたらやりたいことを今のうちに書いておこう。

  • fotolog掲示板の日本語文字化けを回避するような何かを作る。
  • PostgreSQLで、オブジェクトの依存関係を可視化する何かを作る。
  • pg_dumpをちょっと勉強したい。(っつーか本当は作りなおしたい)。
  • ユーザー定義関数とかの書きかたについて何かまとめる。
  • flex, bisonについて勉強してまとめる。
  • Javaの勉強する(っつーか資格とりたい)
  • 英語の勉強する
  • 運動する
  • Code Reading読みたい。

2004-06-20追記

  • 文字コードの勉強
  • gettext()あたりを勉強

にせfotolog

昨日は"時間ができたらやりたい"とかいってたけど、やってみたらできてしまった。でもポリシー的にアリなのかどうかよくわからん。

最初はここまでやるのはやめておこうと思ったんだけど、けっこう大勢の人がfotolog掲示板で日本語が表示できないことについて落胆している様子が見えて(だったらもっと早くにやれよって話もあるんだけど)。思わずここまでやっちゃいました。

http://www.mono-space.net/fotolog/

AZIK

AZIKとACTはローマ字入力、英文入力との互換性を保ちながらより快適に入力する方法です。

だそうです。これ面白い。SKKIMEで使えるなら使ってみたいな。普通のローマ字入力は使えた上で、"CA,CU,CO"は"ちゃ、ちゅ、ちょ"になったり、"kt"は"こと"になったりするというものだ。

体験アプレットをやってると、考えられないような間違いを連発して面白い。"こうこうせい"は"kpkpsw"と打つんだけど、"kpkpsr"と間違えたために"こうこうする"になってしまった^^;;

拡張ローマ字入力『AZIK』/『ACT』

PuTTYでscreen

GNU Screenを入れてみた。なかなか便利かもしれないが、なんだかBSキーがきかない(BSを押すと"~"が表示される)。bash上でCtrl+Vの後にBSを押すとこんな感じ。

$ echo '^[[3~' | hd
00000000  1b 5b 33 7e 0a                                    |.[3~.|
00000005

色々悩んだ末、PuTTYの設定で[端末]-[キーボード]-[バックスペースキー]の所をControl-Hに設定することでちゃんと動くようになった。

GNU Screen
Screen を使う
Let's use SCREEN
GNU screen を使い倒せ!

ソフトウェアライセンス占い

あきをさんのライセンスは 新 BSD ライセンス です!

● 新 BSD ライセンスが適用された貴方は、とても優しく、柔らかなムードの持ち主。柔軟性に富んでいて、どんな人でも受け入れられる、懐の広さを持っています。いつも明るく愛嬌たっぷりの貴方が、実は引っ込み思案で目立つのが苦手、しかも内面的には意外に強情で保守的と知ったら、周りの人はびっくりしてしまうかもしれませんね。また、持ち前の柔軟性が、時として器用貧乏になってしまうことも。特に仕事面では、どんなものでも一定のレベルまでこなせてしまうからこそ、かえって定職につきにくい傾向があります。そんなときは、最も興味のある分野のスペシャリストを目指してみて。細かい手先作業や組込みのお仕事が向いているかも。恋愛面でも柔軟性が移り気に変わらなければ、素敵な人と楽しい恋を育んでいけます。

● あきをさんの本当のお母さんは、現在、下関の漁港あたりをさまよい歩きながら、あなたの名前を叫んでいます。

orkuktに登録

自分には絶対縁の無いと思っていたorkutに招待された。微妙に多きな対価を払った気もするが。

全部英語なのでプロフィール書くのも大変。sexual orientationとか意味わからずにうっかり書くと大変なことになるじゃん。やべぇ。仕事しなきゃ。

なかなかよくできてる。便利だと思うし、楽しい気分にさせる仕組みだと思う。ソーシャルネットワークとかいう呼び名はちょっと気持悪いが。

で、登録したけどこれってどうやって楽しむんだ。っつーか今更気がついたけど俺って真性の精神的ヒキコモリなのか!?

orkut簡易マニュアル
orkut faq和訳

偽善者度診断

【あなたは 25 % 〜です】

あなたはいい人です。青少年期の純な心を持ち、時に傷つき悩みながら一生懸命に生きています。あなたには本当の意味での親友がいますし、心を許せる恋人もいます。出世やお金儲けとは無縁かもしれませんが、本音を言える暖かい家庭をもうけて平和に暮らして行けるでしょう。

そもそも偽善の反対が善だという定義が間違っとるんじゃぁ(ささくれだった心で)。

新山さんの言葉

blosxomインストール

とりあえずどのへんのプラグインを入れればよいのかわからない。 entries_indexとcategorylistは使えそう。 ちょっとがんばれば自分でもプラグインを作れそうな気がする。

ああ、こんなの見つけました。 とりあえず入れとけなプラグイン。 まあwritebackはいいや。archives、categories、entries_indexをいれる。

色々調べているうちに、 blosxomは(日記的な使いかたよりも) まとまったドキュメントを整理するのに良いというようなことを書いている人がいた。 (どこだったか忘れたけど)。 この木構造がいいんだろうな。 ブックマークとかに使ってみたらどうだろう。

MovableTypeのブラウザで何でも編集できちゃうのは便利だったけど、 blosxomのようにプレーンテキストでエントリを書く方がやっぱ使いやすい。 独自のマークアップで書いてスクリプトでhtmlに変換するとかもアリだし。

なんか今のblogのイメージって変だと思うし。 もっとメモみたいな感じでいいじゃん。

惜しまずコードを書き続けること

スタイルいじり中

スタイルシートいじり中。

こだわりすぎないように気をつけてスタイルシートを作る。 archivesやcategoriesで使われている <li>のインデントが大きすぎるのをどうにかしたいが、まあいっか。

と思っていたら、flatarchivesとかcategorylistとかいうpluginがあった。こっちのほうがいいや。

IEとMozillaでデフォルトのフォントの大きさが激しく違うのはどうにかならないんだろうか。

Home

Search
Feeds
Profile
石田@苫小牧市と名乗りつつ札幌の某社に勤務するプログラマ
書いた本
Links

Page Top