LightDB Oracle互換性強化:GREATEST/LEAST、DBMS_UTILITY.GET_TIME、MOD関数の内核レベル対応

LightDBは、Oracleユーザーが既存のSQLを一切変更せずに移行できるよう、高度なOracle互換性を提供することを目標としています。このため、Orafce拡張とLightDB独自のカーネル機能を統合し、構文・セマンティクス・エラーハンドリングの両面で一貫した動作を実現しています。バージョン LightDB1.0.V202303.00.000 では、以下のOracle固有機能がカーネルレベルでサポートされました:

  • GREATESTLEAST のNULL挙動および型変換ルールの厳密な再現
  • DBMS_UTILITY.GET_TIME() 関数(1/100秒単位の経過時間取得)
  • MOD(a, b) のゼロ除算時のOracle準拠動作(b = 0 のとき a を返す)

すべての例は、接続パラメータ lightdb_dblevel_syntax_compatible_type = 'oracle' が有効な状態で実行されています。

GREATEST/LEAST のOracle互換動作

PostgreSQL本体にはGREATEST/LEASTが存在しますが、Oracleとの挙動に差異がありました。本バージョンでは以下の3点をカーネルで再定義しました:

  1. 任意の引数がNULLの場合、結果は必ずNULL(短絡評価)
  2. 第1引数のデータ型を基準とし、他の引数は暗黙的にその型へキャストされる
  3. NULLを含む引数が検出された時点で、残りの引数の評価を中止(例:2/0のような例外式も評価されない)
-- NULLが含まれる場合、即座にNULLを返す(2/0は評価されない)
SELECT GREATEST(1, NULL, 2/0) FROM DUAL;

-- 文字列と数値の混合でも、先頭引数の型(ここではTEXT)に統一
CREATE TABLE sample_data (x TEXT, y NUMERIC, z INTEGER);
INSERT INTO sample_data VALUES ('abc', 42, 99);
SELECT GREATEST(x, y, z) FROM sample_data;  -- 結果: 'abc'

-- 全てNULLの場合はNULL、空文字列とは区別される
SELECT LEAST(NULL, NULL, NULL) FROM DUAL;

DBMS_UTILITY.GET_TIME():高精度タイマー関数

この関数は、Oracle互換のミリ秒精度(正確には1/100秒=10ms単位)の時刻取得を提供します。PL/pgSQLブロック内で実行時間計測に利用できます。

DO $$
DECLARE
  t0 INT := DBMS_UTILITY.GET_TIME();
  t1 INT;
BEGIN
  PERFORM pg_sleep(1.5);  -- 1.5秒待機
  t1 := DBMS_UTILITY.GET_TIME();
  RAISE INFO '処理時間: % 秒', ROUND((t1 - t0)::DECIMAL / 100, 2);
END $$;

出力例:INFO: 処理時間: 1.5 秒

MOD関数のゼロ除算対応

OracleではMOD(a, 0)a自身を返します(SQL ServerやMySQLとは異なる)。LightDBもこの挙動を内核で再現します。

-- Oracleと同じ:MOD(7, 0) → 7
SELECT MOD(7, 0) AS result FROM DUAL;

-- 複数行データでも安全に適用可能
SELECT id, amount, MOD(amount, divisor) AS remainder
FROM (
  VALUES (1, 100, 7),
         (2, 200, 0),
         (3, 300, 13)
) AS t(id, amount, divisor);

結果セットの2行目では、divisor = 0のためremainder = 200が返されます。

タグ: lightdb oracle-compatibility plpgsql sql-function dbms-utility

7月29日 16:40 投稿