Removing MySQL-specific schema code from core, improving support for PostgreSQL sequences, most tests passing

git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@6355 3807eeeb-6ff5-0310-8944-8be069107fe0
This commit is contained in:
nate 2008-01-10 08:44:38 +00:00
parent 188ff4737d
commit cbd715618b
32 changed files with 126 additions and 144 deletions

View file

@ -185,9 +185,6 @@ class DboMysql extends DboSource {
if(!empty($column[0]['Key']) && isset($this->index[$column[0]['Key']])) {
$fields[$column[0]['Field']]['key'] = $this->index[$column[0]['Key']];
}
if(!empty($column[0]['Extra'])) {
$fields[$column[0]['Field']]['extra'] = $column[0]['Extra'];
}
}
}
$this->__cacheDescription($this->fullTableName($model, false), $fields);

View file

@ -158,17 +158,12 @@ class DboPostgres extends DboSource {
* @return array Fields in table. Keys are name and type
*/
function &describe(&$model) {
if (isset($model->sequence)) {
$this->_sequenceMap[$this->fullTableName($model, false)] = $model->sequence;
}
$fields = parent::describe($model);
$table = $this->fullTableName($model, false);
$this->_sequenceMap[$table] = array();
$cache = parent::describe($model);
if ($cache != null) {
return $cache;
}
$fields = false;
$cols = $this->fetchAll("SELECT DISTINCT column_name AS name, data_type AS type, is_nullable AS null, column_default AS default, ordinal_position AS position, character_maximum_length AS char_length, character_octet_length AS oct_length FROM information_schema.columns WHERE table_name =" . $this->value($model->tablePrefix . $model->table) . " ORDER BY position");
if ($fields === null) {
$cols = $this->fetchAll("SELECT DISTINCT column_name AS name, data_type AS type, is_nullable AS null, column_default AS default, ordinal_position AS position, character_maximum_length AS char_length, character_octet_length AS oct_length FROM information_schema.columns WHERE table_name =" . $this->value($table) . " ORDER BY position");
foreach ($cols as $column) {
$colKey = array_keys($column);
@ -179,9 +174,6 @@ class DboPostgres extends DboSource {
if (isset($column[0])) {
$c = $column[0];
if (strpos($c['default'], 'nextval(') === 0) {
$c['default'] = null;
}
if (!empty($c['char_length'])) {
$length = intval($c['char_length']);
} elseif (!empty($c['oct_length'])) {
@ -195,9 +187,17 @@ class DboPostgres extends DboSource {
'default' => preg_replace('/::.*/', '', $c['default']),
'length' => $length
);
if (preg_match('/nextval\([\'"]?(\w+)/', $c['default'], $seq)) {
$this->_sequenceMap[$table][$c['name']] = $seq[1];
$fields[$c['name']]['default'] = null;
}
}
$this->__cacheDescription($model->tablePrefix . $model->table, $fields);
}
$this->__cacheDescription($table, $fields);
}
if (isset($model->sequence)) {
$this->_sequenceMap[$table][$model->primaryKey] = $model->sequence;
}
return $fields;
}
/**
@ -345,24 +345,52 @@ class DboPostgres extends DboSource {
* @return integer
*/
function lastInsertId($source, $field = 'id') {
foreach ($this->__descriptions[$source] as $name => $sourceinfo) {
if (strcasecmp($name, $field) == 0) {
break;
}
}
if (isset($this->_sequenceMap[$source])) {
$seq = $this->_sequenceMap[$source];
} elseif (preg_match('/^nextval\(\'(\w+)\'/', $sourceinfo['default'], $matches)) {
$seq = $matches[1];
} else {
$seq = "{$source}_{$field}_seq";
}
$res = $this->rawQuery("SELECT last_value AS max FROM \"{$seq}\"");
$data = $this->fetchRow($res);
$seq = $this->getSequence($source, $field);
$data = $this->fetchRow("SELECT last_value AS max FROM \"{$seq}\"");
return $data[0]['max'];
}
/**
* Gets the associated sequence for the given table/field
*
* @param mixed $table Either a full table name (with prefix) as a string, or a model object
* @param string $field Name of the ID database field. Defaults to "id"
* @return string The associated sequence name from the sequence map, defaults to "{$table}_{$field}_seq"
*/
function getSequence($table, $field = 'id') {
if (is_object($table)) {
$table = $this->fullTableName($table, false);
}
if (isset($this->_sequenceMap[$table]) && isset($this->_sequenceMap[$table][$field])) {
return $this->_sequenceMap[$table][$field];
} else {
return "{$source}_{$field}_seq";
}
}
/**
* Deletes all the records in a table and drops all associated auto-increment sequences
*
* @param mixed $table A string or model class representing the table to be truncated
* @param integer $reset If -1, sequences are dropped, if 0 (default), sequences are reset,
* and if 1, sequences are not modified
* @return boolean SQL TRUNCATE TABLE statement, false if not applicable.
* @access public
*/
function truncate($table, $reset = 0) {
if (parent::truncate($table)) {
$table = $this->fullTableName($table, false);
if (isset($this->_sequenceMap[$table]) && $reset !== 1) {
foreach ($this->_sequenceMap[$table] as $field => $sequence) {
if ($reset === 0) {
$this->execute("ALTER SEQUENCE \"{$sequence}\" RESTART WITH 1");
} elseif ($reset === -1) {
$this->execute("DROP SEQUENCE IF EXISTS \"{$sequence}\"");
}
}
}
return true;
}
return false;
}
/**
* Generates and executes an SQL UPDATE statement for given model, fields, and values.
*
@ -674,52 +702,8 @@ class DboPostgres extends DboSource {
* @return string
*/
function buildColumn($column) {
$name = $type = null;
$column = array_merge(array('null' => true), $column);
extract($column);
if (empty($name) || empty($type)) {
trigger_error('Column name or type not defined in schema', E_USER_WARNING);
return null;
}
if (!isset($this->columns[$type])) {
trigger_error("Column type {$type} does not exist", E_USER_WARNING);
return null;
}
$real = $this->columns[$type];
$out = $this->name($name) . ' ' . $real['name'];
if (isset($real['limit']) || isset($real['length']) || isset($column['limit']) || isset($column['length'])) {
if (isset($column['length'])) {
$length = $column['length'];
} elseif (isset($column['limit'])) {
$length = $column['limit'];
} elseif (isset($real['length'])) {
$length = $real['length'];
} else {
$length = $real['limit'];
}
if (!in_array($type, array('integer', 'binary'))) {
$out .= '(' . $length . ')';
}
}
if (isset($column['key']) && $column['key'] == 'primary' && (isset($column['extra']) && $column['extra'] == 'auto_increment')) {
preg_match('/("\w+")/', $out, $field);
$out = $field[0] . ' serial NOT NULL';
} elseif (isset($column['key']) && $column['key'] == 'primary') {
$out .= ' NOT NULL';
} elseif (isset($column['default']) && isset($column['null']) && $column['null'] == false) {
$out .= ' DEFAULT ' . $this->value($column['default'], $type) . ' NOT NULL';
} elseif (isset($column['default'])) {
$out .= ' DEFAULT ' . $this->value($column['default'], $type);
} elseif (isset($column['null']) && $column['null'] == true) {
$out .= ' DEFAULT NULL';
} elseif (isset($column['null']) && $column['null'] == false) {
$out .= ' NOT NULL';
}
return $out;
$out = str_replace('integer serial', 'serial', parent::buildColumn($column));
return preg_replace('/integer\([0-9]+\)/', 'integer', $out);
}
/**
* Format indexes for create table

View file

@ -172,7 +172,6 @@ class DboSqlite extends DboSource {
'null' => false,
'default' => $column[0]['dflt_value'],
'key' => $this->index['PRI'],
'extra' => 'auto_increment',
'length' => 11
);
}

View file

@ -993,26 +993,29 @@ class Model extends Overloadable {
* Initializes the model for writing a new record, loading the default values
* for those fields that are not defined in $data.
*
* @param array $data Optional data to assign to the model after it is created
* @return array The current data of the model
* @param mixed $data Optional data array to assign to the model after it is created. If null or false,
* schema data defaults are not merged.
* @return mixed The current data of the model, or true if $data is empty
* @access public
*/
function create($data = array()) {
$defaults = array();
$this->id = false;
$this->data = array();
$defaults = array();
$fields = $this->schema();
foreach ($fields as $field => $properties) {
$this->validationErrors = array();
if ($data !== null && $data !== false) {
foreach ($this->schema() as $field => $properties) {
if ($this->primaryKey !== $field && isset($properties['default'])) {
$defaults[$field] = $properties['default'];
}
}
$this->validationErrors = array();
if ($data !== null && $data !== false) {
$this->set(Set::filter($defaults));
$this->set($data);
}
if (empty($this->data)) {
return true;
}
return $this->data;
}
/**
@ -1318,10 +1321,12 @@ class Model extends Overloadable {
* Updates the counter cache of belongsTo associations after a save or delete operation
*
* @param array $keys Optional foreign key data, defaults to the information $this->data
* @param boolean $created True if a new record was created, otherwise only associations with
* 'counterScope' defined get updated
* @return void
* @access public
*/
function updateCounterCache($keys = array()) {
function updateCounterCache($keys = array(), $created = false) {
if (empty($keys)) {
$keys = $this->data[$this->alias];
}

View file

@ -469,9 +469,6 @@ class CakeSchema extends Object {
if (empty($value['key'])) {
unset($value['key']);
}
if (empty($value['extra'])) {
unset($value['extra']);
}
$columns[$name] = $value;
}

View file

@ -35,7 +35,7 @@
class AcoFixture extends CakeTestFixture {
var $name = 'Aco';
var $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary', 'extra'=> 'auto_increment'),
'id' => array('type' => 'integer', 'key' => 'primary'),
'parent_id' => array('type' => 'integer', 'length' => 10, 'null' => true),
'model' => array('type' => 'string', 'default' => ''),
'foreign_key' => array('type' => 'integer', 'length' => 10, 'null' => true),

View file

@ -35,7 +35,7 @@
class AdvertisementFixture extends CakeTestFixture {
var $name = 'Advertisement';
var $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary', 'extra'=> 'auto_increment'),
'id' => array('type' => 'integer', 'key' => 'primary'),
'title' => array('type' => 'string', 'null' => false),
'created' => 'datetime',
'updated' => 'datetime'

View file

@ -35,7 +35,7 @@
class AnotherArticleFixture extends CakeTestFixture {
var $name = 'AnotherArticle';
var $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary', 'extra'=> 'auto_increment'),
'id' => array('type' => 'integer', 'key' => 'primary'),
'title' => array('type' => 'string', 'null' => false),
'created' => 'datetime',
'updated' => 'datetime'

View file

@ -35,7 +35,7 @@
class AppleFixture extends CakeTestFixture {
var $name = 'Apple';
var $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary', 'extra'=> 'auto_increment'),
'id' => array('type' => 'integer', 'key' => 'primary'),
'apple_id' => array('type' => 'integer', 'null' => true),
'color' => array('type' => 'string', 'length' => 40, 'null' => false),
'name' => array('type' => 'string', 'length' => 40, 'null' => false),

View file

@ -36,7 +36,7 @@ class AroFixture extends CakeTestFixture {
var $name = 'Aro';
var $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary', 'extra'=> 'auto_increment'),
'id' => array('type' => 'integer', 'key' => 'primary'),
'parent_id' => array('type' => 'integer', 'length' => 10, 'null' => true),
'model' => array('type' => 'string', 'default' => ''),
'foreign_key' => array('type' => 'integer', 'length' => 10, 'null' => true),

View file

@ -35,7 +35,7 @@
class ArosAcoFixture extends CakeTestFixture {
var $name = 'ArosAco';
var $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary', 'extra'=> 'auto_increment'),
'id' => array('type' => 'integer', 'key' => 'primary'),
'aro_id' => array('type' => 'integer', 'length' => 10, 'null' => false),
'aco_id' => array('type' => 'integer', 'length' => 10, 'null' => false),
'_create' => array('type' => 'string', 'length' => 2, 'null' => false, 'default' => '0'),

View file

@ -35,7 +35,7 @@
class ArticleFeaturedFixture extends CakeTestFixture {
var $name = 'ArticleFeatured';
var $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary', 'extra'=> 'auto_increment'),
'id' => array('type' => 'integer', 'key' => 'primary'),
'user_id' => array('type' => 'integer', 'null' => false),
'title' => array('type' => 'string', 'null' => false),
'body' => 'text',

View file

@ -35,7 +35,7 @@
class ArticleFixture extends CakeTestFixture {
var $name = 'Article';
var $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary', 'extra'=> 'auto_increment'),
'id' => array('type' => 'integer', 'key' => 'primary'),
'user_id' => array('type' => 'integer', 'null' => false),
'title' => array('type' => 'string', 'null' => false),
'body' => 'text',

View file

@ -35,7 +35,7 @@
class AttachmentFixture extends CakeTestFixture {
var $name = 'Attachment';
var $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary', 'extra'=> 'auto_increment'),
'id' => array('type' => 'integer', 'key' => 'primary'),
'comment_id' => array('type' => 'integer', 'null' => false),
'attachment' => array('type' => 'string', 'null' => false),
'created' => 'datetime',

View file

@ -35,7 +35,7 @@
class AuthUserFixture extends CakeTestFixture {
var $name = 'AuthUser';
var $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary', 'extra'=> 'auto_increment'),
'id' => array('type' => 'integer', 'key' => 'primary'),
'username' => array('type' => 'string', 'null' => false),
'password' => array('type' => 'string', 'null' => false),
'created' => 'datetime',

View file

@ -35,7 +35,7 @@
class AuthorFixture extends CakeTestFixture {
var $name = 'Author';
var $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary', 'extra' => 'auto_increment'),
'id' => array('type' => 'integer', 'key' => 'primary'),
'user' => array('type' => 'string', 'null' => false),
'password' => array('type' => 'string', 'null' => false),
'created' => 'datetime',

View file

@ -35,7 +35,7 @@
class BidFixture extends CakeTestFixture {
var $name = 'Bid';
var $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary', 'extra'=> 'auto_increment'),
'id' => array('type' => 'integer', 'key' => 'primary'),
'message_id' => array('type' => 'integer', 'null' => false),
'name' => array('type' => 'string', 'null' => false)
);

View file

@ -35,7 +35,7 @@
class CategoryFixture extends CakeTestFixture {
var $name = 'Category';
var $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary', 'extra'=> 'auto_increment'),
'id' => array('type' => 'integer', 'key' => 'primary'),
'parent_id' => array('type' => 'integer', 'null' => false),
'name' => array('type' => 'string', 'null' => false),
'created' => 'datetime',

View file

@ -35,7 +35,7 @@
class CategoryThreadFixture extends CakeTestFixture {
var $name = 'CategoryThread';
var $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary', 'extra'=> 'auto_increment'),
'id' => array('type' => 'integer', 'key' => 'primary'),
'parent_id' => array('type' => 'integer', 'null' => false),
'name' => array('type' => 'string', 'null' => false),
'created' => 'datetime',

View file

@ -35,7 +35,7 @@
class CommentFixture extends CakeTestFixture {
var $name = 'Comment';
var $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary', 'extra'=> 'auto_increment'),
'id' => array('type' => 'integer', 'key' => 'primary'),
'article_id' => array('type' => 'integer', 'null'=>false),
'user_id' => array('type' => 'integer', 'null'=>false),
'comment' => 'text',

View file

@ -35,7 +35,7 @@
class DeviceFixture extends CakeTestFixture {
var $name = 'Device';
var $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary', 'extra'=> 'auto_increment'),
'id' => array('type' => 'integer', 'key' => 'primary'),
'device_type_id' => array('type' => 'integer', 'null' => false),
'name' => array('type' => 'string', 'null' => false),
'typ' => array('type' => 'integer', 'null' => false),

View file

@ -35,7 +35,7 @@
class DeviceTypeCategoryFixture extends CakeTestFixture {
var $name = 'DeviceTypeCategory';
var $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary', 'extra'=> 'auto_increment'),
'id' => array('type' => 'integer', 'key' => 'primary'),
'name' => array('type' => 'string', 'null' => false)
);
var $records = array(

View file

@ -35,7 +35,7 @@
class DeviceTypeFixture extends CakeTestFixture {
var $name = 'DeviceType';
var $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary', 'extra'=> 'auto_increment'),
'id' => array('type' => 'integer', 'key' => 'primary'),
'device_type_category_id' => array('type' => 'integer', 'null' => false),
'feature_set_id' => array('type' => 'integer', 'null' => false),
'exterior_type_category_id' => array('type' => 'integer', 'null' => false),

View file

@ -35,7 +35,7 @@
class DocumentDirectoryFixture extends CakeTestFixture {
var $name = 'DocumentDirectory';
var $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary', 'extra'=> 'auto_increment'),
'id' => array('type' => 'integer', 'key' => 'primary'),
'name' => array('type' => 'string', 'null' => false)
);
var $records = array(

View file

@ -35,7 +35,7 @@
class DocumentFixture extends CakeTestFixture {
var $name = 'Document';
var $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary', 'extra'=> 'auto_increment'),
'id' => array('type' => 'integer', 'key' => 'primary'),
'document_directory_id' => array('type' => 'integer', 'null' => false),
'name' => array('type' => 'string', 'null' => false)
);

View file

@ -35,7 +35,7 @@
class ExteriorTypeCategoryFixture extends CakeTestFixture {
var $name = 'ExteriorTypeCategory';
var $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary', 'extra'=> 'auto_increment'),
'id' => array('type' => 'integer', 'key' => 'primary'),
'image_id' => array('type' => 'integer', 'null' => false),
'name' => array('type' => 'string', 'null' => false)
);

View file

@ -35,7 +35,7 @@
class FeatureSetFixture extends CakeTestFixture {
var $name = 'FeatureSet';
var $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary', 'extra'=> 'auto_increment'),
'id' => array('type' => 'integer', 'key' => 'primary'),
'name' => array('type' => 'string', 'null' => false)
);
var $records = array(

View file

@ -35,7 +35,7 @@
class FeaturedFixture extends CakeTestFixture {
var $name = 'Featured';
var $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary', 'extra'=> 'auto_increment'),
'id' => array('type' => 'integer', 'key' => 'primary'),
'article_featured_id' => array('type' => 'integer', 'null' => false),
'category_id' => array('type' => 'integer', 'null' => false),
'published_date' => 'datetime',

View file

@ -35,7 +35,7 @@
class HomeFixture extends CakeTestFixture {
var $name = 'Home';
var $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary', 'extra'=> 'auto_increment'),
'id' => array('type' => 'integer', 'key' => 'primary'),
'another_article_id' => array('type' => 'integer', 'null' => false),
'advertisement_id' => array('type' => 'integer', 'null' => false),
'title' => array('type' => 'string', 'null' => false),

View file

@ -35,7 +35,7 @@
class ImageFixture extends CakeTestFixture {
var $name = 'Image';
var $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary', 'extra'=> 'auto_increment'),
'id' => array('type' => 'integer', 'key' => 'primary'),
'name' => array('type' => 'string', 'null' => false)
);
var $records = array(

View file

@ -35,7 +35,7 @@
class ItemFixture extends CakeTestFixture {
var $name = 'Item';
var $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary', 'extra'=> 'auto_increment'),
'id' => array('type' => 'integer', 'key' => 'primary'),
'syfile_id' => array('type' => 'integer', 'null' => false),
'name' => array('type' => 'string', 'null' => false)
);

View file

@ -35,7 +35,7 @@
class ItemsPortfolioFixture extends CakeTestFixture {
var $name = 'ItemsPortfolio';
var $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary', 'extra'=> 'auto_increment'),
'id' => array('type' => 'integer', 'key' => 'primary'),
'item_id' => array('type' => 'integer', 'null' => false),
'portfolio_id' => array('type' => 'integer', 'null' => false)
);