主键为uuid。
UserModel::create($data);报错:SQLSTATE[25P02]: In failed sql transaction: 7 ERROR: current transaction is aborted, commands ignored until end of transaction block,是在获取添加记录的主键id时报错。
$lastInsId = $this->getLastInsID($query, $sequence);思路:通过pgsql手册https://www.postgresql.org/docs/13/dml-returning.html得到获取主键的SQL语句是
INSERT INTO users (firstname, lastname) VALUES ('Joe', 'Cool') RETURNING id;解决方案:1. think\db\builder\Pgsql类
$insertSql属性
protected $insertSql = 'INSERT INTO %TABLE% (%FIELD%) VALUES (%DATA%) %COMMENT%';改为protected $insertSql = 'INSERT INTO %TABLE% (%FIELD%) VALUES (%DATA%) %COMMENT% RETURNING %PK%';2. 复制think\db\Build类中的insert方法到think\db\builder\Pgsql类里面。添加主键pk到insert语句中。public function insert(Query $query): string
{
$options = $query->getOptions();
// 分析并处理数据
$data = $this->parseData($query, $options['data']);
if (empty($data)) {
return '';
}
$fields = array_keys($data);
$values = array_values($data);
return str_replace(
['%INSERT%', '%TABLE%', '%EXTRA%', '%FIELD%', '%DATA%', '%COMMENT%', '%PK%'],
[
!empty($options['replace']) ? 'REPLACE' : 'INSERT',
$this->parseTable($query, $options['table']),
$this->parseExtra($query, $options['extra']),
implode(' , ', $fields),
implode(' , ', $values),
$this->parseComment($query, $options['comment']),
$query->getPk()
],
$this->insertSql);
}3. 复制think\db\PDOConnection类的insert方法和pdoExecute方法到think\db\connector\Pgsql中,并将Pgsql中的pdoExecute方法改为pdoInsertExecute,已视为Pgsql的insert专用执行方法。更改think\db\connector\Pgsql的pdoInsertExecute方法,让该方法返回 原值(受影响的记录数)和 主键值。
protected function pdoInsertExecute(BaseQuery $query, string $sql, array $bind = [], bool $origin = false): array
{
if ($origin) {
$query->parseOptions();
}
$sth = $this->queryPDOStatement($query->master(true), $sql, $bind);
$result = $sth->fetch(PDO::FETCH_NUM);
if (!$origin && !empty($this->config['deploy']) && !empty($this->config['read_master'])) {
$this->readMaster = true;
}
$this->numRows = $this->PDOStatement->rowCount();
if ($query->getOptions('cache')) {
// 清理缓存数据
$cacheItem = $this->parseCache($query, $query->getOptions('cache'));
$key = $cacheItem->getKey();
$tag = $cacheItem->getTag();
if (isset($key) && $this->cache->has($key)) {
$this->cache->delete($key);
} elseif (!empty($tag) && method_exists($this->cache, 'tag')) {
$this->cache->tag($tag)->clear();
}
}
return [$this->numRows,$result[0]];
}更改think\db\connector\Pgsql的insert方法,让其直接从pdoInsertExecute获取主键值public function insert(BaseQuery $query, bool $getLastInsID = false)
{
// 分析查询表达式
$options = $query->parseOptions();
// 生成SQL语句
$sql = $this->builder->insert($query);
// 执行操作
$result = '' == $sql ? 0 : $this->pdoInsertExecute($query, $sql, $query->getBind());
if ($result[0]) {
$sequence = $options['sequence'] ?? null;
$lastInsId = $result[1];
$data = $options['data'];
if ($lastInsId) {
$pk = $query->getAutoInc();
if ($pk) {
$data[$pk] = $lastInsId;
}
}
$query->setOption('data', $data);
$this->db->trigger('after_insert', $query);
if ($getLastInsID && $lastInsId) {
return $lastInsId;
}
}
return $result;
}调用 $entity = UserModel::create(['username'=>'测试1']);
dump($entity->toArray());
注意:代码没有经过实战,可能有其他bug。
最佳答案