Nette\Database, insert a PostgreSQL
- PaBi3
- Bronze Partner | 62
PostgreSQL databáza
create table a (
id serial primary key,
name varchar(40) not null
);
create table b (
id serial primary key,
name varchar(40) not null,
a_id int not null references a(id) on update cascade on delete cascade
);
PHP kód
<?php
try {
$db->exec('begin');
$row = $db->table('a')->insert($data1);
$row->related('b')->insert($data2);
$db->exec('commit');
} catch (Exception $e) {
$db->exec('rollback');
}
?>
Pri použití prvého insertu sa nezistí ID vkladaného záznamu do tabuľky a. Čiže druhý insert bude neúspešný. Je to spôsobené tým, že metóda lastInsertId() z PDO, ktorá je použitá tu vráti false, pretože potrebuje parameter, ktorý definuje názov sekvencie.
Navrhovaná oprava:
<?php
/**
* Inserts row in a table.
* @param mixed array($column => $value)|Traversable for single row insert or TableSelection|string for INSERT ... SELECT
* @return TableRow or FALSE in case of an error or number of affected rows for INSERT ... SELECT
*/
public function insert($data)
{
if ($data instanceof TableSelection) {
$data = $data->getSql();
} elseif ($data instanceof \Traversable) {
$data = iterator_to_array($data);
}
$return = $this->connection->query("INSERT INTO $this->delimitedName", $data);
$this->rows = NULL;
if (!is_array($data)) {
return $return->rowCount();
}
$driver = $this->connection->getAttribute(\PDO::ATTR_DRIVER_NAME);
if ($driver == 'pgsql') {
$seq = $this->name . '_' . $this->primary . '_seq';
/* alebo cez SELECT pg_get_serial_sequence($this->delimitedName, $this->delimitedPrimary */
} else {
$seq = NULL;
}
if (!isset($data[$this->primary]) && ($id = $this->connection->lastInsertId($seq))) {
$data[$this->primary] = $id;
}
return new TableRow($data, $this);
}
?>
Nezisťoval som, či je možné nejakým spôsobom získať názov sekvencie, tak som sa držal konvencie, ktorú používa serial v PostgreSQL, t.j.: [tabulka]_[kluc]_seq.
EDIT: Zistil som, že je ešte nutné vyriešiť neexistujúce sekvencie. Inak PDO vyhodí výnimku v prípade, ak sa ukladá záznam do tabuľky, ktorá nemá sekvenciu. Možno by bolo najlepšie názov sekvencie udávať ako druhý parameter metódy insert().
Editoval PaBi3 (21. 1. 2011 15:55)
- vrana
- Člen | 131
V NotORM to řešit nebudu už jen proto, že insert
má
zabrané všechny parametry (to se používá pro vícehodnotový INSERT) a
další konvenci se mi zavádět nechce. Záznamy lze vložit bez
related
po ručním získání lastInsertId
:
<?php
$db->table('a')->insert($data1);
$data2["a_id"] = $db->lastInsertId("a_id_seq");
$db->table('b')->insert($data2);
?>