HHeLiBeXの日記 正道編

日々の記憶の記録とメモ‥

XMLTABLE関数の謎な挙動

やっていることはものすごくシンプル。

CREATE DATABASE HOGE USING CODESET UTF-8 TERRITORY JP COLLATE USING SYSTEM PAGESIZE 32 K ;
CONNECT TO HOGE USER db2admin USING admin ;
CREATE TABLE DOCUMENT (
    ID VARCHAR(8) NOT NULL,
    DATA XML NOT NULL,
    CONSTRAINT HOGE_DOC_PKEY PRIMARY KEY (ID)) ;
IMPORT FROM import_data OF DEL MODIFIED BY LOBSINFILE INSERT INTO DOCUMENT ;
SELECT COUNT(*) FROM DOCUMENT ;
SELECT D.ID, LENGTH(T.DESC_VC) AS LEN_VC, LENGTH(T.DESC_CLOB) AS LEN_CLOB
    FROM DOCUMENT AS D,
        XMLTABLE('$root/hoge' PASSING D.DATA AS "root"
            COLUMNS
                DESC_CLOB CLOB PATH '.',
                DESC_VC VARCHAR(311) PATH '.'
        ) AS T
    WHERE D.ID = 'HOGE'
;
CONNECT RESET ;
DROP DATABASE HOGE ;
  1. DBを作成
  2. XML型の列を持つテーブルを作成
  3. データを1行インポート
  4. XMLデータのあるノードの値をXMLTABLE関数を使用してVARCHAR(311)とCLOBでそれぞれ取得し、その長さを表示

インポートしているデータは次のようなもの。
ファイル"import_data"の内容:

"HOGE","<XDS FIL='import_data.001.xml' />"

ファイル"import_data.001.xml"の内容:

<?xml version="1.0" encoding="UTF-8" ?><hoge>abcdefあいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよらりるれろわをんアイウエオカキクケコサシスセソ.</hoge>

これをDB2 v9.1.5で実行すると、結果は次のような感じ。

ID       LEN_VC      LEN_CLOB
-------- ----------- -----------
HOGE             190         190

しかし、DB2 v9.5.4で実行すると、次のようになる。

ID       LEN_VC      LEN_CLOB
-------- ----------- -----------
HOGE             190         310

この120バイトの差はなに?と思ったので、エクスポートしてみた。

EXPORT TO
        export_data
        OF DEL MODIFIED BY XMLINSEPFILES LOBSINSEPFILES CODEPAGE=1208
    SELECT D.ID, T.DESC_CLOB, T.DESC_VC
        FROM DOCUMENT AS D,
            XMLTABLE('$root/hoge' PASSING D.DATA AS "root"
                COLUMNS
                    DESC_CLOB CLOB PATH '.',
                    DESC_VC VARCHAR(311) PATH '.'
            ) AS T

DB2 v9.1.5 の場合。

C:\work> dir
    :(省略)
2009/08/05  16:50               223 export_data
2009/08/05  16:50               190 export_data.001.lob
    :(省略)

DB2 v9.5.4 の場合。

C:\work> dir
    :(省略)
2009/08/05  16:50               223 export_data
2009/08/05  16:50               310 export_data.001.lob
    :(省略)

確かに120バイト大きい‥
DB2 v9.1.5 でのexport_data.001.lob。

abcdefあいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよらりるれろわをんアイウエオカキクケコサシスセソ.

DB2 v9.5.4 でのexport_data.001.lob。

abcdefあいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよabcdefあいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよらりるれろわをんアイウエオカキクケコサシスセソ.

‥この先頭の余分な"abcdef‥やゆよ"は何?‥orz

(追記1)
DB2 Express-C(v9.1.2, v9.5.2, v9.7.0)ではどうだろう、と思って試してみたら、v9.5.2において更なる問題を見つけた。v9.5.4では修正済みということなのだろうけど。
「'$root/hoge'」に対して「'.'」では、ノードhogeの値を参照できず、「'$root'」に対して「'.'」としたらv9.5.4と同じ結果が得られた。

-- The following query can be applied only to v9.5.2
SELECT D.ID, LENGTH(T.DESC_VC) AS LEN_VC, LENGTH(T.DESC_CLOB) AS LEN_CLOB
    FROM DOCUMENT AS D,
        XMLTABLE('$root' PASSING D.DATA AS "root"
            COLUMNS
                DESC_CLOB CLOB PATH '.',
                DESC_VC VARCHAR(311) PATH '.'
        ) AS T
    WHERE D.ID = 'HOGE'
;

(追記2)
DB2 Express-C v9.7.0 での実行結果。

ID       LEN_VC      LEN_CLOB
-------- ----------- -----------
HOGE             190         292

DB2 Express-C v9.7.0 でエクスポートしたファイル。

C:\work> dir
    :(省略)
2009/08/05  20:25               223 export_data
2009/08/05  20:25               292 export_data.001.lob
    :(省略)

DB2 Express-C v9.7.0 でのexport_data.001.lob。

abcdefあいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみabcdefあいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよらりるれろわをんアイウエオカキクケコサシスセソ.

v9.5系よりは小さくなったけど、やっぱり先頭の余分な"abcdef‥ほまみ"は何?‥orz

(追記3)
ちなみに、日本語が入っているとかそういうのは関係ないらしい。"aaaaaaaaa‥aaaaa"みたいな文字列でも発生した。