PageRenderTime 63ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/ext/adodb_5.18a/adodb-lib.inc.php

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