FuelPHP:PDO+PostgreSQLで、insert時にidがとれないエラーを回避する


## 問題

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を返すことができる

```sql
create table foo (id serial, name text);
insert into foo (name) values ('bar') returning id;
#=> 
id
---
1
```

ということでfuelPHPに手を入れる
まずはinsert文を作っているところ

```php: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を実行しているところ

```php: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はっておく

```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
```