首頁  >  文章  >  後端開發  >  用 D 建構 PostgreSQL 函式庫

用 D 建構 PostgreSQL 函式庫

Patricia Arquette
Patricia Arquette原創
2024-10-24 06:16:30866瀏覽

Building a PostgreSQL Library in D

我總是對新的程式語言及其框架感到好奇。一直以來,我的經驗和好奇心都只集中在前端開發(不過我也做過一些後端開發?)。我挑戰自己以擴展我的技能,並找到了 D 程式語言。 D簡單來說就是C和CPP的進階版。

D是什麼?網站稱「**D 是一種通用程式語言,具有靜態類型、系統級存取和類似C 的語法。使用D 程式語言,快速寫入、快速讀取和快速運行。 我使用 PostgreSQL 作為我作品的資料庫,這也是我為這個函式庫選擇它的原因。 PostgreSQL 是該公司現在使用的主要開源 SQL 資料庫系統之一,其功能正在不斷擴展。

為什麼要建立自訂 ORM 庫?

在搞D語言的時候找不到一個能滿足我需求的包,要嘛是停止維護了,要嘛是可以直接查詢。我有 JavaScript 背景,使用 Sequalize ORM。這讓我想到了一個主意,D 中類似的怎麼樣。

所以,我做了一些研究,發現 Postgres 為 C 提供了函式庫。然後我想,如何在 D 中使用 C 綁定並使用它來開發 ORM。 我從 https://github.com/adamdruppe/arsd/blob/master/postgres.d 找到了用於將 C 程式庫綁定到 D 的原始程式碼。

入門

要求:

您的系統中必須安裝 PostgreSQL。 (
    我為 PostgreSQL 16 開發)
  • IDE(Zed/ VSCode/Vim)
  • DMD - d 語言編譯器
  • 要建立新項目,請在終端機中使用以下命令:

開啟終端機或命令提示字元。
  1. 導航到您要建立專案的目錄。
  2. 運行指令:
此指令將建立一個具有指定名稱的新專案目錄,並設定 D 專案的基本結構。
dub init <project_name>
  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"
    ]

安裝並正確連結必要的程式庫後,您可以繼續設定 D 專案以使用 PostgreSQL。

實作 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: 一個用來處理重複鍵錯誤的簡單異常類別。它只接受一個訊息參數並將其傳遞給 Exception 基底類別。

當我從事這個專案時,我將添加更多例外和其他情況

現在建立一個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 模板的主要特點:

  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. 模板類別: Model 類別被定義為具有類型參數 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"
    ]

app.d

sudo apt-get install libpq-dev

讓我們分解程式碼並解釋其主要組件:

進口

程式碼從標準函式庫和Sequalized函式庫導入必要的模組:

  • std.stdio:用於基本輸入/輸出操作
  • postgres._internal.connection:處理資料庫連線詳細資訊
  • postgres.implementation.core:PostgreSQL 操作的核心功能
  • postgres.model:提供用於定義資料庫模型的模型混合
  • postgres._internal.consts:包含庫中使用的常數值

主要功能

main函數示範如何使用Sequalized函式庫:

  • 它會建立一個包含連接詳細資訊的 DatabaseConnectionOption 物件
  • 使用這些選項初始化 Postgres 物件
  • 建立Example類別的實例
  • 呼叫sync()在資料庫中建立對應的表
  • 設定文字欄位的值並將記錄插入資料庫

範例類

此類定義資料庫表的模型:

  • 它使用 Model mixin 來繼承 ORM 功能
  • 定義兩個欄位:id 和 textField
  • 使用 @Type、@PmKey 和 @unique 等屬性指定欄位屬性

我沒有包含完整的過程,供你了解:)

如果您願意為我的專案做出貢獻,這裡是儲存庫的連結:
https://github.com/rodevasia/sequelized

以上是用 D 建構 PostgreSQL 函式庫的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn