我总是对新的编程语言及其框架感到好奇。一直以来,我的经验和好奇心都只集中在前端开发上(不过我也做过一些后端开发?)。我挑战自己以扩展我的技能,并找到了 D 编程语言。 D简单来说就是C和CPP的高级版本。
D是什么?该网站称“**D 是一种通用编程语言,具有静态类型、系统级访问和类似 C 的语法。使用D 编程语言,快速写入、快速读取和快速运行。”
我使用 PostgreSQL 作为我作品的数据库,这也是我为这个库选择它的原因。 PostgreSQL 是公司现在使用的主要开源 SQL 数据库系统之一,其功能正在不断扩展。
在搞D语言的时候找不到一个能满足我需求的包,要么是停止维护了,要么是可以直接查询。我有 JavaScript 背景,使用 Sequalize ORM。这让我想到了一个主意,D 中类似的怎么样。
所以,我做了一些研究,发现 Postgres 为 C 提供了库。然后我想,如何在 D 中使用 C 绑定并使用它来开发 ORM。 我从 https://github.com/adamdruppe/arsd/blob/master/postgres.d 找到了用于将 C 库绑定到 D 的源代码。
要求:
要创建新项目,请在终端中使用以下命令:
dub init <project_name>
此命令将创建一个具有指定名称的新项目目录,并设置 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。
这是 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中文网其他相关文章!