
Contents
実行環境 Windows 7 + PostgreSQL 9.5.0 に PL/v8 をインストール PostGIS 2.2 のインストールは 9.5 RC1 の時と同様(以上、1 月 23 日) PNG ファイルをインポートして PostGIS ラスタのサンプルデータを作る インポートしたラスタを再び PNG ファイルに出力して確認(以上、1 月 24 日) PostGIS ラスタで画像処理、続けて PNG ファイルに出力するテンプレート PostGIS の関数のソースを見て、PL/v8 への置き換えを考える(以上、1 月 25 日) - コールバック関数
ST_Range4ma の PL/v8 版を作る - PL/pgSQL
の単純化バージョンも作る - SQL
でもコールバック関数を作る - テストの全体
(以下、1 月 28 日) コールバック関数 4 つ × 周辺範囲 5 つ × 複数回テスト、を一つのクエリで テスト結果の TSV を PostgreSQL にインポート PL/v8 の方が、元からある PL/pgSQL の数倍速い (以下、1 月 31 日) テスト結果の PostgreSQL テーブルを R で読み込む 今回のテストと外れ値、95% 信頼区間について 全体を一つの棒グラフにまとめる(エラーバー付) ピクセル範囲から所要時間を予測する回帰式(関数別) 全体のまとめ
コールバック関数 ST_Range4ma の PL/v8 版を作る
やっと本題に来ました。昨日の最後にソースを見たST_Range4ma(PostGIS中身は、配列の最大値-最小値を出すだけで
create or replace function plv8_range4ma ( val float[][][], pos int[][] default NULL :: int[][], userargs text[] default NULL :: text[] ) returns float language plv8 immutable as $$ return Math.max.apply(null, val) - Math.min.apply(null, val); $$; -- Check select plv8_range4ma( '{ { { 1, 2, 3 }, { 4, 5, 6 }, { 4, 5, 6 }, { 7, 8, 9 } } }'); +---------------+ | plv8_range4ma | +---------------+ | 8 | +---------------+ (1 row)

関数の動作チェックのクエリは、ラスタと同様の
ところで、昨年
create or replace function plv8_range4ma_tarray ( val plv8_float8array, -- Typed Array pos int[][] default NULL :: int[][], userargs text[] default NULL :: text[] ) returns float language plv8 immutable as $$ return Math.max.apply(null, val) - Math.min.apply(null, val); $$; -- in vain select plv8_range4ma_tarray( '{ { { 1, 2, 3 }, { 4, 5, 6 }, { 4, 5, 6 }, { 7, 8, 9 } } }');ERROR: NULL element, or multi-dimension array not allowed in external array type

PL/pgSQL の単純化バージョンも作る
前項の最初に書いたとおり、PL/v8create or replace function simple_range4ma ( val float[][][], int[][] default NULL :: int[][], text[] default NULL :: text[] -- PL/v8と違い、引数名を省略できる ) returns float language plpgsql immutable as $$ declare nras int := array_length(val, 1); nrow int := array_length(val, 2); ncol int := array_length(val, 3); ras int; row int; col int; min float; max float; tmp float; begin for ras in 1 .. nras loop for row in 1 .. nrow loop for col in 1 .. ncol loop tmp := val[ras][row][col]; if min is null or tmp < min then min := tmp; end if; if max is null or max < tmp then max := tmp; end if; end loop; end loop; end loop; return max - min; end; $$;

SQL でもコールバック関数を作る
今回ならったPostgres Online Journalcreate or replace function sql_range4ma ( val float[][][], int[][] default NULL :: int[][], text[] default NULL :: text[] ) returns float language sql immutable as $$ select max(v) - min(v) from unnest(val) as v; $$;

unnest
select unnest( '{ { { 1, 2, 3 }, { 4, 5, 6 }, { 4, 5, 6 }, { 7, 8, 9 } } }' :: text[]); +--------+ | unnest | +--------+ | 1 | | 2 | | 3 | | 4 | | 5 | | 6 | | 4 | | 5 | | 6 | | 7 | | 8 | | 9 | +--------+ (12 rows)

テストの全体
以上でテストの準備が整いました。コールバック関数は次の- PL/pgSQL(PostGIS
に元からある版)→ 出力ファイル st_range4ma_xx.png - PL/pgSQL(単純化した自作版)→
simple_range4ma_xx.png - PL/v8
→ plv8_range4ma_xx.png - SQL
→ sql_range4ma_xx.png
ラスタ演算に用いる「周辺の範囲」は次の
- 0, 0(全ピクセルがゼロになる。対象ピクセル=周辺ピクセルで、どこでも最大値=最小値だから)
- 1, 1
- 2, 2
- 3, 3
- 4, 4
以上、4
copy ( select ST_AsPNG(ST_MapAlgebra ( rast, 1, 'コールバック関数名(float[][][], int[][], text[])', '8BUI', 'FIRST', NULL, 周辺範囲・南北, 周辺範囲・東西) ) from adbadge_tall ) to program '"D:/AppsPortable/GitPortable/2.6.2/App/Git/usr/bin/xxd" -r -p > "出力先PNGファイルパス"';

参考まで、出力した全
20