1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
26: 27: 28:
29: App::import('Vendor', 'NewADOConnection', array('file' => 'adodb' . DS . 'adodb.inc.php'));
30: 31: 32: 33: 34: 35: 36: 37:
38: class DboAdodb extends DboSource {
39: 40: 41: 42: 43:
44: var $description = "ADOdb DBO Driver";
45: 46: 47: 48: 49: 50:
51: var $_adodb = null;
52: 53: 54: 55: 56: 57:
58: var $_adodbColumnTypes = array(
59: 'string' => 'C',
60: 'text' => 'X',
61: 'date' => 'D',
62: 'timestamp' => 'T',
63: 'time' => 'T',
64: 'datetime' => 'T',
65: 'boolean' => 'L',
66: 'float' => 'N',
67: 'integer' => 'I',
68: 'binary' => 'R',
69: );
70: 71: 72: 73: 74:
75: var $columns = array(
76: 'primary_key' => array('name' => 'R', 'limit' => 11),
77: 'string' => array('name' => 'C', 'limit' => '255'),
78: 'text' => array('name' => 'X'),
79: 'integer' => array('name' => 'I', 'limit' => '11', 'formatter' => 'intval'),
80: 'float' => array('name' => 'N', 'formatter' => 'floatval'),
81: 'timestamp' => array('name' => 'T', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'),
82: 'time' => array('name' => 'T', 'format' => 'H:i:s', 'formatter' => 'date'),
83: 'datetime' => array('name' => 'T', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'),
84: 'date' => array('name' => 'D', 'format' => 'Y-m-d', 'formatter' => 'date'),
85: 'binary' => array('name' => 'B'),
86: 'boolean' => array('name' => 'L', 'limit' => '1')
87: );
88: 89: 90: 91: 92:
93: function connect() {
94: $config = $this->config;
95: $persistent = strrpos($config['connect'], '|p');
96:
97: if ($persistent === false) {
98: $adodb_driver = $config['connect'];
99: $connect = 'Connect';
100: } else {
101: $adodb_driver = substr($config['connect'], 0, $persistent);
102: $connect = 'PConnect';
103: }
104: if (!$this->enabled()) {
105: return false;
106: }
107: $this->_adodb = NewADOConnection($adodb_driver);
108:
109: $this->_adodbDataDict = NewDataDictionary($this->_adodb, $adodb_driver);
110:
111: $this->startQuote = $this->_adodb->nameQuote;
112: $this->endQuote = $this->_adodb->nameQuote;
113:
114: $this->connected = $this->_adodb->$connect($config['host'], $config['login'], $config['password'], $config['database']);
115: $this->_adodbMetatyper = &$this->_adodb->execute('Select 1');
116: return $this->connected;
117: }
118: 119: 120: 121: 122:
123: function enabled() {
124: return function_exists('NewADOConnection');
125: }
126: 127: 128: 129: 130:
131: function disconnect() {
132: return $this->_adodb->Close();
133: }
134: 135: 136: 137: 138: 139:
140: function _execute($sql) {
141: global $ADODB_FETCH_MODE;
142: $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
143: return $this->_adodb->execute($sql);
144: }
145: 146: 147: 148: 149:
150: function fetchRow($sql = null) {
151: if (!empty($sql) && is_string($sql) && strlen($sql) > 5) {
152: if (!$this->execute($sql)) {
153: return null;
154: }
155: }
156:
157: if (!$this->hasResult()) {
158: return null;
159: } else {
160: $resultRow = $this->_result->FetchRow();
161: $this->resultSet($resultRow);
162: return $this->fetchResult();
163: }
164: }
165: 166: 167: 168: 169: 170: 171:
172: function begin(&$model) {
173: if (parent::begin($model)) {
174: if ($this->_adodb->BeginTrans()) {
175: $this->_transactionStarted = true;
176: return true;
177: }
178: }
179: return false;
180: }
181: 182: 183: 184: 185: 186: 187: 188:
189: function commit(&$model) {
190: if (parent::commit($model)) {
191: $this->_transactionStarted = false;
192: return $this->_adodb->CommitTrans();
193: }
194: return false;
195: }
196: 197: 198: 199: 200: 201: 202: 203:
204: function rollback(&$model) {
205: if (parent::rollback($model)) {
206: return $this->_adodb->RollbackTrans();
207: }
208: return false;
209: }
210: 211: 212: 213: 214:
215: function listSources() {
216: $tables = $this->_adodb->MetaTables('TABLES');
217:
218: if (!count($tables) > 0) {
219: trigger_error(ERROR_NO_TABLE_LIST, E_USER_NOTICE);
220: exit;
221: }
222: return $tables;
223: }
224: 225: 226: 227: 228: 229:
230: function describe(&$model) {
231: $cache = parent::describe($model);
232: if ($cache != null) {
233: return $cache;
234: }
235:
236: $fields = false;
237: $cols = $this->_adodb->MetaColumns($this->fullTableName($model, false));
238:
239: foreach ($cols as $column) {
240: $fields[$column->name] = array(
241: 'type' => $this->column($column->type),
242: 'null' => !$column->not_null,
243: 'length' => $column->max_length,
244: );
245: if ($column->has_default) {
246: $fields[$column->name]['default'] = $column->default_value;
247: }
248: if ($column->primary_key == 1) {
249: $fields[$column->name]['key'] = 'primary';
250: }
251: }
252:
253: $this->__cacheDescription($this->fullTableName($model, false), $fields);
254: return $fields;
255: }
256: 257: 258: 259: 260:
261: function lastError() {
262: return $this->_adodb->ErrorMsg();
263: }
264: 265: 266: 267: 268:
269: function lastAffected() {
270: return $this->_adodb->Affected_Rows();
271: }
272: 273: 274: 275: 276:
277: function lastNumRows() {
278: return $this->_result ? $this->_result->RecordCount() : false;
279: }
280: 281: 282: 283: 284: 285: 286:
287: function lastInsertId() {
288: return $this->_adodb->Insert_ID();
289: }
290: 291: 292: 293: 294: 295: 296: 297:
298: function limit($limit, $offset = null) {
299: if ($limit) {
300: $rt = '';
301: if (!strpos(strtolower($limit), 'limit') || strpos(strtolower($limit), 'limit') === 0) {
302: $rt = ' LIMIT';
303: }
304:
305: if ($offset) {
306: $rt .= ' ' . $offset . ',';
307: }
308:
309: $rt .= ' ' . $limit;
310: return $rt;
311: }
312: return null;
313:
314:
315: }
316: 317: 318: 319: 320: 321:
322: function column($real) {
323: $metaTypes = array_flip($this->_adodbColumnTypes);
324:
325: $interpreted_type = $this->_adodbMetatyper->MetaType($real);
326:
327: if (!isset($metaTypes[$interpreted_type])) {
328: return 'text';
329: }
330: return $metaTypes[$interpreted_type];
331: }
332: 333: 334: 335: 336: 337: 338: 339:
340: function value($data, $column = null, $safe = false) {
341: $parent = parent::value($data, $column, $safe);
342: if ($parent != null) {
343: return $parent;
344: }
345:
346: if ($data === null) {
347: return 'NULL';
348: }
349:
350: if ($data === '') {
351: return "''";
352: }
353: return $this->_adodb->qstr($data);
354: }
355:
356: 357: 358: 359: 360: 361: 362: 363:
364: function fields(&$model, $alias = null, $fields = array(), $quote = true) {
365: if (empty($alias)) {
366: $alias = $model->alias;
367: }
368: $fields = parent::fields($model, $alias, $fields, false);
369:
370: if (!$quote) {
371: return $fields;
372: }
373: $count = count($fields);
374:
375: if ($count >= 1 && $fields[0] != '*' && strpos($fields[0], 'COUNT(*)') === false) {
376: for ($i = 0; $i < $count; $i++) {
377: if (!preg_match('/^.+\\(.*\\)/', $fields[$i]) && !preg_match('/\s+AS\s+/', $fields[$i])) {
378: $prepend = '';
379: if (strpos($fields[$i], 'DISTINCT') !== false) {
380: $prepend = 'DISTINCT ';
381: $fields[$i] = trim(str_replace('DISTINCT', '', $fields[$i]));
382: }
383:
384: if (strrpos($fields[$i], '.') === false) {
385: $fields[$i] = $prepend . $this->name($alias) . '.' . $this->name($fields[$i]) . ' AS ' . $this->name($alias . '__' . $fields[$i]);
386: } else {
387: $build = explode('.', $fields[$i]);
388: $fields[$i] = $prepend . $this->name($build[0]) . '.' . $this->name($build[1]) . ' AS ' . $this->name($build[0] . '__' . $build[1]);
389: }
390: }
391: }
392: }
393: return $fields;
394: }
395: 396: 397: 398: 399:
400: function resultSet(&$results) {
401: $num_fields = count($results);
402: $fields = array_keys($results);
403: $this->results =& $results;
404: $this->map = array();
405: $index = 0;
406: $j = 0;
407:
408: while ($j < $num_fields) {
409: $columnName = $fields[$j];
410:
411: if (strpos($columnName, '__')) {
412: $parts = explode('__', $columnName);
413: $this->map[$index++] = array($parts[0], $parts[1]);
414: } else {
415: $this->map[$index++] = array(0, $columnName);
416: }
417: $j++;
418: }
419: }
420: 421: 422: 423: 424:
425: function fetchResult() {
426: if (!empty($this->results)) {
427: $row = $this->results;
428: $this->results = null;
429: } else {
430: $row = $this->_result->FetchRow();
431: }
432:
433: if (empty($row)) {
434: return false;
435: }
436:
437: $resultRow = array();
438: $fields = array_keys($row);
439: $count = count($fields);
440: $i = 0;
441: for ($i = 0; $i < $count; $i++) {
442: list($table, $column) = $this->map[$i];
443: $resultRow[$table][$column] = $row[$fields[$i]];
444: }
445: return $resultRow;
446: }
447: 448: 449: 450: 451: 452: 453:
454: function buildColumn($column) {
455: $name = $type = null;
456: extract(array_merge(array('null' => true), $column));
457:
458: if (empty($name) || empty($type)) {
459: trigger_error('Column name or type not defined in schema', E_USER_WARNING);
460: return null;
461: }
462:
463:
464: if (!isset($this->_adodbColumnTypes[$type])) {
465: trigger_error("Column type {$type} does not exist", E_USER_WARNING);
466: return null;
467: }
468: $metaType = $this->_adodbColumnTypes[$type];
469: $concreteType = $this->_adodbDataDict->ActualType($metaType);
470: $real = $this->columns[$type];
471:
472:
473: if ($type == 'string' && isset($real['length']) && $real['length'] == 36) {
474: $concreteType = 'CHAR';
475: }
476:
477: $out = $this->name($name) . ' ' . $concreteType;
478:
479: if (isset($real['limit']) || isset($real['length']) || isset($column['limit']) || isset($column['length'])) {
480: if (isset($column['length'])) {
481: $length = $column['length'];
482: } elseif (isset($column['limit'])) {
483: $length = $column['limit'];
484: } elseif (isset($real['length'])) {
485: $length = $real['length'];
486: } else {
487: $length = $real['limit'];
488: }
489: $out .= '(' . $length . ')';
490: }
491: $_notNull = $_default = $_autoInc = $_constraint = $_unsigned = false;
492:
493: if (isset($column['key']) && $column['key'] == 'primary' && $type == 'integer') {
494: $_constraint = '';
495: $_autoInc = true;
496: } elseif (isset($column['key']) && $column['key'] == 'primary') {
497: $_notNull = '';
498: } elseif (isset($column['default']) && isset($column['null']) && $column['null'] == false) {
499: $_notNull = true;
500: $_default = $column['default'];
501: } elseif ( isset($column['null']) && $column['null'] == true) {
502: $_notNull = false;
503: $_default = 'NULL';
504: }
505: if (isset($column['default']) && $_default == false) {
506: $_default = $this->value($column['default']);
507: }
508: if (isset($column['null']) && $column['null'] == false) {
509: $_notNull = true;
510: }
511:
512: $out .= $this->_adodbDataDict->_CreateSuffix($out, $metaType, $_notNull, $_default, $_autoInc, $_constraint, $_unsigned);
513: return $out;
514:
515: }
516: 517: 518: 519: 520:
521: function hasResult() {
522: return is_object($this->_result) && !$this->_result->EOF;
523: }
524: }
525: ?>