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