ホームページ >バックエンド開発 >C++ >D での PostgreSQL ライブラリの構築

D での PostgreSQL ライブラリの構築

Patricia Arquette
Patricia Arquetteオリジナル
2024-10-24 06:16:30943ブラウズ

Building a PostgreSQL Library in D

私は常に新しいプログラミング言語とそのフレームワークに興味がありました。これまでずっと、私の経験と好奇心はフロントエンド開発のみに広がっていました (バックエンドもいくつかやったことがありますが?)。自分のスキルを拡張することに挑戦し、D プログラミング言語に出会いました。 D は、簡単に言うと C と CPP の上級バージョンです。

Dとは何ですか?ウェブサイトには「**D は、静的型付け、システムレベルのアクセス、および C に似た構文を備えた汎用プログラミング言語です。 D プログラミング言語 を使用すると、高速に書き込み、高速に読み取り、高速に実行できます。

私は作品のデータベースとして PostgreSQL を使用しており、それがこのライブラリにも PostgreSQL を選択した理由です。 PostgreSQL は、現在企業が使用している主要なオープンソース SQL データベース システムの 1 つであり、その機能はさらに拡張されています。

カスタム ORM ライブラリを構築する理由

D 言語をいじっているときに、満足のいくパッケージが 1 つも見つかりませんでした。パッケージはメンテナンスが停止されているか、直接クエリとして使用できるかのどちらかです。 JavaScript のバックグラウンドから、Sequalize ORM を使用しました。それは私にアイデアを与えます。D で同様のものはどうでしょうか。

そこで、少し調べてみたところ、Postgres が C 用のライブラリを提供していることがわかりました。そこで、C のバインディングを D で使用して、ORM の開発に使用してはどうだろうと考えました。 C ライブラリを D にバインドするためのソース コードを https://github.com/adamdruppe/arsd/blob/master/postgres.d から見つけました。

はじめる

要件:

  • PostgreSQL がシステムにインストールされている必要があります。 ( PostgreSQL 16 用に開発しました)
  • IDE (Zed/VSCode/Vim)
  • DMD - d 言語コンパイラ

新しいプロジェクトを作成するには、ターミナルで次のコマンドを使用します:

  1. ターミナルまたはコマンド プロンプトを開きます。
  2. プロジェクトを作成するディレクトリに移動します。
  3. 次のコマンドを実行します。
dub init <project_name>

このコマンドは、指定された名前で新しいプロジェクト ディレクトリを作成し、D プロジェクトの基本構造をセットアップします。

  1. 次の情報を入力するよう求められます:
    • 形式 - .sdl または .json (私は json を選択しました)
    • プロジェクトの説明 (オプション)
    • 著者名
    • ライセンス (MIT、BSD など)
    • 著作権文字列
    • 依存関係の追加 (オプション)
  2. 情報を提供すると、dub はプロジェクト名で新しいディレクトリを作成し、次のファイルを生成します。
    • dub.json: プロジェクトの構成ファイル
    • source/app.d: メインソースファイル
    • .gitignore: Git 無視ファイル
  3. 新しいプロジェクト ディレクトリに移動します: cd
  4. D プロジェクトの開発を開始できるようになりました!

これらの手順を完了すると、基本的な D プロジェクト構造がセットアップされ、開発の準備が整います。

Windows では、以下のセクションを dub.json に追加する必要があります。

dub init <project_name>

または

私が行った方法は、必要なすべての DLL ファイルを lib (手動で作成した) フォルダーにコピーし、以下のコードを追加しました。

"libs": [ "pq" ],
    "lflags-windows-x86_64": [ "-LIBPATH:C:/Program Files/PostgreSQL/16/lib/" ],
    "copyFiles-windows-x86_64": [
        "C:/Program Files/PostgreSQL/16/lib/libpq.dll",
        "C:/Program Files/PostgreSQL/16/bin/libintl-9.dll",
        "C:/Program Files/PostgreSQL/16/bin/libssl-3-x64.dll",
        "C:/Program Files/PostgreSQL/16/bin/libcrypto-3-x64.dll",
        "C:/Program Files/PostgreSQL/16/bin/libwinpthread-1.dll",
        "C:/Program Files/PostgreSQL/16/bin/libiconv-2.dll"
    ],

Linux または macOS では、PostgreSQL 開発ライブラリがインストールされ、適切にリンクされていることを確認する必要があります。通常、これを行うには、システムのパッケージ マネージャーを通じて適切なパッケージをインストールします。たとえば、Ubuntu または Debian ベースのシステムでは、次のように使用できます。

"copyFiles-windows": [
        "libs/*.dll"
    ],
    "lflags-windows": [
        "/LIBPATH:$PACKAGE_DIR/libs"
    ],
    "libs": [
        "pq"
    ]

必要なライブラリをインストールして適切にリンクしたら、PostgreSQL で動作するように D プロジェクトのセットアップに進むことができます。

C バインディングの実装:

D の C バインディングは次のとおりです。

sudo apt-get install libpq-dev

これで、D でこれらの関数を簡単に使用できるようになりました。
これは、基本的な例外処理のコードです:

module postgres.implementation.implementationc;

extern (C)
{
    struct PGconn
    {
    }

    struct PGresult
    {
    }

    void PQfinish(PGconn*);

    PGconn* PQconnectdb(const char*);

    int PQstatus(PGconn*); // FIXME check return value

    const(char*) PQerrorMessage(PGconn*);

    char* PQresultVerboseErrorMessage(const PGresult* res,
        PGVerbosity verbosity,
        PGContextVisibility show_context);
    PGresult* PQexec(PGconn*, const char*);
    void PQclear(PGresult*);

    PGresult* PQprepare(PGconn*, const char* stmtName, const char* query,
        ulong nParams, const void* paramTypes);

    PGresult* PQexecPrepared(PGconn*, const char* stmtName,
        int nParams, const char** paramValues,
        const int* paramLengths, const int* paramFormats, int resultFormat);

    int PQresultStatus(PGresult*); // FIXME check return value

    int PQnfields(PGresult*); // number of fields in a result
    const(char*) PQfname(PGresult*, int); // name of field

    int PQntuples(PGresult*); // number of rows in result
    const(char*) PQgetvalue(PGresult*, int row, int column);

    size_t PQescapeString(char* to, const char* from, size_t length);

    enum int CONNECTION_OK = 0;
    enum int PGRES_COMMAND_OK = 1;
    enum int PGRES_TUPLES_OK = 2;
    enum int PGRES_FATAL_ERROR = 7;
    enum PGContextVisibility
    {
        PQSHOW_CONTEXT_NEVER,
        PQSHOW_CONTEXT_ERRORS,
        PQSHOW_CONTEXT_ALWAYS
    }

    enum PGVerbosity
    {
        PQERRORS_TERSE,
        PQERRORS_DEFAULT,
        PQERRORS_VERBOSE,
        PQERRORS_SQLSTATE
    }

    int PQgetlength(const PGresult* res,
        int row_number,
        int column_number);
    int PQgetisnull(const PGresult* res,
        int row_number,
        int column_number);

    int PQfformat(const PGresult* res, int column_number);

    alias Oid = int;
    enum BYTEAOID = 17;
    Oid PQftype(const PGresult* res, int column_number);

    char* PQescapeByteaConn(PGconn* conn,
        const ubyte* from,
        size_t from_length,
        size_t* to_length);
    char* PQunescapeBytea(const char* from, size_t* to_length);
    void PQfreemem(void* ptr);

    char* PQcmdTuples(PGresult* res);

}

  • PGSqlException: 標準の D Exception クラスを継承するカスタム例外クラス。 PostgreSQL 固有のエラーを処理するように設計されています。
  • フィールド:
    • code: エラーコードを格納します
    • sqlState: SQL 状態を保存します
    • message: エラーメッセージを保存します
  • コンストラクター: PGconn* (PostgreSQL 接続) とオプションの PGresult* (クエリの結果) を受け取ります。詳細なエラー情報を抽出するための PQresultVerboseErrorMessage および PQerrorMessage。
  • DuplicateKeyException: 重複キー エラーを処理するための単純な例外クラス。メッセージ パラメーターのみを受け取り、それを基本例外クラスに渡します。

このプロジェクトに取り組みながら、例外やその他の状況をさらに追加していきます

次に、接続コードを記述するためのimplementation/core/core.d ファイルを作成します。

module postgres.implementation.exception;

public:
import std.conv;

private import postgres.implementation.implementationc;

class PGSqlException : Exception
{
    string code;
    string sqlState;
    string message;
    this(PGconn* conn, PGresult* res = null)
    {
        if (res != null)
        {
            char* c = PQresultVerboseErrorMessage(res, PGVerbosity.PQERRORS_VERBOSE, PGContextVisibility
                    .PQSHOW_CONTEXT_ALWAYS);
            char* s = PQresultVerboseErrorMessage(res, PGVerbosity.PQERRORS_SQLSTATE, PGContextVisibility
                    .PQSHOW_CONTEXT_ALWAYS);
           string ss = to!string(c);
           import std.string:split;
           this.code = to!string(ss.split(':')[1]);

            this.sqlState = to!string(s);
        }
        const char* m = PQerrorMessage(conn);

        this.message = to!string(m);
        super(this.message);
    }
}

class DuplicateKeyException : Exception
{
    this(string message)
    {
        super(message);
    }
}

上記のコードの重要なポイント:

  • Postgres クラス: PostgreSQL データベース接続を表します。
    • 接続の作成、クエリ、準備されたステートメントの実行を管理します。
    • 前に定義した C バインディングを使用して、PostgreSQL ライブラリと対話します。
  • QueryResult クラス: データベース クエリの結果をカプセル化します。
    • クエリ結果を構造化形式で保存します。
    • PostgreSQL から返されるさまざまなデータ型と形式を処理します。
  • エラー処理: PostgreSQL エラーのカスタム例外処理を実装します。
  • 接続管理: 接続が失われた場合の自動再接続試行が含まれます。
  • 準備されたステートメント: パラメーター バインディングを使用した準備された SQL ステートメントの実行をサポートします。
  • メモリ管理: デストラクター (~this()) を使用してリソースを適切に解放します。
  • UTF-8 サポート: デフォルトで接続エンコードを UTF-8 に設定します。

この実装は、D アプリケーションが PostgreSQL データベースと対話するための高レベルのインターフェイスを提供し、C API の低レベルの詳細の多くを抽象化します。

接続モジュールが見つかりません」という IDE 警告/エラーが表示される可能性があります

接続モジュールを作成しましょう:

_internal/connection.d ファイルを作成し、次のコードを追加します:

dub init <project_name>

SQL の定数とその他のオプションを追加します:

_internal/consts.d

"libs": [ "pq" ],
    "lflags-windows-x86_64": [ "-LIBPATH:C:/Program Files/PostgreSQL/16/lib/" ],
    "copyFiles-windows-x86_64": [
        "C:/Program Files/PostgreSQL/16/lib/libpq.dll",
        "C:/Program Files/PostgreSQL/16/bin/libintl-9.dll",
        "C:/Program Files/PostgreSQL/16/bin/libssl-3-x64.dll",
        "C:/Program Files/PostgreSQL/16/bin/libcrypto-3-x64.dll",
        "C:/Program Files/PostgreSQL/16/bin/libwinpthread-1.dll",
        "C:/Program Files/PostgreSQL/16/bin/libiconv-2.dll"
    ],

モデルテンプレートの作成

D は、非常に汎用的なコードを作成できる機能である テンプレート メタプログラミング をサポートしています。これは、D には C のものと似た テンプレート があることを意味しますが、より強力で柔軟です。
D のテンプレートの ABC | D ブログ

D's テンプレートの主な特徴:

  1. コンパイル時の型チェック: テンプレートはコンパイル時にチェックされ、型の安全性が確保されます。
  2. コード生成: テンプレートを使用して、さまざまな型または値に特化したコードを生成できます。
  3. 可変引数テンプレート: D は、型や値を含む任意の数の引数を取ることができるテンプレートをサポートします。
  4. 静的 if と mixin: これらを使用すると、条件に基づいてコンパイル中にコードを生成および操作したり、(mixin を使用して) 文字列ベースのコードを挿入したりできます。

次に、テンプレート クラスを作成しましょう。

モデル.d

次に、https://github.com/rodevasia/sequelized/blob/main/source/postgres/model.d のコードをファイルに貼り付けて使用します

提供された GitHub リンクからコードを調べてみましょう:

"copyFiles-windows": [
        "libs/*.dll"
    ],
    "lflags-windows": [
        "/LIBPATH:$PACKAGE_DIR/libs"
    ],
    "libs": [
        "pq"
    ]

このコードは、D でテンプレート クラス Model を定義します。その主要なコンポーネントの内訳は次のとおりです。

  1. モジュール宣言: コードは postgres.model モジュールの一部です。
  2. インポート: クラスで使用するために、さまざまな標準 D ライブラリとカスタム モジュールがインポートされます。
  3. テンプレート クラス: モデル クラスは、型パラメーター T を持つテンプレートとして定義されます。これにより、クラスがさまざまな型で動作できるようになります。
  4. クラス メソッド: このクラスには、save()、update()、delete()、find() などのデータベース操作用のメソッドがいくつか含まれています。
  5. コンパイル時リフレクション: このコードは、D のコンパイル時機能を使用して、型 T のフィールドを検査し、適切な SQL クエリを生成します。
  6. SQL クエリの生成: getInsertQuery() や getUpdateQuery() などのメソッドは、T 型の構造に基づいて SQL クエリを動的に作成します。
  7. データベース対話: このクラスは、Connection オブジェクトを使用して PostgreSQL データベースと対話します。

動作するためのコードはすべて私たちが書きました。ここを図書館にしましょう。これを dub.json に追加します

dub init <project_name>

ライブラリの使用:

新しいプロジェクトを作成しましょう:

"libs": [ "pq" ],
    "lflags-windows-x86_64": [ "-LIBPATH:C:/Program Files/PostgreSQL/16/lib/" ],
    "copyFiles-windows-x86_64": [
        "C:/Program Files/PostgreSQL/16/lib/libpq.dll",
        "C:/Program Files/PostgreSQL/16/bin/libintl-9.dll",
        "C:/Program Files/PostgreSQL/16/bin/libssl-3-x64.dll",
        "C:/Program Files/PostgreSQL/16/bin/libcrypto-3-x64.dll",
        "C:/Program Files/PostgreSQL/16/bin/libwinpthread-1.dll",
        "C:/Program Files/PostgreSQL/16/bin/libiconv-2.dll"
    ],

dub.json にライブラリを依存関係として追加します

"copyFiles-windows": [
        "libs/*.dll"
    ],
    "lflags-windows": [
        "/LIBPATH:$PACKAGE_DIR/libs"
    ],
    "libs": [
        "pq"
    ]

アプリd

sudo apt-get install libpq-dev

コードを分解して、その主要コンポーネントを説明しましょう:

輸入品

コードは、標準ライブラリと Sequalized ライブラリから必要なモジュールをインポートします。

  • std.stdio: 基本的な入出力操作用
  • postgres._internal.connection: データベース接続の詳細を処理します
  • postgres.implementation.core: PostgreSQL 操作のコア機能
  • postgres.model: データベース モデルを定義するためのモデル ミックスインを提供します
  • postgres._internal.consts: ライブラリで使用される定数値が含まれます

主な機能

メイン関数は、Sequalized ライブラリの使用方法を示します。

  • 接続の詳細を含む DatabaseConnectionOption オブジェクトを作成します
  • これらのオプションを使用して Postgres オブジェクトを初期化します
  • Example クラスのインスタンスを作成します
  • sync() を呼び出して、データベース内に対応するテーブルを作成します
  • textField の値を設定し、データベースにレコードを挿入します

クラス例

このクラスはデータベース テーブルのモデルを定義します:

  • モデル ミックスインを使用して ORM 機能を継承します
  • id と textField の 2 つのフィールドを定義します
  • @Type、@PmKey、@unique などの属性を使用してフィールド プロパティを指定します

完全なプロセスは含めていません。それはあなたが調べてください:)

私のプロジェクトに貢献したい場合は、ここにリポジトリへのリンクがあります:
https://github.com/rodevasia/sequelized

以上がD での PostgreSQL ライブラリの構築の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。