Mark -- Thanks for the question regarding "Retrieving DBMS_OUTPUT.put_line from JDBC?", version 9.2.0.4

PL/SQLDBMS_OUTPUT.PUT_LINE()に出した内容をJDBC経由で取得する方法。
なるほど,DBMS_OUTPUT.GET_LINE()を使うのか。


ただのバッチ処理向けに作ったPL/SQLは,Java経由で呼ばれる事など気にしないので普通にDBMS_OUTPUT.PUT_LINE()でレポートしてたりするわけだ。せっかく気を利かせて(?)JUnitでテスト組んでも,この部分の証跡が取れないので困っていたが,これで解決。:-D
#こんなことなら,もっと早く調べておけばよかった。


なお,Groovy(GSQL)だともっと簡単(バッファサイズとかはテキトウに調整して)。

void showOutput() {
  def exitFlag = false

  println ">>> 標準出力の内容:BEGIN -----"
  while (!exitFlag) {
    sql.call("""
    DECLARE
      l_line varchar2(255);
      l_done number;
      l_buffer long;
    BEGIN
      LOOP
        EXIT WHEN LENGTH(l_buffer) + 255 > 32000 OR l_done = 1;
        DBMS_OUTPUT.GET_LINE(l_line, l_done);
        l_buffer := l_buffer || l_line || CHR(10);
      END LOOP;
      ${Sql.INTEGER} := l_done;
      ${Sql.VARCHAR} := l_buffer;
    END;""") { done, buffer ->
      print buffer
      exitFlag = done == 1
    }
  }
  println "<<< 標準出力の内容:END ----"
}

もちょっとシンプルに。これでも動いてる。

void showOutput() {
  def exitFlag = false

  println ">>> 標準出力の内容:BEGIN -----"
  while (!exitFlag) {
    sql.call("BEGIN DBMS_OUTPUT.GET_LINE(${Sql.VARCHAR}, ${Sql.INTEGER}); END;") { buffer, done ->
      println "${buffer ?: ""}"
      exitFlag = done == 1
    }
  }
  println "<<< 標準出力の内容:END ----"
}

あとは,setup()/teardown()にこんなコード仕込んでおしまい。

setup():
  sql.call("BEGIN DBMS_OUTPUT.ENABLE(1000000); END;")
teardown():
  sql.call("BEGIN DBMS_OUTPUT.DISABLE; END;")