blob: 48f7c4a9ae14b8b9c0024e99b81f67d5b646efad [file] [log] [blame]
adminb0dd10f2006-08-25 17:25:49 +00001<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
2/**
3 * Code Igniter
4 *
5 * An open source application development framework for PHP 4.3.2 or newer
6 *
7 * @package CodeIgniter
8 * @author Rick Ellis
9 * @copyright Copyright (c) 2006, pMachine, Inc.
10 * @license http://www.codeignitor.com/user_guide/license.html
11 * @link http://www.codeigniter.com
12 * @since Version 1.0
13 * @filesource
14 */
15
16// ------------------------------------------------------------------------
17
18/**
19 * Database Driver Class
20 *
21 * This is the platform-independent base DB implementation class.
22 * This class will not be called directly. Rather, the adapter
23 * class for the specific database will extend and instantiate it.
24 *
25 * @package CodeIgniter
26 * @subpackage Drivers
27 * @category Database
28 * @author Rick Ellis
admin58083462006-09-24 17:58:27 +000029 * @link http://www.codeigniter.com/user_guide/database/
adminb0dd10f2006-08-25 17:25:49 +000030 */
31class CI_DB_driver {
32
33 var $username;
34 var $password;
35 var $hostname;
36 var $database;
37 var $dbdriver = 'mysql';
38 var $dbprefix = '';
admin2ed76d52006-09-02 17:34:52 +000039 var $port = '';
adminb0dd10f2006-08-25 17:25:49 +000040 var $pconnect = FALSE;
41 var $conn_id = FALSE;
42 var $result_id = FALSE;
43 var $db_debug = FALSE;
44 var $benchmark = 0;
45 var $query_count = 0;
46 var $bind_marker = '?';
47 var $queries = array();
admin66530a82006-09-23 19:58:55 +000048 var $trans_enabled = TRUE;
49 var $_trans_depth = 0;
50 var $_trans_failure = FALSE; // Used with transactions to determine if a rollback should occur
51
admine348efb2006-09-20 21:13:26 +000052 // These are use with Oracle
53 var $stmt_id;
54 var $curs_id;
55 var $limit_used;
admin66530a82006-09-23 19:58:55 +000056
admine348efb2006-09-20 21:13:26 +000057
adminb0dd10f2006-08-25 17:25:49 +000058 /**
59 * Constructor. Accepts one parameter containing the database
60 * connection settings.
61 *
62 * Database settings can be passed as discreet
63 * parameters or as a data source name in the first
64 * parameter. DSNs must have this prototype:
65 * $dsn = 'driver://username:password@hostname/database';
66 *
67 * @param mixed. Can be an array or a DSN string
68 */
69 function CI_DB_driver($params)
70 {
71 $this->initialize($params);
72 log_message('debug', 'Database Driver Class Initialized');
73 }
74
75 // --------------------------------------------------------------------
76
77 /**
78 * Initialize Database Settings
79 *
80 * @access private Called by the constructor
81 * @param mixed
82 * @return void
83 */
84 function initialize($params = '')
85 {
86 if (is_array($params))
87 {
admin2ed76d52006-09-02 17:34:52 +000088 foreach (array('hostname' => '', 'username' => '', 'password' => '', 'database' => '', 'dbdriver' => 'mysql', 'dbprefix' => '', 'port' => '', 'pconnect' => FALSE, 'db_debug' => FALSE) as $key => $val)
adminb0dd10f2006-08-25 17:25:49 +000089 {
90 $this->$key = ( ! isset($params[$key])) ? $val : $params[$key];
91 }
92 }
93 elseif (strpos($params, '://'))
94 {
95 if (FALSE === ($dsn = @parse_url($params)))
96 {
97 log_message('error', 'Invalid DB Connection String');
98
admin57b3d392006-08-27 15:28:31 +000099 if ($this->db_debug)
adminb0dd10f2006-08-25 17:25:49 +0000100 {
101 return $this->display_error('db_invalid_connection_str');
102 }
103 return FALSE;
104 }
105
106 $this->hostname = ( ! isset($dsn['host'])) ? '' : rawurldecode($dsn['host']);
107 $this->username = ( ! isset($dsn['user'])) ? '' : rawurldecode($dsn['user']);
108 $this->password = ( ! isset($dsn['pass'])) ? '' : rawurldecode($dsn['pass']);
109 $this->database = ( ! isset($dsn['path'])) ? '' : rawurldecode(substr($dsn['path'], 1));
110 }
111
112 if ($this->pconnect == FALSE)
113 {
114 $this->conn_id = $this->db_connect();
115 }
116 else
117 {
118 $this->conn_id = $this->db_pconnect();
119 }
120
121 if ( ! $this->conn_id)
122 {
123 log_message('error', 'Unable to connect to the database');
124
125 if ($this->db_debug)
126 {
127 $this->display_error('db_unable_to_connect');
128 }
129 }
130 else
131 {
132 if ( ! $this->db_select())
133 {
134 log_message('error', 'Unable to select database: '.$this->database);
135
136 if ($this->db_debug)
137 {
138 $this->display_error('db_unable_to_select', $this->database);
139 }
140 }
141 }
142 }
143
144 // --------------------------------------------------------------------
145
146 /**
147 * Database Version Number. Returns a string containing the
148 * version of the database being used
149 *
150 * @access public
151 * @return string
152 */
153 function version()
154 {
155 if (FALSE === ($sql = $this->_version()))
156 {
157 if ($this->db_debug)
158 {
159 return $this->display_error('db_unsupported_function');
160 }
161 return FALSE;
162 }
admine348efb2006-09-20 21:13:26 +0000163
164 if ($this->dbdriver == 'oci8')
165 {
166 return $sql;
167 }
adminb0dd10f2006-08-25 17:25:49 +0000168
169 $query = $this->query($sql);
170 $row = $query->row();
171 return $row->ver;
172 }
173
174 // --------------------------------------------------------------------
175
176 /**
177 * Execute the query
178 *
179 * Accepts an SQL string as input and returns a result object upon
180 * successful execution of a "read" type query. Returns boolean TRUE
181 * upon successful execution of a "write" type query. Returns boolean
182 * FALSE upon failure, and if the $db_debug variable is set to TRUE
183 * will raise an error.
184 *
185 * @access public
186 * @param string An SQL query string
187 * @param array An array of binding data
188 * @return mixed
189 */
admine348efb2006-09-20 21:13:26 +0000190 function query($sql, $binds = FALSE, $return_object = TRUE)
adminb0dd10f2006-08-25 17:25:49 +0000191 {
adminb0dd10f2006-08-25 17:25:49 +0000192 if ($sql == '')
193 {
194 if ($this->db_debug)
195 {
196 log_message('error', 'Invalid query: '.$sql);
197 return $this->display_error('db_invalid_query');
198 }
199 return FALSE;
200 }
201
202 // Compile binds if needed
203 if ($binds !== FALSE)
204 {
205 $sql = $this->compile_binds($sql, $binds);
206 }
207
adminb0dd10f2006-08-25 17:25:49 +0000208 // Save the query for debugging
209 $this->queries[] = $sql;
admin66530a82006-09-23 19:58:55 +0000210
211 // Start the Query Timer
212 $time_start = list($sm, $ss) = explode(' ', microtime());
213
adminb0dd10f2006-08-25 17:25:49 +0000214 // Run the Query
admin66530a82006-09-23 19:58:55 +0000215 if (FALSE === ($this->result_id = $this->simple_query($sql)))
adminb0dd10f2006-08-25 17:25:49 +0000216 {
admin66530a82006-09-23 19:58:55 +0000217 // This will trigger a rollback if transactions are being used
218 $this->_trans_failure = TRUE;
219
adminb0dd10f2006-08-25 17:25:49 +0000220 if ($this->db_debug)
221 {
222 log_message('error', 'Query error: '.$this->error_message());
223 return $this->display_error(
224 array(
225 'Error Number: '.$this->error_number(),
226 $this->error_message(),
227 $sql
228 )
229 );
230 }
231
232 return FALSE;
233 }
234
235 // Stop and aggregate the query time results
236 $time_end = list($em, $es) = explode(' ', microtime());
237 $this->benchmark += ($em + $es) - ($sm + $ss);
238
239 // Increment the query counter
240 $this->query_count++;
241
242 // Was the query a "write" type?
admine348efb2006-09-20 21:13:26 +0000243 // If so we'll simply return true
adminb0dd10f2006-08-25 17:25:49 +0000244 if ($this->is_write_type($sql) === TRUE)
245 {
246 return TRUE;
247 }
admine348efb2006-09-20 21:13:26 +0000248
249 // Return TRUE if we don't need to create a result object
250 // Currently only the Oracle driver uses this when stored
251 // procedures are used
252 if ($return_object !== TRUE)
253 {
254 return TRUE;
255 }
adminb0dd10f2006-08-25 17:25:49 +0000256
257 // Instantiate and return the DB result object
258 $result = 'CI_DB_'.$this->dbdriver.'_result';
259
260 $RES = new $result();
261 $RES->conn_id = $this->conn_id;
262 $RES->db_debug = $this->db_debug;
263 $RES->result_id = $this->result_id;
admine348efb2006-09-20 21:13:26 +0000264
265 if ($this->dbdriver == 'oci8')
266 {
267 $RES->stmt_id = $this->stmt_id;
268 $RES->curs_id = NULL;
269 $RES->limit_used = $this->limit_used;
270 }
adminb0dd10f2006-08-25 17:25:49 +0000271
272 return $RES;
273 }
274
275 // --------------------------------------------------------------------
276
277 /**
admin66530a82006-09-23 19:58:55 +0000278 * Simple Query
279 * This is a simiplified version of the query() function. Internally
280 * we only use it when running transaction commands since they do
281 * not require all the features of the main query() function.
282 *
283 * @access public
284 * @param string the sql query
285 * @return mixed
286 */
287 function simple_query($sql)
288 {
289 if ( ! $this->conn_id)
290 {
291 $this->initialize();
292 }
293
294 return $this->_execute($sql, $this->conn_id);
295 }
296
297 // --------------------------------------------------------------------
298
299 /**
300 * Disable Transactions
301 * This permits transactions to be disabled at run-time.
302 *
303 * @access public
304 * @return void
305 */
306 function trans_off()
307 {
308 $this->trans_enabled = FALSE;
309 }
310
311 // --------------------------------------------------------------------
312
313 /**
314 * Start Transaction
315 *
316 * @access public
317 * @return void
318 */
admin8b180be2006-09-24 01:12:22 +0000319 function trans_start($test_mode = FALSE)
admin66530a82006-09-23 19:58:55 +0000320 {
321 if ( ! $this->trans_enabled)
322 {
323 return FALSE;
324 }
325
326 // When transactions are nested we only begin/commit/rollback the outermost ones
327 if ($this->_trans_depth > 0)
328 {
329 $this->_trans_depth += 1;
330 return;
331 }
332
admin8b180be2006-09-24 01:12:22 +0000333 $this->trans_begin($test_mode);
admin66530a82006-09-23 19:58:55 +0000334 }
335
336 // --------------------------------------------------------------------
337
338 /**
339 * Complete Transaction
340 *
341 * @access public
342 * @return bool
343 */
344 function trans_complete()
345 {
346 if ( ! $this->trans_enabled)
347 {
348 return FALSE;
349 }
350
351 // When transactions are nested we only begin/commit/rollback the outermost ones
352 if ($this->_trans_depth > 1)
353 {
354 $this->_trans_depth -= 1;
355 return TRUE;
356 }
357
358 // The query() function will set this flag to TRUE in the event that a query failed
359 if ($this->_trans_failure === TRUE)
360 {
361 $this->trans_rollback();
362
363 if ($this->db_debug)
364 {
365 return $this->display_error('db_transaction_failure');
366 }
367 return FALSE;
368 }
369
370 $this->trans_commit();
371 return TRUE;
372 }
373
374 // --------------------------------------------------------------------
375
376 /**
admin8b180be2006-09-24 01:12:22 +0000377 * Lets you retrieve the transaction flag to determine if it has failed
378 *
379 * @access public
380 * @return bool
381 */
382 function trans_status()
383 {
384 return $this->_trans_failure;
385 }
386
387
388 // --------------------------------------------------------------------
389
390 /**
adminb0dd10f2006-08-25 17:25:49 +0000391 * Enables a native PHP function to be run, using a platform agnostic wrapper.
392 *
393 * @access public
394 * @param string the function name
395 * @param mixed any parameters needed by the function
396 * @return mixed
397 */
398 function call_function($function)
399 {
400 $driver = ($this->dbdriver == 'postgre') ? 'pg_' : $this->dbdriver.'_';
401
402 if (FALSE === strpos($driver, $function))
403 {
404 $function = $driver.$function;
405 }
406
407 if ( ! function_exists($function))
408 {
admin57b3d392006-08-27 15:28:31 +0000409 if ($this->db_debug)
adminb0dd10f2006-08-25 17:25:49 +0000410 {
411 return $this->display_error('db_unsupported_function');
412 }
413 return FALSE;
414 }
415 else
416 {
417 $args = (func_num_args() > 1) ? array_shift(func_get_args()) : null;
418
419 return call_user_func_array($function, $args);
420 }
421 }
422
423 // --------------------------------------------------------------------
424
425 /**
426 * Determines if a query is a "write" type.
427 *
428 * @access public
429 * @param string An SQL query string
430 * @return boolean
431 */
432 function is_write_type($sql)
433 {
434 if ( ! preg_match('/^\s*"?(INSERT|UPDATE|DELETE|REPLACE|CREATE|DROP|LOAD DATA|COPY|ALTER|GRANT|REVOKE|LOCK|UNLOCK)\s+/i', $sql))
435 {
436 return FALSE;
437 }
438 return TRUE;
439 }
440
441 // --------------------------------------------------------------------
442
443 /**
444 * Calculate the aggregate query elapsed time
445 *
446 * @access public
447 * @param intiger The number of decimal places
448 * @return integer
449 */
450 function elapsed_time($decimals = 6)
451 {
452 return number_format($this->benchmark, $decimals);
453 }
454
455 // --------------------------------------------------------------------
456
457 /**
458 * Returns the total number of queries
459 *
460 * @access public
461 * @return integer
462 */
463 function total_queries()
464 {
465 return $this->query_count;
466 }
467
468 // --------------------------------------------------------------------
469
470 /**
471 * Returns the last query that was executed
472 *
473 * @access public
474 * @return void
475 */
476 function last_query()
477 {
478 return end($this->queries);
479 }
480
481 // --------------------------------------------------------------------
482
483 /**
484 * "Smart" Escape String
485 *
486 * Escapes data based on type
487 * Sets boolean and null types
488 *
489 * @access public
490 * @param string
491 * @return integer
492 */
493 function escape($str)
494 {
admine348efb2006-09-20 21:13:26 +0000495 switch (gettype($str))
adminb0dd10f2006-08-25 17:25:49 +0000496 {
admine348efb2006-09-20 21:13:26 +0000497 case 'string' : $str = "'".$this->escape_str($str)."'";
498 break;
499 case 'boolean' : $str = ($str === FALSE) ? 0 : 1;
500 break;
501 default : $str = ($str === NULL) ? 'NULL' : $str;
502 break;
503 }
504
adminb0dd10f2006-08-25 17:25:49 +0000505 return $str;
506 }
507
508 // --------------------------------------------------------------------
509
510 /**
511 * Returns an array of table names
512 *
513 * @access public
514 * @return array
515 */
516 function tables()
517 {
518 if (FALSE === ($sql = $this->_show_tables()))
519 {
520 if ($this->db_debug)
521 {
522 return $this->display_error('db_unsupported_function');
523 }
524 return FALSE;
525 }
526
527 $retval = array();
528 $query = $this->query($sql);
529
530 if ($query->num_rows() > 0)
531 {
532 foreach($query->result_array() as $row)
533 {
admine348efb2006-09-20 21:13:26 +0000534 if (isset($row['TABLE_NAME']))
535 {
536 $retval[] = $row['TABLE_NAME'];
537 }
538 else
539 {
540 $retval[] = array_shift($row);
541 }
adminb0dd10f2006-08-25 17:25:49 +0000542 }
543 }
544
545 return $retval;
546 }
547
548 // --------------------------------------------------------------------
549
550 /**
551 * Determine if a particular table exists
552 * @access public
553 * @return boolean
554 */
555 function table_exists($table_name)
556 {
557 return ( ! in_array($this->dbprefix.$table_name, $this->tables())) ? FALSE : TRUE;
558 }
559
560 // --------------------------------------------------------------------
561
562 /**
563 * Fetch MySQL Field Names
564 *
565 * @access public
566 * @param string the table name
567 * @return array
568 */
569 function field_names($table = '')
570 {
571 if ($table == '')
572 {
admin57b3d392006-08-27 15:28:31 +0000573 if ($this->db_debug)
adminb0dd10f2006-08-25 17:25:49 +0000574 {
575 return $this->display_error('db_field_param_missing');
576 }
577 return FALSE;
578 }
579
580 if (FALSE === ($sql = $this->_show_columns($this->dbprefix.$table)))
581 {
582 if ($this->db_debug)
583 {
584 return $this->display_error('db_unsupported_function');
585 }
586 return FALSE;
587 }
588
589 $query = $this->query($sql);
590
591 $retval = array();
592 foreach($query->result_array() as $row)
593 {
admine348efb2006-09-20 21:13:26 +0000594 if (isset($row['COLUMN_NAME']))
adminb0dd10f2006-08-25 17:25:49 +0000595 {
596 $retval[] = $row['COLUMN_NAME'];
597 }
598 else
599 {
600 $retval[] = current($row);
601 }
602 }
603
604 return $retval;
605 }
606
607 // --------------------------------------------------------------------
608
609 /**
610 * Returns an object with field data
611 *
612 * @access public
613 * @param string the table name
614 * @return object
615 */
616 function field_data($table = '')
617 {
618 if ($table == '')
619 {
admin57b3d392006-08-27 15:28:31 +0000620 if ($this->db_debug)
adminb0dd10f2006-08-25 17:25:49 +0000621 {
622 return $this->display_error('db_field_param_missing');
623 }
624 return FALSE;
625 }
626
627 return $this->_field_data($this->dbprefix.$table);
admin58083462006-09-24 17:58:27 +0000628 }
adminb0dd10f2006-08-25 17:25:49 +0000629
630 // --------------------------------------------------------------------
631
632 /**
633 * Primary
634 *
635 * Retrieves the primary key. It assumes that the row in the first
636 * position is the primary key
637 *
638 * @access public
639 * @param string the table name
640 * @return string
641 */
642 function primary($table = '')
643 {
644 $fields = $this->field_names($table);
645
646 if ( ! is_array($fields))
647 {
648 return FALSE;
649 }
650
651 return current($fields);
652 }
653
654 // --------------------------------------------------------------------
655
656 /**
657 * Compile Bindings
658 *
659 * @access public
660 * @param string the sql statement
661 * @param array an array of bind data
662 * @return string
663 */
664 function compile_binds($sql, $binds)
665 {
666 if (FALSE === strpos($sql, $this->bind_marker))
667 {
668 return $sql;
669 }
670
671 if ( ! is_array($binds))
672 {
673 $binds = array($binds);
674 }
675
676 foreach ($binds as $val)
677 {
678 $val = $this->escape($val);
679
680 // Just in case the replacement string contains the bind
681 // character we'll temporarily replace it with a marker
682 $val = str_replace($this->bind_marker, '{%bind_marker%}', $val);
admin57b3d392006-08-27 15:28:31 +0000683 $sql = preg_replace("#".preg_quote($this->bind_marker, '#')."#", str_replace('$', '\$', $val), $sql, 1);
adminb0dd10f2006-08-25 17:25:49 +0000684 }
685
686 return str_replace('{%bind_marker%}', $this->bind_marker, $sql);
687 }
688
689 // --------------------------------------------------------------------
690
691 /**
692 * Generate an insert string
693 *
694 * @access public
695 * @param string the table upon which the query will be performed
696 * @param array an associative array data of key/values
697 * @return string
698 */
699 function insert_string($table, $data)
700 {
701 $fields = array();
702 $values = array();
703
704 foreach($data as $key => $val)
705 {
706 $fields[] = $key;
707 $values[] = $this->escape($val);
708 }
709
710 return $this->_insert($this->dbprefix.$table, $fields, $values);
711 }
712
713 // --------------------------------------------------------------------
714
715 /**
716 * Generate an update string
717 *
718 * @access public
719 * @param string the table upon which the query will be performed
720 * @param array an associative array data of key/values
721 * @param mixed the "where" statement
722 * @return string
723 */
724 function update_string($table, $data, $where)
725 {
726 if ($where == '')
727 return false;
728
729 $fields = array();
730 foreach($data as $key => $val)
731 {
732 $fields[$key] = $this->escape($val);
733 }
734
735 if ( ! is_array($where))
736 {
737 $dest = array($where);
738 }
739 else
740 {
741 $dest = array();
742 foreach ($where as $key => $val)
743 {
744 $prefix = (count($dest) == 0) ? '' : ' AND ';
745
746 if ($val != '')
747 {
748 if ( ! $this->_has_operator($key))
749 {
750 $key .= ' =';
751 }
752
753 $val = ' '.$this->escape($val);
754 }
755
756 $dest[] = $prefix.$key.$val;
757 }
758 }
759
760 return $this->_update($this->dbprefix.$table, $fields, $dest);
761 }
762
763 // --------------------------------------------------------------------
764
765 /**
766 * Close DB Connection
767 *
768 * @access public
769 * @return void
770 */
771 function close()
772 {
773 if (is_resource($this->conn_id))
774 {
775 $this->destroy($this->conn_id);
776 }
777 $this->conn_id = FALSE;
778 }
779
780 // --------------------------------------------------------------------
781
782 /**
783 * Display an error message
784 *
785 * @access public
786 * @param string the error message
787 * @param string any "swap" values
788 * @param boolean whether to localize the message
789 * @return string sends the application/errror_db.php template
790 */
791 function display_error($error = '', $swap = '', $native = FALSE)
792 {
793 $LANG = new CI_Language();
794 $LANG->load('db');
795
796 $heading = 'MySQL Error';
797
798 if ($native == TRUE)
799 {
800 $message = $error;
801 }
802 else
803 {
804 $message = ( ! is_array($error)) ? array(str_replace('%s', $swap, $LANG->line($error))) : $error;
805 }
806
807 if ( ! class_exists('CI_Exceptions'))
808 {
admin58083462006-09-24 17:58:27 +0000809 include_once(BASEPATH.'libraries/Exceptions'.EXT);
adminb0dd10f2006-08-25 17:25:49 +0000810 }
811
812 $error = new CI_Exceptions();
813 echo $error->show_error('An Error Was Encountered', $message, 'error_db');
814 exit;
815
816 }
817
adminb0dd10f2006-08-25 17:25:49 +0000818}
819
820
821/**
822 * Database Result Class
823 *
824 * This is the platform-independent result class.
825 * This class will not be called directly. Rather, the adapter
826 * class for the specific database will extend and instantiate it.
827 *
828 * @category Database
829 * @author Rick Ellis
admin58083462006-09-24 17:58:27 +0000830 * @link http://www.codeigniter.com/user_guide/database/
adminb0dd10f2006-08-25 17:25:49 +0000831 */
832class CI_DB_result {
833
834 var $conn_id = FALSE;
835 var $result_id = FALSE;
836 var $db_debug = FALSE;
837 var $result_array = array();
838 var $result_object = array();
839 var $current_row = 0;
840
841 /**
842 * Query result. Acts as a wrapper function for the following functions.
843 *
844 * @access public
845 * @param string can be "object" or "array"
846 * @return mixed either a result object or array
847 */
848 function result($type = 'object')
849 {
850 return ($type == 'object') ? $this->result_object() : $this->result_array();
851 }
852
853 // --------------------------------------------------------------------
854
855 /**
856 * Query result. "object" version.
857 *
858 * @access public
859 * @return object
860 */
861 function result_object()
862 {
863 if (count($this->result_object) > 0)
864 {
865 return $this->result_object;
866 }
867
868 while ($row = $this->_fetch_object())
869 {
870 $this->result_object[] = $row;
871 }
872
873 if (count($this->result_object) == 0)
874 {
875 return FALSE;
876 }
877
878 return $this->result_object;
879 }
880
881 // --------------------------------------------------------------------
882
883 /**
884 * Query result. "array" version.
885 *
886 * @access public
887 * @return array
888 */
889 function result_array()
890 {
891 if (count($this->result_array) > 0)
892 {
893 return $this->result_array;
894 }
895
896 while ($row = $this->_fetch_assoc())
897 {
898 $this->result_array[] = $row;
899 }
900
901 if (count($this->result_array) == 0)
902 {
903 return FALSE;
904 }
905
906 return $this->result_array;
907 }
908
909 // --------------------------------------------------------------------
910
911 /**
912 * Query result. Acts as a wrapper function for the following functions.
913 *
914 * @access public
915 * @param string can be "object" or "array"
916 * @return mixed either a result object or array
917 */
918 function row($n = 0, $type = 'object')
919 {
920 return ($type == 'object') ? $this->row_object($n) : $this->row_array($n);
921 }
922
923 // --------------------------------------------------------------------
924
925 /**
926 * Returns a single result row - object version
927 *
928 * @access public
929 * @return object
930 */
931 function row_object($n = 0)
932 {
933 if (FALSE === ($result = $this->result_object()))
934 {
935 return FALSE;
936 }
937
938 if ($n != $this->current_row AND isset($result[$n]))
939 {
940 $this->current_row = $n;
941 }
942
943 return $result[$this->current_row];
944 }
945
946 // --------------------------------------------------------------------
947
948 /**
949 * Returns a single result row - array version
950 *
951 * @access public
952 * @return array
953 */
954 function row_array($n = 0)
955 {
956 if (FALSE === ($result = $this->result_array()))
957 {
958 return FALSE;
959 }
960
961 if ($n != $this->current_row AND isset($result[$n]))
962 {
963 $this->current_row = $n;
964 }
965
966 return $result[$this->current_row];
967 }
968
969 // --------------------------------------------------------------------
970
971 /**
972 * Returns the "next" row
973 *
974 * @access public
975 * @return object
976 */
977 function next_row($type = 'object')
978 {
979 if (FALSE === ($result = $this->result($type)))
980 {
981 return FALSE;
982 }
983
984 if (isset($result[$this->current_row + 1]))
985 {
986 ++$this->current_row;
987 }
988
989 return $result[$this->current_row];
990 }
991
992 // --------------------------------------------------------------------
993
994 /**
995 * Returns the "previous" row
996 *
997 * @access public
998 * @return object
999 */
1000 function previous_row($type = 'object')
1001 {
1002 if (FALSE === ($result = $this->result($type)))
1003 {
1004 return FALSE;
1005 }
1006
1007 if (isset($result[$this->current_row - 1]))
1008 {
1009 --$this->current_row;
1010 }
1011 return $result[$this->current_row];
1012 }
1013
1014 // --------------------------------------------------------------------
1015
1016 /**
1017 * Returns the "first" row
1018 *
1019 * @access public
1020 * @return object
1021 */
1022 function first_row($type = 'object')
1023 {
1024 if (FALSE === ($result = $this->result($type)))
1025 {
1026 return FALSE;
1027 }
1028 return $result[0];
1029 }
1030
1031 // --------------------------------------------------------------------
1032
1033 /**
1034 * Returns the "last" row
1035 *
1036 * @access public
1037 * @return object
1038 */
1039 function last_row($type = 'object')
1040 {
1041 if (FALSE === ($result = $this->result($type)))
1042 {
1043 return FALSE;
1044 }
1045 return $result[count($result) -1];
1046 }
1047
1048}
1049
adminb0dd10f2006-08-25 17:25:49 +00001050?>