dbo_mssql.php

Go to the documentation of this file.
00001 <?php
00002 /* SVN FILE: $Id: dbo_mssql.php 8265 2009-07-31 02:08:20Z renan.saddam $ */
00003 /**
00004  * MS SQL layer for DBO
00005  *
00006  * Long description for file
00007  *
00008  * PHP versions 4 and 5
00009  *
00010  * CakePHP(tm) :  Rapid Development Framework (http://www.cakephp.org)
00011  * Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
00012  *
00013  * Licensed under The MIT License
00014  * Redistributions of files must retain the above copyright notice.
00015  *
00016  * @filesource
00017  * @copyright     Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
00018  * @link          http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
00019  * @package       cake
00020  * @subpackage    cake.cake.libs.model.datasources.dbo
00021  * @since         CakePHP(tm) v 0.10.5.1790
00022  * @version       $Revision: 8265 $
00023  * @modifiedby    $LastChangedBy: renan.saddam $
00024  * @lastmodified  $Date: 2009-07-30 22:08:20 -0400 (Thu, 30 Jul 2009) $
00025  * @license       http://www.opensource.org/licenses/mit-license.php The MIT License
00026  */
00027 /**
00028  * Short description for class.
00029  *
00030  * Long description for class
00031  *
00032  * @package       cake
00033  * @subpackage    cake.cake.libs.model.datasources.dbo
00034  */
00035 class DboMssql extends DboSource {
00036 /**
00037  * Driver description
00038  *
00039  * @var string
00040  */
00041     var $description = "MS SQL DBO Driver";
00042 /**
00043  * Starting quote character for quoted identifiers
00044  *
00045  * @var string
00046  */
00047     var $startQuote = "[";
00048 /**
00049  * Ending quote character for quoted identifiers
00050  *
00051  * @var string
00052  */
00053     var $endQuote = "]";
00054 /**
00055  * Creates a map between field aliases and numeric indexes.  Workaround for the
00056  * SQL Server driver's 30-character column name limitation.
00057  *
00058  * @var array
00059  */
00060     var $__fieldMappings = array();
00061 /**
00062  * Base configuration settings for MS SQL driver
00063  *
00064  * @var array
00065  */
00066     var $_baseConfig = array(
00067         'persistent' => true,
00068         'host' => 'localhost',
00069         'login' => 'root',
00070         'password' => '',
00071         'database' => 'cake',
00072         'port' => '1433',
00073     );
00074 /**
00075  * MS SQL column definition
00076  *
00077  * @var array
00078  */
00079     var $columns = array(
00080         'primary_key' => array('name' => 'IDENTITY (1, 1) NOT NULL'),
00081         'string'    => array('name' => 'varchar', 'limit' => '255'),
00082         'text'      => array('name' => 'text'),
00083         'integer'   => array('name' => 'int', 'formatter' => 'intval'),
00084         'float'     => array('name' => 'numeric', 'formatter' => 'floatval'),
00085         'datetime'  => array('name' => 'datetime', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'),
00086         'timestamp' => array('name' => 'timestamp', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'),
00087         'time'      => array('name' => 'datetime', 'format' => 'H:i:s', 'formatter' => 'date'),
00088         'date'      => array('name' => 'datetime', 'format' => 'Y-m-d', 'formatter' => 'date'),
00089         'binary'    => array('name' => 'image'),
00090         'boolean'   => array('name' => 'bit')
00091     );
00092 /**
00093  * Index of basic SQL commands
00094  *
00095  * @var array
00096  * @access protected
00097  */
00098     var $_commands = array(
00099         'begin'    => 'BEGIN TRANSACTION',
00100         'commit'   => 'COMMIT',
00101         'rollback' => 'ROLLBACK'
00102     );
00103 /**
00104  * MS SQL DBO driver constructor; sets SQL Server error reporting defaults
00105  *
00106  * @param array $config Configuration data from app/config/databases.php
00107  * @return boolean True if connected successfully, false on error
00108  */
00109     function __construct($config, $autoConnect = true) {
00110         if ($autoConnect) {
00111             if (!function_exists('mssql_min_message_severity')) {
00112                 trigger_error("PHP SQL Server interface is not installed, cannot continue.  For troubleshooting information, see http://php.net/mssql/", E_USER_WARNING);
00113             }
00114             mssql_min_message_severity(15);
00115             mssql_min_error_severity(2);
00116         }
00117         return parent::__construct($config, $autoConnect);
00118     }
00119 /**
00120  * Connects to the database using options in the given configuration array.
00121  *
00122  * @return boolean True if the database could be connected, else false
00123  */
00124     function connect() {
00125         $config = $this->config;
00126 
00127         $os = env('OS');
00128         if (!empty($os) && strpos($os, 'Windows') !== false) {
00129             $sep = ',';
00130         } else {
00131             $sep = ':';
00132         }
00133         $this->connected = false;
00134 
00135         if (is_numeric($config['port'])) {
00136             $port = $sep . $config['port']; // Port number
00137         } elseif ($config['port'] === null) {
00138             $port = '';                     // No port - SQL Server 2005
00139         } else {
00140             $port = '\\' . $config['port']; // Named pipe
00141         }
00142 
00143         if (!$config['persistent']) {
00144             $this->connection = mssql_connect($config['host'] . $port, $config['login'], $config['password'], true);
00145         } else {
00146             $this->connection = mssql_pconnect($config['host'] . $port, $config['login'], $config['password']);
00147         }
00148 
00149         if (mssql_select_db($config['database'], $this->connection)) {
00150             $this->_execute("SET DATEFORMAT ymd");
00151             $this->connected = true;
00152         }
00153         return $this->connected;
00154     }
00155 /**
00156  * Disconnects from database.
00157  *
00158  * @return boolean True if the database could be disconnected, else false
00159  */
00160     function disconnect() {
00161         @mssql_free_result($this->results);
00162         $this->connected = !@mssql_close($this->connection);
00163         return !$this->connected;
00164     }
00165 /**
00166  * Executes given SQL statement.
00167  *
00168  * @param string $sql SQL statement
00169  * @return resource Result resource identifier
00170  * @access protected
00171  */
00172     function _execute($sql) {
00173         return mssql_query($sql, $this->connection);
00174     }
00175 /**
00176  * Returns an array of sources (tables) in the database.
00177  *
00178  * @return array Array of tablenames in the database
00179  */
00180     function listSources() {
00181         $cache = parent::listSources();
00182 
00183         if ($cache != null) {
00184             return $cache;
00185         }
00186         $result = $this->fetchAll('SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES', false);
00187 
00188         if (!$result || empty($result)) {
00189             return array();
00190         } else {
00191             $tables = array();
00192 
00193             foreach ($result as $table) {
00194                 $tables[] = $table[0]['TABLE_NAME'];
00195             }
00196 
00197             parent::listSources($tables);
00198             return $tables;
00199         }
00200     }
00201 /**
00202  * Returns an array of the fields in given table name.
00203  *
00204  * @param Model $model Model object to describe
00205  * @return array Fields in table. Keys are name and type
00206  */
00207     function describe(&$model) {
00208         $cache = parent::describe($model);
00209 
00210         if ($cache != null) {
00211             return $cache;
00212         }
00213 
00214         $table = $this->fullTableName($model, false);
00215         $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);
00216 
00217         $fields = false;
00218         foreach ($cols as $column) {
00219             $field = $column[0]['Field'];
00220             $fields[$field] = array(
00221                 'type' => $this->column($column[0]['Type']),
00222                 'null' => (strtoupper($column[0]['Null']) == 'YES'),
00223                 'default' => preg_replace("/^[(]{1,2}'?([^')]*)?'?[)]{1,2}$/", "$1", $column[0]['Default']),
00224                 'length' => intval($column[0]['Length']),
00225                 'key' => ($column[0]['Key'] == '1') ? 'primary' : false
00226             );
00227             if ($fields[$field]['default'] === 'null') {
00228                 $fields[$field]['default'] = null;
00229             } else {
00230                 $this->value($fields[$field]['default'], $fields[$field]['type']);
00231             }
00232 
00233             if ($fields[$field]['key'] && $fields[$field]['type'] == 'integer') {
00234                 $fields[$field]['length'] = 11;
00235             } elseif (!$fields[$field]['key']) {
00236                 unset($fields[$field]['key']);
00237             }
00238             if (in_array($fields[$field]['type'], array('date', 'time', 'datetime', 'timestamp'))) {
00239                 $fields[$field]['length'] = null;
00240             }
00241         }
00242         $this->__cacheDescription($this->fullTableName($model, false), $fields);
00243         return $fields;
00244     }
00245 /**
00246  * Returns a quoted and escaped string of $data for use in an SQL statement.
00247  *
00248  * @param string $data String to be prepared for use in an SQL statement
00249  * @param string $column The column into which this data will be inserted
00250  * @param boolean $safe Whether or not numeric data should be handled automagically if no column data is provided
00251  * @return string Quoted and escaped data
00252  */
00253     function value($data, $column = null, $safe = false) {
00254         $parent = parent::value($data, $column, $safe);
00255 
00256         if ($parent != null) {
00257             return $parent;
00258         }
00259         if ($data === null) {
00260             return 'NULL';
00261         }
00262         if ($data === '') {
00263             return "''";
00264         }
00265 
00266         switch ($column) {
00267             case 'boolean':
00268                 $data = $this->boolean((bool)$data);
00269             break;
00270             default:
00271                 if (get_magic_quotes_gpc()) {
00272                     $data = stripslashes(str_replace("'", "''", $data));
00273                 } else {
00274                     $data = str_replace("'", "''", $data);
00275                 }
00276             break;
00277         }
00278 
00279         if (in_array($column, array('integer', 'float', 'binary')) && is_numeric($data)) {
00280             return $data;
00281         }
00282         return "'" . $data . "'";
00283     }
00284 /**
00285  * Generates the fields list of an SQL query.
00286  *
00287  * @param Model $model
00288  * @param string $alias Alias tablename
00289  * @param mixed $fields
00290  * @return array
00291  */
00292     function fields(&$model, $alias = null, $fields = array(), $quote = true) {
00293         if (empty($alias)) {
00294             $alias = $model->alias;
00295         }
00296         $fields = parent::fields($model, $alias, $fields, false);
00297         $count = count($fields);
00298 
00299         if ($count >= 1 && strpos($fields[0], 'COUNT(*)') === false) {
00300             $result = array();
00301             for ($i = 0; $i < $count; $i++) {
00302                 $prepend = '';
00303 
00304                 if (strpos($fields[$i], 'DISTINCT') !== false) {
00305                     $prepend = 'DISTINCT ';
00306                     $fields[$i] = trim(str_replace('DISTINCT', '', $fields[$i]));
00307                 }
00308                 $fieldAlias = count($this->__fieldMappings);
00309 
00310                 if (!preg_match('/\s+AS\s+/i', $fields[$i])) {
00311                     if (substr($fields[$i], -1) == '*') {
00312                         if (strpos($fields[$i], '.') !== false && $fields[$i] != $alias . '.*') {
00313                             $build = explode('.', $fields[$i]);
00314                             $AssociatedModel = $model->{$build[0]};
00315                         } else {
00316                             $AssociatedModel = $model;
00317                         }
00318 
00319                         $_fields = $this->fields($AssociatedModel, $AssociatedModel->alias, array_keys($AssociatedModel->schema()));
00320                         $result = array_merge($result, $_fields);
00321                         continue;
00322                     }
00323 
00324                     if (strpos($fields[$i], '.') === false) {
00325                         $this->__fieldMappings[$alias . '__' . $fieldAlias] = $alias . '.' . $fields[$i];
00326                         $fieldName  = $this->name($alias . '.' . $fields[$i]);
00327                         $fieldAlias = $this->name($alias . '__' . $fieldAlias);
00328                     } else {
00329                         $build = explode('.', $fields[$i]);
00330                         $this->__fieldMappings[$build[0] . '__' . $fieldAlias] = $fields[$i];
00331                         $fieldName  = $this->name($build[0] . '.' . $build[1]);
00332                         $fieldAlias = $this->name(preg_replace("/^\[(.+)\]$/", "$1", $build[0]) . '__' . $fieldAlias);
00333                     }
00334                     if ($model->getColumnType($fields[$i]) == 'datetime') {
00335                         $fieldName = "CONVERT(VARCHAR(20), {$fieldName}, 20)";
00336                     }
00337                     $fields[$i] =  "{$fieldName} AS {$fieldAlias}";
00338                 }
00339                 $result[] = $prepend . $fields[$i];
00340             }
00341             return $result;
00342         } else {
00343             return $fields;
00344         }
00345     }
00346 /**
00347  * Generates and executes an SQL INSERT statement for given model, fields, and values.
00348  * Removes Identity (primary key) column from update data before returning to parent, if
00349  * value is empty.
00350  *
00351  * @param Model $model
00352  * @param array $fields
00353  * @param array $values
00354  * @param mixed $conditions
00355  * @return array
00356  */
00357     function create(&$model, $fields = null, $values = null) {
00358         if (!empty($values)) {
00359             $fields = array_combine($fields, $values);
00360         }
00361         $primaryKey = $this->_getPrimaryKey($model);
00362 
00363         if (array_key_exists($primaryKey, $fields)) {
00364             if (empty($fields[$primaryKey])) {
00365                 unset($fields[$primaryKey]);
00366             } else {
00367                 $this->_execute('SET IDENTITY_INSERT ' . $this->fullTableName($model) . ' ON');
00368             }
00369         }
00370         $result = parent::create($model, array_keys($fields), array_values($fields));
00371         if (array_key_exists($primaryKey, $fields) && !empty($fields[$primaryKey])) {
00372             $this->_execute('SET IDENTITY_INSERT ' . $this->fullTableName($model) . ' OFF');
00373         }
00374         return $result;
00375     }
00376 /**
00377  * Generates and executes an SQL UPDATE statement for given model, fields, and values.
00378  * Removes Identity (primary key) column from update data before returning to parent.
00379  *
00380  * @param Model $model
00381  * @param array $fields
00382  * @param array $values
00383  * @param mixed $conditions
00384  * @return array
00385  */
00386     function update(&$model, $fields = array(), $values = null, $conditions = null) {
00387         if (!empty($values)) {
00388             $fields = array_combine($fields, $values);
00389         }
00390         if (isset($fields[$model->primaryKey])) {
00391             unset($fields[$model->primaryKey]);
00392         }
00393         if (empty($fields)) {
00394             return true;
00395         }
00396         return parent::update($model, array_keys($fields), array_values($fields), $conditions);
00397     }
00398 /**
00399  * Returns a formatted error message from previous database operation.
00400  *
00401  * @return string Error message with error number
00402  */
00403     function lastError() {
00404         $error = mssql_get_last_message($this->connection);
00405 
00406         if ($error) {
00407             if (!preg_match('/contexto de la base de datos a|contesto di database|changed database|datenbankkontext/i', $error)) {
00408                 return $error;
00409             }
00410         }
00411         return null;
00412     }
00413 /**
00414  * Returns number of affected rows in previous database operation. If no previous operation exists,
00415  * this returns false.
00416  *
00417  * @return integer Number of affected rows
00418  */
00419     function lastAffected() {
00420         if ($this->_result) {
00421             return mssql_rows_affected($this->connection);
00422         }
00423         return null;
00424     }
00425 /**
00426  * Returns number of rows in previous resultset. If no previous resultset exists,
00427  * this returns false.
00428  *
00429  * @return integer Number of rows in resultset
00430  */
00431     function lastNumRows() {
00432         if ($this->_result) {
00433             return @mssql_num_rows($this->_result);
00434         }
00435         return null;
00436     }
00437 /**
00438  * Returns the ID generated from the previous INSERT operation.
00439  *
00440  * @param unknown_type $source
00441  * @return in
00442  */
00443     function lastInsertId($source = null) {
00444         $id = $this->fetchRow('SELECT SCOPE_IDENTITY() AS insertID', false);
00445         return $id[0]['insertID'];
00446     }
00447 /**
00448  * Returns a limit statement in the correct format for the particular database.
00449  *
00450  * @param integer $limit Limit of results returned
00451  * @param integer $offset Offset from which to start results
00452  * @return string SQL limit/offset statement
00453  */
00454     function limit($limit, $offset = null) {
00455         if ($limit) {
00456             $rt = '';
00457             if (!strpos(strtolower($limit), 'top') || strpos(strtolower($limit), 'top') === 0) {
00458                 $rt = ' TOP';
00459             }
00460             $rt .= ' ' . $limit;
00461             if (is_int($offset) && $offset > 0) {
00462                 $rt .= ' OFFSET ' . $offset;
00463             }
00464             return $rt;
00465         }
00466         return null;
00467     }
00468 /**
00469  * Converts database-layer column types to basic types
00470  *
00471  * @param string $real Real database-layer column type (i.e. "varchar(255)")
00472  * @return string Abstract column type (i.e. "string")
00473  */
00474     function column($real) {
00475         if (is_array($real)) {
00476             $col = $real['name'];
00477 
00478             if (isset($real['limit'])) {
00479                 $col .= '(' . $real['limit'] . ')';
00480             }
00481             return $col;
00482         }
00483         $col = str_replace(')', '', $real);
00484         $limit = null;
00485         if (strpos($col, '(') !== false) {
00486             list($col, $limit) = explode('(', $col);
00487         }
00488 
00489         if (in_array($col, array('date', 'time', 'datetime', 'timestamp'))) {
00490             return $col;
00491         }
00492         if ($col == 'bit') {
00493             return 'boolean';
00494         }
00495         if (strpos($col, 'int') !== false) {
00496             return 'integer';
00497         }
00498         if (strpos($col, 'char') !== false) {
00499             return 'string';
00500         }
00501         if (strpos($col, 'text') !== false) {
00502             return 'text';
00503         }
00504         if (strpos($col, 'binary') !== false || $col == 'image') {
00505             return 'binary';
00506         }
00507         if (in_array($col, array('float', 'real', 'decimal', 'numeric'))) {
00508             return 'float';
00509         }
00510         return 'text';
00511     }
00512 /**
00513  * Enter description here...
00514  *
00515  * @param unknown_type $results
00516  */
00517     function resultSet(&$results) {
00518         $this->results =& $results;
00519         $this->map = array();
00520         $numFields = mssql_num_fields($results);
00521         $index = 0;
00522         $j = 0;
00523 
00524         while ($j < $numFields) {
00525             $column = mssql_field_name($results, $j);
00526 
00527             if (strpos($column, '__')) {
00528                 if (isset($this->__fieldMappings[$column]) && strpos($this->__fieldMappings[$column], '.')) {
00529                     $map = explode('.', $this->__fieldMappings[$column]);
00530                 } elseif (isset($this->__fieldMappings[$column])) {
00531                     $map = array(0, $this->__fieldMappings[$column]);
00532                 } else {
00533                     $map = array(0, $column);
00534                 }
00535                 $this->map[$index++] = $map;
00536             } else {
00537                 $this->map[$index++] = array(0, $column);
00538             }
00539             $j++;
00540         }
00541     }
00542 /**
00543  * Builds final SQL statement
00544  *
00545  * @param string $type Query type
00546  * @param array $data Query data
00547  * @return string
00548  */
00549     function renderStatement($type, $data) {
00550         switch (strtolower($type)) {
00551             case 'select':
00552                 extract($data);
00553                 $fields = trim($fields);
00554 
00555                 if (strpos($limit, 'TOP') !== false && strpos($fields, 'DISTINCT ') === 0) {
00556                     $limit = 'DISTINCT ' . trim($limit);
00557                     $fields = substr($fields, 9);
00558                 }
00559 
00560                 if (preg_match('/offset\s+([0-9]+)/i', $limit, $offset)) {
00561                     $limit = preg_replace('/\s*offset.*$/i', '', $limit);
00562                     preg_match('/top\s+([0-9]+)/i', $limit, $limitVal);
00563                     $offset = intval($offset[1]) + intval($limitVal[1]);
00564                     $rOrder = $this->__switchSort($order);
00565                     list($order2, $rOrder) = array($this->__mapFields($order), $this->__mapFields($rOrder));
00566                     return "SELECT * FROM (SELECT {$limit} * FROM (SELECT TOP {$offset} {$fields} FROM {$table} {$alias} {$joins} {$conditions} {$group} {$order}) AS Set1 {$rOrder}) AS Set2 {$order2}";
00567                 } else {
00568                     return "SELECT {$limit} {$fields} FROM {$table} {$alias} {$joins} {$conditions} {$group} {$order}";
00569                 }
00570             break;
00571             case "schema":
00572                 extract($data);
00573 
00574                 foreach ($indexes as $i => $index) {
00575                     if (preg_match('/PRIMARY KEY/', $index)) {
00576                         unset($indexes[$i]);
00577                         break;
00578                     }
00579                 }
00580 
00581                 foreach (array('columns', 'indexes') as $var) {
00582                     if (is_array(${$var})) {
00583                         ${$var} = "\t" . join(",\n\t", array_filter(${$var}));
00584                     }
00585                 }
00586                 return "CREATE TABLE {$table} (\n{$columns});\n{$indexes}";
00587             break;
00588             default:
00589                 return parent::renderStatement($type, $data);
00590             break;
00591         }
00592     }
00593 /**
00594  * Reverses the sort direction of ORDER statements to get paging offsets to work correctly
00595  *
00596  * @param string $order
00597  * @return string
00598  * @access private
00599  */
00600     function __switchSort($order) {
00601         $order = preg_replace('/\s+ASC/i', '__tmp_asc__', $order);
00602         $order = preg_replace('/\s+DESC/i', ' ASC', $order);
00603         return preg_replace('/__tmp_asc__/', ' DESC', $order);
00604     }
00605 /**
00606  * Translates field names used for filtering and sorting to shortened names using the field map
00607  *
00608  * @param string $sql A snippet of SQL representing an ORDER or WHERE statement
00609  * @return string The value of $sql with field names replaced
00610  * @access private
00611  */
00612     function __mapFields($sql) {
00613         if (empty($sql) || empty($this->__fieldMappings)) {
00614             return $sql;
00615         }
00616         foreach ($this->__fieldMappings as $key => $val) {
00617             $sql = preg_replace('/' . preg_quote($val) . '/', $this->name($key), $sql);
00618             $sql = preg_replace('/' . preg_quote($this->name($val)) . '/', $this->name($key), $sql);
00619         }
00620         return $sql;
00621     }
00622 /**
00623  * Returns an array of all result rows for a given SQL query.
00624  * Returns false if no rows matched.
00625  *
00626  * @param string $sql SQL statement
00627  * @param boolean $cache Enables returning/storing cached query results
00628  * @return array Array of resultset rows, or false if no rows matched
00629  */
00630     function read(&$model, $queryData = array(), $recursive = null) {
00631         $results = parent::read($model, $queryData, $recursive);
00632         $this->__fieldMappings = array();
00633         return $results;
00634     }
00635 /**
00636  * Fetches the next row from the current result set
00637  *
00638  * @return unknown
00639  */
00640     function fetchResult() {
00641         if ($row = mssql_fetch_row($this->results)) {
00642             $resultRow = array();
00643             $i = 0;
00644 
00645             foreach ($row as $index => $field) {
00646                 list($table, $column) = $this->map[$index];
00647                 $resultRow[$table][$column] = $row[$index];
00648                 $i++;
00649             }
00650             return $resultRow;
00651         } else {
00652             return false;
00653         }
00654     }
00655 /**
00656  * Inserts multiple values into a table
00657  *
00658  * @param string $table
00659  * @param string $fields
00660  * @param array $values
00661  * @access protected
00662  */
00663     function insertMulti($table, $fields, $values) {
00664         $primaryKey = $this->_getPrimaryKey($table);
00665         $hasPrimaryKey = $primaryKey != null && (
00666             (is_array($fields) && in_array($primaryKey, $fields)
00667             || (is_string($fields) && strpos($fields, $this->startQuote . $primaryKey . $this->endQuote) !== false))
00668         );
00669 
00670         if ($hasPrimaryKey) {
00671             $this->_execute('SET IDENTITY_INSERT ' . $this->fullTableName($table) . ' ON');
00672         }
00673         parent::insertMulti($table, $fields, $values);
00674         if ($hasPrimaryKey) {
00675             $this->_execute('SET IDENTITY_INSERT ' . $this->fullTableName($table) . ' OFF');
00676         }
00677     }
00678 /**
00679  * Generate a database-native column schema string
00680  *
00681  * @param array $column An array structured like the following: array('name'=>'value', 'type'=>'value'[, options]),
00682  *   where options can be 'default', 'length', or 'key'.
00683  * @return string
00684  */
00685     function buildColumn($column) {
00686         $result = preg_replace('/(int|integer)\([0-9]+\)/i', '$1', parent::buildColumn($column));
00687         if (strpos($result, 'DEFAULT NULL') !== false) {
00688             $result = str_replace('DEFAULT NULL', 'NULL', $result);
00689         } else if (array_keys($column) == array('type', 'name')) {
00690             $result .= ' NULL';
00691         }
00692         return $result;
00693     }
00694 /**
00695  * Format indexes for create table
00696  *
00697  * @param array $indexes
00698  * @param string $table
00699  * @return string
00700  */
00701     function buildIndex($indexes, $table = null) {
00702         $join = array();
00703 
00704         foreach ($indexes as $name => $value) {
00705             if ($name == 'PRIMARY') {
00706                 $out = 'PRIMARY KEY  (' . $this->name($value['column']) . ')';
00707             } else {
00708                 $out = "ALTER TABLE {$table} ADD CONSTRAINT {$name} UNIQUE";
00709 
00710                 if (is_array($value['column'])) {
00711                     $value['column'] = join(', ', array_map(array(&$this, 'name'), $value['column']));
00712                 } else {
00713                     $value['column'] = $this->name($value['column']);
00714                 }
00715                 $out .= "({$value['column']});";
00716             }
00717             $join[] = $out;
00718         }
00719         return $join;
00720     }
00721 /**
00722  * Makes sure it will return the primary key
00723  *
00724  * @param mixed $model
00725  * @access protected
00726  * @return string
00727  */
00728     function _getPrimaryKey($model) {
00729         if (is_object($model)) {
00730             $schema = $model->schema();
00731         } else {
00732             $schema = $this->describe($model);
00733         }
00734 
00735         foreach ($schema as $field => $props) {
00736             if (isset($props['key']) && $props['key'] == 'primary') {
00737                 return $field;
00738             }
00739         }
00740         return null;
00741     }
00742 }
00743 ?>

Generated on Sun Nov 22 00:30:53 2009 for CakePHP 1.2.x.x (v1.2.4.8284) by doxygen 1.4.7