/* C言語プログラムでPostgreSQLで「あればUPDATE、なければINSERT」をUPSERTを使わずにやってみる。 g++ -g db.cpp -o db -I"D:\PostgreSQL\10\include" -L"D:\PostgreSQL\10\lib" -llibpq -lwsock32 -lws2_32 // 状態をPostgreSQLに書き込み続ける // プログラム実行中にも、経過情報が読めるようにする為 まず、以下の手順でテーブルを作っておく C:\Users\yrl-user>psql -h localhost -U postgres postgres=# \l postgres=# \connect ca_db(データベース名) 以下をコピペしてテーブルとその内容を直接書き込む create table q_state ( number int, action_type int, q int); ca_db=# \dt データベースのテーブルの中身を確認する ca_db=# select * from q_state; // 検索の基本形 ====================== 本プログラムは、 (1)numberとaction_typeの値の両方が同じ行がある場合、qの値を書き換えること (2)同じ行がない場合には、行を追加する を実施する、かなりスマートではない方法である (が、とりあえずは動く) ====================== */ #include#include //#include // sleep(1) #include // sleep(1) #include #include #include #include "libpq-fe.h" const char *conninfo = "host=localhost user=postgres password=xxxxxxx dbname=ca_db port=5433"; PGconn *conn; int open_db() { // データベースとの接続を確立する //PGconn *conn = PQconnectdb(conninfo); conn = PQconnectdb(conninfo); /* バックエンドとの接続確立に成功したかを確認する */ if (PQstatus(conn) != CONNECTION_OK){ fprintf(stderr, "Connection to database failed: %s", PQerrorMessage(conn)); } return 0; }; int delete_db() { // テーブルの中身を空にする(全行を消去する) char stringSQL2[512] = {0}; sprintf(stringSQL2, "DELETE FROM q_state;"); PGresult *res = PQexec(conn, stringSQL2); // INSERT等値を返さないコマンドの場合戻り値は PGRES_COMMAND_OK if (res == NULL || PQresultStatus(res) != PGRES_COMMAND_OK) { // SQLコマンドが失敗した場合 fprintf(stderr, "INSERT COMMAND IS FAILED.", PQerrorMessage(conn)); } // 値セットが無い場合でも必ず結果をクリアする PQclear(res); return 0; }; int write_db(int number, int action_type, int q) { char stringSQL2[512] = {0}; char stringSQL1[512] = {0}; sprintf(stringSQL2, "UPDATE q_state SET number = %d, action_type = %d, q = %d where number = %d and action_type = %d;", number, action_type, q, number, action_type); PGresult *res = PQexec(conn, stringSQL2); ExecStatusType est = PQresultStatus(res); char mes[10] = {0}; strcpy(mes,PQcmdStatus(res)); // UPDATEできなかった場合には、"UPDATE 0"というメッセージが帰ってくるので、 // そのメッセージを使って、UPDATEの失敗を判断して、INSERTの処理を行う int c = strcmp(mes, "UPDATE 0"); if (c == 0){ sprintf(stringSQL1, "INSERT INTO q_state(number , action_type , q) VALUES(%d,%d,%d);", number, action_type, q); PGresult *res = PQexec(conn, stringSQL1); } // INSERT等値を返さないコマンドの場合戻り値は PGRES_COMMAND_OK if (res == NULL || PQresultStatus(res) != PGRES_COMMAND_OK) { // SQLコマンドが失敗した場合 fprintf(stderr, "INSERT COMMAND IS FAILED.", PQerrorMessage(conn)); } // 値セットが無い場合でも必ず結果をクリアする PQclear(res); return 0; }; int close_db() { // 最後必ずデータベースとの接続を閉じる PQfinish(conn); return 0; } int main() { open_db(); delete_db(); write_db(1, 2, 4); write_db(1, 2, 3); write_db(2, 1, 4); write_db(2, 2, 4); write_db(2, 1, 5); write_db(1, 2, 5); /* struct timespec ts; fprintf(stderr, "start\n"); ts.tv_sec = 1; ts.tv_nsec = 0; nanosleep(&ts, NULL); fprintf(stderr, "end\n"); */ close_db(); }