前々回のPostgreSQLウォッチでは7.3.5と7.4.1のリリースをお知らせしたが,今回更に7.3系と7.4系のマイナー・バージョンアップ・リリースが行われた。

PostgreSQL 7.3.6リリース

 7.3.6は昨年12月3日にリリースされた7.3.5のバグ修正版である。深刻ではないものの,セキュリティfixも含まれるため,できればバージョンアップすることをおすすめする。

権限のないユーザーが更新できるぜい弱性を修正

 PostgreSQLにはルールという独自の機能があり,特定のSQL文が実行されたときにそれを一定の規則で書き換えることができる。ルールを使えば,ビューに対して更新処理が行われたときに元のテーブルを更新することによって見かけ上更新可能なビューを作ることもできる(ビューに関しては前々回でも解説しているので,そちらも参照してほしい)。

 今回見つかったセキュリティ・ホールは,ルールの書き方によっては,更新権限のないユーザーがテーブルを更新できるというものである。次の例を見ていただきたい。

 CREATE TABLE mypg_shadow (
   usename name NOT NULL,
   usesysid integer NOT NULL,
   usecreatedb boolean NOT NULL,
   usesuper boolean NOT NULL,
   usecatupd boolean NOT NULL,
   passwd text,
   valuntil abstime,
   useconfig text[]
 ) WITHOUT OIDS;
 このようなテーブルがあったとして,次のようなビューを定義する。
CREATE VIEW myview AS SELECT usename, usesuper FROM mypg_shadow;
 そして,以下のルールを定義する。
CREATE RULE myrule AS ON UPDATE TO myview DO INSTEAD
UPDATE mypg_shadow SET usename = NEW.usename,
 usesuper = NEW.usesuper WHERE usename = OLD.usename;
 これは,ビューmyviewに更新があったときに,かわりにもとのテーブルmypg_shadowを更新するというルールである。

 そしてmyviewにSELECT権限だけを与えておく。

GRANT SELECT ON myview TO PUBLIC;
 このとき,mypg_shadowにUPDATE権限のないユーザーがmyviewに対する更新を行うと,ルールを通じて更新権限のないはずのmypg_shadowの更新ができてしまう。例えば,
UPDATE myview SET usename = 'bar',usesuper = 't' WHERE usename = 'bar';
のような更新も可能である。このようなルールの使い方をしているユーザーは,7.3.6へのアップデートが必要である。

ディスクの空き領域がない状態での不具合などを修正

このほか,以下のような問題が修正された。

  • ディスクの空き領域がない状態でのデータベースの動作不具合を修正。特に,リカバリ処理に失敗するなどの不具合が修正された。

  • pg_restoreが4Gバイト以上のバックアップファイルを作れない問題を修正。

  • マルチバイト処理の不具合で,ある種のLIKE検索が正しい結果を返さないことがあるのを修正。

  • text_position()関数がマルチバイトを正しく処理せず,間違った結果を返すことがある不具合を修正。

     詳細に関してはいつものように,SRAのページ(http://osb.sra.co.jp/PostgreSQL/7.3.6/changes.html)を参考にしていただきたい。

    PostgreSQL 7.4.2リリース

     7.4.2は昨年12月22日にリリースされた7.4.1のバグ修正版である.7.4.1では,システム・カタログに問題があり,正しい最適化が行われなかったり,問い合わせ処理中にクラッシュする可能性があることが分かった。この問題は,WHERE節でFLOAT8(DOUBLE PRECISION)やTIMESTAMP型を使っている場合に発生する。

    7.4系のユーザーは7.4.2への移行が必須

     また,7.4.2では,上記7.3.6のセキュリティfixも修正されている.7.4.1のユーザーはすみやかに7.4.2に移行することをおすすめする。

     ただし,問題がシステム・カタログにあるため,移行のためにはデータベースのバックアップ,initdb,データベースのリストアという手順が必要になる。データベースのバックアップ・リストアをやりたくない場合には,いくつかのSQL文を発行することによってシステム・カタログを修正することも可能である。その方法については,ソースに付属のHISTORYというファイルを参照されたい。

    正常なSQLがエラーになることがある

     PostgreSQL 7.3では正常に実行できるSQL文が7.4.1でエラーになることがある。以下,PostgreSQL日本語メーリングリスト(pgsql-jp)に投稿された記事から,投稿者の田村氏の許可を得て再現例を示す。

     以下のような3つのテーブルがあるとする。

    test=> select * from 商品;
     id | name
    ----+------
     1 | 果物
     2 | 野菜
     3 | 肉
     4 | 魚
    
    test=> select * from 売上A;
     id | subid | value
    ----+-------+-------
     1 |   1 |  100
     1 |   2 |  150
     2 |   1 |  200
     2 |   2 |  250
    (4 rows)
    
    test=> select * from 売上B;
     id | subid | value
    ----+-------+-------
     2 |   1 |  300
     2 |   3 |  350
     3 |   2 |  400
     3 |   3 |  450
    (4 rows)
    
     これらのテーブルに対し,以下のクエリーを実行する。
    SELECT name,SUM(value)
       FROM 商品
       NATURAL LEFT JOIN
       (SELECT id,subid,value
        FROM 売上A
        UNION ALL
       SELECT id,subid,value
        FROM 売上B) AS 合計
       GROUP BY id,name
       ORDER BY id;
    
     すると,7.3では正しく実行できるのに,7.4.1では以下のエラーとなる。
    ERROR: column "商品.id" must appear
     in the GROUP BY clause or be used in an aggregate function
    

    7.3.6での修正は7.4.2にも取り込まれている

     前述の7.3.6での修正個所はすべて7.4.2にも取り込まれている。

     そのほかの7.4.2の修正個所の詳細に関しては(http://osb.sra.co.jp/PostgreSQL/7.4.2/changes.html)を参考にしていただきたい。

    開発中の7.5では,エラー箇所をわかりやすく表示

     本題のほかに,現在開発がすすんでいる7.5の話題についても報告しておこう。PITR(Point In Time Recovery)などの大物のほかに,細かな改良が多数行われている。その中から2,3紹介しよう。

  • LOCKコマンドにNOWAITオプションを追加

     LOCKはテーブルロックを行うSQLコマンドである。PostgreSQLでは,同じテーブルに競合するロックをかけている他のトランザクションが存在すると,後からLOCKコマンドは発行したトランザクションは,先にロックをかけていたトランザクションがコミットするか,アボートするまでは(クエリをキャンセルしない限り)ずっと待たされることになる。

     7.5では,NOWAITオプションを付けてLOCKコマンドを実行すると,ロックを取得できなかった場合には直ちにエラーが返るようになった。実行例を示そう。

    test=# LOCK TABLE t1 NOWAIT;
    ERROR: could not aquire relation lock
    
  • psqlでSQL文法エラーの個所を表示

     SQLを実行して文法エラーが発生すると,現状では以下のようにエラー個所が表示される。

    test=# SELECT * FROMbar;
    ERROR: parser: parse error at or near "FROMbar" at character 10
    
     つまり,10文字目の"F"が悪いというわけだが,これではちょっとわかりにくいかもしれない。そこで7.5では,エラーの個所を「^」で分かりやすく表示するようになった。



     なかなか気の効いた改良ではないだろうか(もちろん,エラーの位置が正しく表示されるためには,いわゆる当幅フォントを使っていることが前提である)。

    石井達夫(Tasuo Ishii)

    ■著者紹介
    石井達夫(いしい・たつお)氏
    1984年,SRA入社。主にUNIX関連の開発に従事するかたわら,95年からPostgreSQLのメーリング・リストを主宰。現在はオープンソースソリューション部でPostgreSQL関連のビジネス活動を技術支援。著書に『PostgreSQL完全攻略ガイド』(技術評論社),『PHPxPostgreSQLで作る最強Webシステム』(技術評論社),『PostgreSQL構築・運用ガイド』(日経BP,共著)などがある。日本PostgreSQLユーザ会理事長。