From 691d68ba549efc69c129ac34796e0b5d46e6ddf3 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Wed, 30 May 2012 14:23:27 -0500 Subject: [PATCH] improve / fix postgres support. --- laravel/database/connection.php | 10 +++++++++ laravel/database/connectors/postgres.php | 12 +++++++++++ laravel/database/eloquent/model.php | 2 +- laravel/database/query.php | 21 ++++++++++++------- laravel/database/query/grammars/grammar.php | 13 ++++++++++++ laravel/database/query/grammars/postgres.php | 20 ++++++++++++++++++ laravel/database/schema/grammars/postgres.php | 2 +- laravel/database/schema/table.php | 4 +++- 8 files changed, 73 insertions(+), 11 deletions(-) create mode 100644 laravel/database/query/grammars/postgres.php diff --git a/laravel/database/connection.php b/laravel/database/connection.php index dd1d8de6..66601ef8 100644 --- a/laravel/database/connection.php +++ b/laravel/database/connection.php @@ -89,6 +89,9 @@ protected function grammar() case 'sqlsrv': return $this->grammar = new Query\Grammars\SQLServer($this); + case 'pgsql': + return $this->grammar = new Query\Grammars\Postgres($this); + default: return $this->grammar = new Query\Grammars\Grammar($this); } @@ -190,6 +193,13 @@ public function query($sql, $bindings = array()) { return $statement->rowCount(); } + // For insert statements that use the "returning" clause, which is allowed + // by databsae systems such as Postgres, we need to actually return the + // real query result so the consumer can get the ID. + elseif (stripos($sql, 'insert') === 0 and stripos($sql, 'returning') !== false) + { + return $this->fetch($statement, Config::get('database.fetch')); + } else { return $result; diff --git a/laravel/database/connectors/postgres.php b/laravel/database/connectors/postgres.php index 233914fd..3721f368 100644 --- a/laravel/database/connectors/postgres.php +++ b/laravel/database/connectors/postgres.php @@ -2,6 +2,18 @@ class Postgres extends Connector { + /** + * The PDO connection options. + * + * @var array + */ + protected $options = array( + PDO::ATTR_CASE => PDO::CASE_LOWER, + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL, + PDO::ATTR_STRINGIFY_FETCHES => false, + ); + /** * Establish a PDO database connection. * diff --git a/laravel/database/eloquent/model.php b/laravel/database/eloquent/model.php index 3af49057..91aedd6e 100644 --- a/laravel/database/eloquent/model.php +++ b/laravel/database/eloquent/model.php @@ -399,7 +399,7 @@ public function save() // then we can consider the insert successful. else { - $id = $this->query()->insert_get_id($this->attributes, $this->sequence()); + $id = $this->query()->insert_get_id($this->attributes, $this->key()); $this->set_key($id); diff --git a/laravel/database/query.php b/laravel/database/query.php index 607a8627..83c92b83 100644 --- a/laravel/database/query.php +++ b/laravel/database/query.php @@ -3,6 +3,7 @@ use Closure; use Laravel\Database; use Laravel\Paginator; +use Laravel\Database\Query\Grammars\Postgres; use Laravel\Database\Query\Grammars\SQLServer; class Query { @@ -751,19 +752,23 @@ public function insert($values) * Insert an array of values into the database table and return the ID. * * @param array $values - * @param string $sequence + * @param string $column * @return int */ - public function insert_get_id($values, $sequence = null) + public function insert_get_id($values, $column = 'id') { - $sql = $this->grammar->insert($this, $values); + $sql = $this->grammar->insert_get_id($this, $values, $column); - $this->connection->query($sql, array_values($values)); + $result = $this->connection->query($sql, array_values($values)); - // Some database systems (Postgres) require a sequence name to be - // given when retrieving the auto-incrementing ID, so we'll pass - // the given sequence into the method just in case. - return (int) $this->connection->pdo->lastInsertId($sequence); + if ($this->grammar instanceof Postgres) + { + return (int) $result[0]->$column; + } + else + { + return (int) $this->connection->pdo->lastInsertId(); + } } /** diff --git a/laravel/database/query/grammars/grammar.php b/laravel/database/query/grammars/grammar.php index e7d9e284..65c62cf3 100644 --- a/laravel/database/query/grammars/grammar.php +++ b/laravel/database/query/grammars/grammar.php @@ -375,6 +375,19 @@ public function insert(Query $query, $values) return "INSERT INTO {$table} ({$columns}) VALUES {$parameters}"; } + /** + * Compile a SQL INSERT and get ID statment from a Query instance. + * + * @param Query $query + * @param array $values + * @param string $column + * @return string + */ + public function insert_get_id(Query $query, $values, $column) + { + return $this->insert($query, $values); + } + /** * Compile a SQL UPDATE statment from a Query instance. * diff --git a/laravel/database/query/grammars/postgres.php b/laravel/database/query/grammars/postgres.php new file mode 100644 index 00000000..002b4cc7 --- /dev/null +++ b/laravel/database/query/grammars/postgres.php @@ -0,0 +1,20 @@ +insert($query, $values)." RETURNING $column"; + } + +} \ No newline at end of file diff --git a/laravel/database/schema/grammars/postgres.php b/laravel/database/schema/grammars/postgres.php index e0492ba7..930c5160 100644 --- a/laravel/database/schema/grammars/postgres.php +++ b/laravel/database/schema/grammars/postgres.php @@ -324,7 +324,7 @@ protected function type_string(Fluent $column) */ protected function type_integer(Fluent $column) { - return ($column->increment) ? 'SERIAL' : 'INTEGER'; + return ($column->increment) ? 'SERIAL' : 'BIGINT'; } /** diff --git a/laravel/database/schema/table.php b/laravel/database/schema/table.php index 9518d6e7..570c5405 100644 --- a/laravel/database/schema/table.php +++ b/laravel/database/schema/table.php @@ -136,7 +136,9 @@ public function key($type, $columns, $name) // the index that can be used when dropping indexes. if (is_null($name)) { - $name = $this->name.'_'.implode('_', $columns).'_'.$type; + $name = str_replace(array('-', '.'), '_', $this->name); + + $name = $name.'_'.implode('_', $columns).'_'.$type; } return $this->command($type, compact('name', 'columns'));