[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
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)." $ss\n<br>\n",false); 1117 else if ($zthis->debug !== -99) 1118 ADOConnection::outp( "<hr>\n($dbt): ".htmlspecialchars($sqlTxt)." $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)." $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)." $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) ? ' ' : "\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 */
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |