]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/WikiDB/adodb/adodb-mysql.inc.php
Cleanup of special PageList column types
[SourceForge/phpwiki.git] / lib / WikiDB / adodb / adodb-mysql.inc.php
1 <?php
2 /**
3  * V1.71 18 Jan 2001 (c) 2000, 2001 John Lim (jlim@natsoft.com.my). All rights reserved.
4  * Released under both BSD license and Lesser GPL library license. 
5  * Whenever there is any discrepancy between the two licenses, 
6  * the BSD license will take precedence.
7  * Set tabs to 4.
8  *
9  * MySQL code that does not support transactions. Use mysqlt if you need transactions.
10  * Requires mysql client. Works on Windows and Unix.
11  * 
12  * 28 Feb 2001: MetaColumns bug fix - suggested by  Freek Dijkstra (phpeverywhere@macfreek.com)
13  */
14 /**
15  * Included with PhpWiki, which uses for now this mysql-specific backend directly, 
16  * instead of going through the main adodb.inc.php library.
17  * Initial port by Lawrence Akka. See lib/WikiDB/ADODB.php
18  */
19
20 if (! defined("_ADODB_MYSQL_LAYER")) {
21  define("_ADODB_MYSQL_LAYER", 1 );
22 rcs_id('$Id: adodb-mysql.inc.php,v 1.2 2004-04-06 20:00:10 rurban Exp $');
23
24 class ADODB_mysql extends ADOConnection {
25         var $databaseType = 'mysql';
26     var $hasInsertID = true;
27     var $hasAffectedRows = true;        
28         var $metaTablesSQL = "SHOW TABLES";     
29         var $metaColumnsSQL = "SHOW COLUMNS FROM %s";
30         var $fmtTimeStamp = "'Y-m-d H:i:s'";
31         var $hasLimit = true;
32         var $hasMoveFirst = true;
33         var $hasGenID = true;
34         var $upperCase = 'upper';
35         var $isoDates = true; // accepts dates in ISO format
36         
37         function ADODB_mysql() 
38         {                       
39         }
40         
41     function _insertid()
42     {
43             return mysql_insert_id($this->_connectionID);
44     }
45     
46     function _affectedrows()
47     {
48             return mysql_affected_rows($this->_connectionID);
49     }
50   
51         // See http://www.mysql.com/doc/M/i/Miscellaneous_functions.html
52         // Reference on Last_Insert_ID on the recommended way to simulate sequences
53         var $_genIDSQL = "update %s set id=LAST_INSERT_ID(id+1);";
54         var $_genSeqSQL = "create table %s (id int not null)";
55         var $_genSeq2SQL = "insert into %s values (%s)";
56         
57         function GenID($seqname='adodbseq',$startID=1)
58         {
59                 //if (!$this->hasGenID) return false;
60                 $getnext = sprintf($this->_genIDSQL,$seqname);
61                 $rs = @$this->Execute($getnext);
62                 if (!$rs) {
63                         $u = strtoupper($seqname);
64                         $this->Execute(sprintf($this->_genSeqSQL,$seqname));
65                         $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));
66                         $rs = $this->Execute($getnext);
67                 }
68                 $this->genID = mysql_insert_id($this->_connectionID);
69                 
70                 if ($rs) $rs->Close();
71                 
72                 return $this->genID;
73         }
74         
75         function &MetaDatabases()
76         {
77                 $qid = mysql_list_dbs($this->_connectionID);
78                 $arr = array();
79                 $i = 0;
80                 $max = mysql_num_rows($qid);
81                 while ($i < $max) {
82                         $arr[] = mysql_tablename($qid,$i);
83                         $i += 1;
84                 }
85                 return $arr;
86         }
87
88         // returns concatenated string
89         function Concat()
90         {
91                 $s = "";
92                 $arr = func_get_args();
93                 $first = true;
94                 /*
95                 foreach($arr as $a) {
96                         if ($first) {
97                                 $s = $a;
98                                 $first = false;
99                         } else $s .= ','.$a;
100                 }*/
101                 
102                 // suggestion by andrew005@mnogo.ru
103                 $s = implode(',',$arr); 
104                 if (strlen($s) > 0) return "CONCAT($s)";
105                 else return '';
106         }
107         
108         // returns true or false
109         function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)
110         {
111                 $this->_connectionID = mysql_connect($argHostname,$argUsername,$argPassword);
112                 if ($this->_connectionID === false) return false;
113                 if ($argDatabasename) return $this->SelectDB($argDatabasename);
114                 return true;    
115         }
116         
117         // returns true or false
118         function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
119         {
120                 $this->_connectionID = mysql_pconnect($argHostname,$argUsername,$argPassword);
121                 if ($this->_connectionID === false) return false;
122                 if ($argDatabasename) return $this->SelectDB($argDatabasename);
123                 return true;    
124         }
125         
126         function &MetaColumns($table) 
127         {
128         
129                 if ($this->metaColumnsSQL) {
130             global $ADODB_FETCH_MODE;
131                 
132                         $save = $ADODB_FETCH_MODE;
133                         $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
134                         
135                         $rs = $this->Execute(sprintf($this->metaColumnsSQL,$table));
136                         
137                         $ADODB_FETCH_MODE = $save;
138                         
139                         if ($rs === false) return false;
140                         
141                         $retarr = array();
142                         while (!$rs->EOF){
143                                 $fld = new ADOFieldObject();
144                                 $fld->name = $rs->fields[0];
145                                 $fld->type = $rs->fields[1];
146                                         
147                                 // split type into type(length):
148                                 if (preg_match("/^(.+)\((\d+)\)$/", $fld->type, $query_array)) {
149                                         $fld->type = $query_array[1];
150                                         $fld->max_length = $query_array[2];
151                                 } else {
152                                         $fld->max_length = -1;
153                                 }
154                                 $fld->not_null = ($rs->fields[2] != 'YES');
155                                 $fld->primary_key = ($rs->fields[3] == 'PRI');
156                                 $fld->auto_increment = (strpos($rs->fields[5], 'auto_increment') !== false);
157                                 $fld->binary = (strpos($fld->type,'blob') !== false);
158                                 if (!$fld->binary) {
159                                         $d = $rs->fields[4];
160                                         if ($d != "" && $d != "NULL") {
161                                                 $fld->has_default = true;
162                                                 $fld->default_value = $d;
163                                         } else {
164                                                 $fld->has_default = false;
165                                         }
166                                 }
167                                 
168                                 $retarr[strtoupper($fld->name)] = $fld; 
169                                 $rs->MoveNext();
170                         }
171                         $rs->Close();
172                         return $retarr; 
173                 }
174                 return false;
175         }
176                 
177         // returns true or false
178         function SelectDB($dbName) 
179         {
180                 $this->databaseName = $dbName;
181                 if ($this->_connectionID) {
182                         return @mysql_select_db($dbName,$this->_connectionID);          
183                 }
184                 else return false;      
185         }
186         
187         // parameters use PostgreSQL convention, not MySQL
188         function &SelectLimit($sql,$nrows=-1,$offset=-1,
189                           $inputarr=false, $arg3=false,$secs=0)
190         {
191                 $offsetStr =($offset>=0) ? "$offset," : '';
192                 
193                 return ($secs) ? $this->CacheExecute($secs,$sql." LIMIT $offsetStr$nrows",$inputarr,$arg3)
194                         : $this->Execute($sql." LIMIT $offsetStr$nrows",$inputarr,$arg3);
195                 
196         }
197         
198         // returns queryID or false
199         function _query($sql,$inputarr)
200         {
201         global $ADODB_COUNTRECS;
202
203                 if($ADODB_COUNTRECS) return mysql_query($sql,$this->_connectionID);
204                 else return mysql_unbuffered_query($sql,$this->_connectionID); // requires PHP >= 4.0.6
205         }
206
207         /*      Returns: the last error message from previous database operation        */      
208         function ErrorMsg() 
209         {
210                 if (empty($this->_connectionID)) $this->_errorMsg = @mysql_error();
211                 else $this->_errorMsg = @mysql_error($this->_connectionID);
212             return $this->_errorMsg;
213         }
214         
215         /*      Returns: the last error number from previous database operation */      
216         function ErrorNo() 
217         {
218                         if (empty($this->_connectionID))  return @mysql_errno();
219                         else return @mysql_errno($this->_connectionID);
220         }
221         
222
223         
224         // returns true or false
225         function _close()
226         {
227                 @mysql_close($this->_connectionID);
228                 $this->_connectionID = false;
229         }
230
231          function ActualType($meta)
232         {
233                 switch($meta) {
234                 case 'C': return 'VARCHAR';
235                 case 'X': return 'LONGTEXT';
236                 
237                 case 'C2': return 'VARCHAR';
238                 case 'X2': return 'LONGTEXT';
239                 
240                 case 'B': return 'LONGBLOB';
241                         
242                 case 'D': return 'DATE';
243                 case 'T': return 'DATETIME';
244                 case 'L': return 'TINYINT';
245                 case 'R': return 'INTEGER NOT NULL AUTO_INCREMENT';
246                 case 'I': return 'INTEGER';  // enough for 9 petabytes!
247                 
248                 case 'F': return 'DOUBLE';
249                 case 'N': return 'NUMERIC';
250                 default:
251                         return false;
252                 }
253         }
254         
255         /*
256         * Maximum size of C field
257         */
258         function CharMax()
259         {
260                 return 255; 
261         }
262         
263         /*
264         * Maximum size of X field
265         */
266         function TextMax()
267         {
268                 return 4294967295; 
269         }
270         
271 }
272         
273 /*------------------------------------------------------------------------------
274          Class Name: Recordset
275 ------------------------------------------------------------------------------*/
276
277 class ADORecordSet_mysql extends ADORecordSet{  
278         
279         var $databaseType = "mysql";
280         var $canSeek = true;
281         
282         function ADORecordSet_mysql($queryID) {
283         GLOBAL $ADODB_FETCH_MODE;
284         
285                 switch ($ADODB_FETCH_MODE)
286                 {
287                 case ADODB_FETCH_NUM: $this->fetchMode = MYSQL_NUM; break;
288                 case ADODB_FETCH_ASSOC:$this->fetchMode = MYSQL_ASSOC; break;
289                 default:
290                 case ADODB_FETCH_DEFAULT:
291                 case ADODB_FETCH_BOTH:$this->fetchMode = MYSQL_BOTH; break;
292                 }
293         
294                 $this->ADORecordSet($queryID);  
295         }
296         
297         function _initrs()
298         {
299         GLOBAL $ADODB_COUNTRECS;
300                 $this->_numOfRows = ($ADODB_COUNTRECS) ? @mysql_num_rows($this->_queryID):-1;
301                 $this->_numOfFields = @mysql_num_fields($this->_queryID);
302         }
303         
304         function &FetchField($fieldOffset = -1) {
305                 if ($fieldOffset != -1) {
306                         $o =  @mysql_fetch_field($this->_queryID, $fieldOffset);
307                         $f = @mysql_field_flags($this->_queryID,$fieldOffset);
308             // suggested by: Jim Nicholson (jnich@att.com)
309                         $o->max_length = @mysql_field_len($this->_queryID,$fieldOffset); 
310             // mysql returns the max length less spaces -- so it is unrealiable
311                         //$o->max_length = -1; 
312                         $o->binary = (strpos($f,'binary')!== false);
313                 }
314         /*      The $fieldOffset argument is not provided thus its -1   */
315                 else if ($fieldOffset == -1) {  
316                         $o = @mysql_fetch_field($this->_queryID);
317             // suggested by: Jim Nicholson (jnich@att.com)
318                         $o->max_length = @mysql_field_len($this->_queryID); 
319             // mysql returns the max length less spaces -- so it is unrealiable
320                         //$o->max_length = -1; 
321                 }
322                 
323                 return $o;
324         }
325
326         function &GetRowAssoc($upper=true)
327         {
328                 if ($this->fetchMode == MYSQL_ASSOC && !$upper) return $rs->fields;
329                 return ADORecordSet::GetRowAssoc($upper);
330         }
331         
332         /* Use associative array to get fields array */
333         function Fields($colname)
334         {
335                 if ($this->fetchMode != MYSQL_NUM) return $this->fields[$colname];
336                 
337                 if (!$this->bind) {
338                         $this->bind = array();
339                         for ($i=0; $i < $this->_numOfFields; $i++) {
340                                 $o = $this->FetchField($i);
341                                 $this->bind[strtoupper($o->name)] = $i;
342                         }
343                 }
344                  return $this->fields[$this->bind[strtoupper($colname)]];
345         }
346         
347         function _seek($row)
348         {
349                 return @mysql_data_seek($this->_queryID,$row);
350         }
351         
352         /*function &FetchRow()
353         {
354                 if ($this->EOF) return false;
355                 
356                 $arr = $this->fields;
357                 $this->_currentRow++;
358                         // using & below slows things down by 20%!
359                 $this->fields = @mysql_fetch_array($this->_queryID,$this->fetchMode);
360                         
361                 if (is_array($this->fields)) return $arr;
362                 $this->EOF = true;
363                 return false;
364         }*/
365         
366         // 10% speedup to move MoveNext to child class
367         function MoveNext() 
368         {
369                 if (!$this->EOF) {              
370                         $this->_currentRow++;
371                         // using & below slows things down by 20%!
372                         $this->fields = @mysql_fetch_array($this->_queryID,$this->fetchMode);
373                         
374                         if (is_array($this->fields)) return true;
375                         $this->EOF = true;
376                 }
377                 /* -- tested raising an error -- appears pointless
378                 $conn = $this->connection;
379                 if ($conn && $conn->raiseErrorFn && ($errno = $conn->ErrorNo())) {
380                         $fn = $conn->raiseErrorFn;
381                         $fn($conn->databaseType,'MOVENEXT',$errno,$conn->ErrorMsg().' ('.$this->sql.')',$conn->host,$conn->database);
382                 }
383                 */
384                 return false;
385         }       
386         
387         function _fetch()
388         {
389                 $this->fields = @mysql_fetch_array($this->_queryID,$this->fetchMode);
390                 return (is_array($this->fields));
391         }
392         
393         function _close() {
394                 @mysql_free_result($this->_queryID);    
395                 $this->_queryID = false;        
396         }
397         
398         function MetaType($t,$len=-1,$fieldobj=false)
399         {
400                 $len = -1; // mysql max_length is not accurate
401                 switch (strtoupper($t)) {
402                 case 'STRING': 
403                 case 'CHAR':
404                 case 'VARCHAR': 
405                 case 'TINYBLOB': 
406                 case 'TINYTEXT': 
407                 case 'ENUM': 
408                 case 'SET': 
409                         if ($len <= $this->blobSize) return 'C';
410                         
411                 case 'TEXT':
412                 case 'LONGTEXT': 
413                 case 'MEDIUMTEXT':
414                         return 'X';
415                         
416                 // php_mysql extension always returns 'blob' even if 'text'
417                 // so we have to check whether binary...
418                 case 'IMAGE':
419                 case 'LONGBLOB': 
420                 case 'BLOB':
421                 case 'MEDIUMBLOB':
422                         return !empty($fieldobj->binary) ? 'B' : 'X';
423                         
424                 case 'DATE': return 'D';
425                 
426                 case 'DATETIME':
427                 case 'TIMESTAMP': return 'T';
428                 
429                 case 'INT': 
430                 case 'INTEGER':
431                 case 'BIGINT':
432                 case 'TINYINT':
433                 case 'MEDIUMINT':
434                 case 'SMALLINT': 
435                         
436                         if (!empty($fieldobj->primary_key)) return 'R';
437                         else return 'I';
438                 
439                 default: return 'N';
440                 }
441         }
442
443 }
444 }
445 // For emacs users
446 // Local Variables:
447 // mode: php
448 // tab-width: 4
449 // c-basic-offset: 4
450 // c-hanging-comment-ender-p: nil
451 // indent-tabs-mode: nil
452 // End:
453 ?>