source: github/program/include/rcube_db.inc @ 1cded85

HEADcourier-fixdev-browser-capabilitiespdorelease-0.6release-0.7release-0.8
Last change on this file since 1cded85 was 1cded85, checked in by thomascube <thomas@…>, 7 years ago

Re-design of caching (new database table added\!); some bugfixes; Postgres support

  • Property mode set to 100755
File size: 8.8 KB
Line 
1<?php
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
23require_once('DB.php');
24
25class 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
37  // PHP 5 constructor
38  function __construct($db_dsnw,$db_dsnr='')
39    {
40    if ($db_dsnr=='')
41      $db_dsnr=$db_dsnw;
42       
43    $this->db_dsnw = $db_dsnw;
44    $this->db_dsnr = $db_dsnr;
45       
46    $dsn_array = DB::parseDSN($db_dsnw);
47    $this->db_provider = $dsn_array['phptype'];       
48    }
49
50
51  // PHP 4 compatibility
52  function rcube_db($db_dsnw,$db_dsnr='')
53    {
54    $this->__construct($db_dsnw,$db_dsnr);
55    }
56
57
58  // Connect to specific database
59  function dsn_connect($dsn)
60    {
61    // Use persistent connections if available
62    $dbh = DB::connect($dsn, array('persistent' => TRUE));
63       
64    if (DB::isError($dbh))
65      raise_error(array('code' => 500,
66                        'type' => 'db',
67                        'line' => __LINE__,
68                        'file' => __FILE__,
69                        'message' => $dbh->getMessage()), TRUE, FALSE);
70
71    else if ($this->db_provider=='sqlite')
72      {
73      $dsn_array = DB::parseDSN($dsn);
74      if (!filesize($dsn_array['database']) && !empty($this->sqlite_initials))
75        $this->_sqlite_create_database($dbh, $this->sqlite_initials);
76      }
77       
78    return $dbh;
79    }
80
81
82  // Connect to appropiate databse   
83  function db_connect ($mode)
84    {
85    $this->db_mode = $mode;
86
87    // Already connected
88    if ($this->db_connected)
89      {
90      // no replication, current connection is ok
91      if ($this->db_dsnw==$this->db_dsnr)
92        return;
93           
94      // connected to master, current connection is ok
95      if ($this->db_mode=='w')
96        return;
97
98      // Same mode, current connection is ok
99      if ($this->db_mode==$mode)
100        return;
101      }
102           
103    if ($mode=='r')
104      $dsn = $this->db_dsnr;
105    else
106      $dsn = $this->db_dsnw;
107
108    $this->db_handle = $this->dsn_connect($dsn);
109    $this->db_connected = true;
110    }
111
112
113  // Query database
114  function query()
115    {
116    $params = func_get_args();
117    $query = array_shift($params);
118
119    return $this->_query($query, 0, 0, $params);
120    }
121
122
123  // Query with limits
124  function limitquery()
125    {
126    $params = func_get_args();
127    $query = array_shift($params);
128    $offset = array_shift($params);
129    $numrows = array_shift($params);
130               
131    return $this->_query($query, $offset, $numrows, $params);
132    }
133
134
135  function _query($query, $offset, $numrows, $params)
136    {
137    // Read or write ?
138    if (strtolower(trim(substr($query,0,6)))=='select')
139      $mode='r';
140    else
141      $mode='w';
142       
143    $this->db_connect($mode);
144
145    if ($this->db_provider == 'sqlite')
146      $this->_sqlite_prepare();
147
148    if ($numrows || $offset)
149      $result = $this->db_handle->limitQuery($query,$offset,$numrows,$params);
150    else   
151      $result = $this->db_handle->query($query, $params);
152       
153    // add result, even if it's an error
154    return $this->_add_result($result);
155    }
156
157
158  function num_rows($res_id=NULL)
159    {
160    if (!$this->db_handle)
161      return FALSE;
162
163    if ($result = $this->_get_result($res_id))   
164      return $result->numRows();
165    else
166      return FALSE;
167    }
168
169
170  function affected_rows($res_id=NULL)
171    {
172    if (!$this->db_handle)
173      return FALSE;
174
175    return $this->db_handle->affectedRows();
176    }
177
178
179  function insert_id($sequence = '')
180    {
181    if (!$this->db_handle || $this->db_mode=='r')
182      return FALSE;
183
184    switch($this->db_provider)
185      {
186      case 'pgsql':
187        // PostgreSQL uses sequences
188        $result =& $this->db_handle->getOne("SELECT CURRVAL('$sequence')");   
189        if (DB::isError($result))
190          raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__,
191                            'message' => $result->getMessage()), TRUE, FALSE);
192
193        return $result;
194               
195      case 'mysql': // This is unfortuneate
196        return mysql_insert_id($this->db_handle->connection);
197
198      case 'mysqli':
199        return mysqli_insert_id($this->db_handle->connection);
200       
201      case 'sqlite':
202        return sqlite_last_insert_rowid($this->db_handle->connection);
203
204      default:
205        die("portability issue with this database, please have the developer fix");
206      }
207    }
208
209
210  function fetch_assoc($res_id=NULL)
211    {
212    $result = $this->_get_result($res_id);
213
214    if (DB::isError($result))
215      {
216      raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__,
217                        'message' => $this->db_link->getMessage()), TRUE, FALSE);
218      return FALSE;
219      }
220                         
221    return $result->fetchRow(DB_FETCHMODE_ASSOC);
222    }
223
224
225  function quote($input, $type=null)
226    {
227    if (!$this->db_handle)
228      $this->db_connect('r');
229
230    return $this->db_handle->quote($input);
231    }
232   
233
234  function quoteIdentifier($str)
235        {
236    if (!$this->db_handle)
237      $this->db_connect('r');
238                       
239    return $this->db_handle->quoteIdentifier($str);
240        }
241
242
243  function quote_identifier($str)
244    {
245    return $this->quoteIdentifier($str);
246    }
247
248
249  function unixtimestamp($field)
250    {
251    switch($this->db_provider)
252      {
253      case 'pgsql':
254        return "EXTRACT (EPOCH FROM $field)";
255        break;
256
257      default:
258        return "UNIX_TIMESTAMP($field)";
259      }
260    }
261
262
263  function fromunixtime($timestamp)
264    {
265    switch($this->db_provider)
266      {
267      case 'mysqli':
268      case 'mysql':
269      case 'sqlite':
270        return "FROM_UNIXTIME($timestamp)";
271
272      default:
273        return date("'Y-m-d H:i:s'", $timestamp);
274      }
275    }
276
277
278  function _add_result($res)
279    {
280    // sql error occured
281    if (DB::isError($res))
282      {
283      raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__,
284                        'message' => $res->getMessage() . " Query: " . substr(preg_replace('/[\r\n]+\s*/', ' ', $res->userinfo), 0, 1024)), TRUE, FALSE);
285      return FALSE;
286      }
287    else
288      {
289      $res_id = sizeof($this->a_query_results);
290      $this->a_query_results[$res_id] = $res;
291      $this->last_res_id = $res_id;
292      return $res_id;
293      }
294    }
295
296
297  function _get_result($res_id)
298    {
299    if ($res_id==NULL)
300      $res_id = $this->last_res_id;
301   
302     if ($res_id && isset($this->a_query_results[$res_id]))
303       return $this->a_query_results[$res_id];
304     else
305       return FALSE;
306    }
307
308
309  // create a sqlite database from a file
310  function _sqlite_create_database($dbh, $fileName)
311    {
312    if (empty($fileName) || !is_string($fileName))
313      return ;
314
315    $data = '';
316    if ($fd = fopen($fileName, 'r'))
317      {
318      $data = fread($fd, filesize($fileName));
319      fclose($fd);
320      }
321
322    if (strlen($data))
323      sqlite_exec($dbh->connection, $data);
324    }
325
326  function _sqlite_prepare()
327    {
328    include_once('include/rcube_sqlite.inc');
329
330    // we emulate via callback some missing MySQL function
331    sqlite_create_function($this->db_handle->connection, "from_unixtime", "rcube_sqlite_from_unixtime");
332    sqlite_create_function($this->db_handle->connection, "unix_timestamp", "rcube_sqlite_unix_timestamp");
333    sqlite_create_function($this->db_handle->connection, "now", "rcube_sqlite_now");
334    sqlite_create_function($this->db_handle->connection, "md5", "rcube_sqlite_md5");   
335    }
336
337/*
338  // transform a query so that it is sqlite2 compliant
339  function _sqlite_prepare_query($query)
340    {
341    if (!is_string($query))
342      return ($query);
343
344
345    $search = array('/NOW\(\)/i', '/`/');
346    $replace = array("datetime('now')", '"');
347    $query = preg_replace($search, $replace, $query);
348
349    return ($query);
350    }
351*/
352  }  // end class rcube_db
353
354?>
Note: See TracBrowser for help on using the repository browser.