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 class DboOracle extends DboSource {
00036
00037
00038
00039
00040
00041
00042 var $config = array();
00043
00044
00045
00046
00047
00048 var $alias = '';
00049
00050
00051
00052 var $_sequences = array();
00053
00054
00055
00056
00057
00058 var $__transactionStarted = false;
00059
00060
00061
00062
00063
00064
00065 var $columns = array(
00066 'primary_key' => array('name' => ''),
00067 'string' => array('name' => 'varchar2', 'limit' => '255'),
00068 'text' => array('name' => 'varchar2'),
00069 'integer' => array('name' => 'number'),
00070 'float' => array('name' => 'float'),
00071 'datetime' => array('name' => 'date', 'format' => 'Y-m-d H:i:s'),
00072 'timestamp' => array('name' => 'date', 'format' => 'Y-m-d H:i:s'),
00073 'time' => array('name' => 'date', 'format' => 'Y-m-d H:i:s'),
00074 'date' => array('name' => 'date', 'format' => 'Y-m-d H:i:s'),
00075 'binary' => array('name' => 'bytea'),
00076 'boolean' => array('name' => 'boolean'),
00077 'number' => array('name' => 'number'),
00078 'inet' => array('name' => 'inet'));
00079
00080
00081
00082
00083
00084
00085 var $connection;
00086
00087
00088
00089
00090
00091
00092 var $_limit = -1;
00093
00094
00095
00096
00097
00098
00099 var $_offset = 0;
00100
00101
00102
00103
00104
00105
00106 var $_map;
00107
00108
00109
00110
00111
00112
00113 var $_currentRow;
00114
00115
00116
00117
00118
00119
00120 var $_numRows;
00121
00122
00123
00124
00125
00126
00127 var $_results;
00128
00129
00130
00131
00132
00133 var $_error;
00134
00135
00136
00137
00138
00139 var $_baseConfig = array(
00140 'persistent' => true,
00141 'host' => 'localhost',
00142 'login' => 'system',
00143 'password' => '',
00144 'database' => 'cake',
00145 'nls_sort' => '',
00146 'nls_sort' => ''
00147 );
00148
00149
00150
00151
00152
00153 var $_sequenceMap = array();
00154
00155
00156
00157
00158
00159
00160 function connect() {
00161 $config = $this->config;
00162 $this->connected = false;
00163 $config['charset'] = !empty($config['charset']) ? $config['charset'] : null;
00164
00165 if ($this->config['persistent']) {
00166 $connect = 'ociplogon';
00167 } else {
00168 $connect = 'ocilogon';
00169 }
00170 $this->connection = @$connect($config['login'], $config['password'], $config['database'], $config['charset']);
00171
00172 if ($this->connection) {
00173 $this->connected = true;
00174 if (!empty($config['nls_sort'])) {
00175 $this->execute('ALTER SESSION SET NLS_SORT='.$config['nls_sort']);
00176 }
00177
00178 if (!empty($config['nls_comp'])) {
00179 $this->execute('ALTER SESSION SET NLS_COMP='.$config['nls_comp']);
00180 }
00181 $this->execute("ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD HH24:MI:SS'");
00182 } else {
00183 $this->connected = false;
00184 $this->_setError();
00185 return false;
00186 }
00187 return $this->connected;
00188 }
00189
00190
00191
00192
00193 function _setError($source = null, $clear = false) {
00194 if ($source) {
00195 $e = ocierror($source);
00196 } else {
00197 $e = ocierror();
00198 }
00199 $this->_error = $e['message'];
00200 if ($clear) {
00201 $this->_error = null;
00202 }
00203 }
00204
00205
00206
00207
00208
00209
00210 function setEncoding($lang) {
00211 if (!$this->execute('ALTER SESSION SET NLS_LANGUAGE='.$lang)) {
00212 return false;
00213 }
00214 return true;
00215 }
00216
00217
00218
00219
00220
00221 function getEncoding() {
00222 $sql = 'SELECT VALUE FROM NLS_SESSION_PARAMETERS WHERE PARAMETER=\'NLS_LANGUAGE\'';
00223 if (!$this->execute($sql)) {
00224 return false;
00225 }
00226
00227 if (!$row = $this->fetchRow()) {
00228 return false;
00229 }
00230 return $row[0]['VALUE'];
00231 }
00232
00233
00234
00235
00236
00237
00238 function disconnect() {
00239 if ($this->connection) {
00240 $this->connected = !ocilogoff($this->connection);
00241 return !$this->connected;
00242 }
00243 }
00244
00245
00246
00247
00248
00249
00250
00251
00252 function _scrapeSQL($sql) {
00253 $sql = str_replace("\"", '', $sql);
00254 $preFrom = preg_split('/\bFROM\b/', $sql);
00255 $preFrom = $preFrom[0];
00256 $find = array('SELECT');
00257 $replace = array('');
00258 $fieldList = trim(str_replace($find, $replace, $preFrom));
00259 $fields = preg_split('/,\s+/', $fieldList);
00260 $lastTableName = '';
00261
00262 foreach($fields as $key => $value) {
00263 if ($value != 'COUNT(*) AS count') {
00264 if (preg_match('/\s+(\w+(\.\w+)*)$/', $value, $matches)) {
00265 $fields[$key] = $matches[1];
00266
00267 if (preg_match('/^(\w+\.)/', $value, $matches)) {
00268 $fields[$key] = $matches[1] . $fields[$key];
00269 $lastTableName = $matches[1];
00270 }
00271 }
00272
00273
00274
00275
00276
00277 }
00278 }
00279 $this->_map = array();
00280
00281 foreach($fields as $f) {
00282 $e = explode('.', $f);
00283 if (count($e) > 1) {
00284 $table = $e[0];
00285 $field = strtolower($e[1]);
00286 } else {
00287 $table = 0;
00288 $field = $e[0];
00289 }
00290 $this->_map[] = array($table, $field);
00291 }
00292 }
00293
00294
00295
00296
00297
00298
00299
00300
00301 function limit($limit = -1, $offset = 0) {
00302 $this->_limit = (int) $limit;
00303 $this->_offset = (int) $offset;
00304 }
00305
00306
00307
00308
00309
00310
00311
00312 function lastNumRows() {
00313 return $this->_numRows;
00314 }
00315
00316
00317
00318
00319
00320
00321
00322 function _execute($sql) {
00323 $this->_statementId = @ociparse($this->connection, $sql);
00324 if (!$this->_statementId) {
00325 $this->_setError($this->connection);
00326 return false;
00327 }
00328
00329 if ($this->__transactionStarted) {
00330 $mode = OCI_DEFAULT;
00331 } else {
00332 $mode = OCI_COMMIT_ON_SUCCESS;
00333 }
00334
00335 if (!@ociexecute($this->_statementId, $mode)) {
00336 $this->_setError($this->_statementId);
00337 return false;
00338 }
00339
00340 $this->_setError(null, true);
00341
00342 switch(ocistatementtype($this->_statementId)) {
00343 case 'DESCRIBE':
00344 case 'SELECT':
00345 $this->_scrapeSQL($sql);
00346 break;
00347 default:
00348 return $this->_statementId;
00349 break;
00350 }
00351
00352 if ($this->_limit >= 1) {
00353 ocisetprefetch($this->_statementId, $this->_limit);
00354 } else {
00355 ocisetprefetch($this->_statementId, 3000);
00356 }
00357 $this->_numRows = ocifetchstatement($this->_statementId, $this->_results, $this->_offset, $this->_limit, OCI_NUM | OCI_FETCHSTATEMENT_BY_ROW);
00358 $this->_currentRow = 0;
00359 $this->limit();
00360 return $this->_statementId;
00361 }
00362
00363
00364
00365
00366
00367
00368 function fetchRow() {
00369 if ($this->_currentRow >= $this->_numRows) {
00370 ocifreestatement($this->_statementId);
00371 $this->_map = null;
00372 $this->_results = null;
00373 $this->_currentRow = null;
00374 $this->_numRows = null;
00375 return false;
00376 }
00377 $resultRow = array();
00378
00379 foreach($this->_results[$this->_currentRow] as $index => $field) {
00380 list($table, $column) = $this->_map[$index];
00381
00382 if (strpos($column, ' count')) {
00383 $resultRow[0]['count'] = $field;
00384 } else {
00385 $resultRow[$table][$column] = $this->_results[$this->_currentRow][$index];
00386 }
00387 }
00388 $this->_currentRow++;
00389 return $resultRow;
00390 }
00391
00392
00393
00394
00395
00396 function fetchResult() {
00397 return $this->fetchRow();
00398 }
00399
00400
00401
00402
00403
00404
00405
00406 function sequenceExists($sequence) {
00407 $sql = "SELECT SEQUENCE_NAME FROM USER_SEQUENCES WHERE SEQUENCE_NAME = '$sequence'";
00408 if (!$this->execute($sql)) {
00409 return false;
00410 }
00411 return $this->fetchRow();
00412 }
00413
00414
00415
00416
00417
00418
00419
00420 function createSequence($sequence) {
00421 $sql = "CREATE SEQUENCE $sequence";
00422 return $this->execute($sql);
00423 }
00424
00425
00426
00427
00428
00429
00430
00431 function createTrigger($table) {
00432 $sql = "CREATE OR REPLACE TRIGGER pk_$table" . "_trigger BEFORE INSERT ON $table FOR EACH ROW BEGIN SELECT pk_$table.NEXTVAL INTO :NEW.ID FROM DUAL; END;";
00433 return $this->execute($sql);
00434 }
00435
00436
00437
00438
00439
00440
00441
00442 function listSources() {
00443 $cache = parent::listSources();
00444 if ($cache != null) {
00445 return $cache;
00446 }
00447 $sql = 'SELECT view_name AS name FROM all_views UNION SELECT table_name AS name FROM all_tables';
00448
00449 if (!$this->execute($sql)) {
00450 return false;
00451 }
00452 $sources = array();
00453
00454 while($r = $this->fetchRow()) {
00455 $sources[] = strtolower($r[0]['name']);
00456 }
00457 parent::listSources($sources);
00458 return $sources;
00459 }
00460
00461
00462
00463
00464
00465
00466
00467 function describe(&$model) {
00468 $table = $model->fullTableName($model, false);
00469
00470 if (!empty($model->sequence)) {
00471 $this->_sequenceMap[$table] = $model->sequence;
00472 } elseif (!empty($model->table)) {
00473 $this->_sequenceMap[$table] = $model->table . '_seq';
00474 }
00475
00476 $cache = parent::describe($model);
00477
00478 if ($cache != null) {
00479 return $cache;
00480 }
00481
00482 $sql = 'SELECT COLUMN_NAME, DATA_TYPE, DATA_LENGTH FROM all_tab_columns WHERE table_name = \'';
00483 $sql .= strtoupper($this->fullTableName($model)) . '\'';
00484
00485 if (!$this->execute($sql)) {
00486 return false;
00487 }
00488
00489 $fields = array();
00490
00491 for ($i = 0; $row = $this->fetchRow(); $i++) {
00492 $fields[strtolower($row[0]['COLUMN_NAME'])] = array(
00493 'type'=> $this->column($row[0]['DATA_TYPE']),
00494 'length'=> $row[0]['DATA_LENGTH']
00495 );
00496 }
00497 $this->__cacheDescription($this->fullTableName($model, false), $fields);
00498
00499 return $fields;
00500 }
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512 function truncate($table, $reset = 0) {
00513
00514 if (empty($this->_sequences)) {
00515 $sql = "SELECT sequence_name FROM all_sequences";
00516 $this->execute($sql);
00517 while ($row = $this->fetchRow()) {
00518 $this->_sequences[] = strtolower($row[0]['sequence_name']);
00519 }
00520 }
00521
00522 $this->execute('DELETE FROM ' . $this->fullTableName($table));
00523 if (!isset($this->_sequenceMap[$table]) || !in_array($this->_sequenceMap[$table], $this->_sequences)) {
00524 return true;
00525 }
00526 if ($reset === 0) {
00527 $this->execute("SELECT {$this->_sequenceMap[$table]}.nextval FROM dual");
00528 $row = $this->fetchRow();
00529 $currval = $row[$this->_sequenceMap[$table]]['nextval'];
00530
00531 $this->execute("SELECT min_value FROM all_sequences WHERE sequence_name = '{$this->_sequenceMap[$table]}'");
00532 $row = $this->fetchRow();
00533 $min_value = $row[0]['min_value'];
00534
00535 if ($min_value == 1) $min_value = 0;
00536 $offset = -($currval - $min_value);
00537
00538 $this->execute("ALTER SEQUENCE {$this->_sequenceMap[$table]} INCREMENT BY $offset MINVALUE $min_value");
00539 $this->execute("SELECT {$this->_sequenceMap[$table]}.nextval FROM dual");
00540 $this->execute("ALTER SEQUENCE {$this->_sequenceMap[$table]} INCREMENT BY 1");
00541 } else {
00542
00543 }
00544 return true;
00545 }
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558 function constraint($action, $table) {
00559 if (empty($table)) {
00560 trigger_error(__('Must specify table to operate on constraints'));
00561 }
00562
00563 $table = strtoupper($table);
00564
00565 if (empty($this->_keyConstraints)) {
00566 $sql = "SELECT
00567 table_name,
00568 c.constraint_name
00569 FROM all_cons_columns cc
00570 LEFT JOIN all_indexes i ON (cc.constraint_name = i.index_name)
00571 LEFT JOIN all_constraints c ON(c.constraint_name = cc.constraint_name)";
00572 $this->execute($sql);
00573 while ($row = $this->fetchRow()) {
00574 $this->_keyConstraints[] = array($row[0]['table_name'], $row['c']['constraint_name']);
00575 }
00576 }
00577
00578 $relatedKeys = array();
00579 foreach ($this->_keyConstraints as $c) {
00580 if ($c[0] == $table) {
00581 $relatedKeys[] = $c[1];
00582 }
00583 }
00584
00585 if (empty($this->_constraints)) {
00586 $sql = "SELECT
00587 table_name,
00588 constraint_name,
00589 r_constraint_name
00590 FROM
00591 all_constraints";
00592 $this->execute($sql);
00593 while ($row = $this->fetchRow()) {
00594 $this->_constraints[] = $row[0];
00595 }
00596 }
00597
00598 $constraints = array();
00599 foreach ($this->_constraints as $c) {
00600 if (in_array($c['r_constraint_name'], $relatedKeys)) {
00601 $constraints[] = array($c['table_name'], $c['constraint_name']);
00602 }
00603 }
00604
00605 foreach ($constraints as $c) {
00606 list($table, $constraint) = $c;
00607 switch ($action) {
00608 case 'enable':
00609 $this->execute("ALTER TABLE $table ENABLE CONSTRAINT $constraint");
00610 break;
00611 case 'disable':
00612 $this->execute("ALTER TABLE $table DISABLE CONSTRAINT $constraint");
00613 break;
00614 case 'list':
00615 return $constraints;
00616 break;
00617 default:
00618 trigger_error(__('DboOracle::constraint() accepts only enable, disable, or list'));
00619 }
00620 }
00621 return true;
00622 }
00623
00624
00625
00626
00627
00628
00629 function index($model) {
00630 $index = array();
00631 $table = $this->fullTableName($model, false);
00632 if ($table) {
00633 $indexes = $this->query('SELECT
00634 cc.table_name,
00635 cc.column_name,
00636 cc.constraint_name,
00637 c.constraint_type,
00638 i.index_name,
00639 i.uniqueness
00640 FROM all_cons_columns cc
00641 LEFT JOIN all_indexes i ON(cc.constraint_name = i.index_name)
00642 LEFT JOIN all_constraints c ON(c.constraint_name = cc.constraint_name)
00643 WHERE cc.table_name = \'' . strtoupper($table) .'\'');
00644 foreach ($indexes as $i => $idx) {
00645 if ($idx['c']['constraint_type'] == 'P') {
00646 $key = 'PRIMARY';
00647 } else {
00648 continue;
00649 }
00650 if (!isset($index[$key])) {
00651 $index[$key]['column'] = strtolower($idx['cc']['column_name']);
00652 $index[$key]['unique'] = intval($idx['i']['uniqueness'] == 'UNIQUE');
00653 } else {
00654 if (!is_array($index[$key]['column'])) {
00655 $col[] = $index[$key]['column'];
00656 }
00657 $col[] = strtolower($idx['cc']['column_name']);
00658 $index[$key]['column'] = $col;
00659 }
00660 }
00661 }
00662 return $index;
00663 }
00664
00665
00666
00667
00668
00669
00670 function alterSchema($compare, $table = null) {
00671 if (!is_array($compare)) {
00672 return false;
00673 }
00674 $out = '';
00675 $colList = array();
00676 foreach($compare as $curTable => $types) {
00677 if (!$table || $table == $curTable) {
00678 $out .= 'ALTER TABLE ' . $this->fullTableName($curTable) . " \n";
00679 foreach($types as $type => $column) {
00680 switch($type) {
00681 case 'add':
00682 foreach($column as $field => $col) {
00683 $col['name'] = $field;
00684 $alter = 'ADD '.$this->buildColumn($col);
00685 if (isset($col['after'])) {
00686 $alter .= ' AFTER '. $this->name($col['after']);
00687 }
00688 $colList[] = $alter;
00689 }
00690 break;
00691 case 'drop':
00692 foreach($column as $field => $col) {
00693 $col['name'] = $field;
00694 $colList[] = 'DROP '.$this->name($field);
00695 }
00696 break;
00697 case 'change':
00698 foreach($column as $field => $col) {
00699 if (!isset($col['name'])) {
00700 $col['name'] = $field;
00701 }
00702 $colList[] = 'CHANGE '. $this->name($field).' '.$this->buildColumn($col);
00703 }
00704 break;
00705 }
00706 }
00707 $out .= "\t" . join(",\n\t", $colList) . ";\n\n";
00708 }
00709 }
00710 return $out;
00711 }
00712
00713
00714
00715
00716
00717
00718
00719
00720 function name($name) {
00721 if (strpos($name, '.') !== false && strpos($name, '"') === false) {
00722 list($model, $field) = explode('.', $name);
00723 if ($field[0] == "_") {
00724 $name = "$model.\"$field\"";
00725 }
00726 } else {
00727 if ($name[0] == "_") {
00728 $name = "\"$name\"";
00729 }
00730 }
00731 return $name;
00732 }
00733
00734
00735
00736
00737
00738
00739
00740 function begin() {
00741 $this->__transactionStarted = true;
00742 return true;
00743 }
00744
00745
00746
00747
00748
00749
00750
00751
00752 function rollback() {
00753 return ocirollback($this->connection);
00754 }
00755
00756
00757
00758
00759
00760
00761
00762
00763 function commit() {
00764 $this->__transactionStarted = false;
00765 return ocicommit($this->connection);
00766 }
00767
00768
00769
00770
00771
00772
00773
00774 function column($real) {
00775 if (is_array($real)) {
00776 $col = $real['name'];
00777
00778 if (isset($real['limit'])) {
00779 $col .= '('.$real['limit'].')';
00780 }
00781 return $col;
00782 } else {
00783 $real = strtolower($real);
00784 }
00785 $col = str_replace(')', '', $real);
00786 $limit = null;
00787 if (strpos($col, '(') !== false) {
00788 list($col, $limit) = explode('(', $col);
00789 }
00790
00791 if (in_array($col, array('date', 'timestamp'))) {
00792 return $col;
00793 }
00794 if (strpos($col, 'number') !== false) {
00795 return 'integer';
00796 }
00797 if (strpos($col, 'integer') !== false) {
00798 return 'integer';
00799 }
00800 if (strpos($col, 'char') !== false) {
00801 return 'string';
00802 }
00803 if (strpos($col, 'text') !== false) {
00804 return 'text';
00805 }
00806 if (strpos($col, 'blob') !== false) {
00807 return 'binary';
00808 }
00809 if (in_array($col, array('float', 'double', 'decimal'))) {
00810 return 'float';
00811 }
00812 if ($col == 'boolean') {
00813 return $col;
00814 }
00815 return 'text';
00816 }
00817
00818
00819
00820
00821
00822
00823
00824 function value($data, $column = null, $safe = false) {
00825 $parent = parent::value($data, $column, $safe);
00826
00827 if ($parent != null) {
00828 return $parent;
00829 }
00830
00831 if ($data === null) {
00832 return 'NULL';
00833 }
00834
00835 if ($data === '') {
00836 return "''";
00837 }
00838
00839 switch($column) {
00840 case 'date':
00841 $data = date('Y-m-d H:i:s', strtotime($data));
00842 $data = "TO_DATE('$data', 'YYYY-MM-DD HH24:MI:SS')";
00843 break;
00844 case 'integer' :
00845 case 'float' :
00846 case null :
00847 if (is_numeric($data)) {
00848 break;
00849 }
00850 default:
00851 $data = str_replace("'", "''", $data);
00852 $data = "'$data'";
00853 break;
00854 }
00855 return $data;
00856 }
00857
00858
00859
00860
00861
00862
00863
00864 function lastInsertId($source) {
00865 $sequence = $this->_sequenceMap[$source];
00866 $sql = "SELECT $sequence.currval FROM dual";
00867
00868 if (!$this->execute($sql)) {
00869 return false;
00870 }
00871
00872 while($row = $this->fetchRow()) {
00873 return $row[$sequence]['currval'];
00874 }
00875 return false;
00876 }
00877
00878
00879
00880
00881
00882
00883 function lastError() {
00884 return $this->_error;
00885 }
00886
00887
00888
00889
00890
00891
00892 function lastAffected() {
00893 return $this->_statementId ? ocirowcount($this->_statementId): false;
00894 }
00895
00896
00897
00898
00899
00900
00901
00902 function renderStatement($type, $data) {
00903 extract($data);
00904 $aliases = null;
00905
00906 switch (strtolower($type)) {
00907 case 'select':
00908 return "SELECT {$fields} FROM {$table} {$alias} {$joins} {$conditions} {$order} {$limit}";
00909 break;
00910 case 'create':
00911 return "INSERT INTO {$table} ({$fields}) VALUES ({$values})";
00912 break;
00913 case 'update':
00914 if (!empty($alias)) {
00915 $aliases = "{$this->alias}{$alias} ";
00916 }
00917 return "UPDATE {$table} {$aliases}SET {$fields} {$conditions}";
00918 break;
00919 case 'delete':
00920 if (!empty($alias)) {
00921 $aliases = "{$this->alias}{$alias} ";
00922 }
00923 return "DELETE FROM {$table} {$aliases}{$conditions}";
00924 break;
00925 case 'schema':
00926 foreach (array('columns', 'indexes') as $var) {
00927 if (is_array(${$var})) {
00928 ${$var} = "\t" . join(",\n\t", array_filter(${$var}));
00929 }
00930 }
00931 if (trim($indexes) != '') {
00932 $columns .= ',';
00933 }
00934 return "CREATE TABLE {$table} (\n{$columns}{$indexes})";
00935 break;
00936 case 'alter':
00937 break;
00938 }
00939 }
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954 function queryAssociation(&$model, &$linkModel, $type, $association, $assocData, &$queryData, $external = false, &$resultSet, $recursive, $stack) {
00955 if ($query = $this->generateAssociationQuery($model, $linkModel, $type, $association, $assocData, $queryData, $external, $resultSet)) {
00956 if (!isset($resultSet) || !is_array($resultSet)) {
00957 if (Configure::read() > 0) {
00958 echo '<div style = "font: Verdana bold 12px; color: #FF0000">' . sprintf(__('SQL Error in model %s:', true), $model->alias) . ' ';
00959 if (isset($this->error) && $this->error != null) {
00960 echo $this->error;
00961 }
00962 echo '</div>';
00963 }
00964 return null;
00965 }
00966 $count = count($resultSet);
00967
00968 if ($type === 'hasMany' && (!isset($assocData['limit']) || empty($assocData['limit']))) {
00969 $ins = $fetch = array();
00970 for ($i = 0; $i < $count; $i++) {
00971 if ($in = $this->insertQueryData('{$__cakeID__$}', $resultSet[$i], $association, $assocData, $model, $linkModel, $stack)) {
00972 $ins[] = $in;
00973 }
00974 }
00975
00976 if (!empty($ins)) {
00977 $fetch = array();
00978 $ins = array_chunk($ins, 1000);
00979 foreach ($ins as $i) {
00980 $q = str_replace('{$__cakeID__$}', join(', ', $i), $query);
00981 $q = str_replace('= (', 'IN (', $q);
00982 $res = $this->fetchAll($q, $model->cacheQueries, $model->alias);
00983 $fetch = array_merge($fetch, $res);
00984 }
00985 }
00986
00987 if (!empty($fetch) && is_array($fetch)) {
00988 if ($recursive > 0) {
00989
00990 foreach ($linkModel->__associations as $type1) {
00991 foreach ($linkModel->{$type1} as $assoc1 => $assocData1) {
00992 $deepModel =& $linkModel->{$assoc1};
00993 $tmpStack = $stack;
00994 $tmpStack[] = $assoc1;
00995
00996 if ($linkModel->useDbConfig === $deepModel->useDbConfig) {
00997 $db =& $this;
00998 } else {
00999 $db =& ConnectionManager::getDataSource($deepModel->useDbConfig);
01000 }
01001 $db->queryAssociation($linkModel, $deepModel, $type1, $assoc1, $assocData1, $queryData, true, $fetch, $recursive - 1, $tmpStack);
01002 }
01003 }
01004 }
01005 }
01006 return $this->__mergeHasMany($resultSet, $fetch, $association, $model, $linkModel, $recursive);
01007 } elseif ($type === 'hasAndBelongsToMany') {
01008 $ins = $fetch = array();
01009 for ($i = 0; $i < $count; $i++) {
01010 if ($in = $this->insertQueryData('{$__cakeID__$}', $resultSet[$i], $association, $assocData, $model, $linkModel, $stack)) {
01011 $ins[] = $in;
01012 }
01013 }
01014
01015 $foreignKey = $model->hasAndBelongsToMany[$association]['foreignKey'];
01016 $joinKeys = array($foreignKey, $model->hasAndBelongsToMany[$association]['associationForeignKey']);
01017 list($with, $habtmFields) = $model->joinModel($model->hasAndBelongsToMany[$association]['with'], $joinKeys);
01018 $habtmFieldsCount = count($habtmFields);
01019
01020 if (!empty($ins)) {
01021 $fetch = array();
01022 $ins = array_chunk($ins, 1000);
01023 foreach ($ins as $i) {
01024 $q = str_replace('{$__cakeID__$}', '(' .join(', ', $i) .')', $query);
01025 $q = str_replace('= (', 'IN (', $q);
01026 $q = str_replace(' WHERE 1 = 1', '', $q);
01027
01028
01029 $q = $this->insertQueryData($q, null, $association, $assocData, $model, $linkModel, $stack);
01030 if ($q != false) {
01031 $res = $this->fetchAll($q, $model->cacheQueries, $model->alias);
01032 $fetch = array_merge($fetch, $res);
01033 }
01034 }
01035 }
01036 }
01037
01038 for ($i = 0; $i < $count; $i++) {
01039 $row =& $resultSet[$i];
01040
01041 if ($type !== 'hasAndBelongsToMany') {
01042 $q = $this->insertQueryData($query, $resultSet[$i], $association, $assocData, $model, $linkModel, $stack);
01043 if ($q != false) {
01044 $fetch = $this->fetchAll($q, $model->cacheQueries, $model->alias);
01045 } else {
01046 $fetch = null;
01047 }
01048 }
01049
01050 if (!empty($fetch) && is_array($fetch)) {
01051 if ($recursive > 0) {
01052
01053 foreach ($linkModel->__associations as $type1) {
01054 foreach ($linkModel->{$type1} as $assoc1 => $assocData1) {
01055
01056 $deepModel =& $linkModel->{$assoc1};
01057 if (($type1 === 'belongsTo') || ($deepModel->alias === $model->alias && $type === 'belongsTo') || ($deepModel->alias != $model->alias)) {
01058 $tmpStack = $stack;
01059 $tmpStack[] = $assoc1;
01060 if ($linkModel->useDbConfig == $deepModel->useDbConfig) {
01061 $db =& $this;
01062 } else {
01063 $db =& ConnectionManager::getDataSource($deepModel->useDbConfig);
01064 }
01065 $db->queryAssociation($linkModel, $deepModel, $type1, $assoc1, $assocData1, $queryData, true, $fetch, $recursive - 1, $tmpStack);
01066 }
01067 }
01068 }
01069 }
01070 if ($type == 'hasAndBelongsToMany') {
01071 $merge = array();
01072 foreach($fetch as $j => $data) {
01073 if (isset($data[$with]) && $data[$with][$foreignKey] === $row[$model->alias][$model->primaryKey]) {
01074 if ($habtmFieldsCount > 2) {
01075 $merge[] = $data;
01076 } else {
01077 $merge[] = Set::diff($data, array($with => $data[$with]));
01078 }
01079 }
01080 }
01081 if (empty($merge) && !isset($row[$association])) {
01082 $row[$association] = $merge;
01083 } else {
01084 $this->__mergeAssociation($resultSet[$i], $merge, $association, $type);
01085 }
01086 } else {
01087 $this->__mergeAssociation($resultSet[$i], $fetch, $association, $type);
01088 }
01089 $resultSet[$i][$association] = $linkModel->afterfind($resultSet[$i][$association]);
01090
01091 } else {
01092 $tempArray[0][$association] = false;
01093 $this->__mergeAssociation($resultSet[$i], $tempArray, $association, $type);
01094 }
01095 }
01096 }
01097 }
01098
01099
01100
01101
01102
01103
01104
01105
01106 function dropSchema($schema, $table = null) {
01107 if (!is_a($schema, 'CakeSchema')) {
01108 trigger_error(__('Invalid schema object', true), E_USER_WARNING);
01109 return null;
01110 }
01111 $out = '';
01112
01113 foreach ($schema->tables as $curTable => $columns) {
01114 if (!$table || $table == $curTable) {
01115 $out .= 'DROP TABLE ' . $this->fullTableName($curTable) . "\n";
01116 }
01117 }
01118 return $out;
01119 }
01120 }
01121 ?>