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