thomascube
2005-11-06 10a699759d4f106f29c077a6d65d3b8d212825e5
commit | author | age
1676e1 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  +-----------------------------------------------------------------------+
adf95d 16  | Author: David Saez Padros <david@ols.es>                              |
1676e1 17  +-----------------------------------------------------------------------+
S 18
19  $Id$
20
21 */
22
23 require_once('DB.php');
24
25 class rcube_db
26 {
adf95d 27     var $db_dsnw;               // DSN for write operations
T 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
1676e1 32
S 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     {
adf95d 39         if ($db_dsnr=='') $db_dsnr=$db_dsnw;
T 40         
1676e1 41         $this->db_dsnw = $db_dsnw;
S 42         $this->db_dsnr = $db_dsnr;
42b113 43         
T 44         $dsn_array = DB::parseDSN($db_dsnw);
45         $this->db_provider = $dsn_array['phptype'];        
1676e1 46     }
S 47
48     // PHP 4 compatibility
49     function rcube_db($db_dsnw,$db_dsnr='')
50     {
51         $this->__construct($db_dsnw,$db_dsnr);
52     }
53
adf95d 54     // Connect to specific database 
T 55     function dsn_connect($dsn)
56     {
597170 57         // Use persistent connections if available
adf95d 58         $dbh = DB::connect($dsn, array('persistent' => $true));
42b113 59         
adf95d 60         if (DB::isError($dbh))
T 61             raise_error(array('code' => 500,
1676e1 62                         'type' => 'db',
S 63                         'line' => __LINE__,
64                         'file' => __FILE__,
65                         'message' => $dbh->getMessage()), TRUE, FALSE);
42b113 66
597170 67         else if ($this->db_provider=='sqlite')
T 68         {
42b113 69             $dsn_array = DB::parseDSN($dsn);
T 70             if (!filesize($dsn_array['database']) && !empty($this->sqlite_initials))
71                 $this->_sqlite_create_database($dbh, $this->sqlite_initials);
597170 72         }
T 73         
adf95d 74         return $dbh;
T 75     }
1676e1 76
adf95d 77     // Connect to appropiate databse    
T 78     function db_connect ($mode)
79     {
42b113 80         $this->db_mode = $mode;
T 81
adf95d 82         // Already connected
T 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;
1676e1 90
adf95d 91             // Same mode, current connection is ok
T 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;
1676e1 99
adf95d 100         $this->db_handle = $this->dsn_connect($dsn);
T 101         $this->db_connected = true;
102     }
1676e1 103
d7cb77 104     // Query database
adf95d 105     
d7cb77 106     function query()
S 107     {
108         $params = func_get_args();
109         $query = array_shift($params);
110         
111         return $this->_query($query, 0, 0, $params);
112     }
113    
114     function limitquery()
115     {
116         $params = func_get_args();
117         $query = array_shift($params);
118         $offset = array_shift($params);
119         $numrows = array_shift($params);
120         
121         return $this->_query($query, $offset, $numrows, $params);
122     }
123     
124     function _query($query, $offset, $numrows, $params)
1676e1 125     {
adf95d 126         // Read or write ?
T 127         if (strtolower(trim(substr($query,0,6)))=='select')
128             $mode='r';
129         else
130             $mode='w';
131         
597170 132         $this->db_connect($mode);
T 133
134         if ($this->db_provider == 'sqlite')
135             $query = $this->_sqlite_prepare_query($query);
53560c 136         
S 137         if ($numrows || $offset)
138             {
d7cb77 139             $result = $this->db_handle->limitQuery($query,$offset,$numrows,$params);
53560c 140             }
S 141         else    
ccfda8 142             $result = $this->db_handle->query($query, $params);
d7cb77 143
1676e1 144         if (DB::isError($result))
d7cb77 145             {
42b113 146             raise_error(array('code' => 500,
T 147                               'type' => 'db',
597170 148                               'line' => __LINE__, 
T 149                               'file' => __FILE__, 
ccfda8 150                               'message' => $result->getMessage().'; QUERY: '.$query), TRUE, FALSE);
d7cb77 151              return false;
S 152             }
153
1676e1 154         return $this->_add_result($result, $query);
S 155     }
adf95d 156     
T 157     function num_rows($res_id=NULL)
1676e1 158     {
S 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
170     function affected_rows($res_id=NULL)
171     {
172         if (!$this->db_handle)
173             return FALSE;
174     
d3d42b 175         return $this->db_handle->affectedRows();
1676e1 176     }
S 177
178     function insert_id($sequence = '')
179     {
42b113 180         if (!$this->db_handle || $this->db_mode=='r')
1676e1 181             return FALSE;
S 182
183         switch($this->db_provider)
184         {
185             case 'pgsql':
186                 // PostgreSQL uses sequences
187                 $result =& $this->db_handle->getOne("SELECT CURRVAL('$sequence')");    
42b113 188                 if (DB::isError($result)) {
1676e1 189                     raise_error( array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, 
S 190                     'message' => $result->getMessage()), TRUE, TRUE);
42b113 191                 }
1676e1 192                 return $result;
S 193                 
194             case 'mysql': // This is unfortuneate
fa3add 195                 return mysql_insert_id($this->db_handle->connection);
597170 196
fa3add 197             case 'mysqli':
S 198                 return mysqli_insert_id($this->db_handle->connection);
199     
597170 200             case 'sqlite':
T 201                 return sqlite_last_insert_rowid($this->db_handle->connection);
202
1676e1 203             default:
S 204                 die("portability issue with this database, please have the developer fix");
205         }
206     }
207
208
209     function fetch_assoc($res_id=NULL)
210     {
211         $result = $this->_get_result($res_id);
212
213         if (DB::isError($result))
42b113 214         {
1676e1 215             raise_error( array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__,
42b113 216                          'message' => $this->db_link->getMessage()), TRUE, FALSE);
T 217             return FALSE;
218         }
1676e1 219                          
S 220         return $result->fetchRow(DB_FETCHMODE_ASSOC);
221     }
222
10a699 223
T 224     function quote($input, $type=null)
225     {
226         if (!$this->db_handle)
227             $this->db_connect('r');
228
229         return $this->db_handle->quote($input);
230     }
231     
232
233     function quoteIdentifier($str)
d7cb77 234     {
S 235         if (!$this->db_handle)
236             $this->db_connect('r');
237             
238         return $this->db_handle->quoteIdentifier($str);
239     }
240     
10a699 241     function quote_identifier($str)
T 242     {
243         return $this->quoteIdentifier($str);
244     }
245
246     
d7cb77 247     function unixtimestamp($field)
S 248     {
249         switch($this->db_provider)
250             {
251             case 'pgsql':
252                 return "EXTRACT (EPOCH FROM $field)";
253                 break;
254             default:
255                 return "UNIX_TIMESTAMP($field)";
256             }
257     }
258     
1676e1 259     function _add_result($res, $query)
S 260     {
261         // sql error occured
262         if (DB::isError($res))
263         {
adf95d 264             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);
1676e1 265              return FALSE;
S 266         }
267         else
268         {
269             $res_id = sizeof($this->a_query_results);
270             $this->a_query_results[$res_id] = $res;
271             $this->last_res_id = $res_id;
272             return $res_id;
273         }
274     }
275
276
277     function _get_result($res_id)
278     {
279         if ($res_id==NULL)
280             $res_id = $this->last_res_id;
281     
282         if ($res_id && isset($this->a_query_results[$res_id]))
283             return $this->a_query_results[$res_id];
284         else
285         return FALSE;
286     }
287
597170 288
T 289     // create a sqlite database from a file
290     function _sqlite_create_database($dbh, $fileName)
291     {
292         if (empty($fileName) || !is_string($fileName))
293             return ;
294
295         $data = '';
42b113 296         if ($fd = fopen($fileName, 'r'))
T 297           {
298           $data = fread($fd, filesize($fileName));
299           fclose($fd);
300           }
597170 301
42b113 302         if (strlen($data))
T 303           sqlite_exec($dbh->connection, $data);
597170 304     }
T 305
306     // transform a query so that it is sqlite2 compliant
307     function _sqlite_prepare_query($query)
308     {
309         if (!is_string($query))
310             return ($query);
ccfda8 311             
T 312         $search = array('/NOW\(\)/i', '/`/');
313         $replace = array("datetime('now')", '"');
597170 314         $query = preg_replace($search, $replace, $query);
T 315
316         return ($query);
317     }
318     
1676e1 319 }
S 320
321 ?>