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

xmlTextReaderRead

xmlTextReaderReadで、次なるノードが見つかるまで移動していく。

Module xmlreader from libxml2
libxml2 で XMLTextReader を使ってみる - えがわたにっき

戻り値1の時は、次のノードが見つかった場合で、その場合は繰り返す。0の場合は、ノードがなくなった場合なので、終了する。
で実行すると、

$ vi main.c
$ gcc main.c -o main -I/usr/include/libxml2 -lxml2
$ ./main
reader = 0x019679c0
Move Next Node!
Move Next Node!
Move Next Node!
Move Next Node!
Move Next Node!
Move Next Node!
Move Next Node!
Move Next Node!
Move Next Node!
Move Next Node!
Move Next Node!
Move Next Node!
Move Next Node!
Move Next Node!
Move Next Node!
Move Next Node!
Move Next Node!
Move Next Node!
Move Next Node!
Move Next Node!
Move Next Node!
Move Next Node!
Move Next Node!
Move Next Node!
Move Next Node!
Move Next Node!
Move Next Node!
End of move!
$

結構な数のノードがある。

Sample/libxml/xmlTextReaderRead/xmlTextReaderRead/src/xmlTextReaderRead at master · bg1bgst333/Sample · GitHub

DELETE

DELETEは、指定の行を削除するSQL文。

DELETE
2.9. 削除

"Saburo"の行を削除する。

testuser1db=> SELECT * FROM user_profile;
  name  | address | age
--------+---------+-----
 Taro   | Tokyo   |  30
 Saburo | Nagoya  |  26
 Jiro   | Sendai  |  28
(3 行)

testuser1db=> DELETE FROM user_profile WHERE name = 'Saburo';
DELETE 1
testuser1db=> SELECT * FROM user_profile;
 name | address | age
------+---------+-----
 Taro | Tokyo   |  30
 Jiro | Sendai  |  28
(2 行)

testuser1db=>

WHEREで削除する行の条件を指定。
今回はnameが"Saburo"の行を削除。
削除できた。

UPDATE

UPDATEは、指定の行を更新するSQL文。

UPDATE
2.8. 更新

"Jiro"のaddressを"Sendai"に変更する。

testuser1db=> SELECT * FROM user_profile;
  name  | address | age
--------+---------+-----
 Taro   | Tokyo   |  30
 Jiro   | Osaka   |  28
 Saburo | Nagoya  |  26
(3 行)

testuser1db=> UPDATE user_profile SET address = 'Sendai' WHERE name = 'Jiro';
UPDATE 1
testuser1db=> SELECT * FROM user_profile;
  name  | address | age
--------+---------+-----
 Taro   | Tokyo   |  30
 Saburo | Nagoya  |  26
 Jiro   | Sendai  |  28
(3 行)

testuser1db=>

SETの後ろに、セットする列名と値。
WHEREの後ろに、セットする行の条件。
更新できた。

SELECT

SELECTは、テーブルやビューに、データ取り出しの問い合わせをするSQL文。

SELECT
2.5. テーブルへの問い合わせ

SELECTの後ろが'*'だと、すべての列を取り出すが、列を選ぶこともできる。

testuser1db=> SELECT * FROM user_profile;
  name  | address | age
--------+---------+-----
 Taro   | Tokyo   |  30
 Jiro   | Osaka   |  28
 Saburo | Nagoya  |  26
(3 行)

testuser1db=> SELECT name , age FROM user_profile;
  name  | age
--------+-----
 Taro   |  30
 Jiro   |  28
 Saburo |  26
(3 行)

testuser1db=> SELECT name , address FROM user_profile;
  name  | address
--------+---------
 Taro   | Tokyo
 Jiro   | Osaka
 Saburo | Nagoya
(3 行)

testuser1db=> SELECT address , age FROM user_profile;
 address | age
---------+-----
 Tokyo   |  30
 Osaka   |  28
 Nagoya  |  26
(3 行)

testuser1db=> SELECT age , name FROM user_profile;
 age |  name  
-----+--------
  30 | Taro
  28 | Jiro
  26 | Saburo
(3 行)

testuser1db=>

SELECTの後ろに、列名を指定することで、その列だけのデータを抽出できる。
カンマで複数指定できる。
順番も変えられる。

INSERT

INSERTは、テーブルに行を挿入するSQL文。

INSERT
2.4. テーブルに行を挿入

user_profileに、nameが"Taro"、addressが"Tokyo"、ageが30という行と、
nameが"Jiro"、addressが"Osaka"、ageが28という行と、
nameが"Saburo"、addressが"Nagoya"、ageが26という行を挿入する。

testuser1db=> INSERT INTO user_profile VALUES ( 'Taro' , 'Tokyo', 30 );
INSERT 0 1
testuser1db=> INSERT INTO user_profile VALUES ( 'Jiro' , 'Osaka', 28 );
INSERT 0 1
testuser1db=> INSERT INTO user_profile VALUES ( 'Saburo' , 'Nagoya', 26 );
INSERT 0 1
testuser1db=> SELECT * FROM user_profile;
  name  | address | age
--------+---------+-----
 Taro   | Tokyo   |  30
 Jiro   | Osaka   |  28
 Saburo | Nagoya  |  26
(3 行)

testuser1db=>

3つ挿入できた。
テーブル全体の問い合わせ表示は、SELECT * FROM <テーブル名>を使う。

2.5. テーブルへの問い合わせ