Aleksander Machniak
2013-03-11 ec6a77bab27984ce05b003af07ac9f42ca410d94
commit | author | age
0d94fd 1 <?php
AM 2
3d231c 3 /**
0d94fd 4  +-----------------------------------------------------------------------+
AM 5  | This file is part of the Roundcube Webmail client                     |
6  | Copyright (C) 2005-2012, The Roundcube Dev Team                       |
7  |                                                                       |
8  | Licensed under the GNU General Public License version 3 or            |
9  | any later version with exceptions for skins & plugins.                |
10  | See the README file for a full license statement.                     |
11  |                                                                       |
12  | PURPOSE:                                                              |
13  |   Database wrapper class that implements PHP PDO functions            |
14  |   for MS SQL Server database                                          |
15  +-----------------------------------------------------------------------+
16  | Author: Aleksander Machniak <alec@alec.pl>                            |
17  +-----------------------------------------------------------------------+
18 */
19
20 /**
21  * Database independent query interface
22  * This is a wrapper for the PHP PDO
23  *
9ab346 24  * @package    Framework
AM 25  * @subpackage Database
0d94fd 26  */
AM 27 class rcube_db_sqlsrv extends rcube_db
28 {
88107d 29     public $db_provider = 'mssql';
TB 30
8c2375 31     /**
AM 32      * Driver initialization
33      */
0d94fd 34     protected function init()
AM 35     {
36         $this->options['identifier_start'] = '[';
37         $this->options['identifier_end'] = ']';
38     }
39
8c2375 40     /**
AM 41      * Database character set setting
42      */
0d94fd 43     protected function set_charset($charset)
AM 44     {
8c2375 45         // UTF-8 is default
0d94fd 46     }
AM 47
48     /**
49      * Return SQL function for current time and date
50      *
51      * @return string SQL function to use in query
52      */
53     public function now()
54     {
55         return "getdate()";
56     }
57
58     /**
59      * Return SQL statement to convert a field value into a unix timestamp
60      *
61      * This method is deprecated and should not be used anymore due to limitations
62      * of timestamp functions in Mysql (year 2038 problem)
63      *
3d231c 64      * @param string $field Field name
0d94fd 65      *
3d231c 66      * @return string SQL statement to use in query
0d94fd 67      * @deprecated
AM 68      */
69     public function unixtimestamp($field)
70     {
71         return "DATEDIFF(second, '19700101', $field) + DATEDIFF(second, GETDATE(), GETUTCDATE())";
72     }
73
74     /**
75      * Abstract SQL statement for value concatenation
76      *
77      * @return string SQL statement to be used in query
78      */
79     public function concat(/* col1, col2, ... */)
80     {
81         $args = func_get_args();
82
83         if (is_array($args[0])) {
84             $args = $args[0];
85         }
86
87         return '(' . join('+', $args) . ')';
88     }
89
90     /**
91      * Adds TOP (LIMIT,OFFSET) clause to the query
92      *
3d231c 93      * @param string $query  SQL query
AM 94      * @param int    $limit  Number of rows
95      * @param int    $offset Offset
8c2375 96      *
AM 97      * @return string SQL query
0d94fd 98      */
AM 99     protected function set_limit($query, $limit = 0, $offset = 0)
100     {
5354c5 101         $limit  = intval($limit);
AM 102         $offset = intval($offset);
ec6a77 103         $end    = $offset + $limit;
AM 104
105         // query without OFFSET
106         if (!$offset) {
107             $query = preg_replace('/^SELECT\s/i', "SELECT TOP $limit ", $query);
108             return $query;
109         }
5354c5 110
AM 111         $orderby = stristr($query, 'ORDER BY');
ec6a77 112         $offset += 1;
AM 113
5354c5 114         if ($orderby !== false) {
ec6a77 115             $query = trim(substr($query, 0, -1 * strlen($orderby)));
AM 116         }
117         else {
118             // it shouldn't happen, paging without sorting has not much sense
119             // @FIXME: I don't know how to build paging query without ORDER BY
120             $orderby = "ORDER BY 1";
0d94fd 121         }
AM 122
ec6a77 123         $query = preg_replace('/^SELECT\s/i', '', $query);
AM 124         $query = "WITH paging AS (SELECT ROW_NUMBER() OVER ($orderby) AS [RowNumber], $query)"
125             . " SELECT * FROM paging WHERE [RowNumber] BETWEEN $offset AND $end ORDER BY [RowNumber]";
0d94fd 126
AM 127         return $query;
128     }
129
130     /**
8c2375 131      * Returns PDO DSN string from DSN array
0d94fd 132      */
AM 133     protected function dsn_string($dsn)
134     {
135         $params = array();
136         $result = 'sqlsrv:';
137
138         if ($dsn['hostspec']) {
139             $host = $dsn['hostspec'];
140
141             if ($dsn['port']) {
142                 $host .= ',' . $dsn['port'];
143             }
144             $params[] = 'Server=' . $host;
145         }
146
147         if ($dsn['database']) {
148             $params[] = 'Database=' . $dsn['database'];
149         }
150
151         if (!empty($params)) {
152             $result .= implode(';', $params);
153         }
154
155         return $result;
156     }
157 }