Scheduler
libpq による PostgreSQL へのアクセス
xgawk の特筆するべき拡張として libpq を用いた PostgreSQL へのアクセスがあります。 従来 awk はテキストのみの処理であるため、自前で CSV, TSV などのデータベースファイルを用意する必要があり、大規模なデータ処理には不向きでした。 libpq を介して PostgreSQL にアクセスすることにより、SQL を直接的に操作することも可能であり、データベースを扱える言語になりました。
ここでは WebCalendar から入力した OSC2008 Tokyo/Spring のスケジュールを PostgreSQL から読み取り表示させるスクリプトを紹介しています。
scheduler.awk
#! /usr/local/bin/xgawk -f
@load pgsql
BEGIN {
# settings
host = "localhost";
dbname = "webcal";
user = "webcal";
password = "XXXXXX";
now_date = strftime("%Y%m%d");
now_hour = strftime("%H");
# main
conn = pg_connect("host=" host " dbname=" dbname " user=" user \
" password=" password);
comm = "select eu.cal_id, eu.cal_status, e.cal_time, e.cal_date, e.cal_name from webcal_entry_user eu, webcal_entry e where eu.cal_id=e.cal_id and eu.cal_status='A';"
if (pg_sendquery(conn, comm) > 0) {
while ((res = pg_getresult(conn)) != "") {
process_result(res);
numres++;
}
}
pg_disconnect(conn);
for (i in pg_contents) {
split(pg_contents[i], a_pg_contents, /\|/);
if (substr(a_pg_contents[3], 1, 2) == now_hour && \
a_pg_contents[4] ~ now_date) {
print a_pg_contents[5];
}
}
}
#---------------------------------------------------------------------
# process_result - get and perform PostgreSQL contents
function process_result(res, nf, nr, col, row, rowdata) {
if (res ~ /^ERROR/) {
printf "error message: %s\n", ERRNO > "/dev/stderr";
if (res ~ /^ERROR BADCONN/) {
print "Attempting to reset the connection." > "/dev/stderr";
if (pg_reset(conn) < 0) {
printf "pg_reset failed: %s\n", ERRNO > "/dev/stderr";
exit 1;
}
}
return;
}
if (res ~ /^OK/) {
return;
}
if (res ~ /^TUPLES /) {
nf = pg_nfields(res);
nr = pg_ntuples(res);
for (row = 0; row < nr; row++) {
for (col = 0; col < nf; col++) {
if (col > 0) {
pg_contents[row] = pg_contents[row] "|";
}
pg_contents[row] = pg_contents[row] (pg_getisnull(res,row,col) ? "<NULL>" : pg_getvalue(res,row,col));
}
##print pg_contents[row];
##printf "\n";
}
pg_clear(res);
return;
}
if (res ~ /^COPY_OUT /) {
row = 0;
while ((rowdata = pg_getcopydata(conn)) != "") {
printf "COPY OUT row %d = %s\n", row++, rowdata;
}
if (ERRNO != "") {
printf "Warning: pg_getcopydata returned error: %s\n",
ERRNO > "/dev/stderr";
}
printf "COPY OUT completed after %d rows, check next result for status\n", row;
return;
}
if (res ~ /^COPY_IN /) {
row = 0;
while (1) {
if (getline <= 0) {
print "unexpected EOF during COPY IN" > "/dev/stderr";
exit 2;
}
if ($0 == ":COPY EOF:") {
break;
}
if (pg_putcopydata(conn, ($0"\n")) < 0) {
printf "pg_putcopydata failed: %s\n", ERRNO > "/dev/stderr";
return;
}
row++;
}
if (pg_putcopyend(conn) < 0) {
printf "pg_putcopyend failed: %s\n", ERRNO > "/dev/stderr";
return;
}
printf "COPY IN complete for %d rows, check next result for status\n", row;
return;
}
printf "unknown result type: %s\n", res > "/dev/stderr";
}
実行結果

