COBOL+Apache+PostgreSQL
2002/03/15
アクセスカウンターをCOBOLで作成してみました。カウンターのデータはPostgreSQLで管理するようにしました。
フリーCOBOLとApacheとPostgreSQL。この組み合わせ結構面白いように思います。
| COBOL | TinyCOBOLを使用(将来的にはOpenCOBOLで作成予定)。 PostgreSQLのアクセス部分はTinyCOBOLのtest.code/tbd02/tdb02a.cを使用。 コンパイルはTinyCOBOLのtest.code/tbd02/MakefileのCOBOLのプログラム名を今回作成したCOBOLのプログラム名(cgi02.cob)に変える事のみでmake。 |
| Apacheの設定 | 特に何も無し。(インストールした時の初期設定) ユーザーは/etc/httpd/conf/httpd.confの初期値のnobody(User nobody)を使用。 |
| PostgreSQLの設定 | createuserでnobodyをPostgreSQLのユーザに追加。 ユーザnobodyに対してGRANTでアクセス権を与える。 libpq.so.2にリンクを設定する。 cd /usr/lib ln -s /usr/local/pgsql/lib/libpq.so.2 . ln -s /usr/local/pgsql/lib/libpq.so.2.0 . 以下の内容でデータベースを作成 データベース名 web テーブル名 count 列名 key(TEXT) count(INTEGER) keyは”1”固定です。countはアクセスされるたびに1が加算されます。 |
上記の設定でCOBOLのアクセスカウンターが実行されます。
こちらをクリックでこのアクセスカウンターが起動されます。
(但し、このサーバーは自宅サーバーです。一日数時間しか立ち上がっておりません。)
以下ソースを紹介します。
| 今回作成したCOBOLソースです。 |
IDENTIFICATION DIVISION.
PROGRAM-ID. cgi02.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
INPUT-OUTPUT SECTION.
DATA DIVISION.
FILE SECTION.
WORKING-STORAGE SECTION.
01 wk-count pic x(05).
77 DATABASE-NAME PIC X(80).
77 SQL-QUERY PIC X(200).
77 DB-HANDLE PIC 9(12) COMP.
77 QRY-HANDLE PIC 9(12) COMP.
77 NTUPLE PIC 9(12) COMP.
77 NFIELD PIC 9(12) COMP.
77 MAX-TUPLE PIC 9(12) COMP.
77 MAX-FIELD PIC 9(12) COMP.
77 COLUMN-VALUE PIC X(80) VALUE SPACES.
77 CMD PIC 9.
77 DB-STATUS PIC 9(12) COMP.
77 DB-MESSAGE Pic X(200).
01 MYTBL-RECORD PIC X(15).
*
PROCEDURE DIVISION.
A-000.
*
*---- DB CONNECT ----*
MOVE "web" TO DATABASE-NAME.
CALL "sql_connect_db" USING DATABASE-NAME
DB-HANDLE
DB-STATUS.
IF DB-STATUS NOT = ZEROS
DISPLAY "Error in database connection!"
STOP RUN.
*
*---- DB SELECT ----*
STRING "UPDATE count SET count = count + 1 where key = '1';;" INTO SQL-QUERY.
CALL "sql_exec_query" USING DB-HANDLE
SQL-QUERY
QRY-HANDLE
DB-STATUS.
IF (DB-STATUS NOT = 1 AND
DB-STATUS NOT = 2)
MOVE SPACES TO DB-MESSAGE
CALL "sql_status_message" USING DB-HANDLE
DB-MESSAGE
DISPLAY DB-MESSAGE.
*
*---- DB SELECT ----*
STRING "select count from count where key = '1';;" INTO SQL-QUERY.
*
CALL "sql_exec_query" USING DB-HANDLE
SQL-QUERY
QRY-HANDLE
DB-STATUS.
IF (DB-STATUS NOT = 1 AND
DB-STATUS NOT = 2)
MOVE SPACES TO DB-MESSAGE
CALL "sql_status_message" USING DB-HANDLE
DB-MESSAGE
DISPLAY DB-MESSAGE.
*
CALL "sql_max_tuple" USING QRY-HANDLE
MAX-TUPLE.
CALL "sql_max_field" USING QRY-HANDLE
MAX-FIELD.
MOVE ZERO TO NTUPLE
PERFORM UNTIL NTUPLE = MAX-TUPLE
CALL "sql_get_tuple" USING QRY-HANDLE
NTUPLE
MYTBL-RECORD
ADD 1 TO NTUPLE
END-PERFORM.
*
CALL "sql_clear_query" USING QRY-HANDLE.
*
*---- DB DISCONNECT ----*
CALL "sql_disconnect_db" USING DB-HANDLE.
*
MOVE MYTBL-RECORD TO wk-count.
display wk-count.
A-999.
EXIT-PROGRAM.
|
| PostgreSQLのアクセス部分(TinyCOBOLのtest.code/tbd02/tdb02a.c)のソースです。 |
/* test program for libpq (postgresql) */
#include <stdio.h>
#include <stdlib.h>
#include <libpq-fe.h>
void
do_exit(PGconn *conn) {
PQfinish(conn);
exit(1);
};
/* this function assumes a command buffer of 80 characters */
void
sql_exec_query( int *dbhandle, char *query, int *qryhandle, int *status ) {
char *r,*s=query;
int nfields, i, j;
PGconn *conn = (PGconn *)*dbhandle;
PGresult *res;
/* detect end of query with 2 successive ';' */
while ( *s != ';' || *(s+1) != ';' ) s++;
*s=0;
res = PQexec(conn, query);
*status = PQresultStatus(res);
*qryhandle = (int) res;
}
void
sql_status_message( int *dbhandle, char *message ) {
PGconn *conn = (PGconn *)*dbhandle;
char *s;
s = PQerrorMessage(conn);
while (*s) {
*message++ = *s++;
}
}
void
sql_max_tuple( int *qryhandle, int *maxtuple ) {
*maxtuple = PQntuples((PGresult *)*qryhandle);
}
void
sql_max_field( int *qryhandle, int *maxfield ) {
*maxfield = PQnfields((PGresult *)*qryhandle);
}
void
sql_get_value( int *qryhandle, int *ntuple, int *nfield, char *value ) {
char *s;
s = PQgetvalue((PGresult *)*qryhandle,*ntuple,*nfield);
while (*s) {
if (*s == '\n') continue;
*value++ = *s++;
}
}
void
sql_get_tuple( int *qryhandle, int *ntuple, char *tuple ) {
char *s;
int nfield=0;
int maxfield = PQnfields((PGresult *)*qryhandle);
while (nfield < maxfield) {
s = PQgetvalue((PGresult *)*qryhandle,*ntuple,nfield);
while (*s) {
*tuple++ = *s++;
}
nfield++;
}
}
void
sql_clear_query( int *qryhandle ) {
PQclear((PGresult *)*qryhandle);
}
void
sql_connect_db( char *dbname, int *dbhandle, int *status ) {
PGconn *conn;
char db[81];
char *s;
/* trim right spaces on the buffer */
memmove(db,dbname,80);
db[80]=0;
s = db+79;
while ((s >= db) && (*s == ' ')) s--;
if (s >= db)
*(s+1)=0;
conn = PQsetdb("","","","",db);
*status = PQstatus(conn);
*dbhandle = (int)conn;
}
void
sql_disconnect_db( int *dbhandle ) {
PGconn *conn = (PGconn *)*dbhandle;
PQfinish(conn);
}
|
| 呼び出し元のHTMLのソースです。 |
| <HTML><HEAD> <TITLE>COBOL カウンター</TITLE></HEAD> <BODY><H1>カウンター</H1>あなたで<!--#exec cmd="../cgi-bin/cgi02"-->人目です。<br> </BODY></HTML> |
実行環境 Vinelinux2.1 Tinycobol0.57 apache1.3.14 PostgreSQL7.1
参考書籍 改訂第3版 PC UNIXユーザのためのPostgreSQL完全攻略ガイド