
Contents
- 普通の
SELECT 文に遅延表示を入れる基本形 - 簡易ランダムウォークの骨組み
- 2
点の色、行ごとの遅延をエスケープシーケンスで追加 - デモ動画
追記 初出時はキャレットを消す方法が不明でしたが、その後(27日夕方)分かったので修正しました。修正前の文書はHTMLの履歴で見れます。
普通の SELECT 文に遅延表示を入れる基本形
実行環境は前回と同じです。エスケープシーケンスを使える他のシェル・ターミナルでも動きそうですが、今回は未確認。PostgreSQL
↓ そのテストと、比較用に
# \t on \\ \pset format unaligned \\ \timing on # select text e'\x1b[?25l' union all select concat(clock_timestamp(),repeat(e'\x1b[m', 2.4E+4 :: int) ) from generate_series(1, 10) union all select e'\x1b[?25h'; # do $$ begin for i in 1..10 loop raise info '%', clock_timestamp();perform pg_sleep(1); end loop; end; $$;

↑ 全部終わった時の画像。10
SELECT
↓ 実行時の動画。確かに
簡易ランダムウォークの骨組み
コンピュータによる普通のランダムウォークは上下左右いずれにもある確率で移動しますが、今回は簡単のため「左下・真下・右下」の↓ まず遅延表示も色もない骨組みを作成。WITH RECURSIVE(再帰クエリ)を使い、後述の終了条件になるまで繰り返します。ウォーク主体は
with recursive setting (ncol, nrow_max) as ( select 30, 30 ), line (rowid, p1, p2) as ( select 1, ncol / 3, ncol / 3 * 2 from setting union all ( select rowid + 1, case when p1 >= p2 or p1 < 1 or ncol < p1 then null elsedirection1(p1) end, case when p2 < 1 or ncol < p2 then null elsedirection1(p2) end from line, setting where p1 is not null and p2 is not null and rowid <= nrow_max order by rowid desc limit 1 ) ) select * from line;
上の赤字
create or replace function direction1(int) returns int language sql immutable as $$ select case when rnd < brk[1] then $1 - 1 when rnd < brk[2] then $1 else $1 + 1 end from cast('{ 0.45, 0.55 }' as float[]) as brk, random() as rnd; $$;
これを実行すると例えば ↓ こんな結果になります。列
+-------+----+----+ | rowid | p1 | p2 | +-------+----+----+ | 1 | 10 | 20 | | 2 | 11 | 21 | | 3 | 12 | 20 | | 4 | 13 | 19 | | 5 | 14 | 19 | | 6 | 13 | 20 | | 7 | 14 | 19 | | 8 | 15 | 18 | | 9 | 16 | 17 | | 10 | 17 | 16 | | 11 | | 17 | +-------+----+----+ (11 行)

上のように途中で終わるのは意外と少なく、大半は終了条件に至らず何

2 点の色、行ごとの遅延をエスケープシーケンスで追加
2create or replace function randwalk_line( ncol int, p1 int, p2 int, color0 text, color1 text, color2 text) returns text language sql immutable as $$ select case when p1 = p2 then concat( repeat(m0, p1 - 1), m1, repeat(m0, ncol - p2)) when p1 = p2 + 1 then concat( repeat(m0, p2 - 1), m2, m1, repeat(m0, ncol - p1)) else concat( repeat(m0, p1 - 1), case when p1 between 1 and p2 then m1 end, repeat(m0, p2 - p1 - 1), case when p1 < p2 then m2 end, repeat(m0, ncol - p2)) end from concat(e'\x1b[38;2;', color0, 'm□') as m0, concat(e'\x1b[38;2;', color1, 'm■') as m1, concat(e'\x1b[38;2;', color2, 'm■') as m2; $$;
上の関数を前項のクエリに加え、各行末に遅延用のエスケープシーケンスを入れて ↓ でき上がり。これで格子とランダムウォークの軌跡が表示されます。冒頭のブロックで列数、最大行数、遅延の長さを変更可。あと前項と同様、実行中だけキャレットを消すため先頭・末尾にもエスケープシーケンスを入れました。
# \t on \\ \pset format unaligned \\ \pset pager off # with recursive setting (ncol, nrow_max, wait) as ( select 30, 30, 1e+4 ), line (rowid, p1, p2) as ( select 1, ncol / 3, ncol / 3 * 2 from setting union all ( select rowid + 1, case when p1 >= p2 or p1 < 1 or ncol < p1 then null else direction1(p1) end, case when p2 < 1 or ncol < p2 then null else direction1(p2) end from line, setting where p1 is not null and p2 is not null and rowid <= nrow_max order by rowid desc limit 1 ) ) select text e'\x1b[?25l' union all select randwalk_line(ncol, p1, p2, '50;50;50', '0;255;0', '255;0;0') || repeat(e'\x1b[m', wait :: int) from line, setting where p1 is not null and p2 is not null union all select e'\x1b[38;2;255;255;255m' || e'\x1b[?25h'; -- reset font color and show caret

稀に
↓ 最後にクエリ全体をストアド化。基本、WITH
create or replace function randwalk1( int, int, float, bool default null) returns setof text language sql immutable as $$ with recursive setting (ncol, nrow_max, wait, init_cls) as ( select $1, $2, $3, coalesce($4, false) -- select 30, 30, 1e+4, true -- ex ), line (rowid, p1, p2) as ( select 1, ncol / 3, ncol / 3 * 2 from setting union all ( select rowid + 1, case when p1 >= p2 or p1 < 1 or ncol < p1 then null elsedirection1 (p1) end, case when p2 < 1 or ncol < p2 then null elsedirection1 (p2) end from line, setting where p1 is not null and p2 is not null and rowid <= nrow_max order by rowid desc limit 1 ) ) select text e'\x1b[?25l' union all select concat(e'\x1b[2J', 'SELECT randwalk1(', ncol, ', ', nrow_max, ', ', wait, ', ', init_cls, ');') from setting where init_cls -- clear screen union all selectrandwalk_line (ncol, p1, p2, '50;50;50', '0;255;0', '255;0;0') || repeat(e'\x1b[m', wait :: int) from line, setting where p1 is not null and p2 is not null union all select e'\x1b[38;2;255;255;255m' || e'\x1b[?25h'; -- reset font color and show caret $$;
デモ動画
ストアドの実行例をキャプチャし、WEBM動画で実行しているクエリは ↓ こちら。2
# \t on \\ \pset format unaligned \\ \pset pager off # select randwalk1(15, 50, 2e+4);
列数

