Remove file execution permission.
[living-lab-site.git] / system / database / drivers / odbc / odbc_driver.php
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  * ODBC Database Adapter Class
20  *
21  * Note: _DB is an extender class that the app controller
22  * creates dynamically based on whether the active record
23  * class is being used or not.
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_odbc_driver extends CI_DB {
32
33         var $dbdriver = 'odbc';
34
35         // the character used to excape - not necessary for ODBC
36         var $_escape_char = '';
37
38         // clause and character used for LIKE escape sequences
39         var $_like_escape_str = " {escape '%s'} ";
40         var $_like_escape_chr = '!';
41
42         /**
43          * The syntax to count rows is slightly different across different
44          * database engines, so this string appears in each driver and is
45          * used for the count_all() and count_all_results() functions.
46          */
47         var $_count_string = "SELECT COUNT(*) AS ";
48         var $_random_keyword;
49
50
51         function CI_DB_odbc_driver($params)
52         {
53                 parent::CI_DB($params);
54
55                 $this->_random_keyword = ' RND('.time().')'; // database specific random keyword
56         }
57
58         /**
59          * Non-persistent database connection
60          *
61          * @access      private called by the base class
62          * @return      resource
63          */
64         function db_connect()
65         {
66                 return @odbc_connect($this->hostname, $this->username, $this->password);
67         }
68
69         // --------------------------------------------------------------------
70
71         /**
72          * Persistent database connection
73          *
74          * @access      private called by the base class
75          * @return      resource
76          */
77         function db_pconnect()
78         {
79                 return @odbc_pconnect($this->hostname, $this->username, $this->password);
80         }
81
82         // --------------------------------------------------------------------
83
84         /**
85          * Reconnect
86          *
87          * Keep / reestablish the db connection if no queries have been
88          * sent for a length of time exceeding the server's idle timeout
89          *
90          * @access      public
91          * @return      void
92          */
93         function reconnect()
94         {
95                 // not implemented in odbc
96         }
97
98         // --------------------------------------------------------------------
99
100         /**
101          * Select the database
102          *
103          * @access      private called by the base class
104          * @return      resource
105          */
106         function db_select()
107         {
108                 // Not needed for ODBC
109                 return TRUE;
110         }
111
112         // --------------------------------------------------------------------
113
114         /**
115          * Set client character set
116          *
117          * @access      public
118          * @param       string
119          * @param       string
120          * @return      resource
121          */
122         function db_set_charset($charset, $collation)
123         {
124                 // @todo - add support if needed
125                 return TRUE;
126         }
127
128         // --------------------------------------------------------------------
129
130         /**
131          * Version number query string
132          *
133          * @access      public
134          * @return      string
135          */
136         function _version()
137         {
138                 return "SELECT version() AS ver";
139         }
140
141         // --------------------------------------------------------------------
142
143         /**
144          * Execute the query
145          *
146          * @access      private called by the base class
147          * @param       string  an SQL query
148          * @return      resource
149          */
150         function _execute($sql)
151         {
152                 $sql = $this->_prep_query($sql);
153                 return @odbc_exec($this->conn_id, $sql);
154         }
155
156         // --------------------------------------------------------------------
157
158         /**
159          * Prep the query
160          *
161          * If needed, each database adapter can prep the query string
162          *
163          * @access      private called by execute()
164          * @param       string  an SQL query
165          * @return      string
166          */
167         function _prep_query($sql)
168         {
169                 return $sql;
170         }
171
172         // --------------------------------------------------------------------
173
174         /**
175          * Begin Transaction
176          *
177          * @access      public
178          * @return      bool
179          */
180         function trans_begin($test_mode = FALSE)
181         {
182                 if ( ! $this->trans_enabled)
183                 {
184                         return TRUE;
185                 }
186
187                 // When transactions are nested we only begin/commit/rollback the outermost ones
188                 if ($this->_trans_depth > 0)
189                 {
190                         return TRUE;
191                 }
192
193                 // Reset the transaction failure flag.
194                 // If the $test_mode flag is set to TRUE transactions will be rolled back
195                 // even if the queries produce a successful result.
196                 $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
197
198                 return odbc_autocommit($this->conn_id, FALSE);
199         }
200
201         // --------------------------------------------------------------------
202
203         /**
204          * Commit Transaction
205          *
206          * @access      public
207          * @return      bool
208          */
209         function trans_commit()
210         {
211                 if ( ! $this->trans_enabled)
212                 {
213                         return TRUE;
214                 }
215
216                 // When transactions are nested we only begin/commit/rollback the outermost ones
217                 if ($this->_trans_depth > 0)
218                 {
219                         return TRUE;
220                 }
221
222                 $ret = odbc_commit($this->conn_id);
223                 odbc_autocommit($this->conn_id, TRUE);
224                 return $ret;
225         }
226
227         // --------------------------------------------------------------------
228
229         /**
230          * Rollback Transaction
231          *
232          * @access      public
233          * @return      bool
234          */
235         function trans_rollback()
236         {
237                 if ( ! $this->trans_enabled)
238                 {
239                         return TRUE;
240                 }
241
242                 // When transactions are nested we only begin/commit/rollback the outermost ones
243                 if ($this->_trans_depth > 0)
244                 {
245                         return TRUE;
246                 }
247
248                 $ret = odbc_rollback($this->conn_id);
249                 odbc_autocommit($this->conn_id, TRUE);
250                 return $ret;
251         }
252
253         // --------------------------------------------------------------------
254
255         /**
256          * Escape String
257          *
258          * @access      public
259          * @param       string
260          * @param       bool    whether or not the string will be used in a LIKE condition
261          * @return      string
262          */
263         function escape_str($str, $like = FALSE)
264         {
265                 if (is_array($str))
266                 {
267                         foreach ($str as $key => $val)
268                         {
269                                 $str[$key] = $this->escape_str($val, $like);
270                         }
271
272                         return $str;
273                 }
274
275                 // ODBC doesn't require escaping
276                 $str = remove_invisible_characters($str);
277
278                 // escape LIKE condition wildcards
279                 if ($like === TRUE)
280                 {
281                         $str = str_replace(     array('%', '_', $this->_like_escape_chr),
282                                                                 array($this->_like_escape_chr.'%', $this->_like_escape_chr.'_', $this->_like_escape_chr.$this->_like_escape_chr),
283                                                                 $str);
284                 }
285
286                 return $str;
287         }
288
289         // --------------------------------------------------------------------
290
291         /**
292          * Affected Rows
293          *
294          * @access      public
295          * @return      integer
296          */
297         function affected_rows()
298         {
299                 return @odbc_num_rows($this->conn_id);
300         }
301
302         // --------------------------------------------------------------------
303
304         /**
305          * Insert ID
306          *
307          * @access      public
308          * @return      integer
309          */
310         function insert_id()
311         {
312                 return @odbc_insert_id($this->conn_id);
313         }
314
315         // --------------------------------------------------------------------
316
317         /**
318          * "Count All" query
319          *
320          * Generates a platform-specific query string that counts all records in
321          * the specified database
322          *
323          * @access      public
324          * @param       string
325          * @return      string
326          */
327         function count_all($table = '')
328         {
329                 if ($table == '')
330                 {
331                         return 0;
332                 }
333
334                 $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE));
335
336                 if ($query->num_rows() == 0)
337                 {
338                         return 0;
339                 }
340
341                 $row = $query->row();
342                 return (int) $row->numrows;
343         }
344
345         // --------------------------------------------------------------------
346
347         /**
348          * Show table query
349          *
350          * Generates a platform-specific query string so that the table names can be fetched
351          *
352          * @access      private
353          * @param       boolean
354          * @return      string
355          */
356         function _list_tables($prefix_limit = FALSE)
357         {
358                 $sql = "SHOW TABLES FROM `".$this->database."`";
359
360                 if ($prefix_limit !== FALSE AND $this->dbprefix != '')
361                 {
362                         //$sql .= " LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr);
363                         return FALSE; // not currently supported
364                 }
365
366                 return $sql;
367         }
368
369         // --------------------------------------------------------------------
370
371         /**
372          * Show column query
373          *
374          * Generates a platform-specific query string so that the column names can be fetched
375          *
376          * @access      public
377          * @param       string  the table name
378          * @return      string
379          */
380         function _list_columns($table = '')
381         {
382                 return "SHOW COLUMNS FROM ".$table;
383         }
384
385         // --------------------------------------------------------------------
386
387         /**
388          * Field data query
389          *
390          * Generates a platform-specific query so that the column data can be retrieved
391          *
392          * @access      public
393          * @param       string  the table name
394          * @return      object
395          */
396         function _field_data($table)
397         {
398                 return "SELECT TOP 1 FROM ".$table;
399         }
400
401         // --------------------------------------------------------------------
402
403         /**
404          * The error message string
405          *
406          * @access      private
407          * @return      string
408          */
409         function _error_message()
410         {
411                 return odbc_errormsg($this->conn_id);
412         }
413
414         // --------------------------------------------------------------------
415
416         /**
417          * The error message number
418          *
419          * @access      private
420          * @return      integer
421          */
422         function _error_number()
423         {
424                 return odbc_error($this->conn_id);
425         }
426
427         // --------------------------------------------------------------------
428
429         /**
430          * Escape the SQL Identifiers
431          *
432          * This function escapes column and table names
433          *
434          * @access      private
435          * @param       string
436          * @return      string
437          */
438         function _escape_identifiers($item)
439         {
440                 if ($this->_escape_char == '')
441                 {
442                         return $item;
443                 }
444
445                 foreach ($this->_reserved_identifiers as $id)
446                 {
447                         if (strpos($item, '.'.$id) !== FALSE)
448                         {
449                                 $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item);
450
451                                 // remove duplicates if the user already included the escape
452                                 return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
453                         }
454                 }
455
456                 if (strpos($item, '.') !== FALSE)
457                 {
458                         $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char;
459                 }
460                 else
461                 {
462                         $str = $this->_escape_char.$item.$this->_escape_char;
463                 }
464
465                 // remove duplicates if the user already included the escape
466                 return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
467         }
468
469         // --------------------------------------------------------------------
470
471         /**
472          * From Tables
473          *
474          * This function implicitly groups FROM tables so there is no confusion
475          * about operator precedence in harmony with SQL standards
476          *
477          * @access      public
478          * @param       type
479          * @return      type
480          */
481         function _from_tables($tables)
482         {
483                 if ( ! is_array($tables))
484                 {
485                         $tables = array($tables);
486                 }
487
488                 return '('.implode(', ', $tables).')';
489         }
490
491         // --------------------------------------------------------------------
492
493         /**
494          * Insert statement
495          *
496          * Generates a platform-specific insert string from the supplied data
497          *
498          * @access      public
499          * @param       string  the table name
500          * @param       array   the insert keys
501          * @param       array   the insert values
502          * @return      string
503          */
504         function _insert($table, $keys, $values)
505         {
506                 return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
507         }
508
509         // --------------------------------------------------------------------
510
511         /**
512          * Update statement
513          *
514          * Generates a platform-specific update string from the supplied data
515          *
516          * @access      public
517          * @param       string  the table name
518          * @param       array   the update data
519          * @param       array   the where clause
520          * @param       array   the orderby clause
521          * @param       array   the limit clause
522          * @return      string
523          */
524         function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
525         {
526                 foreach ($values as $key => $val)
527                 {
528                         $valstr[] = $key." = ".$val;
529                 }
530
531                 $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
532
533                 $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
534
535                 $sql = "UPDATE ".$table." SET ".implode(', ', $valstr);
536
537                 $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : '';
538
539                 $sql .= $orderby.$limit;
540
541                 return $sql;
542         }
543
544
545         // --------------------------------------------------------------------
546
547         /**
548          * Truncate statement
549          *
550          * Generates a platform-specific truncate string from the supplied data
551          * If the database does not support the truncate() command
552          * This function maps to "DELETE FROM table"
553          *
554          * @access      public
555          * @param       string  the table name
556          * @return      string
557          */
558         function _truncate($table)
559         {
560                 return $this->_delete($table);
561         }
562
563         // --------------------------------------------------------------------
564
565         /**
566          * Delete statement
567          *
568          * Generates a platform-specific delete string from the supplied data
569          *
570          * @access      public
571          * @param       string  the table name
572          * @param       array   the where clause
573          * @param       string  the limit clause
574          * @return      string
575          */
576         function _delete($table, $where = array(), $like = array(), $limit = FALSE)
577         {
578                 $conditions = '';
579
580                 if (count($where) > 0 OR count($like) > 0)
581                 {
582                         $conditions = "\nWHERE ";
583                         $conditions .= implode("\n", $this->ar_where);
584
585                         if (count($where) > 0 && count($like) > 0)
586                         {
587                                 $conditions .= " AND ";
588                         }
589                         $conditions .= implode("\n", $like);
590                 }
591
592                 $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
593
594                 return "DELETE FROM ".$table.$conditions.$limit;
595         }
596
597         // --------------------------------------------------------------------
598
599         /**
600          * Limit string
601          *
602          * Generates a platform-specific LIMIT clause
603          *
604          * @access      public
605          * @param       string  the sql query string
606          * @param       integer the number of rows to limit the query to
607          * @param       integer the offset value
608          * @return      string
609          */
610         function _limit($sql, $limit, $offset)
611         {
612                 // Does ODBC doesn't use the LIMIT clause?
613                 return $sql;
614         }
615
616         // --------------------------------------------------------------------
617
618         /**
619          * Close DB Connection
620          *
621          * @access      public
622          * @param       resource
623          * @return      void
624          */
625         function _close($conn_id)
626         {
627                 @odbc_close($conn_id);
628         }
629
630
631 }
632
633
634
635 /* End of file odbc_driver.php */
636 /* Location: ./system/database/drivers/odbc/odbc_driver.php */