commiting uncommited changes on live site
[weblabels.fsf.org.git] / crm.fsf.org / 20131203 / files / sites / all / modules-new / civicrm / packages / DB / odbc.php
1 <?php
2
3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
5 /**
6 * The PEAR DB driver for PHP's odbc extension
7 * for interacting with databases via ODBC connections
8 *
9 * PHP versions 4 and 5
10 *
11 * LICENSE: This source file is subject to version 3.0 of the PHP license
12 * that is available through the world-wide-web at the following URI:
13 * http://www.php.net/license/3_0.txt. If you did not receive a copy of
14 * the PHP License and are unable to obtain it through the web, please
15 * send a note to license@php.net so we can mail you a copy immediately.
16 *
17 * @category Database
18 * @package DB
19 * @author Stig Bakken <ssb@php.net>
20 * @author Daniel Convissor <danielc@php.net>
21 * @copyright 1997-2007 The PHP Group
22 * @license http://www.php.net/license/3_0.txt PHP License 3.0
23 * @version CVS: $Id: odbc.php,v 1.81 2007/07/06 05:19:21 aharvey Exp $
24 * @link http://pear.php.net/package/DB
25 */
26
27 /**
28 * Obtain the DB_common class so it can be extended from
29 */
30 require_once 'DB/common.php';
31
32 /**
33 * The methods PEAR DB uses to interact with PHP's odbc extension
34 * for interacting with databases via ODBC connections
35 *
36 * These methods overload the ones declared in DB_common.
37 *
38 * More info on ODBC errors could be found here:
39 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/trblsql/tr_err_odbc_5stz.asp
40 *
41 * @category Database
42 * @package DB
43 * @author Stig Bakken <ssb@php.net>
44 * @author Daniel Convissor <danielc@php.net>
45 * @copyright 1997-2007 The PHP Group
46 * @license http://www.php.net/license/3_0.txt PHP License 3.0
47 * @version Release: 1.7.13
48 * @link http://pear.php.net/package/DB
49 */
50 class DB_odbc extends DB_common
51 {
52 // {{{ properties
53
54 /**
55 * The DB driver type (mysql, oci8, odbc, etc.)
56 * @var string
57 */
58 var $phptype = 'odbc';
59
60 /**
61 * The database syntax variant to be used (db2, access, etc.), if any
62 * @var string
63 */
64 var $dbsyntax = 'sql92';
65
66 /**
67 * The capabilities of this DB implementation
68 *
69 * The 'new_link' element contains the PHP version that first provided
70 * new_link support for this DBMS. Contains false if it's unsupported.
71 *
72 * Meaning of the 'limit' element:
73 * + 'emulate' = emulate with fetch row by number
74 * + 'alter' = alter the query
75 * + false = skip rows
76 *
77 * NOTE: The feature set of the following drivers are different than
78 * the default:
79 * + solid: 'transactions' = true
80 * + navision: 'limit' = false
81 *
82 * @var array
83 */
84 var $features = array(
85 'limit' => 'emulate',
86 'new_link' => false,
87 'numrows' => true,
88 'pconnect' => true,
89 'prepare' => false,
90 'ssl' => false,
91 'transactions' => false,
92 );
93
94 /**
95 * A mapping of native error codes to DB error codes
96 * @var array
97 */
98 var $errorcode_map = array(
99 '01004' => DB_ERROR_TRUNCATED,
100 '07001' => DB_ERROR_MISMATCH,
101 '21S01' => DB_ERROR_VALUE_COUNT_ON_ROW,
102 '21S02' => DB_ERROR_MISMATCH,
103 '22001' => DB_ERROR_INVALID,
104 '22003' => DB_ERROR_INVALID_NUMBER,
105 '22005' => DB_ERROR_INVALID_NUMBER,
106 '22008' => DB_ERROR_INVALID_DATE,
107 '22012' => DB_ERROR_DIVZERO,
108 '23000' => DB_ERROR_CONSTRAINT,
109 '23502' => DB_ERROR_CONSTRAINT_NOT_NULL,
110 '23503' => DB_ERROR_CONSTRAINT,
111 '23504' => DB_ERROR_CONSTRAINT,
112 '23505' => DB_ERROR_CONSTRAINT,
113 '24000' => DB_ERROR_INVALID,
114 '34000' => DB_ERROR_INVALID,
115 '37000' => DB_ERROR_SYNTAX,
116 '42000' => DB_ERROR_SYNTAX,
117 '42601' => DB_ERROR_SYNTAX,
118 'IM001' => DB_ERROR_UNSUPPORTED,
119 'S0000' => DB_ERROR_NOSUCHTABLE,
120 'S0001' => DB_ERROR_ALREADY_EXISTS,
121 'S0002' => DB_ERROR_NOSUCHTABLE,
122 'S0011' => DB_ERROR_ALREADY_EXISTS,
123 'S0012' => DB_ERROR_NOT_FOUND,
124 'S0021' => DB_ERROR_ALREADY_EXISTS,
125 'S0022' => DB_ERROR_NOSUCHFIELD,
126 'S1009' => DB_ERROR_INVALID,
127 'S1090' => DB_ERROR_INVALID,
128 'S1C00' => DB_ERROR_NOT_CAPABLE,
129 );
130
131 /**
132 * The raw database connection created by PHP
133 * @var resource
134 */
135 var $connection;
136
137 /**
138 * The DSN information for connecting to a database
139 * @var array
140 */
141 var $dsn = array();
142
143
144 /**
145 * The number of rows affected by a data manipulation query
146 * @var integer
147 * @access private
148 */
149 var $affected = 0;
150
151
152 // }}}
153 // {{{ constructor
154
155 /**
156 * This constructor calls <kbd>$this->DB_common()</kbd>
157 *
158 * @return void
159 */
160 function DB_odbc()
161 {
162 $this->DB_common();
163 }
164
165 // }}}
166 // {{{ connect()
167
168 /**
169 * Connect to the database server, log in and open the database
170 *
171 * Don't call this method directly. Use DB::connect() instead.
172 *
173 * PEAR DB's odbc driver supports the following extra DSN options:
174 * + cursor The type of cursor to be used for this connection.
175 *
176 * @param array $dsn the data source name
177 * @param bool $persistent should the connection be persistent?
178 *
179 * @return int DB_OK on success. A DB_Error object on failure.
180 */
181 function connect($dsn, $persistent = false)
182 {
183 if (!PEAR::loadExtension('odbc')) {
184 return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
185 }
186
187 $this->dsn = $dsn;
188 if ($dsn['dbsyntax']) {
189 $this->dbsyntax = $dsn['dbsyntax'];
190 }
191 switch ($this->dbsyntax) {
192 case 'access':
193 case 'db2':
194 case 'solid':
195 $this->features['transactions'] = true;
196 break;
197 case 'navision':
198 $this->features['limit'] = false;
199 }
200
201 /*
202 * This is hear for backwards compatibility. Should have been using
203 * 'database' all along, but prior to 1.6.0RC3 'hostspec' was used.
204 */
205 if ($dsn['database']) {
206 $odbcdsn = $dsn['database'];
207 } elseif ($dsn['hostspec']) {
208 $odbcdsn = $dsn['hostspec'];
209 } else {
210 $odbcdsn = 'localhost';
211 }
212
213 $connect_function = $persistent ? 'odbc_pconnect' : 'odbc_connect';
214
215 if (empty($dsn['cursor'])) {
216 $this->connection = @$connect_function($odbcdsn, $dsn['username'],
217 $dsn['password']);
218 } else {
219 $this->connection = @$connect_function($odbcdsn, $dsn['username'],
220 $dsn['password'],
221 $dsn['cursor']);
222 }
223
224 if (!is_resource($this->connection)) {
225 return $this->raiseError(DB_ERROR_CONNECT_FAILED,
226 null, null, null,
227 $this->errorNative());
228 }
229 return DB_OK;
230 }
231
232 // }}}
233 // {{{ disconnect()
234
235 /**
236 * Disconnects from the database server
237 *
238 * @return bool TRUE on success, FALSE on failure
239 */
240 function disconnect()
241 {
242 $err = @odbc_close($this->connection);
243 $this->connection = null;
244 return $err;
245 }
246
247 // }}}
248 // {{{ simpleQuery()
249
250 /**
251 * Sends a query to the database server
252 *
253 * @param string the SQL query string
254 *
255 * @return mixed + a PHP result resrouce for successful SELECT queries
256 * + the DB_OK constant for other successful queries
257 * + a DB_Error object on failure
258 */
259 function simpleQuery($query)
260 {
261 $this->last_query = $query;
262 $query = $this->modifyQuery($query);
263 $result = @odbc_exec($this->connection, $query);
264 if (!$result) {
265 return $this->odbcRaiseError(); // XXX ERRORMSG
266 }
267 // Determine which queries that should return data, and which
268 // should return an error code only.
269 if ($this->_checkManip($query)) {
270 $this->affected = $result; // For affectedRows()
271 return DB_OK;
272 }
273 $this->affected = 0;
274 return $result;
275 }
276
277 // }}}
278 // {{{ nextResult()
279
280 /**
281 * Move the internal odbc result pointer to the next available result
282 *
283 * @param a valid fbsql result resource
284 *
285 * @access public
286 *
287 * @return true if a result is available otherwise return false
288 */
289 function nextResult($result)
290 {
291 return @odbc_next_result($result);
292 }
293
294 // }}}
295 // {{{ fetchInto()
296
297 /**
298 * Places a row from the result set into the given array
299 *
300 * Formating of the array and the data therein are configurable.
301 * See DB_result::fetchInto() for more information.
302 *
303 * This method is not meant to be called directly. Use
304 * DB_result::fetchInto() instead. It can't be declared "protected"
305 * because DB_result is a separate object.
306 *
307 * @param resource $result the query result resource
308 * @param array $arr the referenced array to put the data in
309 * @param int $fetchmode how the resulting array should be indexed
310 * @param int $rownum the row number to fetch (0 = first row)
311 *
312 * @return mixed DB_OK on success, NULL when the end of a result set is
313 * reached or on failure
314 *
315 * @see DB_result::fetchInto()
316 */
317 function fetchInto($result, &$arr, $fetchmode, $rownum = null)
318 {
319 $arr = array();
320 if ($rownum !== null) {
321 $rownum++; // ODBC first row is 1
322 if (version_compare(phpversion(), '4.2.0', 'ge')) {
323 $cols = @odbc_fetch_into($result, $arr, $rownum);
324 } else {
325 $cols = @odbc_fetch_into($result, $rownum, $arr);
326 }
327 } else {
328 $cols = @odbc_fetch_into($result, $arr);
329 }
330 if (!$cols) {
331 return null;
332 }
333 if ($fetchmode !== DB_FETCHMODE_ORDERED) {
334 for ($i = 0; $i < count($arr); $i++) {
335 $colName = @odbc_field_name($result, $i+1);
336 $a[$colName] = $arr[$i];
337 }
338 if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
339 $a = array_change_key_case($a, CASE_LOWER);
340 }
341 $arr = $a;
342 }
343 if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
344 $this->_rtrimArrayValues($arr);
345 }
346 if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
347 $this->_convertNullArrayValuesToEmpty($arr);
348 }
349 return DB_OK;
350 }
351
352 // }}}
353 // {{{ freeResult()
354
355 /**
356 * Deletes the result set and frees the memory occupied by the result set
357 *
358 * This method is not meant to be called directly. Use
359 * DB_result::free() instead. It can't be declared "protected"
360 * because DB_result is a separate object.
361 *
362 * @param resource $result PHP's query result resource
363 *
364 * @return bool TRUE on success, FALSE if $result is invalid
365 *
366 * @see DB_result::free()
367 */
368 function freeResult($result)
369 {
370 return is_resource($result) ? odbc_free_result($result) : false;
371 }
372
373 // }}}
374 // {{{ numCols()
375
376 /**
377 * Gets the number of columns in a result set
378 *
379 * This method is not meant to be called directly. Use
380 * DB_result::numCols() instead. It can't be declared "protected"
381 * because DB_result is a separate object.
382 *
383 * @param resource $result PHP's query result resource
384 *
385 * @return int the number of columns. A DB_Error object on failure.
386 *
387 * @see DB_result::numCols()
388 */
389 function numCols($result)
390 {
391 $cols = @odbc_num_fields($result);
392 if (!$cols) {
393 return $this->odbcRaiseError();
394 }
395 return $cols;
396 }
397
398 // }}}
399 // {{{ affectedRows()
400
401 /**
402 * Determines the number of rows affected by a data maniuplation query
403 *
404 * 0 is returned for queries that don't manipulate data.
405 *
406 * @return int the number of rows. A DB_Error object on failure.
407 */
408 function affectedRows()
409 {
410 if (empty($this->affected)) { // In case of SELECT stms
411 return 0;
412 }
413 $nrows = @odbc_num_rows($this->affected);
414 if ($nrows == -1) {
415 return $this->odbcRaiseError();
416 }
417 return $nrows;
418 }
419
420 // }}}
421 // {{{ numRows()
422
423 /**
424 * Gets the number of rows in a result set
425 *
426 * Not all ODBC drivers support this functionality. If they don't
427 * a DB_Error object for DB_ERROR_UNSUPPORTED is returned.
428 *
429 * This method is not meant to be called directly. Use
430 * DB_result::numRows() instead. It can't be declared "protected"
431 * because DB_result is a separate object.
432 *
433 * @param resource $result PHP's query result resource
434 *
435 * @return int the number of rows. A DB_Error object on failure.
436 *
437 * @see DB_result::numRows()
438 */
439 function numRows($result)
440 {
441 $nrows = @odbc_num_rows($result);
442 if ($nrows == -1) {
443 return $this->odbcRaiseError(DB_ERROR_UNSUPPORTED);
444 }
445 if ($nrows === false) {
446 return $this->odbcRaiseError();
447 }
448 return $nrows;
449 }
450
451 // }}}
452 // {{{ quoteIdentifier()
453
454 /**
455 * Quotes a string so it can be safely used as a table or column name
456 *
457 * Use 'mssql' as the dbsyntax in the DB DSN only if you've unchecked
458 * "Use ANSI quoted identifiers" when setting up the ODBC data source.
459 *
460 * @param string $str identifier name to be quoted
461 *
462 * @return string quoted identifier string
463 *
464 * @see DB_common::quoteIdentifier()
465 * @since Method available since Release 1.6.0
466 */
467 function quoteIdentifier($str)
468 {
469 switch ($this->dsn['dbsyntax']) {
470 case 'access':
471 return '[' . $str . ']';
472 case 'mssql':
473 case 'sybase':
474 return '[' . str_replace(']', ']]', $str) . ']';
475 case 'mysql':
476 case 'mysqli':
477 return '`' . $str . '`';
478 default:
479 return '"' . str_replace('"', '""', $str) . '"';
480 }
481 }
482
483 // }}}
484 // {{{ quote()
485
486 /**
487 * @deprecated Deprecated in release 1.6.0
488 * @internal
489 */
490 function quote($str)
491 {
492 return $this->quoteSmart($str);
493 }
494
495 // }}}
496 // {{{ nextId()
497
498 /**
499 * Returns the next free id in a sequence
500 *
501 * @param string $seq_name name of the sequence
502 * @param boolean $ondemand when true, the seqence is automatically
503 * created if it does not exist
504 *
505 * @return int the next id number in the sequence.
506 * A DB_Error object on failure.
507 *
508 * @see DB_common::nextID(), DB_common::getSequenceName(),
509 * DB_odbc::createSequence(), DB_odbc::dropSequence()
510 */
511 function nextId($seq_name, $ondemand = true)
512 {
513 $seqname = $this->getSequenceName($seq_name);
514 $repeat = 0;
515 do {
516 $this->pushErrorHandling(PEAR_ERROR_RETURN);
517 $result = $this->query("update ${seqname} set id = id + 1");
518 $this->popErrorHandling();
519 if ($ondemand && DB::isError($result) &&
520 $result->getCode() == DB_ERROR_NOSUCHTABLE) {
521 $repeat = 1;
522 $this->pushErrorHandling(PEAR_ERROR_RETURN);
523 $result = $this->createSequence($seq_name);
524 $this->popErrorHandling();
525 if (DB::isError($result)) {
526 return $this->raiseError($result);
527 }
528 $result = $this->query("insert into ${seqname} (id) values(0)");
529 } else {
530 $repeat = 0;
531 }
532 } while ($repeat);
533
534 if (DB::isError($result)) {
535 return $this->raiseError($result);
536 }
537
538 $result = $this->query("select id from ${seqname}");
539 if (DB::isError($result)) {
540 return $result;
541 }
542
543 $row = $result->fetchRow(DB_FETCHMODE_ORDERED);
544 if (DB::isError($row || !$row)) {
545 return $row;
546 }
547
548 return $row[0];
549 }
550
551 /**
552 * Creates a new sequence
553 *
554 * @param string $seq_name name of the new sequence
555 *
556 * @return int DB_OK on success. A DB_Error object on failure.
557 *
558 * @see DB_common::createSequence(), DB_common::getSequenceName(),
559 * DB_odbc::nextID(), DB_odbc::dropSequence()
560 */
561 function createSequence($seq_name)
562 {
563 return $this->query('CREATE TABLE '
564 . $this->getSequenceName($seq_name)
565 . ' (id integer NOT NULL,'
566 . ' PRIMARY KEY(id))');
567 }
568
569 // }}}
570 // {{{ dropSequence()
571
572 /**
573 * Deletes a sequence
574 *
575 * @param string $seq_name name of the sequence to be deleted
576 *
577 * @return int DB_OK on success. A DB_Error object on failure.
578 *
579 * @see DB_common::dropSequence(), DB_common::getSequenceName(),
580 * DB_odbc::nextID(), DB_odbc::createSequence()
581 */
582 function dropSequence($seq_name)
583 {
584 return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name));
585 }
586
587 // }}}
588 // {{{ autoCommit()
589
590 /**
591 * Enables or disables automatic commits
592 *
593 * @param bool $onoff true turns it on, false turns it off
594 *
595 * @return int DB_OK on success. A DB_Error object if the driver
596 * doesn't support auto-committing transactions.
597 */
598 function autoCommit($onoff = false)
599 {
600 if (!@odbc_autocommit($this->connection, $onoff)) {
601 return $this->odbcRaiseError();
602 }
603 return DB_OK;
604 }
605
606 // }}}
607 // {{{ commit()
608
609 /**
610 * Commits the current transaction
611 *
612 * @return int DB_OK on success. A DB_Error object on failure.
613 */
614 function commit()
615 {
616 if (!@odbc_commit($this->connection)) {
617 return $this->odbcRaiseError();
618 }
619 return DB_OK;
620 }
621
622 // }}}
623 // {{{ rollback()
624
625 /**
626 * Reverts the current transaction
627 *
628 * @return int DB_OK on success. A DB_Error object on failure.
629 */
630 function rollback()
631 {
632 if (!@odbc_rollback($this->connection)) {
633 return $this->odbcRaiseError();
634 }
635 return DB_OK;
636 }
637
638 // }}}
639 // {{{ odbcRaiseError()
640
641 /**
642 * Produces a DB_Error object regarding the current problem
643 *
644 * @param int $errno if the error is being manually raised pass a
645 * DB_ERROR* constant here. If this isn't passed
646 * the error information gathered from the DBMS.
647 *
648 * @return object the DB_Error object
649 *
650 * @see DB_common::raiseError(),
651 * DB_odbc::errorNative(), DB_common::errorCode()
652 */
653 function odbcRaiseError($errno = null)
654 {
655 if ($errno === null) {
656 switch ($this->dbsyntax) {
657 case 'access':
658 if ($this->options['portability'] & DB_PORTABILITY_ERRORS) {
659 $this->errorcode_map['07001'] = DB_ERROR_NOSUCHFIELD;
660 } else {
661 // Doing this in case mode changes during runtime.
662 $this->errorcode_map['07001'] = DB_ERROR_MISMATCH;
663 }
664
665 $native_code = odbc_error($this->connection);
666
667 // S1000 is for "General Error." Let's be more specific.
668 if ($native_code == 'S1000') {
669 $errormsg = odbc_errormsg($this->connection);
670 static $error_regexps;
671 if (!isset($error_regexps)) {
672 $error_regexps = array(
673 '/includes related records.$/i' => DB_ERROR_CONSTRAINT,
674 '/cannot contain a Null value/i' => DB_ERROR_CONSTRAINT_NOT_NULL,
675 );
676 }
677 foreach ($error_regexps as $regexp => $code) {
678 if (preg_match($regexp, $errormsg)) {
679 return $this->raiseError($code,
680 null, null, null,
681 $native_code . ' ' . $errormsg);
682 }
683 }
684 $errno = DB_ERROR;
685 } else {
686 $errno = $this->errorCode($native_code);
687 }
688 break;
689 default:
690 $errno = $this->errorCode(odbc_error($this->connection));
691 }
692 }
693 return $this->raiseError($errno, null, null, null,
694 $this->errorNative());
695 }
696
697 // }}}
698 // {{{ errorNative()
699
700 /**
701 * Gets the DBMS' native error code and message produced by the last query
702 *
703 * @return string the DBMS' error code and message
704 */
705 function errorNative()
706 {
707 if (!is_resource($this->connection)) {
708 return @odbc_error() . ' ' . @odbc_errormsg();
709 }
710 return @odbc_error($this->connection) . ' ' . @odbc_errormsg($this->connection);
711 }
712
713 // }}}
714 // {{{ tableInfo()
715
716 /**
717 * Returns information about a table or a result set
718 *
719 * @param object|string $result DB_result object from a query or a
720 * string containing the name of a table.
721 * While this also accepts a query result
722 * resource identifier, this behavior is
723 * deprecated.
724 * @param int $mode a valid tableInfo mode
725 *
726 * @return array an associative array with the information requested.
727 * A DB_Error object on failure.
728 *
729 * @see DB_common::tableInfo()
730 * @since Method available since Release 1.7.0
731 */
732 function tableInfo($result, $mode = null)
733 {
734 if (is_string($result)) {
735 /*
736 * Probably received a table name.
737 * Create a result resource identifier.
738 */
739 $id = @odbc_exec($this->connection, "SELECT * FROM $result");
740 if (!$id) {
741 return $this->odbcRaiseError();
742 }
743 $got_string = true;
744 } elseif (isset($result->result)) {
745 /*
746 * Probably received a result object.
747 * Extract the result resource identifier.
748 */
749 $id = $result->result;
750 $got_string = false;
751 } else {
752 /*
753 * Probably received a result resource identifier.
754 * Copy it.
755 * Deprecated. Here for compatibility only.
756 */
757 $id = $result;
758 $got_string = false;
759 }
760
761 if (!is_resource($id)) {
762 return $this->odbcRaiseError(DB_ERROR_NEED_MORE_DATA);
763 }
764
765 if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
766 $case_func = 'strtolower';
767 } else {
768 $case_func = 'strval';
769 }
770
771 $count = @odbc_num_fields($id);
772 $res = array();
773
774 if ($mode) {
775 $res['num_fields'] = $count;
776 }
777
778 for ($i = 0; $i < $count; $i++) {
779 $col = $i + 1;
780 $res[$i] = array(
781 'table' => $got_string ? $case_func($result) : '',
782 'name' => $case_func(@odbc_field_name($id, $col)),
783 'type' => @odbc_field_type($id, $col),
784 'len' => @odbc_field_len($id, $col),
785 'flags' => '',
786 );
787 if ($mode & DB_TABLEINFO_ORDER) {
788 $res['order'][$res[$i]['name']] = $i;
789 }
790 if ($mode & DB_TABLEINFO_ORDERTABLE) {
791 $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
792 }
793 }
794
795 // free the result only if we were called on a table
796 if ($got_string) {
797 @odbc_free_result($id);
798 }
799 return $res;
800 }
801
802 // }}}
803 // {{{ getSpecialQuery()
804
805 /**
806 * Obtains the query string needed for listing a given type of objects
807 *
808 * Thanks to symbol1@gmail.com and Philippe.Jausions@11abacus.com.
809 *
810 * @param string $type the kind of objects you want to retrieve
811 *
812 * @return string the list of objects requested
813 *
814 * @access protected
815 * @see DB_common::getListOf()
816 * @since Method available since Release 1.7.0
817 */
818 function getSpecialQuery($type)
819 {
820 switch ($type) {
821 case 'databases':
822 if (!function_exists('odbc_data_source')) {
823 return null;
824 }
825 $res = @odbc_data_source($this->connection, SQL_FETCH_FIRST);
826 if (is_array($res)) {
827 $out = array($res['server']);
828 while($res = @odbc_data_source($this->connection,
829 SQL_FETCH_NEXT))
830 {
831 $out[] = $res['server'];
832 }
833 return $out;
834 } else {
835 return $this->odbcRaiseError();
836 }
837 break;
838 case 'tables':
839 case 'schema.tables':
840 $keep = 'TABLE';
841 break;
842 case 'views':
843 $keep = 'VIEW';
844 break;
845 default:
846 return null;
847 }
848
849 /*
850 * Removing non-conforming items in the while loop rather than
851 * in the odbc_tables() call because some backends choke on this:
852 * odbc_tables($this->connection, '', '', '', 'TABLE')
853 */
854 $res = @odbc_tables($this->connection);
855 if (!$res) {
856 return $this->odbcRaiseError();
857 }
858 $out = array();
859 while ($row = odbc_fetch_array($res)) {
860 if ($row['TABLE_TYPE'] != $keep) {
861 continue;
862 }
863 if ($type == 'schema.tables') {
864 $out[] = $row['TABLE_SCHEM'] . '.' . $row['TABLE_NAME'];
865 } else {
866 $out[] = $row['TABLE_NAME'];
867 }
868 }
869 return $out;
870 }
871
872 // }}}
873
874 }
875
876 /*
877 * Local variables:
878 * tab-width: 4
879 * c-basic-offset: 4
880 * End:
881 */
882
883 ?>