00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 class DboMysqlBase extends DboSource {
00034
00035
00036
00037
00038
00039 var $description = "MySQL DBO Base Driver";
00040
00041
00042
00043
00044
00045 var $startQuote = "`";
00046
00047
00048
00049
00050
00051 var $endQuote = "`";
00052
00053
00054
00055
00056
00057
00058 var $_useAlias = true;
00059
00060
00061
00062
00063
00064
00065 var $_commands = array(
00066 'begin' => 'START TRANSACTION',
00067 'commit' => 'COMMIT',
00068 'rollback' => 'ROLLBACK'
00069 );
00070
00071
00072
00073
00074
00075 var $columns = array(
00076 'primary_key' => array('name' => 'NOT NULL AUTO_INCREMENT'),
00077 'string' => array('name' => 'varchar', 'limit' => '255'),
00078 'text' => array('name' => 'text'),
00079 'integer' => array('name' => 'int', 'limit' => '11', 'formatter' => 'intval'),
00080 'float' => array('name' => 'float', 'formatter' => 'floatval'),
00081 'datetime' => array('name' => 'datetime', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'),
00082 'timestamp' => array('name' => 'timestamp', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'),
00083 'time' => array('name' => 'time', 'format' => 'H:i:s', 'formatter' => 'date'),
00084 'date' => array('name' => 'date', 'format' => 'Y-m-d', 'formatter' => 'date'),
00085 'binary' => array('name' => 'blob'),
00086 'boolean' => array('name' => 'tinyint', 'limit' => '1')
00087 );
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 function update(&$model, $fields = array(), $values = null, $conditions = null) {
00098 if (!$this->_useAlias) {
00099 return parent::update($model, $fields, $values, $conditions);
00100 }
00101
00102 if ($values == null) {
00103 $combined = $fields;
00104 } else {
00105 $combined = array_combine($fields, $values);
00106 }
00107
00108 $alias = $joins = false;
00109 $fields = $this->_prepareUpdateFields($model, $combined, empty($conditions), !empty($conditions));
00110 $fields = join(', ', $fields);
00111 $table = $this->fullTableName($model);
00112
00113 if (!empty($conditions)) {
00114 $alias = $this->name($model->alias);
00115 if ($model->name == $model->alias) {
00116 $joins = implode(' ', $this->_getJoins($model));
00117 }
00118 }
00119 $conditions = $this->conditions($this->defaultConditions($model, $conditions, $alias), true, true, $model);
00120
00121 if ($conditions === false) {
00122 return false;
00123 }
00124
00125 if (!$this->execute($this->renderStatement('update', compact('table', 'alias', 'joins', 'fields', 'conditions')))) {
00126 $model->onError();
00127 return false;
00128 }
00129 return true;
00130 }
00131
00132
00133
00134
00135
00136
00137
00138 function delete(&$model, $conditions = null) {
00139 if (!$this->_useAlias) {
00140 return parent::delete($model, $conditions);
00141 }
00142 $alias = $this->name($model->alias);
00143 $table = $this->fullTableName($model);
00144 $joins = implode(' ', $this->_getJoins($model));
00145
00146 if (empty($conditions)) {
00147 $alias = $joins = false;
00148 }
00149 $conditions = $this->conditions($this->defaultConditions($model, $conditions, $alias), true, true, $model);
00150
00151 if ($conditions === false) {
00152 return false;
00153 }
00154
00155 if ($this->execute($this->renderStatement('delete', compact('alias', 'table', 'joins', 'conditions'))) === false) {
00156 $model->onError();
00157 return false;
00158 }
00159 return true;
00160 }
00161
00162
00163
00164
00165
00166 function setEncoding($enc) {
00167 return $this->_execute('SET NAMES ' . $enc) != false;
00168 }
00169
00170
00171
00172
00173
00174
00175 function index($model) {
00176 $index = array();
00177 $table = $this->fullTableName($model);
00178 if ($table) {
00179 $indexes = $this->query('SHOW INDEX FROM ' . $table);
00180 if (isset($indexes[0]['STATISTICS'])) {
00181 $keys = Set::extract($indexes, '{n}.STATISTICS');
00182 } else {
00183 $keys = Set::extract($indexes, '{n}.0');
00184 }
00185 foreach ($keys as $i => $key) {
00186 if (!isset($index[$key['Key_name']])) {
00187 $col = array();
00188 $index[$key['Key_name']]['column'] = $key['Column_name'];
00189 $index[$key['Key_name']]['unique'] = intval($key['Non_unique'] == 0);
00190 } else {
00191 if (!is_array($index[$key['Key_name']]['column'])) {
00192 $col[] = $index[$key['Key_name']]['column'];
00193 }
00194 $col[] = $key['Column_name'];
00195 $index[$key['Key_name']]['column'] = $col;
00196 }
00197 }
00198 }
00199 return $index;
00200 }
00201
00202
00203
00204
00205
00206
00207 function alterSchema($compare, $table = null) {
00208 if (!is_array($compare)) {
00209 return false;
00210 }
00211 $out = '';
00212 $colList = array();
00213 foreach ($compare as $curTable => $types) {
00214 $indexes = array();
00215 if (!$table || $table == $curTable) {
00216 $out .= 'ALTER TABLE ' . $this->fullTableName($curTable) . " \n";
00217 foreach ($types as $type => $column) {
00218 if (isset($column['indexes'])) {
00219 $indexes[$type] = $column['indexes'];
00220 unset($column['indexes']);
00221 }
00222 switch ($type) {
00223 case 'add':
00224 foreach ($column as $field => $col) {
00225 $col['name'] = $field;
00226 $alter = 'ADD '.$this->buildColumn($col);
00227 if (isset($col['after'])) {
00228 $alter .= ' AFTER '. $this->name($col['after']);
00229 }
00230 $colList[] = $alter;
00231 }
00232 break;
00233 case 'drop':
00234 foreach ($column as $field => $col) {
00235 $col['name'] = $field;
00236 $colList[] = 'DROP '.$this->name($field);
00237 }
00238 break;
00239 case 'change':
00240 foreach ($column as $field => $col) {
00241 if (!isset($col['name'])) {
00242 $col['name'] = $field;
00243 }
00244 $colList[] = 'CHANGE '. $this->name($field).' '.$this->buildColumn($col);
00245 }
00246 break;
00247 }
00248 }
00249 $colList = array_merge($colList, $this->_alterIndexes($curTable, $indexes));
00250 $out .= "\t" . join(",\n\t", $colList) . ";\n\n";
00251 }
00252 }
00253 return $out;
00254 }
00255
00256
00257
00258
00259
00260
00261
00262
00263 function dropSchema($schema, $table = null) {
00264 if (!is_a($schema, 'CakeSchema')) {
00265 trigger_error(__('Invalid schema object', true), E_USER_WARNING);
00266 return null;
00267 }
00268 $out = '';
00269 foreach ($schema->tables as $curTable => $columns) {
00270 if (!$table || $table == $curTable) {
00271 $out .= 'DROP TABLE IF EXISTS ' . $this->fullTableName($curTable) . ";\n";
00272 }
00273 }
00274 return $out;
00275 }
00276
00277
00278
00279
00280
00281
00282
00283 function _alterIndexes($table, $indexes) {
00284 $alter = array();
00285 if (isset($indexes['drop'])) {
00286 foreach($indexes['drop'] as $name => $value) {
00287 $out = 'DROP ';
00288 if ($name == 'PRIMARY') {
00289 $out .= 'PRIMARY KEY';
00290 } else {
00291 $out .= 'KEY ' . $name;
00292 }
00293 $alter[] = $out;
00294 }
00295 }
00296 if (isset($indexes['add'])) {
00297 foreach ($indexes['add'] as $name => $value) {
00298 $out = 'ADD ';
00299 if ($name == 'PRIMARY') {
00300 $out .= 'PRIMARY ';
00301 $name = null;
00302 } else {
00303 if (!empty($value['unique'])) {
00304 $out .= 'UNIQUE ';
00305 }
00306 }
00307 if (is_array($value['column'])) {
00308 $out .= 'KEY '. $name .' (' . join(', ', array_map(array(&$this, 'name'), $value['column'])) . ')';
00309 } else {
00310 $out .= 'KEY '. $name .' (' . $this->name($value['column']) . ')';
00311 }
00312 $alter[] = $out;
00313 }
00314 }
00315 return $alter;
00316 }
00317
00318
00319
00320
00321
00322
00323
00324 function insertMulti($table, $fields, $values) {
00325 $table = $this->fullTableName($table);
00326 if (is_array($fields)) {
00327 $fields = join(', ', array_map(array(&$this, 'name'), $fields));
00328 }
00329 $values = implode(', ', $values);
00330 $this->query("INSERT INTO {$table} ({$fields}) VALUES {$values}");
00331 }
00332 }
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342 class DboMysql extends DboMysqlBase {
00343
00344
00345
00346
00347
00348 var $description = "MySQL DBO Driver";
00349
00350
00351
00352
00353
00354 var $_baseConfig = array(
00355 'persistent' => true,
00356 'host' => 'localhost',
00357 'login' => 'root',
00358 'password' => '',
00359 'database' => 'cake',
00360 'port' => '3306',
00361 'connect' => 'mysql_pconnect'
00362 );
00363
00364
00365
00366
00367
00368 function connect() {
00369 $config = $this->config;
00370 $connect = $config['connect'];
00371 $this->connected = false;
00372
00373 if (!$config['persistent']) {
00374 $this->connection = mysql_connect($config['host'] . ':' . $config['port'], $config['login'], $config['password'], true);
00375 } else {
00376 $this->connection = $connect($config['host'] . ':' . $config['port'], $config['login'], $config['password']);
00377 }
00378
00379 if (mysql_select_db($config['database'], $this->connection)) {
00380 $this->connected = true;
00381 }
00382
00383 if (isset($config['encoding']) && !empty($config['encoding'])) {
00384 $this->setEncoding($config['encoding']);
00385 }
00386
00387 $this->_useAlias = (bool)version_compare(mysql_get_server_info($this->connection), "4.1", ">=");
00388
00389 return $this->connected;
00390 }
00391
00392
00393
00394
00395
00396 function disconnect() {
00397 if (isset($this->results) && is_resource($this->results)) {
00398 mysql_free_result($this->results);
00399 }
00400 $this->connected = !@mysql_close($this->connection);
00401 return !$this->connected;
00402 }
00403
00404
00405
00406
00407
00408
00409
00410 function _execute($sql) {
00411 return mysql_query($sql, $this->connection);
00412 }
00413
00414
00415
00416
00417
00418 function listSources() {
00419 $cache = parent::listSources();
00420 if ($cache != null) {
00421 return $cache;
00422 }
00423 $result = $this->_execute('SHOW TABLES FROM ' . $this->name($this->config['database']) . ';');
00424
00425 if (!$result) {
00426 return array();
00427 } else {
00428 $tables = array();
00429
00430 while ($line = mysql_fetch_array($result)) {
00431 $tables[] = $line[0];
00432 }
00433 parent::listSources($tables);
00434 return $tables;
00435 }
00436 }
00437
00438
00439
00440
00441
00442
00443 function describe(&$model) {
00444 $cache = parent::describe($model);
00445 if ($cache != null) {
00446 return $cache;
00447 }
00448 $fields = false;
00449 $cols = $this->query('DESCRIBE ' . $this->fullTableName($model));
00450
00451 foreach ($cols as $column) {
00452 $colKey = array_keys($column);
00453 if (isset($column[$colKey[0]]) && !isset($column[0])) {
00454 $column[0] = $column[$colKey[0]];
00455 }
00456 if (isset($column[0])) {
00457 $fields[$column[0]['Field']] = array(
00458 'type' => $this->column($column[0]['Type']),
00459 'null' => ($column[0]['Null'] == 'YES' ? true : false),
00460 'default' => $column[0]['Default'],
00461 'length' => $this->length($column[0]['Type']),
00462 );
00463 if (!empty($column[0]['Key']) && isset($this->index[$column[0]['Key']])) {
00464 $fields[$column[0]['Field']]['key'] = $this->index[$column[0]['Key']];
00465 }
00466 }
00467 }
00468 $this->__cacheDescription($this->fullTableName($model, false), $fields);
00469 return $fields;
00470 }
00471
00472
00473
00474
00475
00476
00477
00478
00479 function value($data, $column = null, $safe = false) {
00480 $parent = parent::value($data, $column, $safe);
00481
00482 if ($parent != null) {
00483 return $parent;
00484 }
00485 if ($data === null || (is_array($data) && empty($data))) {
00486 return 'NULL';
00487 }
00488 if ($data === '' && $column !== 'integer' && $column !== 'float' && $column !== 'boolean') {
00489 return "''";
00490 }
00491 if (empty($column)) {
00492 $column = $this->introspectType($data);
00493 }
00494
00495 switch ($column) {
00496 case 'boolean':
00497 return $this->boolean((bool)$data);
00498 break;
00499 case 'integer':
00500 case 'float':
00501 if ($data === '') {
00502 return 'NULL';
00503 }
00504 if ((is_int($data) || is_float($data) || $data === '0') || (
00505 is_numeric($data) && strpos($data, ',') === false &&
00506 $data[0] != '0' && strpos($data, 'e') === false)) {
00507 return $data;
00508 }
00509 default:
00510 $data = "'" . mysql_real_escape_string($data, $this->connection) . "'";
00511 break;
00512 }
00513 return $data;
00514 }
00515
00516
00517
00518
00519
00520 function lastError() {
00521 if (mysql_errno($this->connection)) {
00522 return mysql_errno($this->connection).': '.mysql_error($this->connection);
00523 }
00524 return null;
00525 }
00526
00527
00528
00529
00530
00531
00532 function lastAffected() {
00533 if ($this->_result) {
00534 return mysql_affected_rows($this->connection);
00535 }
00536 return null;
00537 }
00538
00539
00540
00541
00542
00543
00544 function lastNumRows() {
00545 if ($this->hasResult()) {
00546 return mysql_num_rows($this->_result);
00547 }
00548 return null;
00549 }
00550
00551
00552
00553
00554
00555
00556 function lastInsertId($source = null) {
00557 $id = $this->fetchRow('SELECT LAST_INSERT_ID() AS insertID', false);
00558 if ($id !== false && !empty($id) && !empty($id[0]) && isset($id[0]['insertID'])) {
00559 return $id[0]['insertID'];
00560 }
00561
00562 return null;
00563 }
00564
00565
00566
00567
00568
00569
00570 function column($real) {
00571 if (is_array($real)) {
00572 $col = $real['name'];
00573 if (isset($real['limit'])) {
00574 $col .= '('.$real['limit'].')';
00575 }
00576 return $col;
00577 }
00578
00579 $col = str_replace(')', '', $real);
00580 $limit = $this->length($real);
00581 if (strpos($col, '(') !== false) {
00582 list($col, $vals) = explode('(', $col);
00583 }
00584
00585 if (in_array($col, array('date', 'time', 'datetime', 'timestamp'))) {
00586 return $col;
00587 }
00588 if (($col == 'tinyint' && $limit == 1) || $col == 'boolean') {
00589 return 'boolean';
00590 }
00591 if (strpos($col, 'int') !== false) {
00592 return 'integer';
00593 }
00594 if (strpos($col, 'char') !== false || $col == 'tinytext') {
00595 return 'string';
00596 }
00597 if (strpos($col, 'text') !== false) {
00598 return 'text';
00599 }
00600 if (strpos($col, 'blob') !== false || $col == 'binary') {
00601 return 'binary';
00602 }
00603 if (strpos($col, 'float') !== false || strpos($col, 'double') !== false || strpos($col, 'decimal') !== false) {
00604 return 'float';
00605 }
00606 if (strpos($col, 'enum') !== false) {
00607 return "enum($vals)";
00608 }
00609 return 'text';
00610 }
00611
00612
00613
00614
00615
00616 function resultSet(&$results) {
00617 if (isset($this->results) && is_resource($this->results) && $this->results != $results) {
00618 mysql_free_result($this->results);
00619 }
00620 $this->results =& $results;
00621 $this->map = array();
00622 $numFields = mysql_num_fields($results);
00623 $index = 0;
00624 $j = 0;
00625
00626 while ($j < $numFields) {
00627
00628 $column = mysql_fetch_field($results,$j);
00629 if (!empty($column->table)) {
00630 $this->map[$index++] = array($column->table, $column->name);
00631 } else {
00632 $this->map[$index++] = array(0, $column->name);
00633 }
00634 $j++;
00635 }
00636 }
00637
00638
00639
00640
00641
00642 function fetchResult() {
00643 if ($row = mysql_fetch_row($this->results)) {
00644 $resultRow = array();
00645 $i = 0;
00646 foreach ($row as $index => $field) {
00647 list($table, $column) = $this->map[$index];
00648 $resultRow[$table][$column] = $row[$index];
00649 $i++;
00650 }
00651 return $resultRow;
00652 } else {
00653 return false;
00654 }
00655 }
00656
00657
00658
00659
00660
00661 function getEncoding() {
00662 return mysql_client_encoding($this->connection);
00663 }
00664 }
00665 ?>