H2Databaseを追っかけていたりしたブログ

H2 database のリリースノートを読んだりとか。

Version 1.4.179 Beta (2014-06-23)

今回、MVStore周りの大丈夫か?というような不具合が修正されています。ML読んでても、引き続き不具合が出ているようです。まぁ、βだしね...

  • ライセンスがMPL2.0とEPL1.0に変更になった (MPL1.0からMPL2.0へ)
  • Issue565: MVStore: MULTI_THREADEDオプションがある状態で、並行にLOBオブジェクトを追加するとNullPointerExceptionが発生する
  • MVStore: その他のH2のクラスに対しての依存を低減
  • データベースの再オープンを妨げるように高位のIDのテーブル(後に作られたテーブル)のカラムを参照する制約を作成することができていた。これは現在検出されるようになっており、そのようなテーブルの作成は禁止されている。将来のバージョンのH2では、このような問題のために、その他のテーブルの参照はサポートされなくなる
    • 例によってよくわからない..原文は下記の通り.
    • There was a way to prevent a database from being re-opened, by creating a column constraint that references a table with a higher id. This is now detected, and creating the table is prohibited. In future versions of H2, most likely creating references to other tables will no longer be supported because of such problems.
  • MVStore: "nulls first"の降順インデックスが期待した通りに動作していなかった(nullが最後になっていた)
  • 大きな結果セットが、テンポラリファイルの代わりに常にテンポラリテーブルを作成するようになった
  • PageStoreを使っている場合、テンポラリテーブルを使用した場合に、データベースのオープン時にNullPointerExceptionが発生して、失敗するケースがあった(明示的に、あるいは、暗黙的に大きな結果セットを使用する場合)
  • PageStoreファイルフォーマットのファイルが存在する場合、データベースURLに"MV_STORE=FALSE"が含まれていなくても、そのファイルとそのモードが使用されるようになった。MVStoreファイルがあった場合、それが使用される。
  • version 1.3.175以前で作成されたデータベースで、マルチカラムのインデックスと外部キーの組合せを含む場合、幾つかのケースでオープンできないことがある。これは、version 1.3.176 の「参照整合性制約で間違ったインデックスを使用してしまうことがある」の不具合対応によるもの
  • MVStore: 片方がSerializableで、もう片方が共通クラスの場合、ObjectDataTypeの比較メソッドが不正確な動作をする
  • ライセンスがMPL 2.0 + EPL 1.0に変更された
  • MVStore: 結果セットによって作成されたテンポラリテーブルがデータベースの再オープン時にも生き残ってしまい、結果としてClassCastExceptionを引き起こすことがある
  • Issue 566: MVStore: 5000行を超えるテーブルに後付けでユニークインデックスが作成された時正確に動作しない
  • MVStore: 大きなテーブルに第2のインデックスを作成した時、インデックス内で行を見失うことがある
  • Metadata: linked tableのパスワードは管理者しか参照できなくなった。
  • Windowsにて"jdbc:h2:/test"形式のデータベースURLは相対パスと判定され、システムプロパティ"h2.implicitRelativePath"を使用しない場合動作しなくなった。
  • Windows: ベースディレクトリに"C:/"や類似の形式を指定した場合に期待通りに動作していなかった。
  • プロシージャのメタデータについてのJDBC仕様に追随。プロシージャの返り値の型として、P0を使用。
    • P0?
  • Issue 531: IDENTITYがカラム追加の際には無視されていた
  • FileSystem: スローされる例外をJDK互換のものに変更
    • IOExceptionをスローしていたところがNonWritableChannelExceptionに変更されています
  • Spatial Index: クエリにintersect演算子が含まれていない場合、Spatial Indexを使用しないのでコストを調整した
  • TableFunctionを含むビューを使っている場合のマルチスレッドのデッドロックを修正
  • とても小さなBigDecimalの数値で除算を行った場合の不具合を修正

h2databaseを読む3

データがデータファイルに具体的にどのように書き込まれているかを見てみます。

f:id:ysobj:20140607124441p:plain

PageDataLeafをみると、キーとそのオフセット(キーに該当するデータの位置)がデータファイルの前のほうから、実データはデータファイルの後ろの方から並べています。オフセットからオフセットの間がちょうど1行のデータとなります。

1行のデータはどのようになっているかというと次のような感じになっています。

f:id:ysobj:20140607125733p:plain

まずデータ型で1byte。ここのデータ型はCREATE TABLEで指定するデータ型ではありません。データ型の後、実際のデータが続きますが、ここの長さはデータ型により異なります。NULLやBOOLEAN_TRUE,BOOLEAN_FALSEなど、データ型によってはデータ型だけ存在していて、データの値部分が存在しないものもあります。

ふーん、と思ったのは、数値型についてはvarInt/varLongという可変長のint/longを使っている点です。varIntの場合は1~5バイト使用し、varLongの場合は1~10バイト使用されます。平均的に、そんなに大きい値を使う事はない、ということでトータルでこの方が使用サイズは少なくて済むのかな。なお、varInt/varLongではマイナスの値はそれぞれ5バイト、10バイト使ってしまうので、内部データ型で、INTとINT_NEG、LONGとLONG_NEGというようにそれぞれネガティブ型が用意されていて、格納する場合は正の数として書き込んでいて、値を取得する場合に反転しています。ここらへんは、org.h2.store.Data#readValueあたりに書かれています。

内部データ型としては、NULL型、BOOLEAN_TRUE型、BOOLEAN_FALSE型、INT_NEG型、INT型、LONG_NEG型、LONG型、BYTE型、SHORT型を初めとして、約40数個の内部データ型が存在しています。

データの追加と削除については、ページ分割が発生したり、オーバーフローが発生したりする場合以外は、あんまり面白い事はしていません。byteの配列をSystem.arraycopyで地道に移動したり、0埋めしたり、そんな感じです。

h2databaseを読む2

f:id:ysobj:20140526075951p:plain

H2のPageStoreでは、データベースのデータを1つのファイルで管理しており、この1つのファイルをページ単位(PAGE_SIZEで指定可能で、デフォルトは2048バイト。512バイトから32768バイトまでの2のべき乗サイズを指定可能です。)で管理します。この1ページがそのまま1つのorg.h2.store.Pageオブジェクトに対応します。

Pageは入っている中身により、別々の具象クラスがあります。

テーブルのデータはorg.h2.store.Pageを継承するorg.h2.index.PageData(PageDataNode/PageDataLeaf)型で管理されます。
インデックスと同様B-Tree構造になっています。
PageDataNodeはキーとページ番号だけが格納され、PageDataLeafにはキーと実際のテーブルのデータが格納されています。

ここで「キー」と言っているのは、いわゆるプライマリーキーではなく、内部的なキーのことです。プライマリーキーのないテーブルや、プライマリーキーが数値以外の型であってもここでのキーは必ずlong型となります。挙動として、プライマリーキーが数値の場合、プライマリーキーが内部のキーとしてそのまま使われるので効率的です。

なお、1つのPageDataの中には1つのテーブルのデータしか入りません。0行であっても、CREATE TABLEの時点でルートになるページが作成されるので、最低PAGE_SIZE分はデータファイルが拡張します。

org.h2.index.PageDataNode

自分の子供となるPageDataNode/PageDataLeafのページ番号とキーと、そのbyte表現(org.h2.store.Data)を保持しています(このbyte表現がそのままデータファイルのページのフォーマットです)

rootノードのみ、テーブル全体の行数を保持しています(rootノード以外のノードは行数は-1が入っている)。(H2でselect count(*) from TABLE が速いのはここの件数をみるだけだから)

org.h2.index.PageDataLeaf

f:id:ysobj:20140607124441p:plain

テーブルの行オブジェクト(org.h2.result.Rowの配列)と、そのbyte表現(org.h2.store.Data)を保持しています。データファイルは、ヘッダ部分と、キー/オフセット値部分、実際の行データ部分に分かれます。

キーは内部的なキー(前述のとおり、プライマリキーと同じこともあります)で、オフセット値はそのキーの行データがbyte表現の何バイト目から始まるかを示します。キーとオフセットはバイト列を前から使っていき、実際の行データは後ろから使っていきます。これは、PostgreSQLのテーブルのページレイアウトと同じ方式です(この方式、元があるのでしょうか)

org.h2.index.PageDataIndex

PageDataからデータを取得するためのIndexです。これはPageDataNode/PageDataLeafと異なり、データファイルには保存されず、org.h2.store.Pageの子孫でもありません。

Version 1.4.178 Beta (2014-05-02)

思ったより短い間隔でリリースされました。MVStoreとOSGi関連の修正が中心。

  • Issue 559: org.osgi.service.jdbcへの依存をオプションにする
  • ユーザがサポートされないデータベース設定の組み合わせを指定した場合のエラーメッセージの改善
  • MVStore: マルチスレッドモードでNullPointerExceptionやその他の例外が発生していた
  • MVStore: いくつかのデータベースファイルでフィルレートを記帳するためのバグによりコンパクト化が出来ていなかった。また、データベースのコンパクト化が非常に遅かった。これは改善されたが、このあたりの処理についてはなお改善が期待される。
    • Chunkという単位で管理されていて、その中の有効データの充足率=フィルレート
  • MVStore: 変更が記録されない揮発性のマップのサポート
  • MVStore mode: インメモリデータベースでもMVStoreを使用するようになった
  • サーバモードにて、データベースURLに";autocommit=false"を追加すると正しく動作はしているが、Connection.getAutoCommit()の返り値が正しくなかった。
  • Issue 561:OSGi: org.h2のインポートパッケージの宣言がversion 1.4を除外していた
    • 原文は"the import package declaration of org.h2 excluded version 1.4."
    • これ元のIssueのタイトルの方がわかりやすい。"H2 1.4 is using an invalid OSGi version import range"
    • H2 1.4が使用しているOSGi バージョンのインポートの範囲指定が不正
  • Issue 558: MVStoreでLOBを使用していてセッションのコミット時にNullPointerExceptionを起こす可能性がある(LobStorageMap.removeLob)
  • 誤解を減らすために、"h2.MAX_MEMORY_ROWS_DISTINCT"システムプロパティを削除。同様の指定であるMAX_MEMORY_ROWSが既にあるし、こちらのほうがよりよくドキュメント化されている
  • Issue 554: IFrame内でのWeb Consoleが完全にサポートされていなかった

Version 1.4.177 Beta (2014-04-12)

さくっと1.4ベータが出ました。次は1.3.178だったりするんでしょうが、ここらへんのバージョン番号のポリシーは独特ですね。

  • デフォルトで新しいMVStoreストレージを利用するためのMV_STOREオプションが有効に。MVCC設定もデフォルトではMV_STORE設定と同じ値になるため、これもデフォルトで有効となる。テストのため、これらの設定は";MV_STORE=FALSE"や";MVCC=FALSE"をデータベースURLに追記する事で無効化する事が出来る。
  • ファイルロックメソッド'serialized'がサポートされなくなった。このモードは将来のバージョンで復活するかもしれないが、現時点でははっきりしていない。新たな実装と新たなテストケースが必要となる。
  • 日時の新たなストレージのフォーマットが有効になった(システムプロパティ "h2.storeLocalTime") これは、MVStoreモードにおいては常に有効であり、バージョン1.4ではPageStoreモードでも有効となる。
    • PageStoreなくなるかなと思ってたら当面なくならなさそうですね。まぁ、そりゃそうか。
  • 暗黙的な相対パスが無効になった(システムプロパティ "h2.implicitRelativePath")。そのため、データベースURL jdbc:h2:test は jdbc:h2:./test と書く必要がある。
  • H2の標準モードで "select ... fetch first 1 row only" が有効になった。これまで "fetch" はキーワードではなかったため、無効となっていた。Mode.supportOffsetFetch 参照。
    • これ、原文間違っているような気がするんですよね。"fetch" was not a keyword? 以下原文。
    • select ... fetch first 1 row only" is supported with the regular mode. This was disabled so far because "fetch" is now a keyword. See also Mode.supportOffsetFetch.
  • バイト配列が符号なしでソートされるようになった(x'99' は x'09' より大きい)。(システムプロパティ "h2.sortBinaryUnsigned", Mode.binaryUnsigned, および設定 "binary_collation" を参照).
  • Csv.getInstance は1.4の将来のバージョンで削除される。代わりに、publicなコンストラクタを使用すること。
  • 限定的な旧スタイルの"(+)"を使ったアウタージョインのサポートを削除。"outer join"を代わりに使用すること。システムプロパティ "h2.oldStyleOuterJoin".
    • 原文は "Remove support" となっていますが、h2.oldStyleOuterJoin を明示的に設定しておくことでとりあえず現時点では利用可能です(svnのコミットログを見ると"Make old-style outer joins optional"となっているし)。でも、これは結構影響が大きそうな気がしますね。
  • MS SQLサーバの互換性向上のため、DATETIME2をDATETIMEのエイリアスとした
  • Oracle互換の TRANSLATE 関数の追加

Version 1.3.176 (2014-04-05)

今回から、1.4Betaでの変更内容がchangelogに載るようになったようです。最近リリース間隔が広くなってきているので、1.4までは半年くらいかかるのかな。

試してはいませんが、MV_STOREも大分速くなってきたようです。1.4ではデフォルトのストアが現行のPageStoreから切り替わる事になっているので、ここらへんのチューニングが肝ではあるのでしょう。あと、今回はchangelogsvnのコミットログがあまりきっちり対応してなくて見にくかった(ような気がする)

  • ファイルロックのためのメソッド 'serialized' がドキュメントに記載されなくなった。これは、version 1.4 で削除されます。
  • スタティックメソッド Csv.getInstance() が削除された。代わりにパブリックなコンストラクタを使用する事。
  • Script, RunScript, Shell 及び CreateCluster のデフォルトユーザ名が"sa"ではなく、空文字列になった。
  • "そのオブジェクトはクローズされています"という例外のスタックトレースがデフォルトではログに出力されなくなった
  • 結果セットの値自体が結果セットだった場合、結果自体が一度しか読まれなくなった(再利用される)
  • カラムの制約がViewから見えるようになった
  • 既に権限がついているテーブルに対しての追加の権限の付与が動作しなかった
    • ここらへん、細かく制御してるところってどれくらいあるもんなんですかね(自分はWebアプリ界隈ですが、実質制御なしにしているところが多い印象)
    • 1.3.175
sql> create role new_role;
(Update count: 0, 0 ms)
sql> create table hoge(id int);
(Update count: 0, 1 ms)
sql> grant select on hoge to new_role;
(Update count: 0, 2 ms)
sql> select * from information_schema.table_privileges;
GRANTOR | GRANTEE  | TABLE_CATALOG | TABLE_SCHEMA | TABLE_NAME | PRIVILEGE_TYPE | IS_GRANTABLE
null    | NEW_ROLE | UNNAMED       | PUBLIC       | HOGE       | SELECT         | NO
(1 row, 3 ms)
sql> grant insert on hoge to new_role;
(Update count: 0, 1 ms)
sql> select * from information_schema.table_privileges;
GRANTOR | GRANTEE  | TABLE_CATALOG | TABLE_SCHEMA | TABLE_NAME | PRIVILEGE_TYPE | IS_GRANTABLE
null    | NEW_ROLE | UNNAMED       | PUBLIC       | HOGE       | SELECT         | NO
(1 row, 1 ms)
    • 1.3.176
sql> create role new_role;
(Update count: 0, 1 ms)
sql> create table hoge(id int);
(Update count: 0, 0 ms)
sql> grant select on hoge to new_role;
(Update count: 0, 3 ms)
sql> select * from information_schema.table_privileges;
GRANTOR | GRANTEE  | TABLE_CATALOG | TABLE_SCHEMA | TABLE_NAME | PRIVILEGE_TYPE | IS_GRANTABLE
null    | NEW_ROLE | UNNAMED       | PUBLIC       | HOGE       | SELECT         | NO
(1 row, 4 ms)
sql> grant insert on hoge to new_role;
(Update count: 0, 2 ms)
sql> select * from information_schema.table_privileges;
GRANTOR | GRANTEE  | TABLE_CATALOG | TABLE_SCHEMA | TABLE_NAME | PRIVILEGE_TYPE | IS_GRANTABLE
null    | NEW_ROLE | UNNAMED       | PUBLIC       | HOGE       | SELECT         | NO
null    | NEW_ROLE | UNNAMED       | PUBLIC       | HOGE       | INSERT         | NO
(2 rows, 12 ms)
  • Spatial index: 幾つかのバグが修正された(空間制約がビューの中で使われているとき、TCP/IP上でジオメトリオブジェクトが転送するとき、必要に応じジオメトリオブジェクトが必要に応じてコピーされたとき)
    • カッコの中の部分の原文は"(using spatial constraints in views, transferring geometry objects over TCP/IP, the returned geometry object is copied when needed)"
  • Issue 551: データタイプについてのドキュメントが不正確だった
  • Issue 368: 複数行のinsertに対して、ON DUPLICATE KEY UPDATEが動作していなかった
  • OSGi: javax.toolsパッケージがインポートされた(オプションとして)
  • H2 Console: オートコンプリートがデフォルトでは無効に。ただしホットキー(Ctrl+Space)は有効
  • H2 Console: オートコンプリートが複数行ステートメントで無効だった
  • CLOBとBLOGデータがロールバック後即座に削除されていなかった
  • H2内部の型をサポートする新しい集約APIの追加
    • org.h2.api.Aggregateインターフェースが追加になっています。
  • 参照整合性制約が間違ったインデックスを使ってしまうことがあり、参照されるテーブル内で更新された行が整合性違反で不正に更新に失敗することがあった
  • ポーランド語翻訳が完了
  • Issue 545: 不要な重複コードの削除
  • プロファイラツールがフルスレッドダンプを含むファイルを扱えるようになった
  • MVStore: ファイルフォーマットが少し変更された
  • MVStore mode: CLOBとBLOBストレージが再実装され、現在デフォルトのPageStoreよりもずっと速くなった
  • MVStore mode: インデックスの作成がかなり速くなった(多くの場合デフォルトのPageStoreよりも速い)
  • 多様なMVStore関連の不具合の修正。これには、R-tree実装のバグも含む。保存時に一時的なIOExceptionが発生した場合、データベースが不整合になる可能性がある。
    • 原文は"Various bugs in the MVStore storage and have been fixed, including a bug in the R-tree implementation. The database could get corrupt if there were transient IO exceptions while storing."
  • メソッドorg.h2.expression.Function.getCostがNullPointerExceptionをスローする可能性がある
  • 新規データベースでLOBを個別のファイル(メインのデータベースファイル外)へ保存をサポートしなくなった
  • Lucene 2 がサポートされなくなった
    • Lucene 3 はサポートされている...といいつつ今Luceneの最新は4.7だったりするわけで...
  • SEQUENCEのデフォルトのMINとMAXの算出についてのバグ修正
  • IGNORECASE=TRUE で、複数の値を使った IN を含むクエリを処理する際のバグ修正
  • アプリケーションの内部から呼び出せるようにエントリポイントを org.h2.tools.Shell に追加
  • pgServerが停止と起動を複数回繰り返すのを避ける対応のバグ修正
    • いまいち良く分からない 原文は、"Fix bug that prevented the PgServer from being stopped and started multiple times."
  • MySQL向けのDDLの追加サポート
    • ALTER TABLE の CHANGE 構文が追加になったようです。
alter table test change column id id2 int
  • Issue 548: TO_CHARが月もしくは日が1桁の時にMMとDDが正しくフォーマットしていなかった
  • ALIASのvarargsサポートのバグ修正

Version 1.3.175 (2013-01-18)

今回はchangelogに挙った変更点は若干少なめ。ただMVStoreの修正はほとんどchangelogに載らずにばんばん修正入っているようです。

今回のchangelogで初めて知ったのですが、HikariCPという高速が売りのConnection Poolがあるのですね。Tomcat CPの100倍以上速いとか。

https://github.com/brettwooldridge/HikariCP

あと、久しぶりに送ったパッチが取り込まれました。DB2のWITH UR等の isolation-clause と lock-request-clause を読み飛ばすという、DB2との互換性向上のパッチ。

Oracle互換モードで空文字列をnullのように扱う」は結構嬉しい人も多いのではないでしょうか。

  • "ANY" もしくは "SOME" を含むクエリでEXPLAINが不正だった
  • "out"パラメータを含むCallableStatement: 同じステートメントを二度実行すると例外が発生していた("パラメータがセットされていません")
  • Unionクエリ: サブクエリに"order by"を含んでいた場合、重複行が返される場合があった
  • GEOMETRYデータタイプが結果セットを返すユーザ定義関数で動作するようになった
  • PostgreSQL互換性: PgServerがdatabase_to_upperがfalseに設定されている場合に正しく動作していなかった
  • JdbcDataSource: setUrl及びgetUrlがsetURLとgetURLのエイリアスとして追加された。これはHikariCP(Hikari connection pool)との問題を解決するためのもの。
  • Issue 537: H2 Console: スキーマの読み込み時に、不正なJDBC呼び出しが発行されており、"カラムの精度が見つかりません"という例外が発生する原因となっていた
  • Geometry処理の改善(issue 535)
  • 既にあるテーブルと照合順序が同じ場合にデータベースURLで照合順序を設定できるようになった。
    • ちょっとわかりにくい...原文は "The collation can now be set in the database URL, even if there are data tables, if the collection is the same as the current collation."
    • 元々は、テーブルが一つでも作られてしまうと照合順序が同じであっても再セットできない仕様だったため、事実上データベースURLに照合順序を設定できない(初回接続でテーブルを作成すると2回目以降同じデータベースURLでもエラーになってしまう)、ということになっていたので、それを回避するための改修だと思われます。
  • Oracleとの互換性の改善: CASE WHENとDECODE
    • それぞれ短絡評価をするようになったのと、CASE WHENで対象の式を1度しか評価しなくなったっぽいですね。こ、細かい。
    • 1.3.175で実行。
sql> create sequence seq;
(Update count: 0, 2 ms)
sql> select case seq.nextval when 2 then 'two' when 3 then 'three' when 1 then 'one' else 'other' end result from dual;
RESULT
one
(1 row, 5 ms)
sql> select decode(1, 1, '1', 1, '11') r from dual;
R
1
(1 row, 1 ms)
    • 1.3.174で実行。
sql> create sequence seq;
(Update count: 0, 2 ms)
sql> select case seq.nextval when 2 then 'two' when 3 then 'three' when 1 then 'one' else 'other' end result from dual;
RESULT
other
(1 row, 6 ms)
sql> select decode(1, 1, '1', 1, '11') r from dual;
R
11
(1 row, 1 ms)
  • 制約を経由してビューに依存しているテーブルがある場合に"drop all objects"ステートメントが動作していなかった
    • 具体的には下記のような場合(テストケースからの抜粋)
        stat.execute("create table a(x int)");
        stat.execute("create view b as select * from a");
        stat.execute("create table c(y int check (select count(*) from b) = 0)");
  • サブクエリもしくはビューでorder byと一緒にエイリアスが使えなかった。これは1.3.174でのデグレード
    • 下記のSQLが1.3.174では文法エラーになっていた。
select * from (select x as y from dual order by y);
  • Issue 73: MySQLとの互換性の向上: REPLACEのサポート
    • 知らなかったんですが、DB2とかOracleのMERGE文相当なんですね。
  • MVStoreストレージ上でMVCCモードで空間インデックスが動作するようになった
  • MVStore: 同時平行稼働の問題が修正された。APIがシンプルになった。
  • 制約の配下のインデックスを削除しようとした場合のエラーメッセージから制約を特定できるように、エラーメッセージを改善。
  • Issue 518: EXCLUSIVEな接続でLOBを更新した後、java.sql.Connection.commit() でフリーズしていた
  • Issue 517: Create or replace viewステートメントが既に存在しているJDBC接続に対して効果がなかった
    • Aテーブルを参照しているビューXをリプレースして、Bテーブルを参照するようにしてもそれが別のコネクションに反映されなかった(Aテーブルを参照し続けた)、というか厳密には、ビューのリプレース時に内部的なデータベース変更履歴番号が更新されなかったため、クエリキャッシュが無効にならなかった、ということみたい。
  • Javaのような123Lシンタックスのサポート。例) SELECT (2000000000L*2)
  • Issue 520: シーケンスの最大値、最小値、循環のサポート
    • あと、併せてNOCACHEもサポートされたみたい
  • Issue 521: ScriptReaderがCloseableをimplement
    • CloseableってJava7からかと思ってた...
  • Issue 524: RunScript.executeが自身のStatementをクローズしていなかった
  • DB2の"WITH UR"句のサポート
  • MySQLのような values() 関数を伴うON DUPLICATE KEY UPDATE文によるinsertされるデータによるupdateのサポート。
    • なんだかよくわからない文に...原文は"Added support for ON DUPLICATE KEY UPDATE like MySQL with the values() function to update with the value that was to be inserted."
    • MySQL likeといいつつ、MySQLモードでのみのサポート。これもMERGE文みたいなもんですね。
    • テストケースのSQL
INSERT INTO table_test ( id , a_text, some_text ) VALUES (1, 'zzzzzzzzzz', 'abcdefghij') ON DUPLICATE KEY UPDATE some_text='UPDATE';
INSERT INTO table_test ( id , a_text, some_text ) VALUES (3, 'zzzzzzzzzz', 'SOME TEXT') ON DUPLICATE KEY UPDATE some_text=values(some_text);
  • Issue 522: Oracle互換モードで空文字列をnullのように扱う
  • Issue 527: Oracle互換モード: 不正確な位取りの挙動
  • ビューのメタデータの消費メモリをわずかに削減
    • String型の変数1個削減
  • 付与されたユーザがテーブルを操作できるように"GRANT ALTER ANY SCHEMA TO "のサポートの拡張。
  • Issue 532: ErrorCode.ROLES_AND_RIGHT_CANNOT_BE_MIXEDのJavadocが良くなかった
  • Issue 528: Oracle互換の TO_CHAR 関数の追加
  • Issue 534: CREATE ALIAS で NOCACHE のサポート
    • といいつつ、実際の引数としては、NOBUFFER。
  • CLOBでのユニコードサロゲートペアの保存についての課題の解決
  • H2 console: SHIFT+ENTERで"選択された文の実行"
  • DB2の"select * from test with ur"文法のバグの修正
  • DROP ALL OBJECTSで、内部的な依存性の取り扱いのバグの修正

そういやH2追っかけ始めてそろそろ4年。