MindでMySQL(Linux)にクエリーする（3-クエリー実行編）

# はじめに

だいぶ前2017年ごろMindユーザーの @MindZanmai さんのご質問に回答して、MindでLinux上のMySQLにクエリーする方法を詳しくコメントに解説しておりまして、最近SQLServerへのクエリ記事を書かれている @mylifewithviolin さんのおすすめもあって記事にまとめておくことにしました。内容は少し古くなっていますが、MindのDB接続関連の情報は少ないので参考になれば幸いです。

今回はクエリの発行を書いてみました。

# 参考情報

C記述の側は以下の方のWebページを参考にさせていただきました([前回記事](https://qiita.com/drafts/480fd84ea1440b016fdd)の参考ページと違います)。

C言語でMySQLへ接続 - 日常メモ
http://d.hatena.ne.jp/graySpace/20141011/1413014403
上記のプログラム中で、クエリ発行に関する部分は以下になります。

```C
  //～略～
       MYSQL *conn;
       MYSQL_RES *res;
       MYSQL_ROW row;

       //～略～

      // クエリ発行
            if (mysql_query(conn, "show tables")) {
                fprintf(stderr, "%s\n", mysql_error(conn));
                exit(1);
            }
            res = mysql_use_result(conn);

       // 結果表示
        while ((row = mysql_fetch_row(res)) != NULL) {
            printf("%s\n", row[0]);
        }
       mysql_free_result(res);

       // 切断
       mysql_close(conn);
```

# クエリ発行

まず、Cの次の行。

```C
            if (mysql_query(conn, "show tables")) {
```

これは簡単でMindでは以下のように書けばいいはずです。

```mind
　　　　　　　　ＣSQL文は　文字列実体　長さ　・・

　　　　"show tables"を　ＣSQL文に　入れ、　０を　ＣSQL文に　　一文字追加し

　　　　接続ハンドルをつみ　　　　※←引数１
　　　　　ＣSQL文をつみ 　　　　　※←引数２
　　　　　　mysql_queryアドレスで　　　　　※←関数アドレス
　　　　　　　アドレス指定でＡＰＩ呼出し２し
　　　　戻値に　入れ
　　　　戻値が　ゼロ以外
　　　　　　　　ならば　・・エラー処理・・
　　　　　　　　　　　　終り
　　　　　　　　つぎに
```

次に、Cの次の部分です。

```C
       MYSQL_RES *res;
```

上記で「res」の定義は前回の解説でも書きましたが以下のように考えます。
Cの側が MYSQL_RES *res のように「*」を挟んでいます。このタイプは簡単で、アドレスを記憶する変数に過ぎないためMindでは以下のように書けばよいです。

```mind
　　　　結果セットは　変数
```    

次に、Cの次の部分。

```C
            res = mysql_use_result(conn);
```

上記はMindでは以下のように書けばいいはずです。

```mind
　　　　接続ハンドルをつみ　　　　※←引数１
　　　　　mysql_use_resultアドレスで　　　※←関数アドレス
　　　　　　アドレス指定でＡＰＩ呼出し１し
　　　　結果セットに　入れ
　　　　結果セットが　ゼロ？
　　　　　　　　ならば　・・エラー処理・・
　　　　　　　　　　　　終り
　　　　　　　　つぎに
```

次にCの次の部分です。

```C
      MYSQL_ROW row;
        //～略～
```    

上記で「row」の定義は以下のように考えます。
Cの側が MYSQL_ROW row は途中に「*」を挟んで【いない】ので要注意です。やっかいですが、データ型 MYSQL_ROW はどのような定義なのかを調べる必要があります。
以下のWebページに mysql.h の中身の解説がありました。

MySQL: include/mysql.h File Reference
https://dev.mysql.com/doc/dev/mysql-server/8.0.0/include_2mysql_8h.html

上記によると問題の MYSQL_ROW は以下のようなものらしいです。

```C
typedef char **   MYSQL_ROW
```

Cの場合 char * が文字列を格納する変数となりますが、これにもう１つ * が付いているので、文字列変数の配列を示しています。結果として「row」は【文字列変数へのポインタを配列状にしたものへのポインタ】のようです。

配列の実体は確保する必要はないため、Mindの側では型紙を使います。以下のようになるかと思います。

```mind
　　行データ型は　型紙
　　　　Ｃ列データは　変数
　　　全体は
　　　　１００個の　Ｃ列データ。
```

上記には文字列を表すデータ型が書いてありませんが、Cでは文字列といってもその先頭アドレスでしか管理されていないのでこのようになります。

次にCの次の部分です。

```C
    while ((row = mysql_fetch_row(res)) != NULL) {
```

上ではループ構文と結果判定を含めて一気に書かれていて見ずらいですが要点だけ書くと以下となります。
まずCの次の箇所。

```C
    row = mysql_fetch_row(res);
```

上を翻訳してMindでは以下のようにします。

```mind
　　　　結果セットをつみ　　　　※←引数１
　　　　　mysql_fetch_rowアドレスで　　　※←関数アドレス
　　　　　　アドレス指定でＡＰＩ呼出し１し
　　　　行データアドレスに　入れ
```

先のC記述をもう少し範囲を広げると以下となります。

        // 結果表示
        while ((row = mysql_fetch_row(res)) != NULL) {
            printf("%s\n", row[0]);
        }
Mindでは以下のようにすれば良いと思います。

```mind
　　　　ここから
　　　　　　　　結果セットをつみ　　　　※←引数１
　　　　　　　　　mysql_fetch_rowアドレスで　　　※←関数アドレス
　　　　　　　　　　アドレス指定でＡＰＩ呼出し１し
　　　　　　　　行データアドレスに　入れ
　　　　　　　　行データアドレスが　ゼロ？
　　　　　　　　　　　　ならば　打ち切り
　　　　　　　　　　　　つぎに
　　　　　　　　行データアドレスの　Ｃ列データ（１）を　Mind文字列に変換し　一行表示し
　　　　　　　　※　　↑親構造の　　↑型紙要素（Mindでは配列要素を１から数える）　※
　　　　繰り返し
```

上記で使っている「Mind文字列に変換」という処理単語は、C形式の文字列（NULL終端形式の文字列）をMindの文字列（アドレス＋カウントのパック値）に変換するものです。Mind形式に変換してしまえば「表示」など普通の処理に渡せます。

最後に今回のMySQL関連記事の全体を通したMindのプログラムは以下のようになります。

### （１）　　関数アドレスを記憶する変数の追加

```mind
※↓今回追加分
mysql_queryアドレスは 　　　　変数。
mysql_use_resultアドレスは　　変数。
mysql_free_resultアドレスは 　変数。
mysql_fetch_rowアドレスは 　　変数。
```

### （２）　　「mysql関数アドレス群を取得」に上記分の取得を追加

```mind
mysql関数アドレス群を取得とは　（・　→　・）
　　　　～略～
　　　　～略～
　　　　・・・今回追加の関数アドレスの取得処理追加・・・
　　　　・・・今回追加の関数アドレスの取得処理追加・・・
　　　　・・・今回追加の関数アドレスの取得処理追加・・・
　　　　・・・今回追加の関数アドレスの取得処理追加・・・
　　　　。
```

### （３）　　SQL文の発行

```mind
行データ型は　型紙
　　　　Ｃ列データは　変数
　　全体は
　　　　１００個の　Ｃ列データ。

SQL文の発行テストとは　（・　→　・）
　　　　　　　　ＣSQL文は　文字列実体　長さ　５１２　※←この値は十分な長さを指定のこと
　　　　　　　　結果セットは　　変数
　　　　　　　　結果セットは　　変数
　　　　　　　　戻値は　　　　　変数
　　　　　　　　行データアドレスは　変数

　　　　エラークリアし

　　　　"show tables"を　ＣSQL文に　入れ、　０を　ＣSQL文に　　一文字追加し

　　　　接続ハンドルをつみ　　　　※←引数１
　　　　　ＣSQL文をつみ 　　　　　※←引数２
　　　　　　mysql_queryアドレスで　　　　　※←関数アドレス
　　　　　　　アドレス指定でＡＰＩ呼出し２し
　　　　戻値に　入れ
　　　　戻値が　ゼロ以外
　　　　　　　　ならば　「mysql_query()の発行でエラー」を　エラー登録し
　　　　　　　　　　　　終り
　　　　　　　　つぎに

　　　　接続ハンドルをつみ　　　　※←引数１
　　　　　mysql_use_resultアドレスで　　　※←関数アドレス
　　　　　　アドレス指定でＡＰＩ呼出し１し
　　　　結果セットに　入れ
　　　　結果セットが　ゼロ？
　　　　　　　　ならば　「mysql_use_result()の発行でエラー」を　エラー登録し
　　　　　　　　　　　　終り
　　　　　　　　つぎに

　　　　ここから
　　　　　　　　結果セットをつみ　　　　※←引数１
　　　　　　　　　mysql_fetch_rowアドレスで　　　※←関数アドレス
　　　　　　　　　　アドレス指定でＡＰＩ呼出し１し
　　　　　　　　行データアドレスに　入れ
　　　　　　　　行データアドレスが　ゼロ？
　　　　　　　　　　　　ならば　打ち切り
　　　　　　　　　　　　つぎに
　　　　　　　　行データアドレスの　Ｃ列データ（１）を　Mind文字列に変換し　一行表示し
　　　　　　　　※　　↑親構造の　　↑型紙要素（Mindでは配列要素を１から数える）　※
　　　　繰り返し

　　　　結果セットをつみ　　　　　　　　※←引数１
　　　　　mysql_free_resultアドレスで　　　※←関数アドレス
　　　　　　アドレス指定でＡＰＩ呼出し１し
　　　　(結果を)　捨て
　　　　。
```

### （４）　　メイン部分の追加

```mind
メインとは　（・　→　・）
　　　　～略～
　　　　～略～
　　　　「MySQLに接続の後」で　このメッセージでスタック検査し

　　　　「SQL文の発行テスト」を　一行表示し
　　　　SQL文の発行テストし
　　　　エラー？
　　　　　　　　ならば　「エラー：」を　表示し　エラー文字列を　一行表示し
　　　　　　　　つぎに
　　　　「テスト終り」を　一行表示し
　　　　「SQL文の発行テストの後」で　このメッセージでスタック検査し

　　　　「MySQLをクローズ」を　一行表示し
　　　　～略～
　　　　～略～
　　　　。

```

# おわりに

3回にわけてMindからMySQLへ接続しクエリーを処理する方法について解説しました。思えばずいぶん長いコメントを書いたものです(^^;