mirror of
https://github.com/kamilwylegala/cakephp2-php8.git
synced 2025-01-18 18:46:17 +00:00
Fixing database drivers for UPDATE/DELETE changes, updating drivers to comply with model tests, most passing. Fixes #3794.
git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@6350 3807eeeb-6ff5-0310-8944-8be069107fe0
This commit is contained in:
parent
7268121495
commit
3eb04c36db
4 changed files with 241 additions and 47 deletions
|
@ -98,7 +98,6 @@ class DboPostgres extends DboSource {
|
|||
if (!empty($config['encoding'])) {
|
||||
$this->setEncoding($config['encoding']);
|
||||
}
|
||||
|
||||
return $this->connected;
|
||||
}
|
||||
|
||||
|
@ -193,7 +192,7 @@ class DboPostgres extends DboSource {
|
|||
$fields[$c['name']] = array(
|
||||
'type' => $this->column($c['type']),
|
||||
'null' => ($c['null'] == 'NO' ? false : true),
|
||||
'default' => $c['default'],
|
||||
'default' => preg_replace('/::.*/', '', $c['default']),
|
||||
'length' => $length
|
||||
);
|
||||
}
|
||||
|
@ -364,6 +363,86 @@ class DboPostgres extends DboSource {
|
|||
$data = $this->fetchRow($res);
|
||||
return $data[0]['max'];
|
||||
}
|
||||
/**
|
||||
* Generates and executes an SQL UPDATE statement for given model, fields, and values.
|
||||
*
|
||||
* @param Model $model
|
||||
* @param array $fields
|
||||
* @param array $values
|
||||
* @param mixed $conditions
|
||||
* @return array
|
||||
*/
|
||||
function update(&$model, $fields = array(), $values = null, $conditions = null) {
|
||||
if (empty($conditions)) {
|
||||
return parent::update($model, $fields, $values, null);
|
||||
} elseif ($conditions === true) {
|
||||
$conditions = $this->conditions(true);
|
||||
} else {
|
||||
$idList = $model->find('all', array('fields' => $model->escapeField(), 'conditions' => $conditions));
|
||||
|
||||
if (empty($idList)) {
|
||||
return false;
|
||||
}
|
||||
$conditions = $this->conditions(array(
|
||||
$model->primaryKey => Set::extract($idList, "{n}.{$model->alias}.{$model->primaryKey}")
|
||||
));
|
||||
}
|
||||
if ($values == null) {
|
||||
$combined = $fields;
|
||||
} else {
|
||||
$combined = array_combine($fields, $values);
|
||||
}
|
||||
$fields = join(', ', $this->_prepareUpdateFields($model, $combined, false, false));
|
||||
|
||||
$alias = $joins = null;
|
||||
$table = $this->fullTableName($model);
|
||||
|
||||
if (!$this->execute($this->renderStatement('update', compact('table', 'alias', 'joins', 'fields', 'conditions')))) {
|
||||
$model->onError();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Generates and executes an SQL DELETE statement
|
||||
*
|
||||
* @param Model $model
|
||||
* @param mixed $conditions
|
||||
* @return boolean Success
|
||||
*/
|
||||
function delete(&$model, $conditions = null) {
|
||||
if (empty($conditions)) {
|
||||
return parent::delete($model, null);
|
||||
} elseif ($conditions === true) {
|
||||
$conditions = $this->conditions(true);
|
||||
} else {
|
||||
$idList = $model->find('all', array('fields' => $model->escapeField(), 'conditions' => $conditions));
|
||||
|
||||
if (empty($idList)) {
|
||||
return false;
|
||||
}
|
||||
$conditions = $this->conditions(array(
|
||||
$model->primaryKey => Set::extract($idList, "{n}.{$model->alias}.{$model->primaryKey}")
|
||||
));
|
||||
}
|
||||
$alias = $joins = null;
|
||||
$table = $this->fullTableName($model);
|
||||
|
||||
if ($this->execute($this->renderStatement('delete', compact('alias', 'table', 'joins', 'conditions'))) === false) {
|
||||
$model->onError();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Prepares field names to be quoted by parent
|
||||
*
|
||||
* @param string $data
|
||||
* @return string SQL field
|
||||
*/
|
||||
function name($data) {
|
||||
return parent::name(str_replace('"__"', '__', $data));
|
||||
}
|
||||
/**
|
||||
* Generates the fields list of an SQL query.
|
||||
*
|
||||
|
@ -392,8 +471,7 @@ class DboPostgres extends DboSource {
|
|||
$fields[$i] = trim(str_replace('DISTINCT', '', $fields[$i]));
|
||||
}
|
||||
|
||||
$dot = strrpos($fields[$i], '.');
|
||||
if ($dot === false) {
|
||||
if (strrpos($fields[$i], '.') === false) {
|
||||
$fields[$i] = $prepend . $this->name($alias) . '.' . $this->name($fields[$i]) . ' AS ' . $this->name($alias . '__' . $fields[$i]);
|
||||
} else {
|
||||
$build = explode('.', $fields[$i]);
|
||||
|
@ -588,6 +666,88 @@ class DboPostgres extends DboSource {
|
|||
function insertMulti($table, $fields, $values) {
|
||||
parent::__insertMulti($table, $fields, $values);
|
||||
}
|
||||
/**
|
||||
* Generate a Postgres-native column schema string
|
||||
*
|
||||
* @param array $column An array structured like the following: array('name'=>'value', 'type'=>'value'[, options]),
|
||||
* where options can be 'default', 'length', or 'key'.
|
||||
* @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;
|
||||
}
|
||||
/**
|
||||
* Format indexes for create table
|
||||
*
|
||||
* @param array $indexes
|
||||
* @return string
|
||||
*/
|
||||
function buildIndex($indexes) {
|
||||
$join = array();
|
||||
foreach ($indexes as $name => $value) {
|
||||
$out = '';
|
||||
if ($name == 'PRIMARY') {
|
||||
$out .= 'PRIMARY ';
|
||||
$name = null;
|
||||
} else {
|
||||
if (!empty($value['unique'])) {
|
||||
$name .= ' UNIQUE ';
|
||||
}
|
||||
}
|
||||
if (is_array($value['column'])) {
|
||||
$out .= 'CONSTRAINT '. $name .' (' . join(', ', array_map(array(&$this, 'name'), $value['column'])) . ')';
|
||||
} else {
|
||||
$out .= 'KEY '. $name .' (' . $this->name($value['column']) . ')';
|
||||
}
|
||||
$join[] = $out;
|
||||
}
|
||||
return join(",\n\t", $join);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -74,12 +74,12 @@ class DboSqlite extends DboSource {
|
|||
'primary_key' => array('name' => 'integer primary key'),
|
||||
'string' => array('name' => 'varchar', 'limit' => '255'),
|
||||
'text' => array('name' => 'text'),
|
||||
'integer' => array('name' => 'integer', 'limit' => '11', 'formatter' => 'intval'),
|
||||
'integer' => array('name' => 'integer', 'limit' => null, 'formatter' => 'intval'),
|
||||
'float' => array('name' => 'float', 'formatter' => 'floatval'),
|
||||
'datetime' => array('name' => 'timestamp', 'format' => 'YmdHis', 'formatter' => 'date'),
|
||||
'timestamp' => array('name' => 'timestamp', 'format' => 'YmdHis', 'formatter' => 'date'),
|
||||
'time' => array('name' => 'timestamp', 'format' => 'His', 'formatter' => 'date'),
|
||||
'date' => array('name' => 'date', 'format' => 'Ymd', 'formatter' => 'date'),
|
||||
'datetime' => array('name' => 'timestamp', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'),
|
||||
'timestamp' => array('name' => 'timestamp', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'),
|
||||
'time' => array('name' => 'timestamp', 'format' => 'H:i:s', 'formatter' => 'date'),
|
||||
'date' => array('name' => 'date', 'format' => 'Y-m-d', 'formatter' => 'date'),
|
||||
'binary' => array('name' => 'blob'),
|
||||
'boolean' => array('name' => 'integer', 'limit' => '1')
|
||||
);
|
||||
|
@ -173,7 +173,7 @@ class DboSqlite extends DboSource {
|
|||
'default' => $column[0]['dflt_value'],
|
||||
'key' => $this->index['PRI'],
|
||||
'extra' => 'auto_increment',
|
||||
'length' => $this->columns['integer']['limit']
|
||||
'length' => 11
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -353,8 +353,7 @@ class DboSource extends DataSource {
|
|||
$data = str_replace($this->startQuote . $this->startQuote, $this->startQuote, $data);
|
||||
|
||||
if (!empty($this->endQuote) && $this->endQuote == $this->startQuote) {
|
||||
$oddMatches = substr_count($data, $this->endQuote);
|
||||
if ($oddMatches % 2 == 1) {
|
||||
if (substr_count($data, $this->endQuote) % 2 == 1) {
|
||||
$data = trim($data, $this->endQuote);
|
||||
}
|
||||
}
|
||||
|
@ -1237,16 +1236,23 @@ class DboSource extends DataSource {
|
|||
*/
|
||||
function renderStatement($type, $data) {
|
||||
extract($data);
|
||||
$aliases = null;
|
||||
|
||||
switch (strtolower($type)) {
|
||||
case 'select':
|
||||
return "SELECT {$fields} FROM {$table} {$alias} {$joins} {$conditions} {$order} {$limit}";
|
||||
break;
|
||||
case 'update':
|
||||
return "UPDATE {$table} {$this->alias}{$alias} {$joins} SET {$fields} {$conditions}";
|
||||
if (!empty($alias)) {
|
||||
$aliases = "{$this->alias}{$alias} {$joins}";
|
||||
}
|
||||
return "UPDATE {$table} {$aliases}SET {$fields} {$conditions}";
|
||||
break;
|
||||
case 'delete':
|
||||
return "DELETE {$alias} FROM {$table} {$this->alias}{$alias} {$joins} {$conditions}";
|
||||
if (!empty($alias)) {
|
||||
$aliases = "{$this->alias}{$alias} {$joins} ";
|
||||
}
|
||||
return "DELETE {$alias} FROM {$table} {$aliases}{$conditions}";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1285,20 +1291,55 @@ class DboSource extends DataSource {
|
|||
* @return array
|
||||
*/
|
||||
function update(&$model, $fields = array(), $values = null, $conditions = null) {
|
||||
$updates = array();
|
||||
|
||||
if ($values == null) {
|
||||
$combined = $fields;
|
||||
} else {
|
||||
$combined = array_combine($fields, $values);
|
||||
}
|
||||
|
||||
foreach ($combined as $field => $value) {
|
||||
if ($value === null) {
|
||||
$updates[] = $model->escapeField($field) . ' = NULL';
|
||||
$fields = join(', ', $this->_prepareUpdateFields($model, $combined, empty($conditions), !empty($conditions)));
|
||||
$table = $this->fullTableName($model);
|
||||
$alias = $this->name($model->alias);
|
||||
$joins = implode(' ', $this->_getJoins($model));
|
||||
|
||||
if (empty($conditions)) {
|
||||
$alias = $joins = false;
|
||||
}
|
||||
$conditions = $this->conditions($this->defaultConditions($model, $conditions, $alias));
|
||||
|
||||
if ($conditions === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$this->execute($this->renderStatement('update', compact('table', 'alias', 'joins', 'fields', 'conditions')))) {
|
||||
$model->onError();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Quotes and prepares fields and values for an SQL UPDATE statement
|
||||
*
|
||||
* @param Model $model
|
||||
* @param array $fields
|
||||
* @param boolean $quoteValues If values should be quoted, or treated as SQL snippets
|
||||
* @param boolean $alias Include the model alias in the field name
|
||||
* @return array Fields and values, quoted and preparted
|
||||
* @access protected
|
||||
*/
|
||||
function _prepareUpdateFields(&$model, $fields, $quoteValues, $alias) {
|
||||
foreach ($fields as $field => $value) {
|
||||
if ($alias) {
|
||||
$field = $model->escapeField($field);
|
||||
} else {
|
||||
$update = $model->escapeField($field) . ' = ';
|
||||
if ($conditions == null) {
|
||||
$field = $this->name($field);
|
||||
}
|
||||
|
||||
if ($value === null) {
|
||||
$updates[] = $field . ' = NULL';
|
||||
} else {
|
||||
$update = $field . ' = ';
|
||||
if ($quoteValues) {
|
||||
$update .= $this->value($value, $model->getColumnType($field));
|
||||
} else {
|
||||
$update .= $value;
|
||||
|
@ -1306,22 +1347,7 @@ class DboSource extends DataSource {
|
|||
$updates[] = $update;
|
||||
}
|
||||
}
|
||||
$conditions = $this->defaultConditions($model, $conditions);
|
||||
|
||||
if ($conditions === false) {
|
||||
return false;
|
||||
}
|
||||
$fields = join(', ', $updates);
|
||||
$table = $this->fullTableName($model);
|
||||
$conditions = $this->conditions($conditions);
|
||||
$alias = $this->name($model->alias);
|
||||
$joins = implode(' ', $this->_getJoins($model));
|
||||
|
||||
if (!$this->execute($this->renderStatement('update', compact('table', 'alias', 'joins', 'fields', 'conditions')))) {
|
||||
$model->onError();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return $updates;
|
||||
}
|
||||
/**
|
||||
* Generates and executes an SQL DELETE statement for given id on given model.
|
||||
|
@ -1331,17 +1357,19 @@ class DboSource extends DataSource {
|
|||
* @return boolean Success
|
||||
*/
|
||||
function delete(&$model, $conditions = null) {
|
||||
$query = $this->defaultConditions($model, $conditions);
|
||||
|
||||
if ($query === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$alias = $this->name($model->alias);
|
||||
$table = $this->fullTableName($model);
|
||||
$conditions = $this->conditions($query);
|
||||
$joins = implode(' ', $this->_getJoins($model));
|
||||
|
||||
if (empty($conditions)) {
|
||||
$alias = $joins = false;
|
||||
}
|
||||
$conditions = $this->conditions($this->defaultConditions($model, $conditions, $alias));
|
||||
|
||||
if ($conditions === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->execute($this->renderStatement('delete', compact('alias', 'table', 'joins', 'conditions'))) === false) {
|
||||
$model->onError();
|
||||
return false;
|
||||
|
@ -1387,16 +1415,22 @@ class DboSource extends DataSource {
|
|||
*
|
||||
* @param object $model
|
||||
* @param mixed $conditions
|
||||
* @param boolean $useAlias Use model aliases rather than table names when generating conditions
|
||||
* @return mixed
|
||||
*/
|
||||
function defaultConditions(&$model, $conditions) {
|
||||
function defaultConditions(&$model, $conditions, $useAlias = true) {
|
||||
if (!empty($conditions)) {
|
||||
return $conditions;
|
||||
}
|
||||
if (!$model->exists()) {
|
||||
return false;
|
||||
}
|
||||
return array("{$model->alias}.{$model->primaryKey}" => (array)$model->getID());
|
||||
$alias = $model->alias;
|
||||
|
||||
if (!$useAlias) {
|
||||
$alias = $this->fullTableName($model, false);
|
||||
}
|
||||
return array("{$alias}.{$model->primaryKey}" => $model->getID());
|
||||
}
|
||||
/**
|
||||
* Returns a key formatted like a string Model.fieldname(i.e. Post.title, or Country.name)
|
||||
|
|
2
cake/tests/fixtures/join_thing_fixture.php
vendored
2
cake/tests/fixtures/join_thing_fixture.php
vendored
|
@ -38,7 +38,7 @@ class JoinThingFixture extends CakeTestFixture {
|
|||
'id' => array('type' => 'integer', 'key' => 'primary', 'extra'=> 'auto_increment'),
|
||||
'something_id' => array('type' => 'integer', 'length' => 10, 'null' => true),
|
||||
'something_else_id' => array('type' => 'integer', 'default' => ''),
|
||||
'doomed' => array('type' => 'boolean'),
|
||||
'doomed' => array('type' => 'boolean', 'default' => '0'),
|
||||
'created' => array('type' => 'datetime', 'null' => true),
|
||||
'updated' => array('type' => 'datetime', 'null' => true)
|
||||
);
|
||||
|
|
Loading…
Add table
Reference in a new issue