root/releases/elgg0.8rc2/lib/adodb/adodb-lib.inc.php

Revision 725, 33.4 kB (checked in by misja, 2 years ago)

Updated ADODB library.

  • Property svn:eol-style set to native
Line 
1 <?php
2
3 // security - hide paths
4 if (!defined('ADODB_DIR')) die();
5
6 global $ADODB_INCLUDED_LIB;
7 $ADODB_INCLUDED_LIB = 1;
8
9 /*
10  @version V4.93 10 Oct 2006 (c) 2000-2006 John Lim (jlim\@natsoft.com.my). All rights reserved.
11   Released under both BSD license and Lesser GPL library license.
12   Whenever there is any discrepancy between the two licenses,
13   the BSD license will take precedence. See License.txt.
14   Set tabs to 4 for best viewing.
15  
16   Less commonly used functions are placed here to reduce size of adodb.inc.php.
17 */
18
19 function adodb_probetypes(&$array,&$types,$probe=8)
20 {
21 // probe and guess the type
22     $types = array();
23     if ($probe > sizeof($array)) $max = sizeof($array);
24     else $max = $probe;
25     
26     
27     for ($j=0;$j < $max; $j++) {
28         $row =& $array[$j];
29         if (!$row) break;
30         $i = -1;
31         foreach($row as $v) {
32             $i += 1;
33
34             if (isset($types[$i]) && $types[$i]=='C') continue;
35             
36             //print " ($i ".$types[$i]. "$v) ";
37             $v = trim($v);
38             
39             if (!preg_match('/^[+-]{0,1}[0-9\.]+$/',$v)) {
40                 $types[$i] = 'C'; // once C, always C
41                 
42                 continue;
43             }
44             if ($j == 0) {
45             // If empty string, we presume is character
46             // test for integer for 1st row only
47             // after that it is up to testing other rows to prove
48             // that it is not an integer
49                 if (strlen($v) == 0) $types[$i] = 'C';
50                 if (strpos($v,'.') !== false) $types[$i] = 'N';
51                 else  $types[$i] = 'I';
52                 continue;
53             }
54             
55             if (strpos($v,'.') !== false) $types[$i] = 'N';
56             
57         }
58     }
59 }
60
61 function  &adodb_transpose(&$arr, &$newarr, &$hdr)
62 {
63     $oldX = sizeof(reset($arr));
64     $oldY = sizeof($arr);   
65     
66     if ($hdr) {
67         $startx = 1;
68         $hdr = array();
69         for ($y = 0; $y < $oldY; $y++) {
70             $hdr[] = $arr[$y][0];
71         }
72     } else
73         $startx = 0;
74
75     for ($x = $startx; $x < $oldX; $x++) {
76         $newarr[] = array();
77         for ($y = 0; $y < $oldY; $y++) {
78             $newarr[$x-$startx][] = $arr[$y][$x];
79         }
80     }
81 }
82
83 // Force key to upper.
84 // See also http://www.php.net/manual/en/function.array-change-key-case.php
85 function _array_change_key_case($an_array)
86 {
87     if (is_array($an_array)) {
88         $new_array = array();
89         foreach($an_array as $key=>$value)
90             $new_array[strtoupper($key)] = $value;
91
92            return $new_array;
93    }
94
95     return $an_array;
96 }
97
98 function _adodb_replace(&$zthis, $table, $fieldArray, $keyCol, $autoQuote, $has_autoinc)
99 {
100         if (count($fieldArray) == 0) return 0;
101         $first = true;
102         $uSet = '';
103         
104         if (!is_array($keyCol)) {
105             $keyCol = array($keyCol);
106         }
107         foreach($fieldArray as $k => $v) {
108             if ($autoQuote && !is_numeric($v) and strncmp($v,"'",1) !== 0 and strcasecmp($v,$zthis->null2null)!=0) {
109                 $v = $zthis->qstr($v);
110                 $fieldArray[$k] = $v;
111             }
112             if (in_array($k,$keyCol)) continue; // skip UPDATE if is key
113             
114             if ($first) {
115                 $first = false;           
116                 $uSet = "$k=$v";
117             } else
118                 $uSet .= ",$k=$v";
119         }
120         
121         $where = false;
122         foreach ($keyCol as $v) {
123             if (isset($fieldArray[$v])) {
124                 if ($where) $where .= ' and '.$v.'='.$fieldArray[$v];
125                 else $where = $v.'='.$fieldArray[$v];
126             }
127         }
128         
129         if ($uSet && $where) {
130             $update = "UPDATE $table SET $uSet WHERE $where";
131
132             $rs = $zthis->Execute($update);
133             
134             
135             if ($rs) {
136                 if ($zthis->poorAffectedRows) {
137                 /*
138                  The Select count(*) wipes out any errors that the update would have returned.
139                 http://phplens.com/lens/lensforum/msgs.php?id=5696
140                 */
141                     if ($zthis->ErrorNo()<>0) return 0;
142                     
143                 # affected_rows == 0 if update field values identical to old values
144                 # for mysql - which is silly.
145             
146                     $cnt = $zthis->GetOne("select count(*) from $table where $where");
147                     if ($cnt > 0) return 1; // record already exists
148                 } else {
149                     if (($zthis->Affected_Rows()>0)) return 1;
150                 }
151             } else
152                 return 0;
153         }
154         
155     //    print "<p>Error=".$this->ErrorNo().'<p>';
156         $first = true;
157         foreach($fieldArray as $k => $v) {
158             if ($has_autoinc && in_array($k,$keyCol)) continue; // skip autoinc col
159             
160             if ($first) {
161                 $first = false;           
162                 $iCols = "$k";
163                 $iVals = "$v";
164             } else {
165                 $iCols .= ",$k";
166                 $iVals .= ",$v";
167             }               
168         }
169         $insert = "INSERT INTO $table ($iCols) VALUES ($iVals)";
170         $rs = $zthis->Execute($insert);
171         return ($rs) ? 2 : 0;
172 }
173
174 // Requires $ADODB_FETCH_MODE = ADODB_FETCH_NUM
175 function _adodb_getmenu(&$zthis, $name,$defstr='',$blank1stItem=true,$multiple=false,
176             $size=0, $selectAttr='',$compareFields0=true)
177 {
178     $hasvalue = false;
179
180     if ($multiple or is_array($defstr)) {
181         if ($size==0) $size=5;
182         $attr = ' multiple size="'.$size.'"';
183         if (!strpos($name,'[]')) $name .= '[]';
184     } else if ($size) $attr = ' size="'.$size.'"';
185     else $attr ='';
186     
187     $s = '<select name="'.$name.'"'.$attr.' '.$selectAttr.'>';
188     if ($blank1stItem)
189         if (is_string($blank1stItem))  {
190             $barr = explode(':',$blank1stItem);
191             if (sizeof($barr) == 1) $barr[] = '';
192             $s .= "\n<option value=\"".$barr[0]."\">".$barr[1]."</option>";
193         } else $s .= "\n<option></option>";
194
195     if ($zthis->FieldCount() > 1) $hasvalue=true;
196     else $compareFields0 = true;
197     
198     $value = '';
199     $optgroup = null;
200     $firstgroup = true;
201     $fieldsize = $zthis->FieldCount();
202     while(!$zthis->EOF) {
203         $zval = rtrim(reset($zthis->fields));
204
205         if ($blank1stItem && $zval=="") {
206             $zthis->MoveNext();
207             continue;
208         }
209
210         if ($fieldsize > 1) {
211             if (isset($zthis->fields[1]))
212                 $zval2 = rtrim($zthis->fields[1]);
213             else
214                 $zval2 = rtrim(next($zthis->fields));
215         }
216         $selected = ($compareFields0) ? $zval : $zval2;
217         
218         $group = '';
219         if ($fieldsize > 2) {
220             $group = rtrim($zthis->fields[2]);
221         }
222 /*
223         if ($optgroup != $group) {
224             $optgroup = $group;
225             if ($firstgroup) {
226                 $firstgroup = false;
227                 $s .="\n<optgroup label='". htmlspecialchars($group) ."'>";
228             } else {
229                 $s .="\n</optgroup>";
230                 $s .="\n<optgroup label='". htmlspecialchars($group) ."'>";
231             }
232         }
233 */
234         if ($hasvalue)
235             $value = " value='".htmlspecialchars($zval2)."'";
236         
237         if (is_array($defstr))  {
238             
239             if (in_array($selected,$defstr))
240                 $s .= "\n<option selected='selected'$value>".htmlspecialchars($zval).'</option>';
241             else
242                 $s .= "\n<option".$value.'>'.htmlspecialchars($zval).'</option>';
243         }
244         else {
245             if (strcasecmp($selected,$defstr)==0)
246                 $s .= "\n<option selected='selected'$value>".htmlspecialchars($zval).'</option>';
247             else
248                 $s .= "\n<option".$value.'>'.htmlspecialchars($zval).'</option>';
249         }
250         $zthis->MoveNext();
251     } // while
252     
253     // closing last optgroup
254     if($optgroup != null) {
255         $s .= "\n</optgroup>";
256     }
257     return $s ."\n</select>\n";
258 }
259
260 // Requires $ADODB_FETCH_MODE = ADODB_FETCH_NUM
261 function _adodb_getmenu_gp(&$zthis, $name,$defstr='',$blank1stItem=true,$multiple=false,
262             $size=0, $selectAttr='',$compareFields0=true)
263 {
264     $hasvalue = false;
265
266     if ($multiple or is_array($defstr)) {
267         if ($size==0) $size=5;
268         $attr = ' multiple size="'.$size.'"';
269         if (!strpos($name,'[]')) $name .= '[]';
270     } else if ($size) $attr = ' size="'.$size.'"';
271     else $attr ='';
272     
273     $s = '<select name="'.$name.'"'.$attr.' '.$selectAttr.'>';
274     if ($blank1stItem)
275         if (is_string($blank1stItem))  {
276             $barr = explode(':',$blank1stItem);
277             if (sizeof($barr) == 1) $barr[] = '';
278             $s .= "\n<option value=\"".$barr[0]."\">".$barr[1]."</option>";
279         } else $s .= "\n<option></option>";
280
281     if ($zthis->FieldCount() > 1) $hasvalue=true;
282     else $compareFields0 = true;
283     
284     $value = '';
285     $optgroup = null;
286     $firstgroup = true;
287     $fieldsize = sizeof($zthis->fields);
288     while(!$zthis->EOF) {
289         $zval = rtrim(reset($zthis->fields));
290
291         if ($blank1stItem && $zval=="") {
292             $zthis->MoveNext();
293             continue;
294         }
295
296         if ($fieldsize > 1) {
297             if (isset($zthis->fields[1]))
298                 $zval2 = rtrim($zthis->fields[1]);
299             else
300                 $zval2 = rtrim(next($zthis->fields));
301         }
302         $selected = ($compareFields0) ? $zval : $zval2;
303         
304         $group = '';
305         if (isset($zthis->fields[2])) {
306             $group = rtrim($zthis->fields[2]);
307         }
308  
309         if ($optgroup != $group) {
310             $optgroup = $group;
311             if ($firstgroup) {
312                 $firstgroup = false;
313                 $s .="\n<optgroup label='". htmlspecialchars($group) ."'>";
314             } else {
315                 $s .="\n</optgroup>";
316                 $s .="\n<optgroup label='". htmlspecialchars($group) ."'>";
317             }
318         }
319     
320         if ($hasvalue)
321             $value = " value='".htmlspecialchars($zval2)."'";
322         
323         if (is_array($defstr))  {
324             
325             if (in_array($selected,$defstr))
326                 $s .= "\n<option selected='selected'$value>".htmlspecialchars($zval).'</option>';
327             else
328                 $s .= "\n<option".$value.'>'.htmlspecialchars($zval).'</option>';
329         }
330         else {
331             if (strcasecmp($selected,$defstr)==0)
332                 $s .= "\n<option selected='selected'$value>".htmlspecialchars($zval).'</option>';
333             else
334                 $s .= "\n<option".$value.'>'.htmlspecialchars($zval).'</option>';
335         }
336         $zthis->MoveNext();
337     } // while
338     
339     // closing last optgroup
340     if($optgroup != null) {
341         $s .= "\n</optgroup>";
342     }
343     return $s ."\n</select>\n";
344 }
345
346
347 /*
348     Count the number of records this sql statement will return by using
349     query rewriting heuristics...
350     
351     Does not work with UNIONs, except with postgresql and oracle.
352     
353     Usage:
354     
355     $conn->Connect(...);
356     $cnt = _adodb_getcount($conn, $sql);
357     
358 */
359 function _adodb_getcount(&$zthis, $sql,$inputarr=false,$secs2cache=0)
360 {
361     $qryRecs = 0;
362     
363      if (!empty($zthis->_nestedSQL) || preg_match("/^\s*SELECT\s+DISTINCT/is", $sql) ||
364          preg_match('/\s+GROUP\s+BY\s+/is',$sql) ||
365         preg_match('/\s+UNION\s+/is',$sql)) {
366         // ok, has SELECT DISTINCT or GROUP BY so see if we can use a table alias
367         // but this is only supported by oracle and postgresql...
368         if ($zthis->dataProvider == 'oci8') {
369             
370             $rewritesql = preg_replace('/(\sORDER\s+BY\s[^)]*)/is','',$sql);
371             
372             // Allow Oracle hints to be used for query optimization, Chris Wrye
373             if (preg_match('#/\\*+.*?\\*\\/#', $sql, $hint)) {
374                 $rewritesql = "SELECT ".$hint[0]." COUNT(*) FROM (".$rewritesql.")";
375             } else
376                 $rewritesql = "SELECT COUNT(*) FROM (".$rewritesql.")";
377             
378         } else if (strncmp($zthis->databaseType,'postgres',8) == 0)  {
379             $rewritesql = preg_replace('/(\sORDER\s+BY\s[^)]*)/is','',$sql);
380             $rewritesql = "SELECT COUNT(*) FROM ($rewritesql) _ADODB_ALIAS_";
381         }
382     } else {
383         // now replace SELECT ... FROM with SELECT COUNT(*) FROM
384         $rewritesql = preg_replace(
385                     '/^\s*SELECT\s.*\s+FROM\s/Uis','SELECT COUNT(*) FROM ',$sql);
386
387         
388         
389         // fix by alexander zhukov, alex#unipack.ru, because count(*) and 'order by' fails
390         // with mssql, access and postgresql. Also a good speedup optimization - skips sorting!
391         // also see http://phplens.com/lens/lensforum/msgs.php?id=12752
392         if (preg_match('/\sORDER\s+BY\s*\(/i',$rewritesql))
393             $rewritesql = preg_replace('/(\sORDER\s+BY\s.*)/is','',$rewritesql);
394         else
395             $rewritesql = preg_replace('/(\sORDER\s+BY\s[^)]*)/is','',$rewritesql);
396     }
397     
398     
399     
400     if (isset($rewritesql) && $rewritesql != $sql) {
401         if (preg_match('/\sLIMIT\s+[0-9]+/i',$sql,$limitarr)) $rewritesql .= $limitarr[1];
402         
403         if ($secs2cache) {
404             // we only use half the time of secs2cache because the count can quickly
405             // become inaccurate if new records are added
406             $qryRecs = $zthis->CacheGetOne($secs2cache/2,$rewritesql,$inputarr);
407             
408         } else {
409             $qryRecs = $zthis->GetOne($rewritesql,$inputarr);
410           }
411         if ($qryRecs !== false) return $qryRecs;
412     }
413     //--------------------------------------------
414     // query rewrite failed - so try slower way...
415     
416     
417     // strip off unneeded ORDER BY if no UNION
418     if (preg_match('/\s*UNION\s*/is', $sql)) $rewritesql = $sql;
419     else $rewritesql = preg_replace('/(\sORDER\s+BY\s.*)/is','',$sql);
420     
421     if (preg_match('/\sLIMIT\s+[0-9]+/i',$sql,$limitarr)) $rewritesql .= $limitarr[0];
422         
423     $rstest = &$zthis->Execute($rewritesql,$inputarr);
424     if (!$rstest) $rstest = $zthis->Execute($sql,$inputarr);
425     
426     if ($rstest) {
427               $qryRecs = $rstest->RecordCount();
428         if ($qryRecs == -1) {
429         global $ADODB_EXTENSION;
430         // some databases will return -1 on MoveLast() - change to MoveNext()
431             if ($ADODB_EXTENSION) {
432                 while(!$rstest->EOF) {
433                     adodb_movenext($rstest);
434                 }
435             } else {
436                 while(!$rstest->EOF) {
437                     $rstest->MoveNext();
438                 }
439             }
440             $qryRecs = $rstest->_currentRow;
441         }
442         $rstest->Close();
443         if ($qryRecs == -1) return 0;
444     }
445     return $qryRecs;
446 }
447
448 /*
449      Code originally from "Cornel G" <conyg@fx.ro>
450
451     This code might not work with SQL that has UNION in it   
452     
453     Also if you are using CachePageExecute(), there is a strong possibility that
454     data will get out of synch. use CachePageExecute() only with tables that
455     rarely change.
456 */
457 function &_adodb_pageexecute_all_rows(&$zthis, $sql, $nrows, $page,
458                         $inputarr=false, $secs2cache=0)
459 {
460     $atfirstpage = false;
461     $atlastpage = false;
462     $lastpageno=1;
463
464     // If an invalid nrows is supplied,
465     // we assume a default value of 10 rows per page
466     if (!isset($nrows) || $nrows <= 0) $nrows = 10;
467
468     $qryRecs = false; //count records for no offset
469     
470     $qryRecs = _adodb_getcount($zthis,$sql,$inputarr,$secs2cache);
471     $lastpageno = (int) ceil($qryRecs / $nrows);
472     $zthis->_maxRecordCount = $qryRecs;
473     
474
475<