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