PQntuples

PQntuplesで、タプルの数を取得する。

https://www.postgresql.jp/document/8.4/html/libpq-exec.html

実行すると、

[bg1@localhost PQntuples]$ vi main.c
[bg1@localhost PQntuples]$ gcc main.c -o main -lpq
[bg1@localhost PQntuples]$ ./main
CONNECTION_OK
PGRES_TUPLES_OK
field_count = 3
tuple_count = 2
name address age
[bg1@localhost PQntuples]$

タプルの数は2であることがわかる。

Sample/libpq/PQntuples/PQntuples/src/PQntuples at master · bg1bgst333/Sample · GitHub

PQfname

PQfnameで、指定の位置のフィールド名を取得する。

https://www.postgresql.jp/document/8.4/html/libpq-exec.html

PQfnameでi番目のフィールド名を取得して、スペースを区切りにして、横に並べる。

[bg1@localhost PQfname]$ vi main.c
[bg1@localhost PQfname]$ gcc main.c -o main -lpq
[bg1@localhost PQfname]$ ./main
CONNECTION_OK
PGRES_TUPLES_OK
field_count = 3
name address age
[bg1@localhost PQfname]$

name, address, ageの3つがフィールド名。

Sample/libpq/PQfname/PQfname/src/PQfname at master · bg1bgst333/Sample · GitHub

PQnfields

PQnfieldsで、フィールドの数を取得する。

https://www.postgresql.jp/document/8.4/html/libpq-exec.html

実行すると、

[bg1@localhost PQnfields]$ vi main.c
[bg1@localhost PQnfields]$ gcc main.c -o main -lpq
[bg1@localhost PQnfields]$ ./main
CONNECTION_OK
PGRES_TUPLES_OK
field_count = 3
[bg1@localhost PQnfields]$

フィールドの数は3であることがわかる。

Sample/libpq/PQnfields/PQnfields/src/PQnfields at master · bg1bgst333/Sample · GitHub

PQresultStatus

PQresultStatusで、PQexecの結果を取得する。

https://www.postgresql.jp/document/7.3/programmer/libpq-exec.html

    /* SQL実行 */
    res = PQexec(con, ""); /* PQexecでSQL文"SELECT * FROM user_profile;"を実行. */
    type = PQresultStatus(res); /* PQresultStatusで結果を取得. */
    if (type == PGRES_TUPLES_OK){ /* 成功 */
      printf("PGRES_TUPLES_OK\n"); /* "PGRES_TUPLES_OK"と出力. */
      PQclear(res); /* resの解放 */
      PQfinish(con); /* PQfinishでconの接続を終了. */
      return 0; /* 0を返して正常終了. */
    }
    else if (type == PGRES_EMPTY_QUERY){ /* クエリが空. */
      printf("PGRES_EMPTY_QUERY\n"); /* "PGRES_EMPTY_QUERY"と出力. */
      PQclear(res); /* resの解放 */
      PQfinish(con); /* PQfinishでconの接続を終了. */
      return -1; /* -1を返して異常終了. */
    }
    else if (type == PGRES_FATAL_ERROR){ /* SQL文がおかしい場合など. */
      printf("PGRES_FATAL_ERROR\n"); /* "PGRES_FATAL_ERROR"と出力. */
      PQclear(res); /* resの解放 */
      PQfinish(con); /* PQfinishでconの接続を終了. */
      return -1; /* -1を返して異常終了. */
    }
    else{ /* その他の失敗 */
      printf("NG\n"); /* "NG"と出力. */
      PQclear(res); /* resの解放 */
      PQfinish(con); /* PQfinishでconの接続を終了. */
      return -1; /* -1を返して異常終了. */
    }

SQL文が""という空の場合、

[bg1@localhost PQresultStatus]$ vi main.c
[bg1@localhost PQresultStatus]$ gcc main.c -o main -lpq
[bg1@localhost PQresultStatus]$ ./main
CONNECTION_OK
PGRES_EMPTY_QUERY
[bg1@localhost PQresultStatus]$

PGRES_EMPTY_QUERYが返る。

    /* SQL実行 */
    res = PQexec(con, "SELECT * FROM"); /* PQexecでSQL文"SELECT * FROM user_profile;"を実行. */
    type = PQresultStatus(res); /* PQresultStatusで結果を取得. */
    if (type == PGRES_TUPLES_OK){ /* 成功 */
      printf("PGRES_TUPLES_OK\n"); /* "PGRES_TUPLES_OK"と出力. */
      PQclear(res); /* resの解放 */
      PQfinish(con); /* PQfinishでconの接続を終了. */
      return 0; /* 0を返して正常終了. */
    }
    else if (type == PGRES_EMPTY_QUERY){ /* クエリが空. */
      printf("PGRES_EMPTY_QUERY\n"); /* "PGRES_EMPTY_QUERY"と出力. */
      PQclear(res); /* resの解放 */
      PQfinish(con); /* PQfinishでconの接続を終了. */
      return -1; /* -1を返して異常終了. */
    }
    else if (type == PGRES_FATAL_ERROR){ /* SQL文がおかしい場合など. */
      printf("PGRES_FATAL_ERROR\n"); /* "PGRES_FATAL_ERROR"と出力. */
      PQclear(res); /* resの解放 */
      PQfinish(con); /* PQfinishでconの接続を終了. */
      return -1; /* -1を返して異常終了. */
    }
    else{ /* その他の失敗 */
      printf("NG\n"); /* "NG"と出力. */
      PQclear(res); /* resの解放 */
      PQfinish(con); /* PQfinishでconの接続を終了. */
      return -1; /* -1を返して異常終了. */
    }

SQL文がおかしい場合には、

[bg1@localhost PQresultStatus]$ vi main.c
[bg1@localhost PQresultStatus]$ gcc main.c -o main -lpq
[bg1@localhost PQresultStatus]$ ./main
CONNECTION_OK
PGRES_FATAL_ERROR
[bg1@localhost PQresultStatus]$

PGRES_FATAL_ERRORが返る。

正しいSQL文なら、

[bg1@localhost PQresultStatus]$ vi main.c
[bg1@localhost PQresultStatus]$ gcc main.c -o main -lpq
[bg1@localhost PQresultStatus]$ ./main
CONNECTION_OK
PGRES_TUPLES_OK
[bg1@localhost PQresultStatus]$

PGRES_TUPLES_OKが返る。

Sample/libpq/PQresultStatus/PQresultStatus/src/PQresultStatus at master · bg1bgst333/Sample · GitHub

PQexec

PQexecは、指定したSQL文を実行する。

https://www.postgresql.jp/document/8.4/html/libpq-exec.html

PQexecにconとSQL文をセットして実行。
PQresultStatusが、PGRES_TUPLES_OKなら、成功と言える。
resは、PQclearで解放する必要あり。

$ vi main.c
$ gcc main.c -o main -lpq
$ ./main
CONNECTION_OK
OK
$

成功した。

Sample/libpq/PQexec/PQexec/src/PQexec at master · bg1bgst333/Sample · GitHub

PQstatus

PQstatusは、接続の状態を返す。

https://www.postgresql.jp/document/9.3/html/libpq-status.html

/* ヘッダファイルのインクルード */
#include <stdio.h> /* 標準入出力 */
#include <libpq-fe.h> /* libpqフロントエンド */

/* main関数 */
int main(void){

  /* 変数の宣言 */
  PGconn *con; /* PGconnポインタcon */

  /* DB接続 */
  con = PQconnectdb("host=localhost dbname=testuser1db user=testuser1 password=hogehoge"); /* PQconnectdbでtestuser1dbに接続. */
  if (PQstatus(con) == CONNECTION_OK){ /* 接続成功 */
    printf("CONNECTION_OK\n"); /* "CONNECTION_OK"を出力. */
    PQfinish(con); /* PQfinishでconの接続を終了. */
    return 0; /* 0を返して正常終了. */
  }
  else if (PQstatus(con) == CONNECTION_BAD){ /* 接続失敗 */
    printf("CONNECTION_BAD\n"); /* "CONNECTION_BAD"を出力. */
    return -1; /* -1を返して異常終了. */
  }

}

passwordが間違っていると、

$ vi main.c
$ gcc main.c -o main -lpq
$ ./main
CONNECTION_BAD
$

失敗だが、

これなら、

$ vi main.c
$ gcc main.c -o main -lpq
$ ./main
CONNECTION_OK
$

合っているので成功。

Sample/libpq/PQstatus/PQstatus/src/PQstatus at master · bg1bgst333/Sample · GitHub

PQconnectdb

libpqC言語からPostgreSQLのDBに接続する。
接続には、PQconnectdbを使う。

https://www.postgresql.jp/document/8.4/html/libpq-connect.html
postgreSQL

まず、インストール。

[bg1@localhost ~]$ su
パスワード:
[root@localhost bg1]# yum install postgresql-devel
Fedora Modular 31 - x86_64                       11 kB/s | 6.4 kB     00:00    
Fedora Modular 31 - x86_64 - Updates             16 kB/s | 5.4 kB     00:00    
Fedora 31 - x86_64 - Updates                    9.7 kB/s | 5.5 kB     00:00    
Fedora 31 - x86_64 - Updates                    541 kB/s | 2.6 MB     00:04    
Fedora 31 - x86_64                               11 kB/s | 6.5 kB     00:00    
依存関係が解決しました。
================================================================================
 Package             Architecture   Version               Repository       Size
================================================================================
インストール:
 libpq-devel         x86_64         12.2-1.fc31           updates          98 k

トランザクションの概要
================================================================================
インストール  1 パッケージ

ダウンロードサイズの合計: 98 k
インストール済みのサイズ: 336 k
これでよろしいですか? [y/N]: y
パッケージのダウンロード:
libpq-devel-12.2-1.fc31.x86_64.rpm              136 kB/s |  98 kB     00:00    
--------------------------------------------------------------------------------
合計                                             62 kB/s |  98 kB     00:01    
トランザクションの確認を実行中
トランザクションの確認に成功しました。
トランザクションのテストを実行中
トランザクションのテストに成功しました。
トランザクションを実行中
  準備             :                                                        1/1
  インストール中   : libpq-devel-12.2-1.fc31.x86_64                         1/1
  scriptletの実行中: libpq-devel-12.2-1.fc31.x86_64                         1/1
  検証             : libpq-devel-12.2-1.fc31.x86_64                         1/1

インストール済み:
  libpq-devel-12.2-1.fc31.x86_64                                                

完了しました!
[root@localhost bg1]#

意外とlibpq-develが入ってなかった。

PQconnectdbの接続だけ。
ソースコードはこれでいいんだけど、今の状態だと、Ident認証なので、bg1からtestuser1の持つtestuser1dbにアクセスできない。
(testuser1dbに接続できるのはtestuser1ロールであり、Linuxユーザのtestuser1でログインしていないといけない。)
そこで、

PostgreSQLの設定 - 初めてのVPS構築

[root@localhost PQconnectdb]# cd /var/lib/pgsql/data/
[root@localhost data]# vi pg_hba.conf

pg_hba.confを開いて、

修正前
修正前

修正前は、identとある部分を、

修正後
修正後

passwordに変更する。
(md5にするとか、USERとかDATABSEとかいろいろいじったけど、セキュリティはともかく、この方法でしか上手くいかなかった。)

あと、Linuxユーザのtestuser1にパスワードをセットしていたけど、PostgreSQLのロールのtesuser1にはパスワード設定していなかった気がするので、psqlで、

postgres=# ALTER USER testuser1 WITH PASSWORD <パスワード>;

これもやっておかないとたぶん接続できないのでは。

[root@localhost data]# psql -U testuser1 -h localhost -d testuser1db
psql: FATAL:  ユーザ"testuser1"のIdent認証に失敗しました
[root@localhost data]# cd /var/lib/pgsql/data/
[root@localhost data]# vi pg_hba.conf
[root@localhost data]# service postgresql restart
Redirecting to /bin/systemctl restart postgresql.service
[root@localhost data]# psql -U testuser1 -h localhost -d testuser1db
ユーザ testuser1 のパスワード:
psql (11.7)
"help" でヘルプを表示します。

testuser1db=> exit
[root@localhost data]#

このように、rootからtestuser1でのtestuser1db接続は出来ないはずだが、
先程のpg_hba.conf編集の後は、接続できる。
bg1ユーザで、C言語プログラムからも接続できるはず。

[bg1@localhost PQconnectdb]$ vi main.c
[bg1@localhost PQconnectdb]$ gcc main.c -o main -lpq
[bg1@localhost PQconnectdb]$ ./main
OK
[bg1@localhost PQconnectdb]$

接続できた。
いろいろ調べたけど、結構ハマった・・・。
ちゃんとアクセス制限はしないといけないけど、今回はとりあえずこれで・・・。

Sample/libpq/PQconnectdb/PQconnectdb/src/PQconnectdb at master · bg1bgst333/Sample · GitHub