【发布时间】:2013-07-13 21:12:28
【问题描述】:
我一直在编写自己的 PHP 模型系统,它提供基本的 ORM 和 DBAL 支持,仅作为学习课程。它让我可以编写我以前从未做过的事情,并使用我从未使用过的 SQLite 和 PostgreSQL 等数据库。
模型包:https://github.com/titon/Model PgSQL包:https://github.com/titon/Model.PostgreSQL
我遇到的问题是对 PgSQL 驱动程序进行单元测试(我有 MySQL 和 SQLite 工作)。每次运行单元测试时,我都会收到以下错误:
PDOException : SQLSTATE[55000]: Object not in prerequisite state: 7 ERROR: currval of sequence "users_id_seq" is not yet defined in this session
我知道这个问题是什么,但我似乎没有解决它。它甚至没有达到我的单元测试,它在夹具设置部分失败。以下是每个单元测试期间采取的步骤:
- 驱动程序在
setUp()期间初始化并连接 - 单元测试方法被调用
- 夹具已加载
- CREATE TABLE 语句被调用
- 调用 CREATE INDEX 语句
- INSERT 记录被调用
- 已运行单元测试
-
调用
tearDown()卸载固定装置(DROP TABLE 和 INDEX)并断开驱动程序
在步骤 3.3 插入夹具记录时发生错误。它插入第一条记录(共 10 条),但尝试获取最后一条插入 ID 失败(上面的序列错误)。当我检查 PGAdmin 时,表和序列确实存在,所以我很困惑。
- 在调用插入时序列是否尚未完全创建?
- 我的连接会话是否过早终止?
- 我该如何解决这个问题?
我对 PgSQL 非常陌生,因此我们将不胜感激。作为记录,代码使用 PHP PDO 并调用 lastInsertId('table_column_seq') 来检索最后一个 ID。
如果您有兴趣,这里是夹具设置 SQL。
CREATE TABLE IF NOT EXISTS "users" (
"id" serial NOT NULL,
"country_id" integer NULL DEFAULT NULL,
"username" varchar(255) NULL,
"password" varchar(255) NULL,
"email" varchar(255) NULL,
"firstName" varchar(255) NULL,
"lastName" varchar(255) NULL,
"age" smallint NULL,
"created" timestamp NULL DEFAULT NULL,
"modified" timestamp NULL DEFAULT NULL,
UNIQUE ("username")
);
CREATE INDEX "country_id" ON "users" ("country_id");
INSERT INTO "users" ("id", "country_id", "username", "firstName", "lastName", "password", "email", "age", "created") VALUES ('1', 1, 'miles', 'Miles', 'Johnson', '1Z5895jf72yL77h', 'miles@email.com', 25, '1988-02-26 21:22:34');
# Fails right after this insert
【问题讨论】:
-
如果要使用序列(SERIAL 数据类型),为什么要在 INSERT 语句中传递文字 ID?为什么要将该文字作为字符串而不是整数传递?为什么没有主键?为什么用户名是唯一的,但可以为空?
-
固定装置基本上是简单的数据,带有随机模式和类型,其中一些在文字 prod 设置中没有意义。固定装置也在 MySQL、PgSQL、SQLite 和 MongoDB 之间共享,因此有一些怪癖可以让一切正常工作。此外,语句输出也不是完全匹配,因为 PDO 语句无法与其绑定值一起看到。这些只是自动生成的。
标签: php unit-testing postgresql pdo