我總是對新的程式語言及其框架感到好奇。一直以來,我的經驗和好奇心都只集中在前端開發(不過我也做過一些後端開發?)。我挑戰自己以擴展我的技能,並找到了 D 程式語言。 D簡單來說就是C和CPP的進階版。
D是什麼?網站稱「**D 是一種通用程式語言,具有靜態類型、系統級存取和類似C 的語法。使用D 程式語言,快速寫入、快速讀取和快速運行。 我使用 PostgreSQL 作為我作品的資料庫,這也是我為這個函式庫選擇它的原因。 PostgreSQL 是該公司現在使用的主要開源 SQL 資料庫系統之一,其功能正在不斷擴展。
為什麼要建立自訂 ORM 庫?
所以,我做了一些研究,發現 Postgres 為 C 提供了函式庫。然後我想,如何在 D 中使用 C 綁定並使用它來開發 ORM。 我從 https://github.com/adamdruppe/arsd/blob/master/postgres.d 找到了用於將 C 程式庫綁定到 D 的原始程式碼。
入門
您的系統中必須安裝 PostgreSQL。 (
開啟終端機或命令提示字元。
dub init <project_name>
完成這些步驟後,您將建立一個基本的 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。
這是 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); }
當我從事這個專案時,我將添加更多例外和其他情況
現在建立一個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); } }
上述程式碼重點:
此實作為 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
現在使用 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。以下是其關鍵組件的細分:
我們寫了所有工作程式碼。讓我們把它變成一個圖書館。將其添加到您的 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函式庫導入必要的模組:
main函數示範如何使用Sequalized函式庫:
此類定義資料庫表的模型:
我沒有包含完整的過程,供你了解:)
如果您願意為我的專案做出貢獻,這裡是儲存庫的連結:
https://github.com/rodevasia/sequelized
以上是用 D 建構 PostgreSQL 函式庫的詳細內容。更多資訊請關注PHP中文網其他相關文章!