[ Index ]
 

Code source de Mantis 1.1.0rc3

Accédez au Source d'autres logiciels libres

Classes | Fonctions | Variables | Constantes | Tables

title

Body

[fermer]

/core/adodb/ -> adodb-lib.inc.php (source)

   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.94 23 Jan 2007 (c) 2000-2007 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_strip_order_by($sql)
  20  {
  21      $rez = preg_match('/(\sORDER\s+BY\s[^)]*)/is',$sql,$arr);
  22      if ($arr)
  23          if (strpos($arr[0],'(') !== false) {
  24              $at = strpos($sql,$arr[0]);
  25              $cntin = 0;
  26              for ($i=$at, $max=strlen($sql); $i < $max; $i++) {
  27                  $ch = $sql[$i];
  28                  if ($ch == '(') {
  29                      $cntin += 1;
  30                  } elseif($ch == ')') {
  31                      $cntin -= 1;
  32                      if ($cntin < 0) {
  33                          break;
  34                      }
  35                  }
  36              }
  37              $sql = substr($sql,0,$at).substr($sql,$i);
  38          } else
  39              $sql = str_replace($arr[0], '', $sql); 
  40      return $sql;
  41   }
  42  
  43  if (false) {
  44      $sql = 'select * from (select a from b order by a(b),b(c) desc)';
  45      $sql = '(select * from abc order by 1)';
  46      die(adodb_strip_order_by($sql));
  47  }
  48  
  49  function adodb_probetypes(&$array,&$types,$probe=8)
  50  {
  51  // probe and guess the type
  52      $types = array();
  53      if ($probe > sizeof($array)) $max = sizeof($array);
  54      else $max = $probe;
  55      
  56      
  57      for ($j=0;$j < $max; $j++) {
  58          $row =& $array[$j];
  59          if (!$row) break;
  60          $i = -1;
  61          foreach($row as $v) {
  62              $i += 1;
  63  
  64              if (isset($types[$i]) && $types[$i]=='C') continue;
  65              
  66              //print " ($i ".$types[$i]. "$v) ";
  67              $v = trim($v);
  68              
  69              if (!preg_match('/^[+-]{0,1}[0-9\.]+$/',$v)) {
  70                  $types[$i] = 'C'; // once C, always C
  71                  
  72                  continue;
  73              }
  74              if ($j == 0) { 
  75              // If empty string, we presume is character
  76              // test for integer for 1st row only
  77              // after that it is up to testing other rows to prove
  78              // that it is not an integer
  79                  if (strlen($v) == 0) $types[$i] = 'C';
  80                  if (strpos($v,'.') !== false) $types[$i] = 'N';
  81                  else  $types[$i] = 'I';
  82                  continue;
  83              }
  84              
  85              if (strpos($v,'.') !== false) $types[$i] = 'N';
  86              
  87          }
  88      }
  89      
  90  }
  91  
  92  function  adodb_transpose(&$arr, &$newarr, &$hdr, &$fobjs)
  93  {
  94      $oldX = sizeof(reset($arr));
  95      $oldY = sizeof($arr);    
  96      
  97      if ($hdr) {
  98          $startx = 1;
  99          $hdr = array('Fields');
 100          for ($y = 0; $y < $oldY; $y++) {
 101              $hdr[] = $arr[$y][0];
 102          }
 103      } else
 104          $startx = 0;
 105  
 106      for ($x = $startx; $x < $oldX; $x++) {
 107          if ($fobjs) {
 108              $o = $fobjs[$x];
 109              $newarr[] = array($o->name);
 110          } else
 111              $newarr[] = array();
 112              
 113          for ($y = 0; $y < $oldY; $y++) {
 114              $newarr[$x-$startx][] = $arr[$y][$x];
 115          }
 116      }
 117  }
 118  
 119  // Force key to upper. 
 120  // See also http://www.php.net/manual/en/function.array-change-key-case.php
 121  function _array_change_key_case($an_array)
 122  {
 123      if (is_array($an_array)) {
 124          $new_array = array();
 125          foreach($an_array as $key=>$value)
 126              $new_array[strtoupper($key)] = $value;
 127  
 128             return $new_array;
 129     }
 130  
 131      return $an_array;
 132  }
 133  
 134  function _adodb_replace(&$zthis, $table, $fieldArray, $keyCol, $autoQuote, $has_autoinc)
 135  {
 136          if (count($fieldArray) == 0) return 0;
 137          $first = true;
 138          $uSet = '';
 139          
 140          if (!is_array($keyCol)) {
 141              $keyCol = array($keyCol);
 142          }
 143          foreach($fieldArray as $k => $v) {
 144              if ($v === null) {
 145                  $v = 'NULL';
 146                  $fieldArray[$k] = $v;
 147              } else if ($autoQuote && !is_numeric($v) /*and strncmp($v,"'",1) !== 0 -- sql injection risk*/ and strcasecmp($v,$zthis->null2null)!=0) {
 148                  $v = $zthis->qstr($v);
 149                  $fieldArray[$k] = $v;
 150              }
 151              if (in_array($k,$keyCol)) continue; // skip UPDATE if is key
 152              
 153              if ($first) {
 154                  $first = false;            
 155                  $uSet = "$k=$v";
 156              } else
 157                  $uSet .= ",$k=$v";
 158          }
 159           
 160          $where = false;
 161          foreach ($keyCol as $v) {
 162              if (isset($fieldArray[$v])) {
 163                  if ($where) $where .= ' and '.$v.'='.$fieldArray[$v];
 164                  else $where = $v.'='.$fieldArray[$v];
 165              }
 166          }
 167          
 168          if ($uSet && $where) {
 169              $update = "UPDATE $table SET $uSet WHERE $where";
 170  
 171              $rs = $zthis->Execute($update);
 172              
 173              
 174              if ($rs) {
 175                  if ($zthis->poorAffectedRows) {
 176                  /*
 177                   The Select count(*) wipes out any errors that the update would have returned. 
 178                  http://phplens.com/lens/lensforum/msgs.php?id=5696
 179                  */
 180                      if ($zthis->ErrorNo()<>0) return 0;
 181                      
 182                  # affected_rows == 0 if update field values identical to old values
 183                  # for mysql - which is silly. 
 184              
 185                      $cnt = $zthis->GetOne("select count(*) from $table where $where");
 186                      if ($cnt > 0) return 1; // record already exists
 187                  } else {
 188                      if (($zthis->Affected_Rows()>0)) return 1;
 189                  }
 190              } else
 191                  return 0;
 192          }
 193          
 194      //    print "<p>Error=".$this->ErrorNo().'<p>';
 195          $first = true;
 196          foreach($fieldArray as $k => $v) {
 197              if ($has_autoinc && in_array($k,$keyCol)) continue; // skip autoinc col
 198              
 199              if ($first) {
 200                  $first = false;            
 201                  $iCols = "$k";
 202                  $iVals = "$v";
 203              } else {
 204                  $iCols .= ",$k";
 205                  $iVals .= ",$v";
 206              }                
 207          }
 208          $insert = "INSERT INTO $table ($iCols) VALUES ($iVals)"; 
 209          $rs = $zthis->Execute($insert);
 210          return ($rs) ? 2 : 0;
 211  }
 212  
 213  // Requires $ADODB_FETCH_MODE = ADODB_FETCH_NUM
 214  function _adodb_getmenu(&$zthis, $name,$defstr='',$blank1stItem=true,$multiple=false,
 215              $size=0, $selectAttr='',$compareFields0=true)
 216  {
 217      $hasvalue = false;
 218  
 219      if ($multiple or is_array($defstr)) {
 220          if ($size==0) $size=5;
 221          $attr = ' multiple size="'.$size.'"';
 222          if (!strpos($name,'[]')) $name .= '[]';
 223      } else if ($size) $attr = ' size="'.$size.'"';
 224      else $attr ='';
 225      
 226      $s = '<select name="'.$name.'"'.$attr.' '.$selectAttr.'>';
 227      if ($blank1stItem) 
 228          if (is_string($blank1stItem))  {
 229              $barr = explode(':',$blank1stItem);
 230              if (sizeof($barr) == 1) $barr[] = '';
 231              $s .= "\n<option value=\"".$barr[0]."\">".$barr[1]."</option>";
 232          } else $s .= "\n<option></option>";
 233  
 234      if ($zthis->FieldCount() > 1) $hasvalue=true;
 235      else $compareFields0 = true;
 236      
 237      $value = '';
 238      $optgroup = null;
 239      $firstgroup = true;
 240      $fieldsize = $zthis->FieldCount();
 241      while(!$zthis->EOF) {
 242          $zval = rtrim(reset($zthis->fields));
 243  
 244          if ($blank1stItem && $zval=="") {
 245              $zthis->MoveNext();
 246              continue;
 247          }
 248  
 249          if ($fieldsize > 1) {
 250              if (isset($zthis->fields[1]))
 251                  $zval2 = rtrim($zthis->fields[1]);
 252              else
 253                  $zval2 = rtrim(next($zthis->fields));
 254          }
 255          $selected = ($compareFields0) ? $zval : $zval2;
 256          
 257          $group = '';
 258          if ($fieldsize > 2) {
 259              $group = rtrim($zthis->fields[2]);
 260          }
 261  /* 
 262          if ($optgroup != $group) {
 263              $optgroup = $group;
 264              if ($firstgroup) {
 265                  $firstgroup = false;
 266                  $s .="\n<optgroup label='". htmlspecialchars($group) ."'>";
 267              } else {
 268                  $s .="\n</optgroup>";
 269                  $s .="\n<optgroup label='". htmlspecialchars($group) ."'>";
 270              }
 271          }
 272  */
 273          if ($hasvalue) 
 274              $value = " value='".htmlspecialchars($zval2)."'";
 275          
 276          if (is_array($defstr))  {
 277              
 278              if (in_array($selected,$defstr)) 
 279                  $s .= "\n<option selected='selected'$value>".htmlspecialchars($zval).'</option>';
 280              else 
 281                  $s .= "\n<option".$value.'>'.htmlspecialchars($zval).'</option>';
 282          }
 283          else {
 284              if (strcasecmp($selected,$defstr)==0) 
 285                  $s .= "\n<option selected='selected'$value>".htmlspecialchars($zval).'</option>';
 286              else
 287                  $s .= "\n<option".$value.'>'.htmlspecialchars($zval).'</option>';
 288          }
 289          $zthis->MoveNext();
 290      } // while
 291      
 292      // closing last optgroup
 293      if($optgroup != null) {
 294          $s .= "\n</optgroup>";
 295      }
 296      return $s ."\n</select>\n";
 297  }
 298  
 299  // Requires $ADODB_FETCH_MODE = ADODB_FETCH_NUM
 300  function _adodb_getmenu_gp(&$zthis, $name,$defstr='',$blank1stItem=true,$multiple=false,
 301              $size=0, $selectAttr='',$compareFields0=true)
 302  {
 303      $hasvalue = false;
 304  
 305      if ($multiple or is_array($defstr)) {
 306          if ($size==0) $size=5;
 307          $attr = ' multiple size="'.$size.'"';
 308          if (!strpos($name,'[]')) $name .= '[]';
 309      } else if ($size) $attr = ' size="'.$size.'"';
 310      else $attr ='';
 311      
 312      $s = '<select name="'.$name.'"'.$attr.' '.$selectAttr.'>';
 313      if ($blank1stItem) 
 314          if (is_string($blank1stItem))  {
 315              $barr = explode(':',$blank1stItem);
 316              if (sizeof($barr) == 1) $barr[] = '';
 317              $s .= "\n<option value=\"".$barr[0]."\">".$barr[1]."</option>";
 318          } else $s .= "\n<option></option>";
 319  
 320      if ($zthis->FieldCount() > 1) $hasvalue=true;
 321      else $compareFields0 = true;
 322      
 323      $value = '';
 324      $optgroup = null;
 325      $firstgroup = true;
 326      $fieldsize = sizeof($zthis->fields);
 327      while(!$zthis->EOF) {
 328          $zval = rtrim(reset($zthis->fields));
 329  
 330          if ($blank1stItem && $zval=="") {
 331              $zthis->MoveNext();
 332              continue;
 333          }
 334  
 335          if ($fieldsize > 1) {
 336              if (isset($zthis->fields[1]))
 337                  $zval2 = rtrim($zthis->fields[1]);
 338              else
 339                  $zval2 = rtrim(next($zthis->fields));
 340          }
 341          $selected = ($compareFields0) ? $zval : $zval2;
 342          
 343          $group = '';
 344          if (isset($zthis->fields[2])) {
 345              $group = rtrim($zthis->fields[2]);
 346          }
 347   
 348          if ($optgroup != $group) {
 349              $optgroup = $group;
 350              if ($firstgroup) {
 351                  $firstgroup = false;
 352                  $s .="\n<optgroup label='". htmlspecialchars($group) ."'>";
 353              } else {
 354                  $s .="\n</optgroup>";
 355                  $s .="\n<optgroup label='". htmlspecialchars($group) ."'>";
 356              }
 357          }
 358      
 359          if ($hasvalue) 
 360              $value = " value='".htmlspecialchars($zval2)."'";
 361          
 362          if (is_array($defstr))  {
 363              
 364              if (in_array($selected,$defstr)) 
 365                  $s .= "\n<option selected='selected'$value>".htmlspecialchars($zval).'</option>';
 366              else 
 367                  $s .= "\n<option".$value.'>'.htmlspecialchars($zval).'</option>';
 368          }
 369          else {
 370              if (strcasecmp($selected,$defstr)==0) 
 371                  $s .= "\n<option selected='selected'$value>".htmlspecialchars($zval).'</option>';
 372              else
 373                  $s .= "\n<option".$value.'>'.htmlspecialchars($zval).'</option>';
 374          }
 375          $zthis->MoveNext();
 376      } // while
 377      
 378      // closing last optgroup
 379      if($optgroup != null) {
 380          $s .= "\n</optgroup>";
 381      }
 382      return $s ."\n</select>\n";
 383  }
 384  
 385  
 386  /*
 387      Count the number of records this sql statement will return by using
 388      query rewriting heuristics...
 389      
 390      Does not work with UNIONs, except with postgresql and oracle.
 391      
 392      Usage:
 393      
 394      $conn->Connect(...);
 395      $cnt = _adodb_getcount($conn, $sql);
 396      
 397  */
 398  function _adodb_getcount(&$zthis, $sql,$inputarr=false,$secs2cache=0) 
 399  {
 400      $qryRecs = 0;
 401      
 402       if (!empty($zthis->_nestedSQL) || preg_match("/^\s*SELECT\s+DISTINCT/is", $sql) || 
 403           preg_match('/\s+GROUP\s+BY\s+/is',$sql) || 
 404          preg_match('/\s+UNION\s+/is',$sql)) {
 405          
 406          $rewritesql = adodb_strip_order_by($sql);
 407          
 408          // ok, has SELECT DISTINCT or GROUP BY so see if we can use a table alias
 409          // but this is only supported by oracle and postgresql...
 410          if ($zthis->dataProvider == 'oci8') {
 411              // Allow Oracle hints to be used for query optimization, Chris Wrye
 412              if (preg_match('#/\\*+.*?\\*\\/#', $sql, $hint)) {
 413                  $rewritesql = "SELECT ".$hint[0]." COUNT(*) FROM (".$rewritesql.")"; 
 414              } else
 415                  $rewritesql = "SELECT COUNT(*) FROM (".$rewritesql.")"; 
 416              
 417          } else if (strncmp($zthis->databaseType,'postgres',8) == 0)  {
 418              $rewritesql = "SELECT COUNT(*) FROM ($rewritesql) _ADODB_ALIAS_";
 419          }
 420      } else {        
 421          // now replace SELECT ... FROM with SELECT COUNT(*) FROM
 422          $rewritesql = preg_replace(
 423                      '/^\s*SELECT\s.*\s+FROM\s/Uis','SELECT COUNT(*) FROM ',$sql);
 424          // fix by alexander zhukov, alex#unipack.ru, because count(*) and 'order by' fails 
 425          // with mssql, access and postgresql. Also a good speedup optimization - skips sorting!
 426          // also see http://phplens.com/lens/lensforum/msgs.php?id=12752
 427          $rewritesql = adodb_strip_order_by($rewritesql);
 428      }
 429      
 430      if (isset($rewritesql) && $rewritesql != $sql) {
 431          if (preg_match('/\sLIMIT\s+[0-9]+/i',$sql,$limitarr)) $rewritesql .= $limitarr[0];
 432  
 433          if ($secs2cache) {
 434              // we only use half the time of secs2cache because the count can quickly
 435              // become inaccurate if new records are added
 436              $qryRecs = $zthis->CacheGetOne($secs2cache/2,$rewritesql,$inputarr);
 437              
 438          } else {
 439              $qryRecs = $zthis->GetOne($rewritesql,$inputarr);
 440            }
 441          if ($qryRecs !== false) return $qryRecs;
 442      }
 443      //--------------------------------------------
 444      // query rewrite failed - so try slower way...
 445      
 446      
 447      // strip off unneeded ORDER BY if no UNION
 448      if (preg_match('/\s*UNION\s*/is', $sql)) $rewritesql = $sql;
 449      else $rewritesql = $rewritesql = adodb_strip_order_by($sql); 
 450      
 451      if (preg_match('/\sLIMIT\s+[0-9]+/i',$sql,$limitarr)) $rewritesql .= $limitarr[0];
 452          
 453      $rstest = &$zthis->Execute($rewritesql,$inputarr);
 454      if (!$rstest) $rstest = $zthis->Execute($sql,$inputarr);
 455      
 456      if ($rstest) {
 457                $qryRecs = $rstest->RecordCount();
 458          if ($qryRecs == -1) { 
 459          global $ADODB_EXTENSION;
 460          // some databases will return -1 on MoveLast() - change to MoveNext()
 461              if ($ADODB_EXTENSION) {
 462                  while(!$rstest->EOF) {
 463                      adodb_movenext($rstest);
 464                  }
 465              } else {
 466                  while(!$rstest->EOF) {
 467                      $rstest->MoveNext();
 468                  }
 469              }
 470              $qryRecs = $rstest->_currentRow;
 471          }
 472          $rstest->Close();
 473          if ($qryRecs == -1) return 0;
 474      }
 475      return $qryRecs;
 476  }
 477  
 478  /*
 479       Code originally from "Cornel G" <conyg@fx.ro>
 480  
 481      This code might not work with SQL that has UNION in it    
 482      
 483      Also if you are using CachePageExecute(), there is a strong possibility that
 484      data will get out of synch. use CachePageExecute() only with tables that
 485      rarely change.
 486  */
 487  function &_adodb_pageexecute_all_rows(&$zthis, $sql, $nrows, $page, 
 488                          $inputarr=false, $secs2cache=0) 
 489  {
 490      $atfirstpage = false;
 491      $atlastpage = false;
 492      $lastpageno=1;
 493  
 494      // If an invalid nrows is supplied, 
 495      // we assume a default value of 10 rows per page
 496      if (!isset($nrows) || $nrows <= 0) $nrows = 10;
 497  
 498      $qryRecs = false; //count records for no offset
 499      
 500      $qryRecs = _adodb_getcount($zthis,$sql,$inputarr,$secs2cache);
 501      $lastpageno = (int) ceil($qryRecs / $nrows);
 502      $zthis->_maxRecordCount = $qryRecs;
 503      
 504  
 505  
 506      // ***** Here we check whether $page is the last page or 
 507      // whether we are trying to retrieve 
 508      // a page number greater than the last page number.
 509      if ($page >= $lastpageno) {
 510          $page = $lastpageno;
 511          $atlastpage = true;
 512      }
 513      
 514      // If page number <= 1, then we are at the first page
 515      if (empty($page) || $page <= 1) {    
 516          $page = 1;
 517          $atfirstpage = true;
 518      }
 519      
 520      // We get the data we want
 521      $offset = $nrows * ($page-1);
 522      if ($secs2cache > 0) 
 523          $rsreturn = &$zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $offset, $inputarr);
 524      else 
 525          $rsreturn = &$zthis->SelectLimit($sql, $nrows, $offset, $inputarr, $secs2cache);
 526  
 527      
 528      // Before returning the RecordSet, we set the pagination properties we need
 529      if ($rsreturn) {
 530          $rsreturn->_maxRecordCount = $qryRecs;
 531          $rsreturn->rowsPerPage = $nrows;
 532          $rsreturn->AbsolutePage($page);
 533          $rsreturn->AtFirstPage($atfirstpage);
 534          $rsreturn->AtLastPage($atlastpage);
 535          $rsreturn->LastPageNo($lastpageno);
 536      }
 537      return $rsreturn;
 538  }
 539  
 540  // Iván Oliva version
 541  function &_adodb_pageexecute_no_last_page(&$zthis, $sql, $nrows, $page, $inputarr=false, $secs2cache=0) 
 542  {
 543  
 544      $atfirstpage = false;
 545      $atlastpage = false;
 546      
 547      if (!isset($page) || $page <= 1) {    // If page number <= 1, then we are at the first page
 548          $page = 1;
 549          $atfirstpage = true;
 550      }
 551      if ($nrows <= 0) $nrows = 10;    // If an invalid nrows is supplied, we assume a default value of 10 rows per page
 552      
 553      // ***** Here we check whether $page is the last page or whether we are trying to retrieve a page number greater than 
 554      // the last page number.
 555      $pagecounter = $page + 1;
 556      $pagecounteroffset = ($pagecounter * $nrows) - $nrows;
 557      if ($secs2cache>0) $rstest = &$zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $pagecounteroffset, $inputarr);
 558      else $rstest = &$zthis->SelectLimit($sql, $nrows, $pagecounteroffset, $inputarr, $secs2cache);
 559      if ($rstest) {
 560          while ($rstest && $rstest->EOF && $pagecounter>0) {
 561              $atlastpage = true;
 562              $pagecounter--;
 563              $pagecounteroffset = $nrows * ($pagecounter - 1);
 564              $rstest->Close();
 565              if ($secs2cache>0) $rstest = &$zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $pagecounteroffset, $inputarr);
 566              else $rstest = &$zthis->SelectLimit($sql, $nrows, $pagecounteroffset, $inputarr, $secs2cache);
 567          }
 568          if ($rstest) $rstest->Close();
 569      }
 570      if ($atlastpage) {    // If we are at the last page or beyond it, we are going to retrieve it
 571          $page = $pagecounter;
 572          if ($page == 1) $atfirstpage = true;    // We have to do this again in case the last page is the same as the first
 573              //... page, that is, the recordset has only 1 page.
 574      }
 575      
 576      // We get the data we want
 577      $offset = $nrows * ($page-1);
 578      if ($secs2cache > 0) $rsreturn = &$zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $offset, $inputarr);
 579      else $rsreturn = &$zthis->SelectLimit($sql, $nrows, $offset, $inputarr, $secs2cache);
 580      
 581      // Before returning the RecordSet, we set the pagination properties we need
 582      if ($rsreturn) {
 583          $rsreturn->rowsPerPage = $nrows;
 584          $rsreturn->AbsolutePage($page);
 585          $rsreturn->AtFirstPage($atfirstpage);
 586          $rsreturn->AtLastPage($atlastpage);
 587      }
 588      return $rsreturn;
 589  }
 590  
 591  function _adodb_getupdatesql(&$zthis,&$rs, $arrFields,$forceUpdate=false,$magicq=false,$force=2)
 592  {
 593      global $ADODB_QUOTE_FIELDNAMES;
 594  
 595          if (!$rs) {
 596              printf(ADODB_BAD_RS,'GetUpdateSQL');
 597              return false;
 598          }
 599      
 600          $fieldUpdatedCount = 0;
 601          $arrFields = _array_change_key_case($arrFields);
 602  
 603          $hasnumeric = isset($rs->fields[0]);
 604          $setFields = '';
 605          
 606          // Loop through all of the fields in the recordset
 607          for ($i=0, $max=$rs->FieldCount(); $i < $max; $i++) {
 608              // Get the field from the recordset
 609              $field = $rs->FetchField($i);
 610  
 611              // If the recordset field is one
 612              // of the fields passed in then process.
 613              $upperfname = strtoupper($field->name);
 614              if (adodb_key_exists($upperfname,$arrFields,$force)) {
 615                  
 616                  // If the existing field value in the recordset
 617                  // is different from the value passed in then
 618                  // go ahead and append the field name and new value to
 619                  // the update query.
 620                  
 621                  if ($hasnumeric) $val = $rs->fields[$i];
 622                  else if (isset($rs->fields[$upperfname])) $val = $rs->fields[$upperfname];
 623                  else if (isset($rs->fields[$field->name])) $val =  $rs->fields[$field->name];
 624                  else if (isset($rs->fields[strtolower($upperfname)])) $val =  $rs->fields[strtolower($upperfname)];
 625                  else $val = '';
 626                  
 627              
 628                  if ($forceUpdate || strcmp($val, $arrFields[$upperfname])) {
 629                      // Set the counter for the number of fields that will be updated.
 630                      $fieldUpdatedCount++;
 631  
 632                      // Based on the datatype of the field
 633                      // Format the value properly for the database
 634                      $type = $rs->MetaType($field->type);
 635                          
 636  
 637                      if ($type == 'null') {
 638                          $type = 'C';
 639                      }
 640                      
 641                      if ((strpos($upperfname,' ') !== false) || ($ADODB_QUOTE_FIELDNAMES))
 642                          $fnameq = $zthis->nameQuote.$upperfname.$zthis->nameQuote;
 643                      else
 644                          $fnameq = $upperfname;
 645                      
 646                      
 647                  // is_null requires php 4.0.4
 648                  //********************************************************//
 649                  if (is_null($arrFields[$upperfname])
 650                      || (empty($arrFields[$upperfname]) && strlen($arrFields[$upperfname]) == 0)
 651                      || $arrFields[$upperfname] === $zthis->null2null
 652                      )
 653                  {
 654                      switch ($force) {
 655  
 656                          //case 0:
 657                          //    //Ignore empty values. This is allready handled in "adodb_key_exists" function.
 658                          //break;
 659  
 660                          case 1:
 661                              //Set null
 662                              $setFields .= $field->name . " = null, ";
 663                          break;
 664                              
 665                          case 2:
 666                              //Set empty
 667                              $arrFields[$upperfname] = "";
 668                              $setFields .= _adodb_column_sql($zthis, 'U', $type, $upperfname, $fnameq,$arrFields, $magicq);
 669                          break;
 670                          default:
 671                          case 3:
 672                              //Set the value that was given in array, so you can give both null and empty values
 673                              if (is_null($arrFields[$upperfname]) || $arrFields[$upperfname] === $zthis->null2null) {
 674                                  $setFields .= $field->name . " = null, ";
 675                              } else {
 676                                  $setFields .= _adodb_column_sql($zthis, 'U', $type, $upperfname, $fnameq,$arrFields, $magicq);
 677                              }
 678                          break;
 679                      }
 680                  //********************************************************//
 681                  } else {
 682                          //we do this so each driver can customize the sql for
 683                          //DB specific column types. 
 684                          //Oracle needs BLOB types to be handled with a returning clause
 685                          //postgres has special needs as well
 686                          $setFields .= _adodb_column_sql($zthis, 'U', $type, $upperfname, $fnameq,
 687                                                            $arrFields, $magicq);
 688                      }
 689                  }
 690              }
 691          }
 692  
 693          // If there were any modified fields then build the rest of the update query.
 694          if ($fieldUpdatedCount > 0 || $forceUpdate) {
 695                      // Get the table name from the existing query.
 696              if (!empty($rs->tableName)) $tableName = $rs->tableName;
 697              else {
 698                  preg_match("/FROM\s+".ADODB_TABLE_REGEX."/is", $rs->sql, $tableName);
 699                  $tableName = $tableName[1];
 700              }
 701              // Get the full where clause excluding the word "WHERE" from
 702              // the existing query.
 703              preg_match('/\sWHERE\s(.*)/is', $rs->sql, $whereClause);
 704              
 705              $discard = false;
 706              // not a good hack, improvements?
 707              if ($whereClause) {
 708              #var_dump($whereClause);
 709                  if (preg_match('/\s(ORDER\s.*)/is', $whereClause[1], $discard));
 710                  else if (preg_match('/\s(LIMIT\s.*)/is', $whereClause[1], $discard));
 711                  else if (preg_match('/\s(FOR UPDATE.*)/is', $whereClause[1], $discard));
 712                  else preg_match('/\s.*(\) WHERE .*)/is', $whereClause[1], $discard); # see http://sourceforge.net/tracker/index.php?func=detail&aid=1379638&group_id=42718&atid=433976
 713              } else
 714                  $whereClause = array(false,false);
 715                  
 716              if ($discard)
 717                  $whereClause[1] = substr($whereClause[1], 0, strlen($whereClause[1]) - strlen($discard[1]));
 718              
 719              $sql = 'UPDATE '.$tableName.' SET '.substr($setFields, 0, -2);
 720              if (strlen($whereClause[1]) > 0) 
 721                  $sql .= ' WHERE '.$whereClause[1];
 722  
 723              return $sql;
 724  
 725          } else {
 726              return false;
 727      }
 728  }
 729  
 730  function adodb_key_exists($key, &$arr,$force=2)
 731  {
 732      if ($force<=0) {
 733          // the following is the old behaviour where null or empty fields are ignored
 734          return (!empty($arr[$key])) || (isset($arr[$key]) && strlen($arr[$key])>0);
 735      }
 736  
 737      if (isset($arr[$key])) return true;
 738      ## null check below
 739      if (ADODB_PHPVER >= 0x4010) return array_key_exists($key,$arr);
 740      return false;
 741  }
 742  
 743  /**
 744   * There is a special case of this function for the oci8 driver.
 745   * The proper way to handle an insert w/ a blob in oracle requires
 746   * a returning clause with bind variables and a descriptor blob.
 747   * 
 748   * 
 749   */
 750  function _adodb_getinsertsql(&$zthis,&$rs,$arrFields,$magicq=false,$force=2)
 751  {
 752  static $cacheRS = false;
 753  static $cacheSig = 0;
 754  static $cacheCols;
 755      global $ADODB_QUOTE_FIELDNAMES;
 756  
 757      $tableName = '';
 758      $values = '';
 759      $fields = '';
 760      $recordSet = null;
 761      $arrFields = _array_change_key_case($arrFields);
 762      $fieldInsertedCount = 0;
 763      
 764      if (is_string($rs)) {
 765          //ok we have a table name
 766          //try and get the column info ourself.
 767          $tableName = $rs;            
 768      
 769          //we need an object for the recordSet
 770          //because we have to call MetaType.
 771          //php can't do a $rsclass::MetaType()
 772          $rsclass = $zthis->rsPrefix.$zthis->databaseType;
 773          $recordSet = new $rsclass(-1,$zthis->fetchMode);
 774          $recordSet->connection = &$zthis;
 775          
 776          if (is_string($cacheRS) && $cacheRS == $rs) {
 777              $columns =& $cacheCols;
 778          } else {
 779              $columns = $zthis->MetaColumns( $tableName );
 780              $cacheRS = $tableName;
 781              $cacheCols = $columns;
 782          }
 783      } else if (is_subclass_of($rs, 'adorecordset')) {
 784          if (isset($rs->insertSig) && is_integer($cacheRS) && $cacheRS == $rs->insertSig) {
 785              $columns =& $cacheCols;
 786          } else {
 787              for ($i=0, $max=$rs->FieldCount(); $i < $max; $i++) 
 788                  $columns[] = $rs->FetchField($i);
 789              $cacheRS = $cacheSig;
 790              $cacheCols = $columns;
 791              $rs->insertSig = $cacheSig++;
 792          }
 793          $recordSet =& $rs;
 794      
 795      } else {
 796          printf(ADODB_BAD_RS,'GetInsertSQL');
 797          return false;
 798      }
 799  
 800      // Loop through all of the fields in the recordset
 801      foreach( $columns as $field ) { 
 802          $upperfname = strtoupper($field->name);
 803          if (adodb_key_exists($upperfname,$arrFields,$force)) {
 804              $bad = false;
 805              if ((strpos($upperfname,' ') !== false) || ($ADODB_QUOTE_FIELDNAMES))
 806                  $fnameq = $zthis->nameQuote.$upperfname.$zthis->nameQuote;
 807              else
 808                  $fnameq = $upperfname;
 809              
 810              $type = $recordSet->MetaType($field->type);
 811              
 812              /********************************************************/
 813              if (is_null($arrFields[$upperfname])
 814                  || (empty($arrFields[$upperfname]) && strlen($arrFields[$upperfname]) == 0)
 815                  || $arrFields[$upperfname] === $zthis->null2null
 816                  )
 817                 {
 818                      switch ($force) {
 819  
 820                          case 0: // we must always set null if missing
 821                              $bad = true;
 822                              break;
 823                              
 824                          case 1:
 825                              $values  .= "null, ";
 826                          break;
 827          
 828                          case 2:
 829                              //Set empty
 830                              $arrFields[$upperfname] = "";
 831                              $values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq,$arrFields, $magicq);
 832                          break;
 833  
 834                          default:
 835                          case 3:
 836                              //Set the value that was given in array, so you can give both null and empty values
 837                              if (is_null($arrFields[$upperfname]) || $arrFields[$upperfname] === $zthis->null2null) { 
 838                                  $values  .= "null, ";
 839                              } else {
 840                                  $values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq, $arrFields, $magicq);
 841                               }
 842                            break;
 843                       } // switch
 844  
 845              /*********************************************************/
 846              } else {
 847                  //we do this so each driver can customize the sql for
 848                  //DB specific column types. 
 849                  //Oracle needs BLOB types to be handled with a returning clause
 850                  //postgres has special needs as well
 851                  $values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq,
 852                                                 $arrFields, $magicq);
 853              }
 854              
 855              if ($bad) continue;
 856              // Set the counter for the number of fields that will be inserted.
 857              $fieldInsertedCount++;
 858              
 859              
 860              // Get the name of the fields to insert
 861              $fields .= $fnameq . ", ";
 862          }
 863      }
 864  
 865  
 866      // If there were any inserted fields then build the rest of the insert query.
 867      if ($fieldInsertedCount <= 0)  return false;
 868      
 869      // Get the table name from the existing query.
 870      if (!$tableName) {
 871          if (!empty($rs->tableName)) $tableName = $rs->tableName;
 872          else if (preg_match("/FROM\s+".ADODB_TABLE_REGEX."/is", $rs->sql, $tableName))
 873              $tableName = $tableName[1];
 874          else 
 875              return false;
 876      }        
 877  
 878      // Strip off the comma and space on the end of both the fields
 879      // and their values.
 880      $fields = substr($fields, 0, -2);
 881      $values = substr($values, 0, -2);
 882  
 883      // Append the fields and their values to the insert query.
 884      return 'INSERT INTO '.$tableName.' ( '.$fields.' ) VALUES ( '.$values.' )';
 885  }
 886  
 887  
 888  /**
 889   * This private method is used to help construct
 890   * the update/sql which is generated by GetInsertSQL and GetUpdateSQL.
 891   * It handles the string construction of 1 column -> sql string based on
 892   * the column type.  We want to do 'safe' handling of BLOBs
 893   * 
 894   * @param string the type of sql we are trying to create
 895   *                'I' or 'U'. 
 896   * @param string column data type from the db::MetaType() method  
 897   * @param string the column name
 898   * @param array the column value
 899   * 
 900   * @return string
 901   * 
 902   */
 903  function _adodb_column_sql_oci8(&$zthis,$action, $type, $fname, $fnameq, $arrFields, $magicq) 
 904  {
 905      $sql = '';
 906      
 907      // Based on the datatype of the field
 908      // Format the value properly for the database
 909      switch($type) {
 910      case 'B':
 911          //in order to handle Blobs correctly, we need
 912          //to do some magic for Oracle
 913  
 914          //we need to create a new descriptor to handle 
 915          //this properly
 916          if (!empty($zthis->hasReturningInto)) {
 917              if ($action == 'I') {
 918                  $sql = 'empty_blob(), ';
 919              } else {
 920                  $sql = $fnameq. '=empty_blob(), ';
 921              }
 922              //add the variable to the returning clause array
 923              //so the user can build this later in
 924              //case they want to add more to it
 925              $zthis->_returningArray[$fname] = ':xx'.$fname.'xx';
 926          } else if (empty($arrFields[$fname])){
 927              if ($action == 'I') {
 928                  $sql = 'empty_blob(), ';
 929              } else {
 930                  $sql = $fnameq. '=empty_blob(), ';
 931              }            
 932          } else {
 933              //this is to maintain compatibility
 934              //with older adodb versions.
 935              $sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq,false);
 936          }
 937          break;
 938  
 939      case "X":
 940          //we need to do some more magic here for long variables
 941          //to handle these correctly in oracle.
 942  
 943          //create a safe bind var name
 944          //to avoid conflicts w/ dupes.
 945         if (!empty($zthis->hasReturningInto)) {
 946              if ($action == 'I') {
 947                  $sql = ':xx'.$fname.'xx, ';                
 948              } else {
 949                  $sql = $fnameq.'=:xx'.$fname.'xx, ';
 950              }
 951              //add the variable to the returning clause array
 952              //so the user can build this later in
 953              //case they want to add more to it
 954              $zthis->_returningArray[$fname] = ':xx'.$fname.'xx';
 955          } else {
 956              //this is to maintain compatibility
 957              //with older adodb versions.
 958              $sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq,false);
 959          }            
 960          break;
 961          
 962      default:
 963          $sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq,  $arrFields, $magicq,false);
 964          break;
 965      }
 966      
 967      return $sql;
 968  }    
 969      
 970  function _adodb_column_sql(&$zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq, $recurse=true) 
 971  {
 972  
 973      if ($recurse) {
 974          switch($zthis->dataProvider)  {
 975          case 'postgres':
 976              if ($type == 'L') $type = 'C';
 977              break;
 978          case 'oci8':
 979              return _adodb_column_sql_oci8($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq);
 980              
 981          }
 982      }
 983          
 984      switch($type) {
 985          case "C":
 986          case "X":
 987          case 'B':
 988              $val = $zthis->qstr($arrFields[$fname],$magicq);
 989              break;
 990  
 991          case "D":
 992              $val = $zthis->DBDate($arrFields[$fname]);
 993              break;
 994  
 995          
 996          case "T":
 997              $val = $zthis->DBTimeStamp($arrFields[$fname]);
 998              break;
 999  
1000          case "N":
1001              $val = $arrFields[$fname];
1002              if (!is_numeric($val)) $val = str_replace(',', '.', (float)$val);
1003              break;
1004  
1005          case "I":
1006          case "R":
1007              $val = $arrFields[$fname];
1008              if (!is_numeric($val)) $val = (integer) $val;
1009              break;
1010  
1011          default:
1012              $val = str_replace(array("'"," ","("),"",$arrFields[$fname]); // basic sql injection defence
1013              if (empty($val)) $val = '0';
1014              break;
1015      }
1016  
1017      if ($action == 'I') return $val . ", ";
1018      
1019      
1020      return $fnameq . "=" . $val  . ", ";
1021      
1022  }
1023  
1024  
1025  
1026  function _adodb_debug_execute(&$zthis, $sql, $inputarr)
1027  {
1028      $ss = '';
1029      if ($inputarr) {
1030          foreach($inputarr as $kk=>$vv) {
1031              if (is_string($vv) && strlen($vv)>64) $vv = substr($vv,0,64).'...';
1032              if (is_null($vv)) $ss .= "($kk=>null) ";
1033              else $ss .= "($kk=>'$vv') ";
1034          }
1035          $ss = "[ $ss ]";
1036      }
1037      $sqlTxt = is_array($sql) ? $sql[0] : $sql;
1038      /*str_replace(', ','##1#__^LF',is_array($sql) ? $sql[0] : $sql);
1039      $sqlTxt = str_replace(',',', ',$sqlTxt);
1040      $sqlTxt = str_replace('##1#__^LF', ', ' ,$sqlTxt);
1041      */
1042      // check if running from browser or command-line
1043      $inBrowser = isset($_SERVER['HTTP_USER_AGENT']);
1044      
1045      $dbt = $zthis->databaseType;
1046      if (isset($zthis->dsnType)) $dbt .= '-'.$zthis->dsnType;
1047      if ($inBrowser) {
1048          if ($ss) {
1049              $ss = '<code>'.htmlspecialchars($ss).'</code>';
1050          }
1051          if ($zthis->debug === -1)
1052              ADOConnection::outp( "<br />\n($dbt): ".htmlspecialchars($sqlTxt)." &nbsp; $ss\n<br />\n",false);
1053          else 
1054              ADOConnection::outp( "<hr />\n($dbt): ".htmlspecialchars($sqlTxt)." &nbsp; $ss\n<hr />\n",false);
1055      } else {
1056          ADOConnection::outp("-----\n($dbt): ".$sqlTxt."\n-----\n",false);
1057      }
1058  
1059      $qID = $zthis->_query($sql,$inputarr);
1060      
1061      /* 
1062          Alexios Fakios notes that ErrorMsg() must be called before ErrorNo() for mssql
1063          because ErrorNo() calls Execute('SELECT @ERROR'), causing recursion
1064      */
1065      if ($zthis->databaseType == 'mssql') { 
1066      // ErrorNo is a slow function call in mssql, and not reliable in PHP 4.0.6
1067          if($emsg = $zthis->ErrorMsg()) {
1068              if ($err = $zthis->ErrorNo()) ADOConnection::outp($err.': '.$emsg);
1069          }
1070      } else if (!$qID) {
1071          ADOConnection::outp($zthis->ErrorNo() .': '. $zthis->ErrorMsg());
1072      }
1073      
1074      if ($zthis->debug === 99) _adodb_backtrace(true,9999,2);
1075      return $qID;
1076  }
1077  
1078  # pretty print the debug_backtrace function
1079  function _adodb_backtrace($printOrArr=true,$levels=9999,$skippy=0)
1080  {
1081      if (!function_exists('debug_backtrace')) return '';
1082       
1083      $html =  (isset($_SERVER['HTTP_USER_AGENT']));
1084      $fmt =  ($html) ? "</font><font color=#808080 size=-1> %% line %4d, file: <a href=\"file:/%s\">%s</a></font>" : "%% line %4d, file: %s";
1085  
1086      $MAXSTRLEN = 128;
1087  
1088      $s = ($html) ? '<pre align=left>' : '';
1089      
1090      if (is_array($printOrArr)) $traceArr = $printOrArr;
1091      else $traceArr = debug_backtrace();
1092      array_shift($traceArr);
1093      array_shift($traceArr);
1094      $tabs = sizeof($traceArr)-2;
1095      
1096      foreach ($traceArr as $arr) {
1097          if ($skippy) {$skippy -= 1; continue;}
1098          $levels -= 1;
1099          if ($levels < 0) break;
1100          
1101          $args = array();
1102          for ($i=0; $i < $tabs; $i++) $s .=  ($html) ? ' &nbsp; ' : "\t";
1103          $tabs -= 1;
1104          if ($html) $s .= '<font face="Courier New,Courier">';
1105          if (isset($arr['class'])) $s .= $arr['class'].'.';
1106          if (isset($arr['args']))
1107           foreach($arr['args'] as $v) {
1108              if (is_null($v)) $args[] = 'null';
1109              else if (is_array($v)) $args[] = 'Array['.sizeof($v).']';
1110              else if (is_object($v)) $args[] = 'Object:'.get_class($v);
1111              else if (is_bool($v)) $args[] = $v ? 'true' : 'false';
1112              else {
1113                  $v = (string) @$v;
1114                  $str = htmlspecialchars(substr($v,0,$MAXSTRLEN));
1115                  if (strlen($v) > $MAXSTRLEN) $str .= '...';
1116                  $args[] = $str;
1117              }
1118          }
1119          $s .= $arr['function'].'('.implode(', ',$args).')';
1120          
1121          
1122          $s .= @sprintf($fmt, $arr['line'],$arr['file'],basename($arr['file']));
1123              
1124          $s .= "\n";
1125      }    
1126      if ($html) $s .= '</pre>';
1127      if ($printOrArr) print $s;
1128      
1129      return $s;
1130  }
1131  /*
1132  function _adodb_find_from($sql) 
1133  {
1134  
1135      $sql = str_replace(array("\n","\r"), ' ', $sql);
1136      $charCount = strlen($sql);
1137      
1138      $inString = false;
1139      $quote = '';
1140      $parentheseCount = 0;
1141      $prevChars = '';
1142      $nextChars = '';
1143      
1144  
1145      for($i = 0; $i < $charCount; $i++) {
1146  
1147          $char = substr($sql,$i,1);
1148          $prevChars = substr($sql,0,$i);
1149          $nextChars = substr($sql,$i+1);
1150  
1151          if((($char == "'" || $char == '"' || $char == '`') && substr($prevChars,-1,1) != '\\') && $inString === false) {
1152              $quote = $char;
1153              $inString = true;
1154          }
1155  
1156          elseif((($char == "'" || $char == '"' || $char == '`') && substr($prevChars,-1,1) != '\\') && $inString === true && $quote == $char) {
1157              $quote = "";
1158              $inString = false;
1159          }
1160  
1161          elseif($char == "(" && $inString === false)
1162              $parentheseCount++;
1163  
1164          elseif($char == ")" && $inString === false && $parentheseCount > 0)
1165              $parentheseCount--;
1166  
1167          elseif($parentheseCount <= 0 && $inString === false && $char == " " && strtoupper(substr($prevChars,-5,5)) == " FROM")
1168              return $i;
1169  
1170      }
1171  }
1172  */
1173  
1174  ?>


Généré le : Thu Nov 29 09:42:17 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics