/lenasys/trunk

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/lenasys/trunk

« back to all changes in this revision

Viewing changes to codeigniter/system/database/DB_driver.php

  • Committer: Gustav Hatvigsson
  • Date: 2013-05-30 12:02:31 UTC
  • mfrom: (85.1.28 lenasys)
  • Revision ID: gustav.hartvigsson@gmail.com-20130530120231-ttqgqjqw2w8enn7g
Merged Ohlsons changes:
added function to get ssn and name for the registrationspages in the user model.
added the registrationpage for students.
edited the registration page for instructors
edited the css for both the registrationpages
minor fix to registration css

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
 
2
/**
 
3
 * CodeIgniter
 
4
 *
 
5
 * An open source application development framework for PHP 5.1.6 or newer
 
6
 *
 
7
 * @package             CodeIgniter
 
8
 * @author              ExpressionEngine Dev Team
 
9
 * @copyright   Copyright (c) 2008 - 2011, EllisLab, Inc.
 
10
 * @license             http://codeigniter.com/user_guide/license.html
 
11
 * @link                http://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              ExpressionEngine Dev Team
 
29
 * @link                http://codeigniter.com/user_guide/database/
 
30
 */
 
31
class CI_DB_driver {
 
32
 
 
33
        var $username;
 
34
        var $password;
 
35
        var $hostname;
 
36
        var $database;
 
37
        var $dbdriver           = 'mysql';
 
38
        var $dbprefix           = '';
 
39
        var $char_set           = 'utf8';
 
40
        var $dbcollat           = 'utf8_general_ci';
 
41
        var $autoinit           = TRUE; // Whether to automatically initialize the DB
 
42
        var $swap_pre           = '';
 
43
        var $port                       = '';
 
44
        var $pconnect           = FALSE;
 
45
        var $conn_id            = FALSE;
 
46
        var $result_id          = FALSE;
 
47
        var $db_debug           = FALSE;
 
48
        var $benchmark          = 0;
 
49
        var $query_count        = 0;
 
50
        var $bind_marker        = '?';
 
51
        var $save_queries       = TRUE;
 
52
        var $queries            = array();
 
53
        var $query_times        = array();
 
54
        var $data_cache         = array();
 
55
        var $trans_enabled      = TRUE;
 
56
        var $trans_strict       = TRUE;
 
57
        var $_trans_depth       = 0;
 
58
        var $_trans_status      = TRUE; // Used with transactions to determine if a rollback should occur
 
59
        var $cache_on           = FALSE;
 
60
        var $cachedir           = '';
 
61
        var $cache_autodel      = FALSE;
 
62
        var $CACHE; // The cache class object
 
63
 
 
64
        // Private variables
 
65
        var $_protect_identifiers       = TRUE;
 
66
        var $_reserved_identifiers      = array('*'); // Identifiers that should NOT be escaped
 
67
 
 
68
        // These are use with Oracle
 
69
        var $stmt_id;
 
70
        var $curs_id;
 
71
        var $limit_used;
 
72
 
 
73
 
 
74
 
 
75
        /**
 
76
         * Constructor.  Accepts one parameter containing the database
 
77
         * connection settings.
 
78
         *
 
79
         * @param array
 
80
         */
 
81
        function __construct($params)
 
82
        {
 
83
                if (is_array($params))
 
84
                {
 
85
                        foreach ($params as $key => $val)
 
86
                        {
 
87
                                $this->$key = $val;
 
88
                        }
 
89
                }
 
90
 
 
91
                log_message('debug', 'Database Driver Class Initialized');
 
92
        }
 
93
 
 
94
        // --------------------------------------------------------------------
 
95
 
 
96
        /**
 
97
         * Initialize Database Settings
 
98
         *
 
99
         * @access      private Called by the constructor
 
100
         * @param       mixed
 
101
         * @return      void
 
102
         */
 
103
        function initialize()
 
104
        {
 
105
                // If an existing connection resource is available
 
106
                // there is no need to connect and select the database
 
107
                if (is_resource($this->conn_id) OR is_object($this->conn_id))
 
108
                {
 
109
                        return TRUE;
 
110
                }
 
111
 
 
112
                // ----------------------------------------------------------------
 
113
 
 
114
                // Connect to the database and set the connection ID
 
115
                $this->conn_id = ($this->pconnect == FALSE) ? $this->db_connect() : $this->db_pconnect();
 
116
 
 
117
                // No connection resource?  Throw an error
 
118
                if ( ! $this->conn_id)
 
119
                {
 
120
                        log_message('error', 'Unable to connect to the database');
 
121
 
 
122
                        if ($this->db_debug)
 
123
                        {
 
124
                                $this->display_error('db_unable_to_connect');
 
125
                        }
 
126
                        return FALSE;
 
127
                }
 
128
 
 
129
                // ----------------------------------------------------------------
 
130
 
 
131
                // Select the DB... assuming a database name is specified in the config file
 
132
                if ($this->database != '')
 
133
                {
 
134
                        if ( ! $this->db_select())
 
135
                        {
 
136
                                log_message('error', 'Unable to select database: '.$this->database);
 
137
 
 
138
                                if ($this->db_debug)
 
139
                                {
 
140
                                        $this->display_error('db_unable_to_select', $this->database);
 
141
                                }
 
142
                                return FALSE;
 
143
                        }
 
144
                        else
 
145
                        {
 
146
                                // We've selected the DB. Now we set the character set
 
147
                                if ( ! $this->db_set_charset($this->char_set, $this->dbcollat))
 
148
                                {
 
149
                                        return FALSE;
 
150
                                }
 
151
 
 
152
                                return TRUE;
 
153
                        }
 
154
                }
 
155
 
 
156
                return TRUE;
 
157
        }
 
158
 
 
159
        // --------------------------------------------------------------------
 
160
 
 
161
        /**
 
162
         * Set client character set
 
163
         *
 
164
         * @access      public
 
165
         * @param       string
 
166
         * @param       string
 
167
         * @return      resource
 
168
         */
 
169
        function db_set_charset($charset, $collation)
 
170
        {
 
171
                if ( ! $this->_db_set_charset($this->char_set, $this->dbcollat))
 
172
                {
 
173
                        log_message('error', 'Unable to set database connection charset: '.$this->char_set);
 
174
 
 
175
                        if ($this->db_debug)
 
176
                        {
 
177
                                $this->display_error('db_unable_to_set_charset', $this->char_set);
 
178
                        }
 
179
 
 
180
                        return FALSE;
 
181
                }
 
182
 
 
183
                return TRUE;
 
184
        }
 
185
 
 
186
        // --------------------------------------------------------------------
 
187
 
 
188
        /**
 
189
         * The name of the platform in use (mysql, mssql, etc...)
 
190
         *
 
191
         * @access      public
 
192
         * @return      string
 
193
         */
 
194
        function platform()
 
195
        {
 
196
                return $this->dbdriver;
 
197
        }
 
198
 
 
199
        // --------------------------------------------------------------------
 
200
 
 
201
        /**
 
202
         * Database Version Number.  Returns a string containing the
 
203
         * version of the database being used
 
204
         *
 
205
         * @access      public
 
206
         * @return      string
 
207
         */
 
208
        function version()
 
209
        {
 
210
                if (FALSE === ($sql = $this->_version()))
 
211
                {
 
212
                        if ($this->db_debug)
 
213
                        {
 
214
                                return $this->display_error('db_unsupported_function');
 
215
                        }
 
216
                        return FALSE;
 
217
                }
 
218
 
 
219
                // Some DBs have functions that return the version, and don't run special
 
220
                // SQL queries per se. In these instances, just return the result.
 
221
                $driver_version_exceptions = array('oci8', 'sqlite', 'cubrid');
 
222
 
 
223
                if (in_array($this->dbdriver, $driver_version_exceptions))
 
224
                {
 
225
                        return $sql;
 
226
                }
 
227
                else
 
228
                {
 
229
                        $query = $this->query($sql);
 
230
                        return $query->row('ver');
 
231
                }
 
232
        }
 
233
 
 
234
        // --------------------------------------------------------------------
 
235
 
 
236
        /**
 
237
         * Execute the query
 
238
         *
 
239
         * Accepts an SQL string as input and returns a result object upon
 
240
         * successful execution of a "read" type query.  Returns boolean TRUE
 
241
         * upon successful execution of a "write" type query. Returns boolean
 
242
         * FALSE upon failure, and if the $db_debug variable is set to TRUE
 
243
         * will raise an error.
 
244
         *
 
245
         * @access      public
 
246
         * @param       string  An SQL query string
 
247
         * @param       array   An array of binding data
 
248
         * @return      mixed
 
249
         */
 
250
        function query($sql, $binds = FALSE, $return_object = TRUE)
 
251
        {
 
252
                if ($sql == '')
 
253
                {
 
254
                        if ($this->db_debug)
 
255
                        {
 
256
                                log_message('error', 'Invalid query: '.$sql);
 
257
                                return $this->display_error('db_invalid_query');
 
258
                        }
 
259
                        return FALSE;
 
260
                }
 
261
 
 
262
                // Verify table prefix and replace if necessary
 
263
                if ( ($this->dbprefix != '' AND $this->swap_pre != '') AND ($this->dbprefix != $this->swap_pre) )
 
264
                {
 
265
                        $sql = preg_replace("/(\W)".$this->swap_pre."(\S+?)/", "\\1".$this->dbprefix."\\2", $sql);
 
266
                }
 
267
 
 
268
                // Compile binds if needed
 
269
                if ($binds !== FALSE)
 
270
                {
 
271
                        $sql = $this->compile_binds($sql, $binds);
 
272
                }
 
273
 
 
274
                // Is query caching enabled?  If the query is a "read type"
 
275
                // we will load the caching class and return the previously
 
276
                // cached query if it exists
 
277
                if ($this->cache_on == TRUE AND stristr($sql, 'SELECT'))
 
278
                {
 
279
                        if ($this->_cache_init())
 
280
                        {
 
281
                                $this->load_rdriver();
 
282
                                if (FALSE !== ($cache = $this->CACHE->read($sql)))
 
283
                                {
 
284
                                        return $cache;
 
285
                                }
 
286
                        }
 
287
                }
 
288
 
 
289
                // Save the  query for debugging
 
290
                if ($this->save_queries == TRUE)
 
291
                {
 
292
                        $this->queries[] = $sql;
 
293
                }
 
294
 
 
295
                // Start the Query Timer
 
296
                $time_start = list($sm, $ss) = explode(' ', microtime());
 
297
 
 
298
                // Run the Query
 
299
                if (FALSE === ($this->result_id = $this->simple_query($sql)))
 
300
                {
 
301
                        if ($this->save_queries == TRUE)
 
302
                        {
 
303
                                $this->query_times[] = 0;
 
304
                        }
 
305
 
 
306
                        // This will trigger a rollback if transactions are being used
 
307
                        $this->_trans_status = FALSE;
 
308
 
 
309
                        if ($this->db_debug)
 
310
                        {
 
311
                                // grab the error number and message now, as we might run some
 
312
                                // additional queries before displaying the error
 
313
                                $error_no = $this->_error_number();
 
314
                                $error_msg = $this->_error_message();
 
315
 
 
316
                                // We call this function in order to roll-back queries
 
317
                                // if transactions are enabled.  If we don't call this here
 
318
                                // the error message will trigger an exit, causing the
 
319
                                // transactions to remain in limbo.
 
320
                                $this->trans_complete();
 
321
 
 
322
                                // Log and display errors
 
323
                                log_message('error', 'Query error: '.$error_msg);
 
324
                                return $this->display_error(
 
325
                                                                                array(
 
326
                                                                                                'Error Number: '.$error_no,
 
327
                                                                                                $error_msg,
 
328
                                                                                                $sql
 
329
                                                                                        )
 
330
                                                                                );
 
331
                        }
 
332
 
 
333
                        return FALSE;
 
334
                }
 
335
 
 
336
                // Stop and aggregate the query time results
 
337
                $time_end = list($em, $es) = explode(' ', microtime());
 
338
                $this->benchmark += ($em + $es) - ($sm + $ss);
 
339
 
 
340
                if ($this->save_queries == TRUE)
 
341
                {
 
342
                        $this->query_times[] = ($em + $es) - ($sm + $ss);
 
343
                }
 
344
 
 
345
                // Increment the query counter
 
346
                $this->query_count++;
 
347
 
 
348
                // Was the query a "write" type?
 
349
                // If so we'll simply return true
 
350
                if ($this->is_write_type($sql) === TRUE)
 
351
                {
 
352
                        // If caching is enabled we'll auto-cleanup any
 
353
                        // existing files related to this particular URI
 
354
                        if ($this->cache_on == TRUE AND $this->cache_autodel == TRUE AND $this->_cache_init())
 
355
                        {
 
356
                                $this->CACHE->delete();
 
357
                        }
 
358
 
 
359
                        return TRUE;
 
360
                }
 
361
 
 
362
                // Return TRUE if we don't need to create a result object
 
363
                // Currently only the Oracle driver uses this when stored
 
364
                // procedures are used
 
365
                if ($return_object !== TRUE)
 
366
                {
 
367
                        return TRUE;
 
368
                }
 
369
 
 
370
                // Load and instantiate the result driver
 
371
 
 
372
                $driver                 = $this->load_rdriver();
 
373
                $RES                    = new $driver();
 
374
                $RES->conn_id   = $this->conn_id;
 
375
                $RES->result_id = $this->result_id;
 
376
 
 
377
                if ($this->dbdriver == 'oci8')
 
378
                {
 
379
                        $RES->stmt_id           = $this->stmt_id;
 
380
                        $RES->curs_id           = NULL;
 
381
                        $RES->limit_used        = $this->limit_used;
 
382
                        $this->stmt_id          = FALSE;
 
383
                }
 
384
 
 
385
                // oci8 vars must be set before calling this
 
386
                $RES->num_rows  = $RES->num_rows();
 
387
 
 
388
                // Is query caching enabled?  If so, we'll serialize the
 
389
                // result object and save it to a cache file.
 
390
                if ($this->cache_on == TRUE AND $this->_cache_init())
 
391
                {
 
392
                        // We'll create a new instance of the result object
 
393
                        // only without the platform specific driver since
 
394
                        // we can't use it with cached data (the query result
 
395
                        // resource ID won't be any good once we've cached the
 
396
                        // result object, so we'll have to compile the data
 
397
                        // and save it)
 
398
                        $CR = new CI_DB_result();
 
399
                        $CR->num_rows           = $RES->num_rows();
 
400
                        $CR->result_object      = $RES->result_object();
 
401
                        $CR->result_array       = $RES->result_array();
 
402
 
 
403
                        // Reset these since cached objects can not utilize resource IDs.
 
404
                        $CR->conn_id            = NULL;
 
405
                        $CR->result_id          = NULL;
 
406
 
 
407
                        $this->CACHE->write($sql, $CR);
 
408
                }
 
409
 
 
410
                return $RES;
 
411
        }
 
412
 
 
413
        // --------------------------------------------------------------------
 
414
 
 
415
        /**
 
416
         * Load the result drivers
 
417
         *
 
418
         * @access      public
 
419
         * @return      string  the name of the result class
 
420
         */
 
421
        function load_rdriver()
 
422
        {
 
423
                $driver = 'CI_DB_'.$this->dbdriver.'_result';
 
424
 
 
425
                if ( ! class_exists($driver))
 
426
                {
 
427
                        include_once(BASEPATH.'database/DB_result.php');
 
428
                        include_once(BASEPATH.'database/drivers/'.$this->dbdriver.'/'.$this->dbdriver.'_result.php');
 
429
                }
 
430
 
 
431
                return $driver;
 
432
        }
 
433
 
 
434
        // --------------------------------------------------------------------
 
435
 
 
436
        /**
 
437
         * Simple Query
 
438
         * This is a simplified version of the query() function.  Internally
 
439
         * we only use it when running transaction commands since they do
 
440
         * not require all the features of the main query() function.
 
441
         *
 
442
         * @access      public
 
443
         * @param       string  the sql query
 
444
         * @return      mixed
 
445
         */
 
446
        function simple_query($sql)
 
447
        {
 
448
                if ( ! $this->conn_id)
 
449
                {
 
450
                        $this->initialize();
 
451
                }
 
452
 
 
453
                return $this->_execute($sql);
 
454
        }
 
455
 
 
456
        // --------------------------------------------------------------------
 
457
 
 
458
        /**
 
459
         * Disable Transactions
 
460
         * This permits transactions to be disabled at run-time.
 
461
         *
 
462
         * @access      public
 
463
         * @return      void
 
464
         */
 
465
        function trans_off()
 
466
        {
 
467
                $this->trans_enabled = FALSE;
 
468
        }
 
469
 
 
470
        // --------------------------------------------------------------------
 
471
 
 
472
        /**
 
473
         * Enable/disable Transaction Strict Mode
 
474
         * When strict mode is enabled, if you are running multiple groups of
 
475
         * transactions, if one group fails all groups will be rolled back.
 
476
         * If strict mode is disabled, each group is treated autonomously, meaning
 
477
         * a failure of one group will not affect any others
 
478
         *
 
479
         * @access      public
 
480
         * @return      void
 
481
         */
 
482
        function trans_strict($mode = TRUE)
 
483
        {
 
484
                $this->trans_strict = is_bool($mode) ? $mode : TRUE;
 
485
        }
 
486
 
 
487
        // --------------------------------------------------------------------
 
488
 
 
489
        /**
 
490
         * Start Transaction
 
491
         *
 
492
         * @access      public
 
493
         * @return      void
 
494
         */
 
495
        function trans_start($test_mode = FALSE)
 
496
        {
 
497
                if ( ! $this->trans_enabled)
 
498
                {
 
499
                        return FALSE;
 
500
                }
 
501
 
 
502
                // When transactions are nested we only begin/commit/rollback the outermost ones
 
503
                if ($this->_trans_depth > 0)
 
504
                {
 
505
                        $this->_trans_depth += 1;
 
506
                        return;
 
507
                }
 
508
 
 
509
                $this->trans_begin($test_mode);
 
510
        }
 
511
 
 
512
        // --------------------------------------------------------------------
 
513
 
 
514
        /**
 
515
         * Complete Transaction
 
516
         *
 
517
         * @access      public
 
518
         * @return      bool
 
519
         */
 
520
        function trans_complete()
 
521
        {
 
522
                if ( ! $this->trans_enabled)
 
523
                {
 
524
                        return FALSE;
 
525
                }
 
526
 
 
527
                // When transactions are nested we only begin/commit/rollback the outermost ones
 
528
                if ($this->_trans_depth > 1)
 
529
                {
 
530
                        $this->_trans_depth -= 1;
 
531
                        return TRUE;
 
532
                }
 
533
 
 
534
                // The query() function will set this flag to FALSE in the event that a query failed
 
535
                if ($this->_trans_status === FALSE)
 
536
                {
 
537
                        $this->trans_rollback();
 
538
 
 
539
                        // If we are NOT running in strict mode, we will reset
 
540
                        // the _trans_status flag so that subsequent groups of transactions
 
541
                        // will be permitted.
 
542
                        if ($this->trans_strict === FALSE)
 
543
                        {
 
544
                                $this->_trans_status = TRUE;
 
545
                        }
 
546
 
 
547
                        log_message('debug', 'DB Transaction Failure');
 
548
                        return FALSE;
 
549
                }
 
550
 
 
551
                $this->trans_commit();
 
552
                return TRUE;
 
553
        }
 
554
 
 
555
        // --------------------------------------------------------------------
 
556
 
 
557
        /**
 
558
         * Lets you retrieve the transaction flag to determine if it has failed
 
559
         *
 
560
         * @access      public
 
561
         * @return      bool
 
562
         */
 
563
        function trans_status()
 
564
        {
 
565
                return $this->_trans_status;
 
566
        }
 
567
 
 
568
        // --------------------------------------------------------------------
 
569
 
 
570
        /**
 
571
         * Compile Bindings
 
572
         *
 
573
         * @access      public
 
574
         * @param       string  the sql statement
 
575
         * @param       array   an array of bind data
 
576
         * @return      string
 
577
         */
 
578
        function compile_binds($sql, $binds)
 
579
        {
 
580
                if (strpos($sql, $this->bind_marker) === FALSE)
 
581
                {
 
582
                        return $sql;
 
583
                }
 
584
 
 
585
                if ( ! is_array($binds))
 
586
                {
 
587
                        $binds = array($binds);
 
588
                }
 
589
 
 
590
                // Get the sql segments around the bind markers
 
591
                $segments = explode($this->bind_marker, $sql);
 
592
 
 
593
                // The count of bind should be 1 less then the count of segments
 
594
                // If there are more bind arguments trim it down
 
595
                if (count($binds) >= count($segments)) {
 
596
                        $binds = array_slice($binds, 0, count($segments)-1);
 
597
                }
 
598
 
 
599
                // Construct the binded query
 
600
                $result = $segments[0];
 
601
                $i = 0;
 
602
                foreach ($binds as $bind)
 
603
                {
 
604
                        $result .= $this->escape($bind);
 
605
                        $result .= $segments[++$i];
 
606
                }
 
607
 
 
608
                return $result;
 
609
        }
 
610
 
 
611
        // --------------------------------------------------------------------
 
612
 
 
613
        /**
 
614
         * Determines if a query is a "write" type.
 
615
         *
 
616
         * @access      public
 
617
         * @param       string  An SQL query string
 
618
         * @return      boolean
 
619
         */
 
620
        function is_write_type($sql)
 
621
        {
 
622
                if ( ! preg_match('/^\s*"?(SET|INSERT|UPDATE|DELETE|REPLACE|CREATE|DROP|TRUNCATE|LOAD DATA|COPY|ALTER|GRANT|REVOKE|LOCK|UNLOCK)\s+/i', $sql))
 
623
                {
 
624
                        return FALSE;
 
625
                }
 
626
                return TRUE;
 
627
        }
 
628
 
 
629
        // --------------------------------------------------------------------
 
630
 
 
631
        /**
 
632
         * Calculate the aggregate query elapsed time
 
633
         *
 
634
         * @access      public
 
635
         * @param       integer The number of decimal places
 
636
         * @return      integer
 
637
         */
 
638
        function elapsed_time($decimals = 6)
 
639
        {
 
640
                return number_format($this->benchmark, $decimals);
 
641
        }
 
642
 
 
643
        // --------------------------------------------------------------------
 
644
 
 
645
        /**
 
646
         * Returns the total number of queries
 
647
         *
 
648
         * @access      public
 
649
         * @return      integer
 
650
         */
 
651
        function total_queries()
 
652
        {
 
653
                return $this->query_count;
 
654
        }
 
655
 
 
656
        // --------------------------------------------------------------------
 
657
 
 
658
        /**
 
659
         * Returns the last query that was executed
 
660
         *
 
661
         * @access      public
 
662
         * @return      void
 
663
         */
 
664
        function last_query()
 
665
        {
 
666
                return end($this->queries);
 
667
        }
 
668
 
 
669
        // --------------------------------------------------------------------
 
670
 
 
671
        /**
 
672
         * "Smart" Escape String
 
673
         *
 
674
         * Escapes data based on type
 
675
         * Sets boolean and null types
 
676
         *
 
677
         * @access      public
 
678
         * @param       string
 
679
         * @return      mixed
 
680
         */
 
681
        function escape($str)
 
682
        {
 
683
                if (is_string($str))
 
684
                {
 
685
                        $str = "'".$this->escape_str($str)."'";
 
686
                }
 
687
                elseif (is_bool($str))
 
688
                {
 
689
                        $str = ($str === FALSE) ? 0 : 1;
 
690
                }
 
691
                elseif (is_null($str))
 
692
                {
 
693
                        $str = 'NULL';
 
694
                }
 
695
 
 
696
                return $str;
 
697
        }
 
698
 
 
699
        // --------------------------------------------------------------------
 
700
 
 
701
        /**
 
702
         * Escape LIKE String
 
703
         *
 
704
         * Calls the individual driver for platform
 
705
         * specific escaping for LIKE conditions
 
706
         *
 
707
         * @access      public
 
708
         * @param       string
 
709
         * @return      mixed
 
710
         */
 
711
        function escape_like_str($str)
 
712
        {
 
713
                return $this->escape_str($str, TRUE);
 
714
        }
 
715
 
 
716
        // --------------------------------------------------------------------
 
717
 
 
718
        /**
 
719
         * Primary
 
720
         *
 
721
         * Retrieves the primary key.  It assumes that the row in the first
 
722
         * position is the primary key
 
723
         *
 
724
         * @access      public
 
725
         * @param       string  the table name
 
726
         * @return      string
 
727
         */
 
728
        function primary($table = '')
 
729
        {
 
730
                $fields = $this->list_fields($table);
 
731
 
 
732
                if ( ! is_array($fields))
 
733
                {
 
734
                        return FALSE;
 
735
                }
 
736
 
 
737
                return current($fields);
 
738
        }
 
739
 
 
740
        // --------------------------------------------------------------------
 
741
 
 
742
        /**
 
743
         * Returns an array of table names
 
744
         *
 
745
         * @access      public
 
746
         * @return      array
 
747
         */
 
748
        function list_tables($constrain_by_prefix = FALSE)
 
749
        {
 
750
                // Is there a cached result?
 
751
                if (isset($this->data_cache['table_names']))
 
752
                {
 
753
                        return $this->data_cache['table_names'];
 
754
                }
 
755
 
 
756
                if (FALSE === ($sql = $this->_list_tables($constrain_by_prefix)))
 
757
                {
 
758
                        if ($this->db_debug)
 
759
                        {
 
760
                                return $this->display_error('db_unsupported_function');
 
761
                        }
 
762
                        return FALSE;
 
763
                }
 
764
 
 
765
                $retval = array();
 
766
                $query = $this->query($sql);
 
767
 
 
768
                if ($query->num_rows() > 0)
 
769
                {
 
770
                        foreach ($query->result_array() as $row)
 
771
                        {
 
772
                                if (isset($row['TABLE_NAME']))
 
773
                                {
 
774
                                        $retval[] = $row['TABLE_NAME'];
 
775
                                }
 
776
                                else
 
777
                                {
 
778
                                        $retval[] = array_shift($row);
 
779
                                }
 
780
                        }
 
781
                }
 
782
 
 
783
                $this->data_cache['table_names'] = $retval;
 
784
                return $this->data_cache['table_names'];
 
785
        }
 
786
 
 
787
        // --------------------------------------------------------------------
 
788
 
 
789
        /**
 
790
         * Determine if a particular table exists
 
791
         * @access      public
 
792
         * @return      boolean
 
793
         */
 
794
        function table_exists($table_name)
 
795
        {
 
796
                return ( ! in_array($this->_protect_identifiers($table_name, TRUE, FALSE, FALSE), $this->list_tables())) ? FALSE : TRUE;
 
797
        }
 
798
 
 
799
        // --------------------------------------------------------------------
 
800
 
 
801
        /**
 
802
         * Fetch MySQL Field Names
 
803
         *
 
804
         * @access      public
 
805
         * @param       string  the table name
 
806
         * @return      array
 
807
         */
 
808
        function list_fields($table = '')
 
809
        {
 
810
                // Is there a cached result?
 
811
                if (isset($this->data_cache['field_names'][$table]))
 
812
                {
 
813
                        return $this->data_cache['field_names'][$table];
 
814
                }
 
815
 
 
816
                if ($table == '')
 
817
                {
 
818
                        if ($this->db_debug)
 
819
                        {
 
820
                                return $this->display_error('db_field_param_missing');
 
821
                        }
 
822
                        return FALSE;
 
823
                }
 
824
 
 
825
                if (FALSE === ($sql = $this->_list_columns($table)))
 
826
                {
 
827
                        if ($this->db_debug)
 
828
                        {
 
829
                                return $this->display_error('db_unsupported_function');
 
830
                        }
 
831
                        return FALSE;
 
832
                }
 
833
 
 
834
                $query = $this->query($sql);
 
835
 
 
836
                $retval = array();
 
837
                foreach ($query->result_array() as $row)
 
838
                {
 
839
                        if (isset($row['COLUMN_NAME']))
 
840
                        {
 
841
                                $retval[] = $row['COLUMN_NAME'];
 
842
                        }
 
843
                        else
 
844
                        {
 
845
                                $retval[] = current($row);
 
846
                        }
 
847
                }
 
848
 
 
849
                $this->data_cache['field_names'][$table] = $retval;
 
850
                return $this->data_cache['field_names'][$table];
 
851
        }
 
852
 
 
853
        // --------------------------------------------------------------------
 
854
 
 
855
        /**
 
856
         * Determine if a particular field exists
 
857
         * @access      public
 
858
         * @param       string
 
859
         * @param       string
 
860
         * @return      boolean
 
861
         */
 
862
        function field_exists($field_name, $table_name)
 
863
        {
 
864
                return ( ! in_array($field_name, $this->list_fields($table_name))) ? FALSE : TRUE;
 
865
        }
 
866
 
 
867
        // --------------------------------------------------------------------
 
868
 
 
869
        /**
 
870
         * Returns an object with field data
 
871
         *
 
872
         * @access      public
 
873
         * @param       string  the table name
 
874
         * @return      object
 
875
         */
 
876
        function field_data($table = '')
 
877
        {
 
878
                if ($table == '')
 
879
                {
 
880
                        if ($this->db_debug)
 
881
                        {
 
882
                                return $this->display_error('db_field_param_missing');
 
883
                        }
 
884
                        return FALSE;
 
885
                }
 
886
 
 
887
                $query = $this->query($this->_field_data($this->_protect_identifiers($table, TRUE, NULL, FALSE)));
 
888
 
 
889
                return $query->field_data();
 
890
        }
 
891
 
 
892
        // --------------------------------------------------------------------
 
893
 
 
894
        /**
 
895
         * Generate an insert string
 
896
         *
 
897
         * @access      public
 
898
         * @param       string  the table upon which the query will be performed
 
899
         * @param       array   an associative array data of key/values
 
900
         * @return      string
 
901
         */
 
902
        function insert_string($table, $data)
 
903
        {
 
904
                $fields = array();
 
905
                $values = array();
 
906
 
 
907
                foreach ($data as $key => $val)
 
908
                {
 
909
                        $fields[] = $this->_escape_identifiers($key);
 
910
                        $values[] = $this->escape($val);
 
911
                }
 
912
 
 
913
                return $this->_insert($this->_protect_identifiers($table, TRUE, NULL, FALSE), $fields, $values);
 
914
        }
 
915
 
 
916
        // --------------------------------------------------------------------
 
917
 
 
918
        /**
 
919
         * Generate an update string
 
920
         *
 
921
         * @access      public
 
922
         * @param       string  the table upon which the query will be performed
 
923
         * @param       array   an associative array data of key/values
 
924
         * @param       mixed   the "where" statement
 
925
         * @return      string
 
926
         */
 
927
        function update_string($table, $data, $where)
 
928
        {
 
929
                if ($where == '')
 
930
                {
 
931
                        return false;
 
932
                }
 
933
 
 
934
                $fields = array();
 
935
                foreach ($data as $key => $val)
 
936
                {
 
937
                        $fields[$this->_protect_identifiers($key)] = $this->escape($val);
 
938
                }
 
939
 
 
940
                if ( ! is_array($where))
 
941
                {
 
942
                        $dest = array($where);
 
943
                }
 
944
                else
 
945
                {
 
946
                        $dest = array();
 
947
                        foreach ($where as $key => $val)
 
948
                        {
 
949
                                $prefix = (count($dest) == 0) ? '' : ' AND ';
 
950
 
 
951
                                if ($val !== '')
 
952
                                {
 
953
                                        if ( ! $this->_has_operator($key))
 
954
                                        {
 
955
                                                $key .= ' =';
 
956
                                        }
 
957
 
 
958
                                        $val = ' '.$this->escape($val);
 
959
                                }
 
960
 
 
961
                                $dest[] = $prefix.$key.$val;
 
962
                        }
 
963
                }
 
964
 
 
965
                return $this->_update($this->_protect_identifiers($table, TRUE, NULL, FALSE), $fields, $dest);
 
966
        }
 
967
 
 
968
        // --------------------------------------------------------------------
 
969
 
 
970
        /**
 
971
         * Tests whether the string has an SQL operator
 
972
         *
 
973
         * @access      private
 
974
         * @param       string
 
975
         * @return      bool
 
976
         */
 
977
        function _has_operator($str)
 
978
        {
 
979
                $str = trim($str);
 
980
                if ( ! preg_match("/(\s|<|>|!|=|is null|is not null)/i", $str))
 
981
                {
 
982
                        return FALSE;
 
983
                }
 
984
 
 
985
                return TRUE;
 
986
        }
 
987
 
 
988
        // --------------------------------------------------------------------
 
989
 
 
990
        /**
 
991
         * Enables a native PHP function to be run, using a platform agnostic wrapper.
 
992
         *
 
993
         * @access      public
 
994
         * @param       string  the function name
 
995
         * @param       mixed   any parameters needed by the function
 
996
         * @return      mixed
 
997
         */
 
998
        function call_function($function)
 
999
        {
 
1000
                $driver = ($this->dbdriver == 'postgre') ? 'pg_' : $this->dbdriver.'_';
 
1001
 
 
1002
                if (FALSE === strpos($driver, $function))
 
1003
                {
 
1004
                        $function = $driver.$function;
 
1005
                }
 
1006
 
 
1007
                if ( ! function_exists($function))
 
1008
                {
 
1009
                        if ($this->db_debug)
 
1010
                        {
 
1011
                                return $this->display_error('db_unsupported_function');
 
1012
                        }
 
1013
                        return FALSE;
 
1014
                }
 
1015
                else
 
1016
                {
 
1017
                        $args = (func_num_args() > 1) ? array_splice(func_get_args(), 1) : null;
 
1018
                        if (is_null($args))
 
1019
                        {
 
1020
                                return call_user_func($function);
 
1021
                        }
 
1022
                        else
 
1023
                        {
 
1024
                                return call_user_func_array($function, $args);
 
1025
                        }
 
1026
                }
 
1027
        }
 
1028
 
 
1029
        // --------------------------------------------------------------------
 
1030
 
 
1031
        /**
 
1032
         * Set Cache Directory Path
 
1033
         *
 
1034
         * @access      public
 
1035
         * @param       string  the path to the cache directory
 
1036
         * @return      void
 
1037
         */
 
1038
        function cache_set_path($path = '')
 
1039
        {
 
1040
                $this->cachedir = $path;
 
1041
        }
 
1042
 
 
1043
        // --------------------------------------------------------------------
 
1044
 
 
1045
        /**
 
1046
         * Enable Query Caching
 
1047
         *
 
1048
         * @access      public
 
1049
         * @return      void
 
1050
         */
 
1051
        function cache_on()
 
1052
        {
 
1053
                $this->cache_on = TRUE;
 
1054
                return TRUE;
 
1055
        }
 
1056
 
 
1057
        // --------------------------------------------------------------------
 
1058
 
 
1059
        /**
 
1060
         * Disable Query Caching
 
1061
         *
 
1062
         * @access      public
 
1063
         * @return      void
 
1064
         */
 
1065
        function cache_off()
 
1066
        {
 
1067
                $this->cache_on = FALSE;
 
1068
                return FALSE;
 
1069
        }
 
1070
 
 
1071
 
 
1072
        // --------------------------------------------------------------------
 
1073
 
 
1074
        /**
 
1075
         * Delete the cache files associated with a particular URI
 
1076
         *
 
1077
         * @access      public
 
1078
         * @return      void
 
1079
         */
 
1080
        function cache_delete($segment_one = '', $segment_two = '')
 
1081
        {
 
1082
                if ( ! $this->_cache_init())
 
1083
                {
 
1084
                        return FALSE;
 
1085
                }
 
1086
                return $this->CACHE->delete($segment_one, $segment_two);
 
1087
        }
 
1088
 
 
1089
        // --------------------------------------------------------------------
 
1090
 
 
1091
        /**
 
1092
         * Delete All cache files
 
1093
         *
 
1094
         * @access      public
 
1095
         * @return      void
 
1096
         */
 
1097
        function cache_delete_all()
 
1098
        {
 
1099
                if ( ! $this->_cache_init())
 
1100
                {
 
1101
                        return FALSE;
 
1102
                }
 
1103
 
 
1104
                return $this->CACHE->delete_all();
 
1105
        }
 
1106
 
 
1107
        // --------------------------------------------------------------------
 
1108
 
 
1109
        /**
 
1110
         * Initialize the Cache Class
 
1111
         *
 
1112
         * @access      private
 
1113
         * @return      void
 
1114
         */
 
1115
        function _cache_init()
 
1116
        {
 
1117
                if (is_object($this->CACHE) AND class_exists('CI_DB_Cache'))
 
1118
                {
 
1119
                        return TRUE;
 
1120
                }
 
1121
 
 
1122
                if ( ! class_exists('CI_DB_Cache'))
 
1123
                {
 
1124
                        if ( ! @include(BASEPATH.'database/DB_cache.php'))
 
1125
                        {
 
1126
                                return $this->cache_off();
 
1127
                        }
 
1128
                }
 
1129
 
 
1130
                $this->CACHE = new CI_DB_Cache($this); // pass db object to support multiple db connections and returned db objects
 
1131
                return TRUE;
 
1132
        }
 
1133
 
 
1134
        // --------------------------------------------------------------------
 
1135
 
 
1136
        /**
 
1137
         * Close DB Connection
 
1138
         *
 
1139
         * @access      public
 
1140
         * @return      void
 
1141
         */
 
1142
        function close()
 
1143
        {
 
1144
                if (is_resource($this->conn_id) OR is_object($this->conn_id))
 
1145
                {
 
1146
                        $this->_close($this->conn_id);
 
1147
                }
 
1148
                $this->conn_id = FALSE;
 
1149
        }
 
1150
 
 
1151
        // --------------------------------------------------------------------
 
1152
 
 
1153
        /**
 
1154
         * Display an error message
 
1155
         *
 
1156
         * @access      public
 
1157
         * @param       string  the error message
 
1158
         * @param       string  any "swap" values
 
1159
         * @param       boolean whether to localize the message
 
1160
         * @return      string  sends the application/error_db.php template
 
1161
         */
 
1162
        function display_error($error = '', $swap = '', $native = FALSE)
 
1163
        {
 
1164
                $LANG =& load_class('Lang', 'core');
 
1165
                $LANG->load('db');
 
1166
 
 
1167
                $heading = $LANG->line('db_error_heading');
 
1168
 
 
1169
                if ($native == TRUE)
 
1170
                {
 
1171
                        $message = $error;
 
1172
                }
 
1173
                else
 
1174
                {
 
1175
                        $message = ( ! is_array($error)) ? array(str_replace('%s', $swap, $LANG->line($error))) : $error;
 
1176
                }
 
1177
 
 
1178
                // Find the most likely culprit of the error by going through
 
1179
                // the backtrace until the source file is no longer in the
 
1180
                // database folder.
 
1181
 
 
1182
                $trace = debug_backtrace();
 
1183
 
 
1184
                foreach ($trace as $call)
 
1185
                {
 
1186
                        if (isset($call['file']) && strpos($call['file'], BASEPATH.'database') === FALSE)
 
1187
                        {
 
1188
                                // Found it - use a relative path for safety
 
1189
                                $message[] = 'Filename: '.str_replace(array(BASEPATH, APPPATH), '', $call['file']);
 
1190
                                $message[] = 'Line Number: '.$call['line'];
 
1191
 
 
1192
                                break;
 
1193
                        }
 
1194
                }
 
1195
 
 
1196
                $error =& load_class('Exceptions', 'core');
 
1197
                echo $error->show_error($heading, $message, 'error_db');
 
1198
                exit;
 
1199
        }
 
1200
 
 
1201
        // --------------------------------------------------------------------
 
1202
 
 
1203
        /**
 
1204
         * Protect Identifiers
 
1205
         *
 
1206
         * This function adds backticks if appropriate based on db type
 
1207
         *
 
1208
         * @access      private
 
1209
         * @param       mixed   the item to escape
 
1210
         * @return      mixed   the item with backticks
 
1211
         */
 
1212
        function protect_identifiers($item, $prefix_single = FALSE)
 
1213
        {
 
1214
                return $this->_protect_identifiers($item, $prefix_single);
 
1215
        }
 
1216
 
 
1217
        // --------------------------------------------------------------------
 
1218
 
 
1219
        /**
 
1220
         * Protect Identifiers
 
1221
         *
 
1222
         * This function is used extensively by the Active Record class, and by
 
1223
         * a couple functions in this class.
 
1224
         * It takes a column or table name (optionally with an alias) and inserts
 
1225
         * the table prefix onto it.  Some logic is necessary in order to deal with
 
1226
         * column names that include the path.  Consider a query like this:
 
1227
         *
 
1228
         * SELECT * FROM hostname.database.table.column AS c FROM hostname.database.table
 
1229
         *
 
1230
         * Or a query with aliasing:
 
1231
         *
 
1232
         * SELECT m.member_id, m.member_name FROM members AS m
 
1233
         *
 
1234
         * Since the column name can include up to four segments (host, DB, table, column)
 
1235
         * or also have an alias prefix, we need to do a bit of work to figure this out and
 
1236
         * insert the table prefix (if it exists) in the proper position, and escape only
 
1237
         * the correct identifiers.
 
1238
         *
 
1239
         * @access      private
 
1240
         * @param       string
 
1241
         * @param       bool
 
1242
         * @param       mixed
 
1243
         * @param       bool
 
1244
         * @return      string
 
1245
         */
 
1246
        function _protect_identifiers($item, $prefix_single = FALSE, $protect_identifiers = NULL, $field_exists = TRUE)
 
1247
        {
 
1248
                if ( ! is_bool($protect_identifiers))
 
1249
                {
 
1250
                        $protect_identifiers = $this->_protect_identifiers;
 
1251
                }
 
1252
 
 
1253
                if (is_array($item))
 
1254
                {
 
1255
                        $escaped_array = array();
 
1256
 
 
1257
                        foreach ($item as $k => $v)
 
1258
                        {
 
1259
                                $escaped_array[$this->_protect_identifiers($k)] = $this->_protect_identifiers($v);
 
1260
                        }
 
1261
 
 
1262
                        return $escaped_array;
 
1263
                }
 
1264
 
 
1265
                // Convert tabs or multiple spaces into single spaces
 
1266
                $item = preg_replace('/[\t ]+/', ' ', $item);
 
1267
 
 
1268
                // If the item has an alias declaration we remove it and set it aside.
 
1269
                // Basically we remove everything to the right of the first space
 
1270
                if (strpos($item, ' ') !== FALSE)
 
1271
                {
 
1272
                        $alias = strstr($item, ' ');
 
1273
                        $item = substr($item, 0, - strlen($alias));
 
1274
                }
 
1275
                else
 
1276
                {
 
1277
                        $alias = '';
 
1278
                }
 
1279
 
 
1280
                // This is basically a bug fix for queries that use MAX, MIN, etc.
 
1281
                // If a parenthesis is found we know that we do not need to
 
1282
                // escape the data or add a prefix.  There's probably a more graceful
 
1283
                // way to deal with this, but I'm not thinking of it -- Rick
 
1284
                if (strpos($item, '(') !== FALSE)
 
1285
                {
 
1286
                        return $item.$alias;
 
1287
                }
 
1288
 
 
1289
                // Break the string apart if it contains periods, then insert the table prefix
 
1290
                // in the correct location, assuming the period doesn't indicate that we're dealing
 
1291
                // with an alias. While we're at it, we will escape the components
 
1292
                if (strpos($item, '.') !== FALSE)
 
1293
                {
 
1294
                        $parts  = explode('.', $item);
 
1295
 
 
1296
                        // Does the first segment of the exploded item match
 
1297
                        // one of the aliases previously identified?  If so,
 
1298
                        // we have nothing more to do other than escape the item
 
1299
                        if (in_array($parts[0], $this->ar_aliased_tables))
 
1300
                        {
 
1301
                                if ($protect_identifiers === TRUE)
 
1302
                                {
 
1303
                                        foreach ($parts as $key => $val)
 
1304
                                        {
 
1305
                                                if ( ! in_array($val, $this->_reserved_identifiers))
 
1306
                                                {
 
1307
                                                        $parts[$key] = $this->_escape_identifiers($val);
 
1308
                                                }
 
1309
                                        }
 
1310
 
 
1311
                                        $item = implode('.', $parts);
 
1312
                                }
 
1313
                                return $item.$alias;
 
1314
                        }
 
1315
 
 
1316
                        // Is there a table prefix defined in the config file?  If not, no need to do anything
 
1317
                        if ($this->dbprefix != '')
 
1318
                        {
 
1319
                                // We now add the table prefix based on some logic.
 
1320
                                // Do we have 4 segments (hostname.database.table.column)?
 
1321
                                // If so, we add the table prefix to the column name in the 3rd segment.
 
1322
                                if (isset($parts[3]))
 
1323
                                {
 
1324
                                        $i = 2;
 
1325
                                }
 
1326
                                // Do we have 3 segments (database.table.column)?
 
1327
                                // If so, we add the table prefix to the column name in 2nd position
 
1328
                                elseif (isset($parts[2]))
 
1329
                                {
 
1330
                                        $i = 1;
 
1331
                                }
 
1332
                                // Do we have 2 segments (table.column)?
 
1333
                                // If so, we add the table prefix to the column name in 1st segment
 
1334
                                else
 
1335
                                {
 
1336
                                        $i = 0;
 
1337
                                }
 
1338
 
 
1339
                                // This flag is set when the supplied $item does not contain a field name.
 
1340
                                // This can happen when this function is being called from a JOIN.
 
1341
                                if ($field_exists == FALSE)
 
1342
                                {
 
1343
                                        $i++;
 
1344
                                }
 
1345
 
 
1346
                                // Verify table prefix and replace if necessary
 
1347
                                if ($this->swap_pre != '' && strncmp($parts[$i], $this->swap_pre, strlen($this->swap_pre)) === 0)
 
1348
                                {
 
1349
                                        $parts[$i] = preg_replace("/^".$this->swap_pre."(\S+?)/", $this->dbprefix."\\1", $parts[$i]);
 
1350
                                }
 
1351
 
 
1352
                                // We only add the table prefix if it does not already exist
 
1353
                                if (substr($parts[$i], 0, strlen($this->dbprefix)) != $this->dbprefix)
 
1354
                                {
 
1355
                                        $parts[$i] = $this->dbprefix.$parts[$i];
 
1356
                                }
 
1357
 
 
1358
                                // Put the parts back together
 
1359
                                $item = implode('.', $parts);
 
1360
                        }
 
1361
 
 
1362
                        if ($protect_identifiers === TRUE)
 
1363
                        {
 
1364
                                $item = $this->_escape_identifiers($item);
 
1365
                        }
 
1366
 
 
1367
                        return $item.$alias;
 
1368
                }
 
1369
 
 
1370
                // Is there a table prefix?  If not, no need to insert it
 
1371
                if ($this->dbprefix != '')
 
1372
                {
 
1373
                        // Verify table prefix and replace if necessary
 
1374
                        if ($this->swap_pre != '' && strncmp($item, $this->swap_pre, strlen($this->swap_pre)) === 0)
 
1375
                        {
 
1376
                                $item = preg_replace("/^".$this->swap_pre."(\S+?)/", $this->dbprefix."\\1", $item);
 
1377
                        }
 
1378
 
 
1379
                        // Do we prefix an item with no segments?
 
1380
                        if ($prefix_single == TRUE AND substr($item, 0, strlen($this->dbprefix)) != $this->dbprefix)
 
1381
                        {
 
1382
                                $item = $this->dbprefix.$item;
 
1383
                        }
 
1384
                }
 
1385
 
 
1386
                if ($protect_identifiers === TRUE AND ! in_array($item, $this->_reserved_identifiers))
 
1387
                {
 
1388
                        $item = $this->_escape_identifiers($item);
 
1389
                }
 
1390
 
 
1391
                return $item.$alias;
 
1392
        }
 
1393
 
 
1394
        // --------------------------------------------------------------------
 
1395
 
 
1396
        /**
 
1397
         * Dummy method that allows Active Record class to be disabled
 
1398
         *
 
1399
         * This function is used extensively by every db driver.
 
1400
         *
 
1401
         * @return      void
 
1402
         */
 
1403
        protected function _reset_select()
 
1404
        {
 
1405
        }
 
1406
 
 
1407
}
 
1408
 
 
1409
/* End of file DB_driver.php */
 
1410
/* Location: ./system/database/DB_driver.php */
 
 
b'\\ No newline at end of file'