Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch '2.0-mssql' into 2.0

  • Loading branch information...
commit 2ea5be5de23723789ad8969f6d6e6c6478e61e09 2 parents a056078 + dee3efa
@jrbasso jrbasso authored
View
4 app/Config/database.php.default
@@ -2,7 +2,7 @@
/**
* This is core configuration file.
*
- * Use it to configure core behaviour ofCake.
+ * Use it to configure core behaviour of Cake.
*
* PHP 5
*
@@ -31,7 +31,7 @@
* Database/Mysql - MySQL 4 & 5,
* Database/Sqlite - SQLite (PHP5 only),
* Database/Postgres - PostgreSQL 7 and higher,
- * Database/Mssql - Microsoft SQL Server 2000 and higher,
+ * Database/Sqlserver - Microsoft SQL Server 2005 and higher,
* Database/Oracle - Oracle 8 and higher
*
* You can add custom database drivers (or override existing drivers) by adding the
View
2  lib/Cake/Console/Command/Task/DbConfigTask.php
@@ -104,7 +104,7 @@ protected function _interactive() {
}
}
- $driver = $this->in(__d('cake_console', 'Driver:'), array('Mssql', 'Mysql', 'Oracle', 'Postgres', 'Sqlite'), 'Mysql');
+ $driver = $this->in(__d('cake_console', 'Driver:'), array('Mysql', 'Oracle', 'Postgres', 'Sqlite', 'Sqlserver'), 'Mysql');
$persistent = $this->in(__d('cake_console', 'Persistent Connection?'), array('y', 'n'), 'n');
if (strtolower($persistent) == 'n') {
View
4 lib/Cake/Console/templates/skel/Config/database.php.default
@@ -2,7 +2,7 @@
/**
* This is core configuration file.
*
- * Use it to configure core behaviour ofCake.
+ * Use it to configure core behaviour of Cake.
*
* PHP 5
*
@@ -31,7 +31,7 @@
* Database/Mysql - MySQL 4 & 5,
* Database/Sqlite - SQLite (PHP5 only),
* Database/Postgres - PostgreSQL 7 and higher,
- * Database/Mssql - Microsoft SQL Server 2000 and higher,
+ * Database/Sqlserver - Microsoft SQL Server 2005 and higher,
* Database/Oracle - Oracle 8 and higher
*
* You can add custom database drivers (or override existing drivers) by adding the
View
383 lib/Cake/Model/Datasource/Database/Mssql.php → ...e/Model/Datasource/Database/Sqlserver.php
@@ -1,6 +1,6 @@
<?php
/**
- * MS SQL layer for DBO
+ * MS SQL Server layer for DBO
*
* PHP 5
*
@@ -17,6 +17,8 @@
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
+App::uses('DboSource', 'Model/Datasource');
+
/**
* MS SQL layer for DBO
*
@@ -24,14 +26,14 @@
*
* @package cake.libs.model.datasources.dbo
*/
-class DboMssql extends DboSource {
+class Sqlserver extends DboSource {
/**
* Driver description
*
* @var string
*/
- public $description = "MS SQL DBO Driver";
+ public $description = "SQL Server DBO Driver";
/**
* Starting quote character for quoted identifiers
@@ -53,7 +55,14 @@ class DboMssql extends DboSource {
*
* @var array
*/
- private $__fieldMappings = array();
+ protected $_fieldMappings = array();
+
+/**
+ * Storing the last affected value
+ *
+ * @var mixed
+ */
+ protected $_lastAffected = false;
/**
* Base configuration settings for MS SQL driver
@@ -62,11 +71,10 @@ class DboMssql extends DboSource {
*/
protected $_baseConfig = array(
'persistent' => true,
- 'host' => 'localhost',
- 'login' => 'root',
+ 'host' => '(local)\sqlexpress',
+ 'login' => '',
'password' => '',
- 'database' => 'cake',
- 'port' => '1433',
+ 'database' => 'cake'
);
/**
@@ -92,7 +100,6 @@ class DboMssql extends DboSource {
* Index of basic SQL commands
*
* @var array
- * @access protected
*/
protected $_commands = array(
'begin' => 'BEGIN TRANSACTION',
@@ -104,92 +111,44 @@ class DboMssql extends DboSource {
* Define if the last query had error
*
* @var string
- * @access private
*/
private $__lastQueryHadError = false;
-/**
- * MS SQL DBO driver constructor; sets SQL Server error reporting defaults
- *
- * @param array $config Configuration data from app/config/databases.php
- * @return boolean True if connected successfully, false on error
- */
- function __construct($config, $autoConnect = true) {
- if ($autoConnect) {
- if (!function_exists('mssql_min_message_severity')) {
- trigger_error(__d('cake_dev', "PHP SQL Server interface is not installed, cannot continue. For troubleshooting information, see http://php.net/mssql/"), E_USER_WARNING);
- }
- mssql_min_message_severity(15);
- mssql_min_error_severity(2);
- }
- return parent::__construct($config, $autoConnect);
- }
/**
* Connects to the database using options in the given configuration array.
*
* @return boolean True if the database could be connected, else false
*/
- function connect() {
+ public function connect() {
$config = $this->config;
-
- $os = env('OS');
- if (!empty($os) && strpos($os, 'Windows') !== false) {
- $sep = ',';
- } else {
- $sep = ':';
- }
$this->connected = false;
-
- if (is_numeric($config['port'])) {
- $port = $sep . $config['port']; // Port number
- } elseif ($config['port'] === null) {
- $port = ''; // No port - SQL Server 2005
- } else {
- $port = '\\' . $config['port']; // Named pipe
- }
-
- if (!$config['persistent']) {
- $this->connection = mssql_connect($config['host'] . $port, $config['login'], $config['password'], true);
- } else {
- $this->connection = mssql_pconnect($config['host'] . $port, $config['login'], $config['password']);
- }
-
- if (mssql_select_db($config['database'], $this->connection)) {
- $this->_execute("SET DATEFORMAT ymd");
+ try {
+ $flags = array(PDO::ATTR_PERSISTENT => $config['persistent']);
+ if (!empty($config['encoding'])) {
+ $flags[PDO::SQLSRV_ATTR_ENCODING] = $config['encoding'];
+ }
+ $this->_connection = new PDO(
+ "sqlsrv:server={$config['host']};Database={$config['database']}",
+ $config['login'],
+ $config['password'],
+ $flags
+ );
$this->connected = true;
+ } catch (PDOException $e) {
+ throw new MissingConnectionException(array('class' => $e->getMessage()));
}
+
+// $this->_execute("SET DATEFORMAT ymd");
return $this->connected;
}
/**
- * Check that MsSQL is installed/loaded
+ * Check that PDO SQL Server is installed/loaded
*
* @return boolean
*/
- function enabled() {
- return extension_loaded('mssql');
- }
-/**
- * Disconnects from database.
- *
- * @return boolean True if the database could be disconnected, else false
- */
- function disconnect() {
- @mssql_free_result($this->results);
- $this->connected = !@mssql_close($this->connection);
- return !$this->connected;
- }
-
-/**
- * Executes given SQL statement.
- *
- * @param string $sql SQL statement
- * @return resource Result resource identifier
- */
- protected function _execute($sql) {
- $result = @mssql_query($sql, $this->connection);
- $this->__lastQueryHadError = ($result === false);
- return $result;
+ public function enabled() {
+ return in_array('sqlsrv', PDO::getAvailableDrivers());
}
/**
@@ -197,23 +156,24 @@ protected function _execute($sql) {
*
* @return array Array of tablenames in the database
*/
- function listSources() {
+ public function listSources() {
$cache = parent::listSources();
-
- if ($cache != null) {
+ if ($cache !== null) {
return $cache;
}
- $result = $this->fetchAll('SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES', false);
+ $result = $this->_execute("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE'");
- if (!$result || empty($result)) {
+ if (!$result) {
+ $result->closeCursor();
return array();
} else {
$tables = array();
- foreach ($result as $table) {
- $tables[] = $table[0]['TABLE_NAME'];
+ while ($line = $result->fetch()) {
+ $tables[] = $line[0];
}
+ $result->closeCursor();
parent::listSources($tables);
return $tables;
}
@@ -225,42 +185,45 @@ function listSources() {
* @param Model $model Model object to describe
* @return array Fields in table. Keys are name and type
*/
- function describe($model) {
+ public function describe($model) {
$cache = parent::describe($model);
-
if ($cache != null) {
return $cache;
}
-
+ $fields = false;
$table = $this->fullTableName($model, false);
- $cols = $this->fetchAll("SELECT COLUMN_NAME as Field, DATA_TYPE as Type, COL_LENGTH('" . $table . "', COLUMN_NAME) as Length, IS_NULLABLE As [Null], COLUMN_DEFAULT as [Default], COLUMNPROPERTY(OBJECT_ID('" . $table . "'), COLUMN_NAME, 'IsIdentity') as [Key], NUMERIC_SCALE as Size FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '" . $table . "'", false);
+ $cols = $this->_execute("SELECT COLUMN_NAME as Field, DATA_TYPE as Type, COL_LENGTH('" . $table . "', COLUMN_NAME) as Length, IS_NULLABLE As [Null], COLUMN_DEFAULT as [Default], COLUMNPROPERTY(OBJECT_ID('" . $table . "'), COLUMN_NAME, 'IsIdentity') as [Key], NUMERIC_SCALE as Size FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '" . $table . "'");
+ if (!$cols) {
+ throw new CakeException(__d('cake_dev', 'Could not describe table for %s', $model->name));
+ }
- $fields = false;
foreach ($cols as $column) {
- $field = $column[0]['Field'];
+ $field = $column->Field;
$fields[$field] = array(
- 'type' => $this->column($column[0]['Type']),
- 'null' => (strtoupper($column[0]['Null']) == 'YES'),
- 'default' => preg_replace("/^[(]{1,2}'?([^')]*)?'?[)]{1,2}$/", "$1", $column[0]['Default']),
- 'length' => intval($column[0]['Length']),
- 'key' => ($column[0]['Key'] == '1') ? 'primary' : false
+ 'type' => $this->column($column->Type),
+ 'null' => ($column->Null === 'YES' ? true : false),
+ 'default' => preg_replace("/^[(]{1,2}'?([^')]*)?'?[)]{1,2}$/", "$1", $column->Default),
+ 'length' => intval($column->Length),
+ 'key' => ($column->Key == '1') ? 'primary' : false
);
+
if ($fields[$field]['default'] === 'null') {
$fields[$field]['default'] = null;
} else {
$this->value($fields[$field]['default'], $fields[$field]['type']);
}
- if ($fields[$field]['key'] && $fields[$field]['type'] == 'integer') {
+ if ($fields[$field]['key'] !== false && $fields[$field]['type'] == 'integer') {
$fields[$field]['length'] = 11;
- } elseif (!$fields[$field]['key']) {
+ } elseif ($fields[$field]['key'] === false) {
unset($fields[$field]['key']);
}
if (in_array($fields[$field]['type'], array('date', 'time', 'datetime', 'timestamp'))) {
$fields[$field]['length'] = null;
}
}
- $this->__cacheDescription($this->fullTableName($model, false), $fields);
+ $this->__cacheDescription($table, $fields);
+ $cols->closeCursor();
return $fields;
}
@@ -272,9 +235,15 @@ function describe($model) {
* @param boolean $safe Whether or not numeric data should be handled automagically if no column data is provided
* @return string Quoted and escaped data
*/
- function value($data, $column = null, $safe = false) {
+ public function value($data, $column = null, $safe = false) {
$parent = parent::value($data, $column, $safe);
+ if ($column === 'float' && strpos($data, '.') !== false) {
+ return rtrim($data, '0');
+ }
+ if ($parent === "''" && ($column === null || $column !== 'string')) {
+ return 'NULL';
+ }
if ($parent != null) {
return $parent;
}
@@ -315,7 +284,7 @@ function value($data, $column = null, $safe = false) {
* @param mixed $fields
* @return array
*/
- function fields($model, $alias = null, $fields = array(), $quote = true) {
+ public function fields($model, $alias = null, $fields = array(), $quote = true) {
if (empty($alias)) {
$alias = $model->alias;
}
@@ -331,7 +300,7 @@ function fields($model, $alias = null, $fields = array(), $quote = true) {
$prepend = 'DISTINCT ';
$fields[$i] = trim(str_replace('DISTINCT', '', $fields[$i]));
}
- $fieldAlias = count($this->__fieldMappings);
+ $fieldAlias = count($this->_fieldMappings);
if (!preg_match('/\s+AS\s+/i', $fields[$i])) {
if (substr($fields[$i], -1) == '*') {
@@ -348,12 +317,12 @@ function fields($model, $alias = null, $fields = array(), $quote = true) {
}
if (strpos($fields[$i], '.') === false) {
- $this->__fieldMappings[$alias . '__' . $fieldAlias] = $alias . '.' . $fields[$i];
+ $this->_fieldMappings[$alias . '__' . $fieldAlias] = $alias . '.' . $fields[$i];
$fieldName = $this->name($alias . '.' . $fields[$i]);
$fieldAlias = $this->name($alias . '__' . $fieldAlias);
} else {
$build = explode('.', $fields[$i]);
- $this->__fieldMappings[$build[0] . '__' . $fieldAlias] = $fields[$i];
+ $this->_fieldMappings[$build[0] . '__' . $fieldAlias] = $fields[$i];
$fieldName = $this->name($build[0] . '.' . $build[1]);
$fieldAlias = $this->name(preg_replace("/^\[(.+)\]$/", "$1", $build[0]) . '__' . $fieldAlias);
}
@@ -381,7 +350,7 @@ function fields($model, $alias = null, $fields = array(), $quote = true) {
* @param mixed $conditions
* @return array
*/
- function create($model, $fields = null, $values = null) {
+ public function create($model, $fields = null, $values = null) {
if (!empty($values)) {
$fields = array_combine($fields, $values);
}
@@ -411,7 +380,7 @@ function create($model, $fields = null, $values = null) {
* @param mixed $conditions
* @return array
*/
- function update($model, $fields = array(), $values = null, $conditions = null) {
+ public function update($model, $fields = array(), $values = null, $conditions = null) {
if (!empty($values)) {
$fields = array_combine($fields, $values);
}
@@ -425,65 +394,13 @@ function update($model, $fields = array(), $values = null, $conditions = null) {
}
/**
- * Returns a formatted error message from previous database operation.
- *
- * @return string Error message with error number
- */
- function lastError() {
- if ($this->__lastQueryHadError) {
- $error = mssql_get_last_message();
- if ($error && !preg_match('/contexto de la base de datos a|contesto di database|changed database|contexte de la base de don|datenbankkontext/i', $error)) {
- return $error;
- }
- }
- return null;
- }
-
-/**
- * Returns number of affected rows in previous database operation. If no previous operation exists,
- * this returns false.
- *
- * @return integer Number of affected rows
- */
- function lastAffected() {
- if ($this->_result) {
- return mssql_rows_affected($this->connection);
- }
- return null;
- }
-
-/**
- * Returns number of rows in previous resultset. If no previous resultset exists,
- * this returns false.
- *
- * @return integer Number of rows in resultset
- */
- function lastNumRows() {
- if ($this->_result) {
- return @mssql_num_rows($this->_result);
- }
- return null;
- }
-
-/**
- * Returns the ID generated from the previous INSERT operation.
- *
- * @param unknown_type $source
- * @return in
- */
- function lastInsertId($source = null) {
- $id = $this->fetchRow('SELECT SCOPE_IDENTITY() AS insertID', false);
- return $id[0]['insertID'];
- }
-
-/**
* Returns a limit statement in the correct format for the particular database.
*
* @param integer $limit Limit of results returned
* @param integer $offset Offset from which to start results
* @return string SQL limit/offset statement
*/
- function limit($limit, $offset = null) {
+ public function limit($limit, $offset = null) {
if ($limit) {
$rt = '';
if (!strpos(strtolower($limit), 'top') || strpos(strtolower($limit), 'top') === 0) {
@@ -504,7 +421,7 @@ function limit($limit, $offset = null) {
* @param string $real Real database-layer column type (i.e. "varchar(255)")
* @return string Abstract column type (i.e. "string")
*/
- function column($real) {
+ public function column($real) {
if (is_array($real)) {
$col = $real['name'];
@@ -544,33 +461,32 @@ function column($real) {
}
/**
- * Enter description here...
+ * Builds a map of the columns contained in a result
*
- * @param unknown_type $results
+ * @param PDOStatement $results
*/
- function resultSet(&$results) {
- $this->results =& $results;
+ public function resultSet($results) {
$this->map = array();
- $numFields = mssql_num_fields($results);
+ $numFields = $results->columnCount();
$index = 0;
- $j = 0;
- while ($j < $numFields) {
- $column = mssql_field_name($results, $j);
+ while ($numFields-- > 0) {
+ $column = $results->getColumnMeta($index);
+ $name = $column['name'];
- if (strpos($column, '__')) {
- if (isset($this->__fieldMappings[$column]) && strpos($this->__fieldMappings[$column], '.')) {
- $map = explode('.', $this->__fieldMappings[$column]);
- } elseif (isset($this->__fieldMappings[$column])) {
- $map = array(0, $this->__fieldMappings[$column]);
+ if (strpos($name, '__')) {
+ if (isset($this->_fieldMappings[$name]) && strpos($this->_fieldMappings[$name], '.')) {
+ $map = explode('.', $this->_fieldMappings[$name]);
+ } elseif (isset($this->_fieldMappings[$name])) {
+ $map = array(0, $this->_fieldMappings[$name]);
} else {
- $map = array(0, $column);
+ $map = array(0, $name);
}
- $this->map[$index++] = $map;
} else {
- $this->map[$index++] = array(0, $column);
+ $map = array(0, $name);
}
- $j++;
+ $map[] = ($column['sqlsrv:decl_type'] == 'bit') ? 'boolean' : $column['native_type'];
+ $this->map[$index++] = $map;
}
}
@@ -581,7 +497,7 @@ function resultSet(&$results) {
* @param array $data Query data
* @return string
*/
- function renderStatement($type, $data) {
+ public function renderStatement($type, $data) {
switch (strtolower($type)) {
case 'select':
extract($data);
@@ -631,9 +547,8 @@ function renderStatement($type, $data) {
*
* @param string $order
* @return string
- * @access private
*/
- function __switchSort($order) {
+ private function __switchSort($order) {
$order = preg_replace('/\s+ASC/i', '__tmp_asc__', $order);
$order = preg_replace('/\s+DESC/i', ' ASC', $order);
return preg_replace('/__tmp_asc__/', ' DESC', $order);
@@ -644,13 +559,12 @@ function __switchSort($order) {
*
* @param string $sql A snippet of SQL representing an ORDER or WHERE statement
* @return string The value of $sql with field names replaced
- * @access private
*/
- function __mapFields($sql) {
- if (empty($sql) || empty($this->__fieldMappings)) {
+ private function __mapFields($sql) {
+ if (empty($sql) || empty($this->_fieldMappings)) {
return $sql;
}
- foreach ($this->__fieldMappings as $key => $val) {
+ foreach ($this->_fieldMappings as $key => $val) {
$sql = preg_replace('/' . preg_quote($val) . '/', $this->name($key), $sql);
$sql = preg_replace('/' . preg_quote($this->name($val)) . '/', $this->name($key), $sql);
}
@@ -665,31 +579,31 @@ function __mapFields($sql) {
* @param boolean $cache Enables returning/storing cached query results
* @return array Array of resultset rows, or false if no rows matched
*/
- function read($model, $queryData = array(), $recursive = null) {
+ public function read($model, $queryData = array(), $recursive = null) {
$results = parent::read($model, $queryData, $recursive);
- $this->__fieldMappings = array();
+ $this->_fieldMappings = array();
return $results;
}
/**
* Fetches the next row from the current result set
*
- * @return unknown
+ * @return mixed
*/
- function fetchResult() {
- if ($row = mssql_fetch_row($this->results)) {
+ public function fetchResult() {
+ if ($row = $this->_result->fetch()) {
$resultRow = array();
- $i = 0;
-
- foreach ($row as $index => $field) {
- list($table, $column) = $this->map[$index];
- $resultRow[$table][$column] = $row[$index];
- $i++;
+ foreach ($this->map as $col => $meta) {
+ list($table, $column, $type) = $meta;
+ $resultRow[$table][$column] = $row[$col];
+ if ($type === 'boolean' && !is_null($row[$col])) {
+ $resultRow[$table][$column] = $this->boolean($resultRow[$table][$column]);
+ }
}
return $resultRow;
- } else {
- return false;
}
+ $this->_result->closeCursor();
+ return false;
}
/**
@@ -709,7 +623,16 @@ public function insertMulti($table, $fields, $values) {
if ($hasPrimaryKey) {
$this->_execute('SET IDENTITY_INSERT ' . $this->fullTableName($table) . ' ON');
}
- parent::insertMulti($table, $fields, $values);
+
+ $table = $this->fullTableName($table);
+ $fields = implode(', ', array_map(array(&$this, 'name'), $fields));
+ $this->begin();
+ foreach ($values as $value) {
+ $holder = implode(', ', array_map(array(&$this, 'value'), $value));
+ $this->_execute("INSERT INTO {$table} ({$fields}) VALUES ({$holder})");
+ }
+ $this->commit();
+
if ($hasPrimaryKey) {
$this->_execute('SET IDENTITY_INSERT ' . $this->fullTableName($table) . ' OFF');
}
@@ -722,10 +645,14 @@ public function insertMulti($table, $fields, $values) {
* where options can be 'default', 'length', or 'key'.
* @return string
*/
- function buildColumn($column) {
+ public function buildColumn($column) {
$result = preg_replace('/(int|integer)\([0-9]+\)/i', '$1', parent::buildColumn($column));
if (strpos($result, 'DEFAULT NULL') !== false) {
- $result = str_replace('DEFAULT NULL', 'NULL', $result);
+ if (isset($column['default']) && $column['default'] === '') {
+ $result = str_replace('DEFAULT NULL', "DEFAULT ''", $result);
+ } else {
+ $result = str_replace('DEFAULT NULL', 'NULL', $result);
+ }
} else if (array_keys($column) == array('type', 'name')) {
$result .= ' NULL';
}
@@ -739,7 +666,7 @@ function buildColumn($column) {
* @param string $table
* @return string
*/
- function buildIndex($indexes, $table = null) {
+ public function buildIndex($indexes, $table = null) {
$join = array();
foreach ($indexes as $name => $value) {
@@ -763,17 +690,14 @@ function buildIndex($indexes, $table = null) {
/**
* Makes sure it will return the primary key
*
- * @param mixed $model
- * @access protected
+ * @param mixed $model Model instance of table name
* @return string
*/
- function _getPrimaryKey($model) {
- if (is_object($model)) {
- $schema = $model->schema();
- } else {
- $schema = $this->describe($model);
+ protected function _getPrimaryKey($model) {
+ if (!is_object($model)) {
+ $model = new Model(false, $model);
}
-
+ $schema = $this->describe($model);
foreach ($schema as $field => $props) {
if (isset($props['key']) && $props['key'] == 'primary') {
return $field;
@@ -781,4 +705,49 @@ function _getPrimaryKey($model) {
}
return null;
}
+
+/**
+ * Returns number of affected rows in previous database operation. If no previous operation exists,
+ * this returns false.
+ *
+ * @return integer Number of affected rows
+ */
+ public function lastAffected() {
+ $affected = parent::lastAffected();
+ if ($affected === null && $this->_lastAffected !== false) {
+ return $this->_lastAffected;
+ }
+ return $affected;
+ }
+/**
+ * Executes given SQL statement.
+ *
+ * @param string $sql SQL statement
+ * @param array $params list of params to be bound to query (supported only in select)
+ * @param array $prepareOptions Options to be used in the prepare statement
+ * @return mixed PDOStatement if query executes with no problem, true as the result of a succesfull, false on error
+ * query returning no rows, suchs as a CREATE statement, false otherwise
+ */
+ protected function _execute($sql, $params = array(), $prepareOptions = array()) {
+ $this->_lastAffected = false;
+ if (strncasecmp($sql, 'SELECT', 6) == 0) {
+ $prepareOptions += array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL);
+ return parent::_execute($sql, $params, $prepareOptions);
+ }
+ try {
+ $this->_lastAffected = $this->_connection->exec($sql);
+ if ($this->_lastAffected === false) {
+ $this->_results = null;
+ $error = $this->_connection->errorInfo();
+ $this->error = $error[2];
+ return false;
+ }
+ return true;
+ } catch (PDOException $e) {
+ $this->_results = null;
+ $this->error = $e->getMessage();
+ return false;
+ }
+ }
+
}
View
7 lib/Cake/Model/Datasource/DboSource.php
@@ -450,10 +450,11 @@ public function execute($sql, $options = array(), $params = array()) {
*
* @param string $sql SQL statement
* @param array $params list of params to be bound to query
- * @return PDOStatement if query executes with no problem, true as the result of a succesfull
+ * @param array $prepareOptions Options to be used in the prepare statement
+ * @return mixed PDOStatement if query executes with no problem, true as the result of a succesfull, false on error
* query returning no rows, suchs as a CREATE statement, false otherwise
*/
- protected function _execute($sql, $params = array()) {
+ protected function _execute($sql, $params = array(), $prepareOptions = array()) {
$sql = trim($sql);
if (preg_match('/^(?:CREATE|ALTER|DROP)/i', $sql)) {
$statements = array_filter(explode(';', $sql));
@@ -464,7 +465,7 @@ protected function _execute($sql, $params = array()) {
}
try {
- $query = $this->_connection->prepare($sql);
+ $query = $this->_connection->prepare($sql, $prepareOptions);
$query->setFetchMode(PDO::FETCH_LAZY);
if (!$query->execute($params)) {
$this->_results = $query;
View
2  lib/Cake/Test/Case/Model/Behavior/ContainableBehaviorTest.php
@@ -3420,7 +3420,7 @@ public function testResetMultipleHabtmAssociations() {
'foreignKey' => 'article_id',
'associationForeignKey' => 'tag_id',
// LENGHT function mysql-only, using LIKE does almost the same
- 'conditions' => 'ShortTag.tag LIKE "???"'
+ 'conditions' => "ShortTag.tag LIKE '???'"
)
)
);
View
4 lib/Cake/Test/Case/Model/Behavior/TranslateBehaviorTest.php
@@ -431,8 +431,8 @@ function testTranslatedFindList() {
$expected = array(1 => 'Titel #1', 2 => 'Titel #2', 3 => 'Titel #3');
$this->assertEqual($expected, $result);
- // MSSQL trigger an error and stops the page even if the debug = 0
- if ($this->db instanceof Mssql) {
+ // SQL Server trigger an error and stops the page even if the debug = 0
+ if ($this->db instanceof Sqlserver) {
$debug = Configure::read('debug');
Configure::write('debug', 0);
View
4 lib/Cake/Test/Case/Model/BehaviorCollectionTest.php
@@ -606,6 +606,8 @@ function testBehaviorToggling() {
* @return void
*/
function testBehaviorFindCallbacks() {
+ $this->skipIf($this->db instanceof Sqlserver, 'This test is not compatible with SQL Server.');
+
$Apple = new Apple();
$expected = $Apple->find('all');
@@ -805,6 +807,8 @@ function testBehaviorHasOneFindCallbacks() {
* @return void
*/
function testBehaviorBelongsToFindCallbacks() {
+ $this->skipIf($this->db instanceof Sqlserver, 'This test is not compatible with SQL Server.');
+
$Apple = new Apple();
$Apple->unbindModel(array('hasMany' => array('Child'), 'hasOne' => array('Sample')), false);
$expected = $Apple->find('all');
View
357 ...e/Model/Datasource/Database/MssqlTest.php → ...del/Datasource/Database/SqlserverTest.php
@@ -1,6 +1,6 @@
<?php
/**
- * DboMssqlTest file
+ * SqlserverTest file
*
* PHP 5
*
@@ -17,90 +17,57 @@
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
-require_once CAKE.'Model'.DS.'Model.php';
-require_once CAKE.'Model'.DS.'Datasource'.DS.'DataSource.php';
-require_once CAKE.'Model'.DS.'Datasource'.DS.'DboSource.php';
-require_once CAKE.'Model'.DS.'Datasource'.DS.'Database'.DS.'Mssql.php';
+App::uses('Model', 'Model');
+App::uses('Sqlserver', 'Model/Datasource/Database');
/**
- * DboMssqlTestDb class
+ * SqlserverTestDb class
*
* @package cake.tests.cases.libs.model.datasources.dbo
*/
-class DboMssqlTestDb extends DboMssql {
+class SqlserverTestDb extends Sqlserver {
/**
* simulated property
*
* @var array
- * @access public
*/
public $simulated = array();
/**
- * simalate property
+ * execute results stack
*
* @var array
- * @access public
*/
- public $simulate = true;
-/**
- * fetchAllResultsStack
- *
- * @var array
- * @access public
- */
- public $fetchAllResultsStack = array();
+ public $executeResultsStack = array();
/**
* execute method
*
* @param mixed $sql
- * @access protected
- * @return void
+ * @return mixed
*/
- function _execute($sql) {
- if ($this->simulate) {
- $this->simulated[] = $sql;
- return null;
- } else {
- return parent::_execute($sql);
- }
+ protected function _execute($sql) {
+ $this->simulated[] = $sql;
+ return empty($this->executeResultsStack) ? null : array_pop($this->executeResultsStack);
}
/**
* fetchAll method
*
* @param mixed $sql
- * @access protected
* @return void
*/
- function _matchRecords($model, $conditions = null) {
+ protected function _matchRecords($model, $conditions = null) {
return $this->conditions(array('id' => array(1, 2)));
}
/**
- * fetchAll method
- *
- * @param mixed $sql
- * @access protected
- * @return void
- */
- function fetchAll($sql, $cache = true, $modelName = null) {
- $result = parent::fetchAll($sql, $cache, $modelName);
- if (!empty($this->fetchAllResultsStack)) {
- return array_pop($this->fetchAllResultsStack);
- }
- return $result;
- }
-
-/**
* getLastQuery method
*
- * @access public
- * @return void
+ * @return string
*/
- function getLastQuery() {
+ public function getLastQuery() {
return $this->simulated[count($this->simulated) - 1];
}
@@ -108,43 +75,50 @@ function getLastQuery() {
* getPrimaryKey method
*
* @param mixed $model
- * @access public
- * @return void
+ * @return string
*/
- function getPrimaryKey($model) {
+ public function getPrimaryKey($model) {
return parent::_getPrimaryKey($model);
}
+
/**
* clearFieldMappings method
*
- * @access public
* @return void
*/
- function clearFieldMappings() {
- $this->__fieldMappings = array();
+ public function clearFieldMappings() {
+ $this->_fieldMappings = array();
+ }
+
+/**
+ * describe method
+ *
+ * @param object $model
+ * @return void
+ */
+ public function describe($model) {
+ return empty($this->describe) ? parent::describe($model) : $this->describe;
}
}
/**
- * MssqlTestModel class
+ * SqlserverTestModel class
*
* @package cake.tests.cases.libs.model.datasources
*/
-class MssqlTestModel extends Model {
+class SqlserverTestModel extends Model {
/**
* name property
*
- * @var string 'MssqlTestModel'
- * @access public
+ * @var string 'SqlserverTestModel'
*/
- public $name = 'MssqlTestModel';
+ public $name = 'SqlserverTestModel';
/**
* useTable property
*
* @var bool false
- * @access public
*/
public $useTable = false;
@@ -152,7 +126,6 @@ class MssqlTestModel extends Model {
* _schema property
*
* @var array
- * @access protected
*/
protected $_schema = array(
'id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8', 'key' => 'primary'),
@@ -179,10 +152,9 @@ class MssqlTestModel extends Model {
* belongsTo property
*
* @var array
- * @access public
*/
public $belongsTo = array(
- 'MssqlClientTestModel' => array(
+ 'SqlserverClientTestModel' => array(
'foreignKey' => 'client_id'
)
);
@@ -193,10 +165,9 @@ class MssqlTestModel extends Model {
* @param mixed $fields
* @param mixed $order
* @param mixed $recursive
- * @access public
* @return void
*/
- function find($conditions = null, $fields = null, $order = null, $recursive = null) {
+ public function find($conditions = null, $fields = null, $order = null, $recursive = null) {
return $conditions;
}
@@ -207,50 +178,37 @@ function find($conditions = null, $fields = null, $order = null, $recursive = nu
* @param mixed $fields
* @param mixed $order
* @param mixed $recursive
- * @access public
- * @return void
+ * @return array
*/
- function findAll($conditions = null, $fields = null, $order = null, $recursive = null) {
+ public function findAll($conditions = null, $fields = null, $order = null, $recursive = null) {
return $conditions;
}
-
-/**
- * setSchema method
- *
- * @param array $schema
- * @access public
- * @return void
- */
- function setSchema($schema) {
- $this->_schema = $schema;
- }
}
/**
- * MssqlClientTestModel class
+ * SqlserverClientTestModel class
*
* @package cake.tests.cases.libs.model.datasources
*/
-class MssqlClientTestModel extends Model {
+class SqlserverClientTestModel extends Model {
/**
* name property
*
- * @var string 'MssqlAssociatedTestModel'
- * @access public
+ * @var string 'SqlserverAssociatedTestModel'
*/
- public $name = 'MssqlClientTestModel';
+ public $name = 'SqlserverClientTestModel';
+
/**
* useTable property
*
* @var bool false
- * @access public
*/
public $useTable = false;
+
/**
* _schema property
*
* @var array
- * @access protected
*/
protected $_schema = array(
'id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8', 'key' => 'primary'),
@@ -260,18 +218,32 @@ class MssqlClientTestModel extends Model {
'updated' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => null)
);
}
+
+/**
+ * SqlserverTestResultIterator class
+ *
+ * @package cake.tests.cases.libs.model.datasources
+ */
+class SqlserverTestResultIterator extends ArrayIterator {
+/**
+ * closeCursor method
+ *
+ * @return void
+ */
+ public function closeCursor() {}
+}
+
/**
- * DboMssqlTest class
+ * SqlserverTest class
*
* @package cake.tests.cases.libs.model.datasources.dbo
*/
-class DboMssqlTest extends CakeTestCase {
+class SqlserverTest extends CakeTestCase {
/**
* The Dbo instance to be tested
*
* @var DboSource
- * @access public
*/
public $db = null;
@@ -279,70 +251,46 @@ class DboMssqlTest extends CakeTestCase {
* autoFixtures property
*
* @var bool false
- * @access public
*/
public $autoFixtures = false;
+
/**
* fixtures property
*
* @var array
- * @access public
*/
public $fixtures = array('core.category');
-/**
- * Skip if cannot connect to mssql
- *
- */
- public function skip() {
- $this->_initDb();
- $this->skipUnless($this->db->config['driver'] == 'mssql', '%s SQL Server connection not available');
- }
/**
- * Make sure all fixtures tables are being created
- *
- */
- public function start() {
- $this->db->simulate = false;
- parent::start();
- $this->db->simulate = true;
- }
-/**
- * Make sure all fixtures tables are being dropped
- *
- */
- public function end() {
- $this->db->simulate = false;
- parent::end();
- $this->db->simulate = true;
- }
-/**
* Sets up a Dbo class instance for testing
*
*/
public function setUp() {
- $db = ConnectionManager::getDataSource('test');
- $this->db = new DboMssqlTestDb($db->config);
- $this->model = new MssqlTestModel();
+ $this->Dbo = ConnectionManager::getDataSource('test');
+ if (!($this->Dbo instanceof Sqlserver)) {
+ $this->markTestSkipped('Please configure the test datasource to use SQL Server.');
+ }
+ $this->db = new SqlserverTestDb($this->Dbo->config);
+ $this->model = new SqlserverTestModel();
}
/**
* tearDown method
*
- * @access public
* @return void
*/
- function tearDown() {
+ public function tearDown() {
+ unset($this->Dbo);
+ unset($this->db);
unset($this->model);
}
/**
* testQuoting method
*
- * @access public
* @return void
*/
- function testQuoting() {
+ public function testQuoting() {
$expected = "1.2";
$result = $this->db->value(1.2, 'float');
$this->assertIdentical($expected, $result);
@@ -366,29 +314,28 @@ function testQuoting() {
/**
* testFields method
*
- * @access public
* @return void
*/
- function testFields() {
+ public function testFields() {
$fields = array(
- '[MssqlTestModel].[id] AS [MssqlTestModel__0]',
- '[MssqlTestModel].[client_id] AS [MssqlTestModel__1]',
- '[MssqlTestModel].[name] AS [MssqlTestModel__2]',
- '[MssqlTestModel].[login] AS [MssqlTestModel__3]',
- '[MssqlTestModel].[passwd] AS [MssqlTestModel__4]',
- '[MssqlTestModel].[addr_1] AS [MssqlTestModel__5]',
- '[MssqlTestModel].[addr_2] AS [MssqlTestModel__6]',
- '[MssqlTestModel].[zip_code] AS [MssqlTestModel__7]',
- '[MssqlTestModel].[city] AS [MssqlTestModel__8]',
- '[MssqlTestModel].[country] AS [MssqlTestModel__9]',
- '[MssqlTestModel].[phone] AS [MssqlTestModel__10]',
- '[MssqlTestModel].[fax] AS [MssqlTestModel__11]',
- '[MssqlTestModel].[url] AS [MssqlTestModel__12]',
- '[MssqlTestModel].[email] AS [MssqlTestModel__13]',
- '[MssqlTestModel].[comments] AS [MssqlTestModel__14]',
- 'CONVERT(VARCHAR(20), [MssqlTestModel].[last_login], 20) AS [MssqlTestModel__15]',
- '[MssqlTestModel].[created] AS [MssqlTestModel__16]',
- 'CONVERT(VARCHAR(20), [MssqlTestModel].[updated], 20) AS [MssqlTestModel__17]'
+ '[SqlserverTestModel].[id] AS [SqlserverTestModel__0]',
+ '[SqlserverTestModel].[client_id] AS [SqlserverTestModel__1]',
+ '[SqlserverTestModel].[name] AS [SqlserverTestModel__2]',
+ '[SqlserverTestModel].[login] AS [SqlserverTestModel__3]',
+ '[SqlserverTestModel].[passwd] AS [SqlserverTestModel__4]',
+ '[SqlserverTestModel].[addr_1] AS [SqlserverTestModel__5]',
+ '[SqlserverTestModel].[addr_2] AS [SqlserverTestModel__6]',
+ '[SqlserverTestModel].[zip_code] AS [SqlserverTestModel__7]',
+ '[SqlserverTestModel].[city] AS [SqlserverTestModel__8]',
+ '[SqlserverTestModel].[country] AS [SqlserverTestModel__9]',
+ '[SqlserverTestModel].[phone] AS [SqlserverTestModel__10]',
+ '[SqlserverTestModel].[fax] AS [SqlserverTestModel__11]',
+ '[SqlserverTestModel].[url] AS [SqlserverTestModel__12]',
+ '[SqlserverTestModel].[email] AS [SqlserverTestModel__13]',
+ '[SqlserverTestModel].[comments] AS [SqlserverTestModel__14]',
+ 'CONVERT(VARCHAR(20), [SqlserverTestModel].[last_login], 20) AS [SqlserverTestModel__15]',
+ '[SqlserverTestModel].[created] AS [SqlserverTestModel__16]',
+ 'CONVERT(VARCHAR(20), [SqlserverTestModel].[updated], 20) AS [SqlserverTestModel__17]'
);
$result = $this->db->fields($this->model);
@@ -396,7 +343,7 @@ function testFields() {
$this->assertEqual($expected, $result);
$this->db->clearFieldMappings();
- $result = $this->db->fields($this->model, null, 'MssqlTestModel.*');
+ $result = $this->db->fields($this->model, null, 'SqlserverTestModel.*');
$expected = $fields;
$this->assertEqual($expected, $result);
@@ -408,23 +355,22 @@ function testFields() {
$this->assertEqual($expected, $result);
$this->db->clearFieldMappings();
- $result = $this->db->fields($this->model, null, array('*', 'MssqlClientTestModel.*'));
+ $result = $this->db->fields($this->model, null, array('*', 'SqlserverClientTestModel.*'));
$expected = array_merge($fields, array(
- '[MssqlClientTestModel].[id] AS [MssqlClientTestModel__18]',
- '[MssqlClientTestModel].[name] AS [MssqlClientTestModel__19]',
- '[MssqlClientTestModel].[email] AS [MssqlClientTestModel__20]',
- 'CONVERT(VARCHAR(20), [MssqlClientTestModel].[created], 20) AS [MssqlClientTestModel__21]',
- 'CONVERT(VARCHAR(20), [MssqlClientTestModel].[updated], 20) AS [MssqlClientTestModel__22]'));
+ '[SqlserverClientTestModel].[id] AS [SqlserverClientTestModel__18]',
+ '[SqlserverClientTestModel].[name] AS [SqlserverClientTestModel__19]',
+ '[SqlserverClientTestModel].[email] AS [SqlserverClientTestModel__20]',
+ 'CONVERT(VARCHAR(20), [SqlserverClientTestModel].[created], 20) AS [SqlserverClientTestModel__21]',
+ 'CONVERT(VARCHAR(20), [SqlserverClientTestModel].[updated], 20) AS [SqlserverClientTestModel__22]'));
$this->assertEqual($expected, $result);
}
/**
* testDistinctFields method
*
- * @access public
* @return void
*/
- function testDistinctFields() {
+ public function testDistinctFields() {
$result = $this->db->fields($this->model, null, array('DISTINCT Car.country_code'));
$expected = array('DISTINCT [Car].[country_code] AS [Car__0]');
$this->assertEqual($expected, $result);
@@ -437,12 +383,11 @@ function testDistinctFields() {
/**
* testDistinctWithLimit method
*
- * @access public
* @return void
*/
- function testDistinctWithLimit() {
+ public function testDistinctWithLimit() {
$this->db->read($this->model, array(
- 'fields' => array('DISTINCT MssqlTestModel.city', 'MssqlTestModel.country'),
+ 'fields' => array('DISTINCT SqlserverTestModel.city', 'SqlserverTestModel.country'),
'limit' => 5
));
$result = $this->db->getLastQuery();
@@ -452,23 +397,20 @@ function testDistinctWithLimit() {
/**
* testDescribe method
*
- * @access public
* @return void
*/
- function testDescribe() {
- $MssqlTableDescription = array(
- 0 => array(
- 0 => array(
- 'Default' => '((0))',
- 'Field' => 'count',
- 'Key' => 0,
- 'Length' => '4',
- 'Null' => 'NO',
- 'Type' => 'integer',
- )
+ public function testDescribe() {
+ $SqlserverTableDescription = new SqlserverTestResultIterator(array(
+ (object) array(
+ 'Default' => '((0))',
+ 'Field' => 'count',
+ 'Key' => 0,
+ 'Length' => '4',
+ 'Null' => 'NO',
+ 'Type' => 'integer'
)
- );
- $this->db->fetchAllResultsStack = array($MssqlTableDescription);
+ ));
+ $this->db->executeResultsStack = array($SqlserverTableDescription);
$dummyModel = $this->model;
$result = $this->db->describe($dummyModel);
$expected = array(
@@ -484,15 +426,15 @@ function testDescribe() {
/**
* testBuildColumn
*
- * @return unknown_type
+ * @return void
*/
public function testBuildColumn() {
- $column = array('name' => 'id', 'type' => 'integer', 'null' => '', 'default' => '', 'length' => '8', 'key' => 'primary');
+ $column = array('name' => 'id', 'type' => 'integer', 'null' => false, 'default' => '', 'length' => '8', 'key' => 'primary');
$result = $this->db->buildColumn($column);
$expected = '[id] int IDENTITY (1, 1) NOT NULL';
$this->assertEqual($expected, $result);
- $column = array('name' => 'client_id', 'type' => 'integer', 'null' => '', 'default' => '0', 'length' => '11');
+ $column = array('name' => 'client_id', 'type' => 'integer', 'null' => false, 'default' => '0', 'length' => '11');
$result = $this->db->buildColumn($column);
$expected = '[client_id] int DEFAULT 0 NOT NULL';
$this->assertEqual($expected, $result);
@@ -513,7 +455,7 @@ public function testBuildColumn() {
$expected = '[name] varchar(255) NULL';
$this->assertEqual($expected, $result);
- $column = array('name' => 'name', 'type' => 'string', 'null' => '', 'default' => '', 'length' => '255');
+ $column = array('name' => 'name', 'type' => 'string', 'null' => false, 'default' => '', 'length' => '255');
$result = $this->db->buildColumn($column);
$expected = '[name] varchar(255) DEFAULT \'\' NOT NULL';
$this->assertEqual($expected, $result);
@@ -570,13 +512,13 @@ public function testBuildIndex() {
* @return void
*/
public function testUpdateAllSyntax() {
- $fields = array('MssqlTestModel.client_id' => '[MssqlTestModel].[client_id] + 1');
- $conditions = array('MssqlTestModel.updated <' => date('2009-01-01 00:00:00'));
+ $fields = array('SqlserverTestModel.client_id' => '[SqlserverTestModel].[client_id] + 1');
+ $conditions = array('SqlserverTestModel.updated <' => date('2009-01-01 00:00:00'));
$this->db->update($this->model, $fields, null, $conditions);
$result = $this->db->getLastQuery();
- $this->assertNoPattern('/MssqlTestModel/', $result);
- $this->assertPattern('/^UPDATE \[mssql_test_models\]/', $result);
+ $this->assertNoPattern('/SqlserverTestModel/', $result);
+ $this->assertPattern('/^UPDATE \[sqlserver_test_models\]/', $result);
$this->assertPattern('/SET \[client_id\] = \[client_id\] \+ 1/', $result);
}
@@ -586,21 +528,16 @@ public function testUpdateAllSyntax() {
* @return void
*/
public function testGetPrimaryKey() {
- // When param is a model
+ $schema = $this->model->schema();
+
+ $this->db->describe = $schema;
$result = $this->db->getPrimaryKey($this->model);
$this->assertEqual($result, 'id');
-
- $schema = $this->model->schema();
+
unset($schema['id']['key']);
- $this->model->setSchema($schema);
+ $this->db->describe = $schema;
$result = $this->db->getPrimaryKey($this->model);
$this->assertNull($result);
-
- // When param is a table name
- $this->db->simulate = false;
- $this->loadFixtures('Category');
- $result = $this->db->getPrimaryKey('categories');
- $this->assertEqual($result, 'id');
}
/**
@@ -609,52 +546,34 @@ public function testGetPrimaryKey() {
* @return void
*/
public function testInsertMulti() {
+ $this->db->describe = $this->model->schema();
+
$fields = array('id', 'name', 'login');
- $values = array('(1, \'Larry\', \'PhpNut\')', '(2, \'Renan\', \'renan.saddam\')');
+ $values = array(
+ array(1, 'Larry', 'PhpNut'),
+ array(2, 'Renan', 'renan.saddam'));
$this->db->simulated = array();
$this->db->insertMulti($this->model, $fields, $values);
$result = $this->db->simulated;
$expected = array(
- 'SET IDENTITY_INSERT [mssql_test_models] ON',
- 'INSERT INTO [mssql_test_models] ([id], [name], [login]) VALUES (1, \'Larry\', \'PhpNut\')',
- 'INSERT INTO [mssql_test_models] ([id], [name], [login]) VALUES (2, \'Renan\', \'renan.saddam\')',
- 'SET IDENTITY_INSERT [mssql_test_models] OFF'
+ 'SET IDENTITY_INSERT [sqlserver_test_models] ON',
+ "INSERT INTO [sqlserver_test_models] ([id], [name], [login]) VALUES (1, 'Larry', 'PhpNut')",
+ "INSERT INTO [sqlserver_test_models] ([id], [name], [login]) VALUES (2, 'Renan', 'renan.saddam')",
+ 'SET IDENTITY_INSERT [sqlserver_test_models] OFF'
);
$this->assertEqual($expected, $result);
$fields = array('name', 'login');
- $values = array('(\'Larry\', \'PhpNut\')', '(\'Renan\', \'renan.saddam\')');
+ $values = array(
+ array('Larry', 'PhpNut'),
+ array('Renan', 'renan.saddam'));
$this->db->simulated = array();
$this->db->insertMulti($this->model, $fields, $values);
$result = $this->db->simulated;
$expected = array(
- 'INSERT INTO [mssql_test_models] ([name], [login]) VALUES (\'Larry\', \'PhpNut\')',
- 'INSERT INTO [mssql_test_models] ([name], [login]) VALUES (\'Renan\', \'renan.saddam\')'
+ "INSERT INTO [sqlserver_test_models] ([name], [login]) VALUES ('Larry', 'PhpNut')",
+ "INSERT INTO [sqlserver_test_models] ([name], [login]) VALUES ('Renan', 'renan.saddam')",
);
$this->assertEqual($expected, $result);
}
-/**
- * testLastError
- *
- * @return void
- */
- public function testLastError() {
- $debug = Configure::read('debug');
- Configure::write('debug', 0);
-
- $this->db->simulate = false;
- $query = 'SELECT [name] FROM [categories]';
- $this->assertTrue($this->db->execute($query) !== false);
- $this->assertNull($this->db->lastError());
-
- $query = 'SELECT [inexistent_field] FROM [categories]';
- $this->assertFalse($this->db->execute($query));
- $this->assertNotNull($this->db->lastError());
-
- $query = 'SELECT [name] FROM [categories]';
- $this->assertTrue($this->db->execute($query) !== false);
- $this->assertNull($this->db->lastError());
-
- Configure::write('debug', $debug);
- }
}
View
4 lib/Cake/Test/Case/Model/ModelIntegrationTest.php
@@ -634,6 +634,8 @@ function testSchema() {
* @return void
*/
function testDeconstructFieldsTime() {
+ $this->skipIf($this->db instanceof Sqlserver, 'This test is not compatible with SQL Server.');
+
$this->loadFixtures('Apple');
$TestModel = new Apple();
@@ -721,6 +723,8 @@ function testDeconstructFieldsTime() {
* @return void
*/
function testDeconstructFieldsDateTime() {
+ $this->skipIf($this->db instanceof Sqlserver, 'This test is not compatible with SQL Server.');
+
$this->loadFixtures('Apple');
$TestModel = new Apple();
View
48 lib/Cake/Test/Case/Model/ModelReadTest.php
@@ -79,8 +79,8 @@ function testFetchingNonUniqueFKJoinTableRecords() {
*/
function testGroupBy() {
$db = ConnectionManager::getDataSource('test');
- $isStrictGroupBy = $this->db instanceof Postgres || $this->db instanceof Sqlite || $this->db instanceof Oracle;
- $message = 'Postgres and Oracle have strict GROUP BY and are incompatible with this test.';
+ $isStrictGroupBy = $this->db instanceof Postgres || $this->db instanceof Sqlite || $this->db instanceof Oracle || $this->db instanceof Sqlserver;
+ $message = 'Postgres, Oracle, SQLite and SQL Server have strict GROUP BY and are incompatible with this test.';
if ($this->skipIf($isStrictGroupBy, $message )) {
return;
@@ -367,13 +367,6 @@ function testParameterMismatch() {
* @return void
*/
function testVeryStrangeUseCase() {
- $message = "skipping SELECT * FROM ? WHERE ? = ? AND ? = ?; prepared query.";
- $message .= " MSSQL is incompatible with this test.";
-
- if ($this->skipIf($this->db instanceof Mssql, $message)) {
- return;
- }
-
$this->loadFixtures('Article', 'User', 'Tag', 'ArticlesTag');
$Article = new Article();
@@ -397,6 +390,10 @@ function testVeryStrangeUseCase() {
* @return void
*/
function testRecursiveUnbind() {
+ if ($this->skipIf($this->db instanceof Sqlserver, 'The test of testRecursiveUnbind test is not compatible with SQL Server, because it check for time columns.')) {
+ return;
+ }
+
$this->loadFixtures('Apple', 'Sample');
$TestModel = new Apple();
$TestModel->recursive = 2;
@@ -2992,7 +2989,7 @@ function testRecursiveUnbind() {
* @return void
*/
function testSelfAssociationAfterFind() {
- $this->loadFixtures('Apple');
+ $this->loadFixtures('Apple', 'Sample');
$afterFindModel = new NodeAfterFind();
$afterFindModel->recursive = 3;
$afterFindData = $afterFindModel->find('all');
@@ -3651,6 +3648,10 @@ public function testFindNeighbors() {
* @return void
*/
function testFindCombinedRelations() {
+ if ($this->skipIf($this->db instanceof Sqlserver, 'The test of testRecursiveUnbind test is not compatible with SQL Server, because it check for time columns.')) {
+ return;
+ }
+
$this->loadFixtures('Apple', 'Sample');
$TestModel = new Apple();
@@ -3947,7 +3948,7 @@ function testFindAllWithConditionInChildQuery() {
$TestModel = new Basket();
$recursive = 3;
- $result = $TestModel->find('all', compact('conditions', 'recursive'));
+ $result = $TestModel->find('all', compact('recursive'));
$expected = array(
array(
@@ -6227,7 +6228,7 @@ function testFindAll() {
// These tests are expected to fail on SQL Server since the LIMIT/OFFSET
// hack can't handle small record counts.
- if ($this->db instanceof Mssql) {
+ if (!($this->db instanceof Sqlserver)) {
$result = $TestModel->find('all', array('limit' => 3, 'page' => 2));
$expected = array(
array(
@@ -6621,13 +6622,9 @@ function testFindFirstNoIdUsed() {
* @return void
*/
function testFindCountDistinct() {
- $skip = $this->skipIf(
- $this->db instanceof Sqlite,
- 'SELECT COUNT(DISTINCT field) is not compatible with SQLite'
- );
- if ($skip) {
- return;
- }
+ $this->skipIf($this->db instanceof Sqlite, 'SELECT COUNT(DISTINCT field) is not compatible with SQLite');
+ $this->skipIf($this->db instanceof Sqlserver, 'This test is not compatible with SQL Server.');
+
$this->loadFixtures('Project');
$TestModel = new Project();
$TestModel->create(array('name' => 'project')) && $TestModel->save();
@@ -7398,10 +7395,13 @@ function testVirtualFields() {
$result = $Post->find('first');
$this->assertEqual($result['Post']['two'], 2);
- $Post->Author->virtualFields = array('false' => '1 = 2');
- $result = $Post->find('first');
- $this->assertEqual($result['Post']['two'], 2);
- $this->assertFalse((bool)$result['Author']['false']);
+ // SQL Server does not support operators in expressions
+ if (!($this->db instanceof Sqlserver)) {
+ $Post->Author->virtualFields = array('false' => '1 = 2');
+ $result = $Post->find('first');
+ $this->assertEqual($result['Post']['two'], 2);
+ $this->assertFalse((bool)$result['Author']['false']);
+ }
$result = $Post->find('first',array('fields' => array('author_id')));
$this->assertFalse(isset($result['Post']['two']));
@@ -7470,7 +7470,7 @@ function testVirtualFields() {
*
*/
public function testVirtualFieldsMysql() {
- if ($this->skipIf(!($this->db instanceof Mysql), 'The rest of virtualFieds test is not compatible with Postgres')) {
+ if ($this->skipIf(!($this->db instanceof Mysql), 'The rest of virtualFieds test only compatible with Mysql')) {
return;
}
$this->loadFixtures('Post', 'Author');
View
13 lib/Cake/Test/Case/Model/ModelWriteTest.php
@@ -415,7 +415,12 @@ public function testCounterCacheWithSelfJoin() {
}
$this->loadFixtures('CategoryThread');
- $this->db->query('ALTER TABLE '. $this->db->fullTableName('category_threads') . " ADD COLUMN child_count INTEGER");
+ $column = 'COLUMN ';
+ if ($this->db instanceof Sqlserver) {
+ $column = '';
+ }
+ $column .= $this->db->buildColumn(array('name' => 'child_count', 'type' => 'integer'));
+ $this->db->query('ALTER TABLE '. $this->db->fullTableName('category_threads') . ' ADD ' . $column);
$Category = new CategoryThread();
$result = $Category->updateAll(array('CategoryThread.name' => "'updated'"), array('CategoryThread.parent_id' => 5));
$this->assertFalse(empty($result));
@@ -424,7 +429,7 @@ public function testCounterCacheWithSelfJoin() {
$Category->belongsTo['ParentCategory']['counterCache'] = 'child_count';
$Category->updateCounterCache(array('parent_id' => 5));
$result = Set::extract($Category->find('all', array('conditions' => array('CategoryThread.id' => 5))), '{n}.CategoryThread.child_count');
- $expected = array_fill(0, 1, 1);
+ $expected = array(1);
$this->assertEqual($expected, $result);
}
@@ -3829,6 +3834,8 @@ function testFindAllForeignKey() {
* @return void
*/
function testUpdateAllEmptyValues() {
+ $this->skipIf($this->db instanceof Sqlserver, 'This test is not compatible with SQL Server.');
+
$this->loadFixtures('Author', 'Post');
$model = new Author();
$result = $model->updateAll(array('user' => '""'));
@@ -3948,6 +3955,8 @@ function testUpdateAllWithoutForeignKey() {
* @return void
*/
function testSaveAllEmptyData() {
+ $this->skipIf($this->db instanceof Sqlserver, 'This test is not compatible with SQL Server.');
+
$this->loadFixtures('Article', 'ProductUpdateAll', 'Comment', 'Attachment');
$model = new Article();
$result = $model->saveAll(array(), array('validate' => 'first'));
View
4 lib/Cake/Test/Case/Network/CakeRequestTest.php
@@ -172,7 +172,7 @@ function testPostParsing() {
function testFILESParsing() {
$_FILES = array('data' => array('name' => array(
'File' => array(
- array('data' => 'cake_mssql_patch.patch'),
+ array('data' => 'cake_sqlserver_patch.patch'),
array('data' => 'controller.diff'),
array('data' => ''),
array('data' => ''),
@@ -221,7 +221,7 @@ function testFILESParsing() {
$expected = array(
'File' => array(
array('data' => array(
- 'name' => 'cake_mssql_patch.patch',
+ 'name' => 'cake_sqlserver_patch.patch',
'type' => '',
'tmp_name' => '/private/var/tmp/phpy05Ywj',
'error' => 0,
View
2  lib/Cake/Test/Fixture/ArticlesTagFixture.php
@@ -41,7 +41,7 @@ class ArticlesTagFixture extends CakeTestFixture {
public $fields = array(
'article_id' => array('type' => 'integer', 'null' => false),
'tag_id' => array('type' => 'integer', 'null' => false),
- 'indexes' => array('UNIQUE_TAG' => array('column'=> array('article_id', 'tag_id'), 'unique'=>1))
+ 'indexes' => array('UNIQUE_TAG2' => array('column'=> array('article_id', 'tag_id'), 'unique'=>1))
);
/**
Please sign in to comment.
Something went wrong with that request. Please try again.