3

我需要用 C 语言为 PostgreSQL ( libpq ) 的数据库访问 API 和可能的其他一些关系数据库管理系统编写一个数据库抽象层。

我正在考虑在pqsql和可能的其他数据库系统中编写我自己的现有函数的抽象。编写这样的数据库抽象 API 时要考虑的最佳策略是什么?

到目前为止,我最喜欢的写作计划可能是:

  1. 为感兴趣的任何特定数据库系统定义标头、函数和包装器。
  2. 当使用第一个连接调用(函数)时,检查并确定它适用于哪个关系数据库管理系统
  3. 包括用于数据库抽象的正确方法和定义集。

但这种处理方式可能一次只允许使用一个关系数据库管理系统。这对于数据库抽象层来说很常见吗?

可以考虑哪些其他选择?

4

2 回答 2

11

不要重新发明这个轮子。

它已经重复地完成了,虽然最流行的系统 ( ODBC ) 无疑是丑陋的,但它已经为您听说过的每个数据库编写了抽象。通过UnixODBC项目,它也存在于 UNIX 和 POSIX UNIX 上,例如 Mac OS X。

libdbi是一个不那么丑陋但支持更窄数据库的替代方案。您不会像 ODBC 那样从供应商那里获得 libdbi 的驱动程序。

怎么反复?

如果 C++ 没问题,我听说过的另一个很好的数据库抽象层是诺基亚(曾经是 TrollTech)提供的Qt 框架的 数据库接口。它的主要优点是已经*编写*和测试过。主要的缺点是,如果您的应用程序核心不是基于 C++ 和 Qt 的,它会有点笨拙。

其他 C++ 选项(我没有亲自使用过)是sqlapi++dtemplatelibSOCI

如果此时您想知道为什么所有这些数据库抽象层都是为 C++ 编写的,也许这是一个提示。如果你用 C 编写一个 DB 抽象层,我敢打赌你会通过函数指针的结构重新发明 C++ 虚方法,并且最终可能会创建几乎和GObject一样丑陋的东西,在这种情况下,你不妨使用libgdb / gnome -分贝。为了避免虚假虚拟方法垃圾,您可以通过运行时库路径在链接时选择您的 DB 层,并只提供一堆普通的旧函数,但我不知道为什么当有这么多现有函数时你会这样做选项就在身边。

顺便说一句,如果事实证明您根本不需要 DB 抽象,只需要一个更好的接口(因为您主要针对 Pg),请查看libpqtypes(纯 C,没有 C++,非常便携),也称为“什么libpq 应该是”。即使您要添加一个抽象层,也可能值得在 libpqtypes 上进行,而不仅仅是 libpq。

如果 ODBC、libdbi、libpqtypes、Qt 等不适合您,您需要定义原因,并创建一组更具体的标准来满足。

或者:如果您的设计允许,您可能需要考虑使用具有 DB 抽象层(如Python ( psycopg )、RubyPerlJava ( JDBC ))的嵌入式高级语言进行数据库访问和相关工作。所有这些都有自己被广泛采用和经过良好测试的数据库抽象层,您可以从中受益,同时仍然用 C 编写大部分程序。或者,就此而言,您可以只用 C 编写程序的性能关键部分作为库并从您选择的语言中使用它,并使用已经为您编写的健全的数据库抽象层。

数据库抽象很难。真的很难。数据库抽象使用起来并不可怕,性能不错,并且足够灵活以使用数据库,因为比愚蠢的行存储更难 - 迟早,你需要的不仅仅是一个愚蠢的行存储。

于 2012-04-18T11:23:12.700 回答
3

我不确定您是在寻找更具体的东西还是只是一般的想法。我看到完成类似事情的常用方法是定义一个包含指向所有相关函数的函数指针的通用结构。

struct dbms {
    int (*connect)(const char *cs);
    int (*disconnect)(void);
    int (*query)(...);
    ...
}

然后对于每个 DBMS,用指向与该 DBMS 相关的函数的指针填充这个数组。然后,您将此指针保存到某个地方适当初始化的结构,并使用它来调用(直接或从某种包装函数)...

每当我看到我想知道为什么不简单地使用 c++ 和虚拟方法。

于 2012-04-18T08:51:40.307 回答