問題
FuelPHPのModel_Crudを継承したモデルでcreateを行うと、生成後のidがとれず下記のようなエラーとなる
Property "id" not found for Model_Monkey. in /vagrant_data/html/fuelphp/fuel/core/classes/model/crud.php on line 441
これはPDOのlastInsertId()を使って生成後のidをとってきているのが原因。PDOのlastInsertId()はPostgreSQLでは最後に追加したidを返さない。
対策
PostgreSQLでserial型(mysqlでいうところのauto_increment相当)を使う場合にはinsert文の最後に returning 節をつけることでidを返すことができる
create table foo (id serial, name text);
insert into foo (name) values ('bar') returning id;
# =>
id
---
1
ということでfuelPHPに手を入れる
まずはinsert文を作っているところ
fuel/core/classes/database/query/builder/insert.php
public function compile($db = null)
{
// .. snip ..
if(in_array("id", $this->_columns)){
$query .= " returning id";
}
return $query;
}
PDOを実行しているところ
fuel/core/classes/database/pdo/connection.php
// .. snip
elseif ($type === \DB::INSERT)
{
$row = $result->fetch(\PDO::FETCH_ASSOC);
$ret_id = array_key_exists('id',$row) ? $row['id'] : 0;
return array($ret_id,
$result->rowCount());
);
}
とりあえず期待の動作はした。こんなんでいいんだろか
変更
idがないテーブルでやってしまうとうまくいかない。つまりmigrationでコケることが判明した
diff
diffはっておく
pg.patch
diff --git fuel/core/classes/database/pdo/connection.php fuel/core/classes/database/pdo/connection.php
index 4c1cd3d..ef352b3 100644
--- fuel/core/classes/database/pdo/connection.php
+++ fuel/core/classes/database/pdo/connection.php
@@ -324,10 +324,14 @@ class Database_PDO_Connection extends \Database_Connection
elseif ($type === \DB::INSERT)
{
// Return a list of insert id and rows created
- return array(
- $this->_connection->lastInsertId(),
- $result->rowCount(),
- );
+ $row = $result->fetch(\PDO::FETCH_ASSOC);
+ if($row){
+ $ret_id = $row && array_key_exists('id',$row) ? $row['id'] : 0;
+ } else {
+ $ret_id = 0;
+ }
+ return array($ret_id,
+ $result->rowCount());
}
else
{
diff --git fuel/core/classes/database/query/builder/insert.php fuel/core/classes/database/query/builder/insert.php
index 68bee47..214b38a 100644
--- fuel/core/classes/database/query/builder/insert.php
+++ fuel/core/classes/database/query/builder/insert.php
@@ -196,6 +196,10 @@ class Database_Query_Builder_Insert extends \Database_Query_Builder
$query .= (string) $this->_values;
}
+ if(in_array("id", $this->_columns)){
+ $query .= " returning id";
+ }
+
return $query;
}
diff --git fuel/core/classes/dbutil.php fuel/core/classes/dbutil.php
index 0951ae4..7d7947a 100644
--- fuel/core/classes/dbutil.php
+++ fuel/core/classes/dbutil.php
@@ -123,7 +123,7 @@ class DBUtil
{
$key_name = \DB::quote_identifier(implode('_', $primary_keys), $db ? $db : static::$connection);
$primary_keys = \DB::quote_identifier($primary_keys, $db ? $db : static::$connection);
- $sql .= ",\n\tPRIMARY KEY ".$key_name." (" . implode(', ', $primary_keys) . ")";
+ $sql .= ",\n\tPRIMARY KEY (" . implode(', ', $primary_keys) . ")";
}
empty($foreign_keys) or $sql .= static::process_foreign_keys($foreign_keys);
@@ -709,4 +709,3 @@ class DBUtil
}
}
-
下記のように実行するとうまくいくのでは
$ patch -p0 -u --ignore-whitespace --verbose < pg.patch