upgrade to codeigniter 1.7.2 for f12
[www-register-wizard.git] / 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 4.3.2 or newer
6  *
7  * @package             CodeIgniter
8  * @author              ExpressionEngine Dev Team
9  * @copyright   Copyright (c) 2008 - 2009, 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                 // Access the CI object
276                 $CI =& get_instance();
277                 
278                 // ODBC doesn't require escaping
279                 $str = $CI->input->_remove_invisible_characters($str);
280                 
281                 // escape LIKE condition wildcards
282                 if ($like === TRUE)
283                 {
284                         $str = str_replace(     array('%', '_', $this->_like_escape_chr),
285                                                                 array($this->_like_escape_chr.'%', $this->_like_escape_chr.'_', $this->_like_escape_chr.$this->_like_escape_chr),
286                                                                 $str);
287                 }
288                 
289                 return $str;
290         }
291         
292         // --------------------------------------------------------------------
293
294         /**
295          * Affected Rows
296          *
297          * @access      public
298          * @return      integer
299          */
300         function affected_rows()
301         {
302                 return @odbc_num_rows($this->conn_id);
303         }
304         
305         // --------------------------------------------------------------------
306
307         /**
308          * Insert ID
309          *
310          * @access      public
311          * @return      integer
312          */
313         function insert_id()
314         {
315                 return @odbc_insert_id($this->conn_id);
316         }
317
318         // --------------------------------------------------------------------
319
320         /**
321          * "Count All" query
322          *
323          * Generates a platform-specific query string that counts all records in
324          * the specified database
325          *
326          * @access      public
327          * @param       string
328          * @return      string
329          */
330         function count_all($table = '')
331         {
332                 if ($table == '')
333                 {
334                         return 0;
335                 }
336
337                 $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE));
338
339                 if ($query->num_rows() == 0)
340                 {
341                         return 0;
342                 }
343
344                 $row = $query->row();
345                 return (int) $row->numrows;
346         }
347
348         // --------------------------------------------------------------------
349
350         /**
351          * Show table query
352          *
353          * Generates a platform-specific query string so that the table names can be fetched
354          *
355          * @access      private
356          * @param       boolean
357          * @return      string
358          */
359         function _list_tables($prefix_limit = FALSE)
360         {
361                 $sql = "SHOW TABLES FROM `".$this->database."`";
362
363                 if ($prefix_limit !== FALSE AND $this->dbprefix != '')
364                 {
365                         //$sql .= " LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_char);
366                         return FALSE; // not currently supported
367                 }
368                 
369                 return $sql;
370         }
371         
372         // --------------------------------------------------------------------
373
374         /**
375          * Show column query
376          *
377          * Generates a platform-specific query string so that the column names can be fetched
378          *
379          * @access      public
380          * @param       string  the table name
381          * @return      string
382          */
383         function _list_columns($table = '')
384         {
385                 return "SHOW COLUMNS FROM ".$table;
386         }
387
388         // --------------------------------------------------------------------
389
390         /**
391          * Field data query
392          *
393          * Generates a platform-specific query so that the column data can be retrieved
394          *
395          * @access      public
396          * @param       string  the table name
397          * @return      object
398          */
399         function _field_data($table)
400         {
401                 return "SELECT TOP 1 FROM ".$table;
402         }
403
404         // --------------------------------------------------------------------
405
406         /**
407          * The error message string
408          *
409          * @access      private
410          * @return      string
411          */
412         function _error_message()
413         {
414                 return odbc_errormsg($this->conn_id);
415         }
416         
417         // --------------------------------------------------------------------
418
419         /**
420          * The error message number
421          *
422          * @access      private
423          * @return      integer
424          */
425         function _error_number()
426         {
427                 return odbc_error($this->conn_id);
428         }
429
430         // --------------------------------------------------------------------
431
432         /**
433          * Escape the SQL Identifiers
434          *
435          * This function escapes column and table names
436          *
437          * @access      private
438          * @param       string
439          * @return      string
440          */
441         function _escape_identifiers($item)
442         {
443                 if ($this->_escape_char == '')
444                 {
445                         return $item;
446                 }
447
448                 foreach ($this->_reserved_identifiers as $id)
449                 {
450                         if (strpos($item, '.'.$id) !== FALSE)
451                         {
452                                 $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item);  
453                                 
454                                 // remove duplicates if the user already included the escape
455                                 return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
456                         }               
457                 }
458         
459                 if (strpos($item, '.') !== FALSE)
460                 {
461                         $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char;                    
462                 }
463                 else
464                 {
465                         $str = $this->_escape_char.$item.$this->_escape_char;
466                 }
467                 
468                 // remove duplicates if the user already included the escape
469                 return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
470         }
471                         
472         // --------------------------------------------------------------------
473
474         /**
475          * From Tables
476          *
477          * This function implicitly groups FROM tables so there is no confusion
478          * about operator precedence in harmony with SQL standards
479          *
480          * @access      public
481          * @param       type
482          * @return      type
483          */
484         function _from_tables($tables)
485         {
486                 if ( ! is_array($tables))
487                 {
488                         $tables = array($tables);
489                 }
490                 
491                 return '('.implode(', ', $tables).')';
492         }
493
494         // --------------------------------------------------------------------
495         
496         /**
497          * Insert statement
498          *
499          * Generates a platform-specific insert string from the supplied data
500          *
501          * @access      public
502          * @param       string  the table name
503          * @param       array   the insert keys
504          * @param       array   the insert values
505          * @return      string
506          */
507         function _insert($table, $keys, $values)
508         {       
509                 return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
510         }
511         
512         // --------------------------------------------------------------------
513
514         /**
515          * Update statement
516          *
517          * Generates a platform-specific update string from the supplied data
518          *
519          * @access      public
520          * @param       string  the table name
521          * @param       array   the update data
522          * @param       array   the where clause
523          * @param       array   the orderby clause
524          * @param       array   the limit clause
525          * @return      string
526          */
527         function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
528         {
529                 foreach($values as $key => $val)
530                 {
531                         $valstr[] = $key." = ".$val;
532                 }
533                 
534                 $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
535                 
536                 $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
537         
538                 $sql = "UPDATE ".$table." SET ".implode(', ', $valstr);
539
540                 $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : '';
541
542                 $sql .= $orderby.$limit;
543                 
544                 return $sql;
545         }
546
547         
548         // --------------------------------------------------------------------
549
550         /**
551          * Truncate statement
552          *
553          * Generates a platform-specific truncate string from the supplied data
554          * If the database does not support the truncate() command
555          * This function maps to "DELETE FROM table"
556          *
557          * @access      public
558          * @param       string  the table name
559          * @return      string
560          */     
561         function _truncate($table)
562         {
563                 return $this->_delete($table);
564         }
565         
566         // --------------------------------------------------------------------
567
568         /**
569          * Delete statement
570          *
571          * Generates a platform-specific delete string from the supplied data
572          *
573          * @access      public
574          * @param       string  the table name
575          * @param       array   the where clause
576          * @param       string  the limit clause
577          * @return      string
578          */     
579         function _delete($table, $where = array(), $like = array(), $limit = FALSE)
580         {
581                 $conditions = '';
582
583                 if (count($where) > 0 OR count($like) > 0)
584                 {
585                         $conditions = "\nWHERE ";
586                         $conditions .= implode("\n", $this->ar_where);
587
588                         if (count($where) > 0 && count($like) > 0)
589                         {
590                                 $conditions .= " AND ";
591                         }
592                         $conditions .= implode("\n", $like);
593                 }
594
595                 $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
596         
597                 return "DELETE FROM ".$table.$conditions.$limit;
598         }
599
600         // --------------------------------------------------------------------
601
602         /**
603          * Limit string
604          *
605          * Generates a platform-specific LIMIT clause
606          *
607          * @access      public
608          * @param       string  the sql query string
609          * @param       integer the number of rows to limit the query to
610          * @param       integer the offset value
611          * @return      string
612          */
613         function _limit($sql, $limit, $offset)
614         {
615                 // Does ODBC doesn't use the LIMIT clause?
616                 return $sql;
617         }
618
619         // --------------------------------------------------------------------
620
621         /**
622          * Close DB Connection
623          *
624          * @access      public
625          * @param       resource
626          * @return      void
627          */
628         function _close($conn_id)
629         {
630                 @odbc_close($conn_id);
631         }
632
633         
634 }
635
636
637
638 /* End of file odbc_driver.php */
639 /* Location: ./system/database/drivers/odbc/odbc_driver.php */