thomascube
2006-01-23 0677ca5a1e745643a9142081c4cbb7ea13e5a2e5
commit | author | age
f45ec7 1 <?php
S 2
3 /*
4  +-----------------------------------------------------------------------+
5  | program/include/rcube_db.inc                                          |
6  |                                                                       |
7  | This file is part of the RoundCube Webmail client                     |
8  | Copyright (C) 2005, RoundCube Dev. - Switzerland                      |
9  | Licensed under the GNU GPL                                            |
10  |                                                                       |
11  | PURPOSE:                                                              |
12  |   PEAR:DB wrapper class that implements PEAR DB functions             |
13  |   See http://pear.php.net/package/DB                                  |
14  |                                                                       |
15  +-----------------------------------------------------------------------+
16  | Author: David Saez Padros <david@ols.es>                              |
17  +-----------------------------------------------------------------------+
18
19  $Id$
20
21 */
22
23 require_once('MDB2.php');
24
25 class rcube_db
26 {
27     var $db_dsnw;               // DSN for write operations
28     var $db_dsnr;               // DSN for read operations
29     var $db_connected=false;    // Already connected ?
30     var $db_mode='';            // Connection mode
31     var $db_handle=0;           // Connection handle
32
33     var $a_query_results = array('dummy');
34     var $last_res_id = 0;
35
36     // PHP 5 constructor
37     function __construct($db_dsnw,$db_dsnr='')
38     {
39         if ($db_dsnr=='') $db_dsnr=$db_dsnw;
40         
41         $this->db_dsnw = $db_dsnw;
42         $this->db_dsnr = $db_dsnr;
43         
44         $dsn_array = MDB2::parseDSN($db_dsnw);
45         $this->db_provider = $dsn_array['phptype'];
46     }
47
48     // PHP 4 compatibility
49     function rcube_db($db_dsnw,$db_dsnr='')
50     {
51         $this->__construct($db_dsnw,$db_dsnr);
52     }
53
54     // Connect to specific database 
55     function dsn_connect($dsn)
56     {
57         // Use persistent connections if available
451834 58         $dbh = MDB2::factory($dsn, array('persistent' => $true));
f45ec7 59         
S 60         if (PEAR::isError($dbh))
61             raise_error(array('code' => 500,
62                         'type' => 'db',
63                         'line' => __LINE__,
64                         'file' => __FILE__,
65                         'message' => $dbh->getMessage()), TRUE, FALSE);
66
67         else if ($this->db_provider=='sqlite')
68         {
69             $dsn_array = MDB2::parseDSN($dsn);
70             if (!filesize($dsn_array['database']) && !empty($this->sqlite_initials))
71                 $this->_sqlite_create_database($dbh, $this->sqlite_initials);
72         }
73         
74         return $dbh;
75     }
76
77     // Connect to appropiate databse    
78     function db_connect ($mode)
79     {
80         $this->db_mode = $mode;
81
82         // Already connected
83         if ($this->db_connected)
84             {
85             // no replication, current connection is ok
86             if ($this->db_dsnw==$this->db_dsnr) return;
87             
88             // connected to master, current connection is ok
89             if ($this->db_mode=='w') return;
90
91             // Same mode, current connection is ok
92             if ($this->db_mode==$mode) return;
93             }
94             
95         if ($mode=='r')
96             $dsn=$this->db_dsnr;
97         else
98             $dsn=$this->db_dsnw;
99
100         $this->db_handle = $this->dsn_connect($dsn);
101         $this->db_connected = true;
102     }
103
d7cb77 104     // Query database
S 105     function query()
106     {
107         $params = func_get_args();
108         $query = array_shift($params);
ccfda8 109
d7cb77 110         return $this->_query($query, 0, 0, $params);
S 111     }
ccfda8 112
T 113
d7cb77 114     function limitquery()
S 115     {
ccfda8 116
d7cb77 117         $params = func_get_args();
S 118         $query = array_shift($params);
119         $offset = array_shift($params);
120         $numrows = array_shift($params);
ccfda8 121
d7cb77 122         return $this->_query($query, $offset, $numrows, $params);
S 123     }
124     
125     function _query($query, $offset, $numrows, $params)
f45ec7 126     {
S 127         // Read or write ?
128         if (strtolower(trim(substr($query,0,6)))=='select')
129             $mode='r';
130         else
131             $mode='w';
132         
133         $this->db_connect($mode);
134
135         if ($this->db_provider == 'sqlite')
136             $query = $this->_sqlite_prepare_query($query);
ccfda8 137
53560c 138         $this->db_handle->row_offset = $offset;
S 139         $this->db_handle->row_limit = $numrows;
ccfda8 140
36df57 141         //$result = $this->db_handle->query($query,$params);
T 142         $q = $this->db_handle->prepare($query);
143         $q->bindParamArray($params);
144         $result = $q->execute();
ccfda8 145
f45ec7 146         if (PEAR::isError($result))
S 147             raise_error(array('code' => 500,
148                               'type' => 'db',
149                               'line' => __LINE__, 
150                               'file' => __FILE__, 
151                               'message' => $result->getMessage()), TRUE, FALSE);
152         
153         return $this->_add_result($result, $query);
154     }
155
10a699 156
f45ec7 157     function num_rows($res_id=NULL)
S 158     {
159         if (!$this->db_handle)
160             return FALSE;
161
162         $result = $this->_get_result($res_id);
163     
164         if ($result)    
165               return $result->numRows();
166         else
167               return FALSE;
168     }
169
10a699 170
f45ec7 171     function affected_rows($res_id=NULL)
S 172     {
173         if (!$this->db_handle)
174             return FALSE;
175     
176         return $this->db_handle->affectedRows();
177     }
10a699 178
f45ec7 179
S 180     function insert_id($sequence = '')
181     {
182         if (!$this->db_handle || $this->db_mode=='r')
183             return FALSE;
184
185         return $this->db_handle->lastInsertID();
186     }
187
188
189     function fetch_assoc($res_id=NULL)
190     {
191         $result = $this->_get_result($res_id);
192
193         if (PEAR::isError($result))
194         {
195             raise_error( array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__,
196                          'message' => $this->db_link->getMessage()), TRUE, FALSE);
197             return FALSE;
198         }
199                          
200         return $result->fetchRow(MDB2_FETCHMODE_ASSOC);
201     }
202
ccfda8 203
10a699 204     function quote($input, $type=null)
T 205     {
d7cb77 206         if (!$this->db_handle)
S 207             $this->db_connect('r');
ccfda8 208
10a699 209         return $this->db_handle->quote($input, $type);
T 210     }
211
212
213     function quoteIdentifier($str)
214     {
215         if (!$this->db_handle)
216             $this->db_connect('r');
ccfda8 217
d7cb77 218         return $this->db_handle->quoteIdentifier($str);
S 219     }
ccfda8 220
10a699 221     function quote_identifier($str)
d7cb77 222     {
10a699 223         return $this->quoteIdentifier($str);
T 224     }
ccfda8 225
10a699 226
T 227     function unixtimestamp($field)
228     {
d7cb77 229         switch($this->db_provider)
S 230             {
231             case 'pgsql':
232                 return "EXTRACT (EPOCH FROM $field)";
233                 break;
ccfda8 234
d7cb77 235             default:
S 236                 return "UNIX_TIMESTAMP($field)";
237             }
238     }
10a699 239
T 240
1cded8 241     function format_date($timestamp)
T 242       {
243         switch($this->db_provider)
244             {
245             case 'mysqli':
246             case 'mysql':
247                 return "FROM_UNIXTIME($timestamp)";
248                 break;
249             case 'sqlite':
250                 return "datetime('$timestamp')";
251                 break;
252             default:
253                 return date("Y-m-d H:i:s", $timestamp);
254             }
255       }
256
f45ec7 257     function _add_result($res, $query)
S 258     {
259         // sql error occured
260         if (PEAR::isError($res))
261         {
262             raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, 'message' => $res->getMessage() . " Query: " . substr(preg_replace('/[\r\n]+\s*/', ' ', $query), 0, 1024)), TRUE, FALSE);
263              return FALSE;
264         }
265         else
266         {
267             $res_id = sizeof($this->a_query_results);
268             $this->a_query_results[$res_id] = $res;
269             $this->last_res_id = $res_id;
270             return $res_id;
271         }
272     }
273
274
275     function _get_result($res_id)
276     {
277         if ($res_id==NULL)
278             $res_id = $this->last_res_id;
279     
280         if ($res_id && isset($this->a_query_results[$res_id]))
281             return $this->a_query_results[$res_id];
282         else
283         return FALSE;
284     }
285
286
287     // create a sqlite database from a file
288     function _sqlite_create_database($dbh, $fileName)
289     {
290         if (empty($fileName) || !is_string($fileName))
291             return ;
292
293         $data = '';
294         if ($fd = fopen($fileName, 'r'))
295           {
296           $data = fread($fd, filesize($fileName));
297           fclose($fd);
298           }
299
300         if (strlen($data))
301           sqlite_exec($dbh->connection, $data);
302     }
303
304     // transform a query so that it is sqlite2 compliant
305     function _sqlite_prepare_query($query)
306     {
307         if (!is_string($query))
308             return ($query);
309
ccfda8 310         $search = array('/NOW\(\)/i', '/`/');
T 311         $replace = array("datetime('now')", '"');
f45ec7 312         $query = preg_replace($search, $replace, $query);
S 313
314         return ($query);
315     }
316     
317 }
318
319 ?>