[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

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

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


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1