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