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