TYPO3 CMS  TYPO3_7-6
adodb-lib.inc.php
Go to the documentation of this file.
1 <?php
2 // security - hide paths
3 if (!defined('ADODB_DIR')) die();
4 
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 
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)';
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 && 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 
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 
968 function _adodb_column_sql_oci8(&$zthis,$action, $type, $fname, $fnameq, $arrFields, $magicq)
969 {
970  $sql = '';
971 
972  // Based on the datatype of the field
973  // Format the value properly for the database
974  switch($type) {
975  case 'B':
976  //in order to handle Blobs correctly, we need
977  //to do some magic for Oracle
978 
979  //we need to create a new descriptor to handle
980  //this properly
981  if (!empty($zthis->hasReturningInto)) {
982  if ($action == 'I') {
983  $sql = 'empty_blob(), ';
984  } else {
985  $sql = $fnameq. '=empty_blob(), ';
986  }
987  //add the variable to the returning clause array
988  //so the user can build this later in
989  //case they want to add more to it
990  $zthis->_returningArray[$fname] = ':xx'.$fname.'xx';
991  } else if (empty($arrFields[$fname])){
992  if ($action == 'I') {
993  $sql = 'empty_blob(), ';
994  } else {
995  $sql = $fnameq. '=empty_blob(), ';
996  }
997  } else {
998  //this is to maintain compatibility
999  //with older adodb versions.
1000  $sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq,false);
1001  }
1002  break;
1003 
1004  case "X":
1005  //we need to do some more magic here for long variables
1006  //to handle these correctly in oracle.
1007 
1008  //create a safe bind var name
1009  //to avoid conflicts w/ dupes.
1010  if (!empty($zthis->hasReturningInto)) {
1011  if ($action == 'I') {
1012  $sql = ':xx'.$fname.'xx, ';
1013  } else {
1014  $sql = $fnameq.'=:xx'.$fname.'xx, ';
1015  }
1016  //add the variable to the returning clause array
1017  //so the user can build this later in
1018  //case they want to add more to it
1019  $zthis->_returningArray[$fname] = ':xx'.$fname.'xx';
1020  } else {
1021  //this is to maintain compatibility
1022  //with older adodb versions.
1023  $sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq,false);
1024  }
1025  break;
1026 
1027  default:
1028  $sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq,false);
1029  break;
1030  }
1031 
1032  return $sql;
1033 }
1034 
1035 function _adodb_column_sql(&$zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq, $recurse=true)
1036 {
1037 
1038  if ($recurse) {
1039  switch($zthis->dataProvider) {
1040  case 'postgres':
1041  if ($type == 'L') $type = 'C';
1042  break;
1043  case 'oci8':
1044  return _adodb_column_sql_oci8($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq);
1045 
1046  }
1047  }
1048 
1049  switch($type) {
1050  case "C":
1051  case "X":
1052  case 'B':
1053  $val = $zthis->qstr($arrFields[$fname],$magicq);
1054  break;
1055 
1056  case "D":
1057  $val = $zthis->DBDate($arrFields[$fname]);
1058  break;
1059 
1060  case "T":
1061  $val = $zthis->DBTimeStamp($arrFields[$fname]);
1062  break;
1063 
1064  case "N":
1065  $val = $arrFields[$fname];
1066  if (!is_numeric($val)) $val = str_replace(',', '.', (float)$val);
1067  break;
1068 
1069  case "I":
1070  case "R":
1071  $val = $arrFields[$fname];
1072  if (!is_numeric($val)) $val = (integer) $val;
1073  break;
1074 
1075  default:
1076  $val = str_replace(array("'"," ","("),"",$arrFields[$fname]); // basic sql injection defence
1077  if (empty($val)) $val = '0';
1078  break;
1079  }
1080 
1081  if ($action == 'I') return $val . ", ";
1082 
1083 
1084  return $fnameq . "=" . $val . ", ";
1085 
1086 }
1087 
1088 
1089 
1090 function _adodb_debug_execute(&$zthis, $sql, $inputarr)
1091 {
1092  $ss = '';
1093  if ($inputarr) {
1094  foreach($inputarr as $kk=>$vv) {
1095  if (is_string($vv) && strlen($vv)>64) $vv = substr($vv,0,64).'...';
1096  if (is_null($vv)) $ss .= "($kk=>null) ";
1097  else $ss .= "($kk=>'$vv') ";
1098  }
1099  $ss = "[ $ss ]";
1100  }
1101  $sqlTxt = is_array($sql) ? $sql[0] : $sql;
1102  /*str_replace(', ','##1#__^LF',is_array($sql) ? $sql[0] : $sql);
1103  $sqlTxt = str_replace(',',', ',$sqlTxt);
1104  $sqlTxt = str_replace('##1#__^LF', ', ' ,$sqlTxt);
1105  */
1106  // check if running from browser or command-line
1107  $inBrowser = isset($_SERVER['HTTP_USER_AGENT']);
1108 
1109  $dbt = $zthis->databaseType;
1110  if (isset($zthis->dsnType)) $dbt .= '-'.$zthis->dsnType;
1111  if ($inBrowser) {
1112  if ($ss) {
1113  $ss = '<code>'.htmlspecialchars($ss).'</code>';
1114  }
1115  if ($zthis->debug === -1)
1116  ADOConnection::outp( "<br>\n($dbt): ".htmlspecialchars($sqlTxt)." &nbsp; $ss\n<br>\n",false);
1117  else if ($zthis->debug !== -99)
1118  ADOConnection::outp( "<hr>\n($dbt): ".htmlspecialchars($sqlTxt)." &nbsp; $ss\n<hr>\n",false);
1119  } else {
1120  $ss = "\n ".$ss;
1121  if ($zthis->debug !== -99)
1122  ADOConnection::outp("-----<hr>\n($dbt): ".$sqlTxt." $ss\n-----<hr>\n",false);
1123  }
1124 
1125  $qID = $zthis->_query($sql,$inputarr);
1126 
1127  /*
1128  Alexios Fakios notes that ErrorMsg() must be called before ErrorNo() for mssql
1129  because ErrorNo() calls Execute('SELECT @ERROR'), causing recursion
1130  */
1131  if ($zthis->databaseType == 'mssql') {
1132  // ErrorNo is a slow function call in mssql, and not reliable in PHP 4.0.6
1133 
1134  if($emsg = $zthis->ErrorMsg()) {
1135  if ($err = $zthis->ErrorNo()) {
1136  if ($zthis->debug === -99)
1137  ADOConnection::outp( "<hr>\n($dbt): ".htmlspecialchars($sqlTxt)." &nbsp; $ss\n<hr>\n",false);
1138 
1139  ADOConnection::outp($err.': '.$emsg);
1140  }
1141  }
1142  } else if (!$qID) {
1143 
1144  if ($zthis->debug === -99)
1145  if ($inBrowser) ADOConnection::outp( "<hr>\n($dbt): ".htmlspecialchars($sqlTxt)." &nbsp; $ss\n<hr>\n",false);
1146  else ADOConnection::outp("-----<hr>\n($dbt): ".$sqlTxt."$ss\n-----<hr>\n",false);
1147 
1148  ADOConnection::outp($zthis->ErrorNo() .': '. $zthis->ErrorMsg());
1149  }
1150 
1151  if ($zthis->debug === 99) _adodb_backtrace(true,9999,2);
1152  return $qID;
1153 }
1154 
1155 # pretty print the debug_backtrace function
1156 function _adodb_backtrace($printOrArr=true,$levels=9999,$skippy=0,$ishtml=null)
1157 {
1158  if (!function_exists('debug_backtrace')) return '';
1159 
1160  if ($ishtml === null) $html = (isset($_SERVER['HTTP_USER_AGENT']));
1161  else $html = $ishtml;
1162 
1163  $fmt = ($html) ? "</font><font color=#808080 size=-1> %% line %4d, file: <a href=\"file:/%s\">%s</a></font>" : "%% line %4d, file: %s";
1164 
1165  $MAXSTRLEN = 128;
1166 
1167  $s = ($html) ? '<pre align=left>' : '';
1168 
1169  if (is_array($printOrArr)) $traceArr = $printOrArr;
1170  else $traceArr = debug_backtrace();
1171  array_shift($traceArr);
1172  array_shift($traceArr);
1173  $tabs = sizeof($traceArr)-2;
1174 
1175  foreach ($traceArr as $arr) {
1176  if ($skippy) {$skippy -= 1; continue;}
1177  $levels -= 1;
1178  if ($levels < 0) break;
1179 
1180  $args = array();
1181  for ($i=0; $i < $tabs; $i++) $s .= ($html) ? ' &nbsp; ' : "\t";
1182  $tabs -= 1;
1183  if ($html) $s .= '<font face="Courier New,Courier">';
1184  if (isset($arr['class'])) $s .= $arr['class'].'.';
1185  if (isset($arr['args']))
1186  foreach($arr['args'] as $v) {
1187  if (is_null($v)) $args[] = 'null';
1188  else if (is_array($v)) $args[] = 'Array['.sizeof($v).']';
1189  else if (is_object($v)) $args[] = 'Object:'.get_class($v);
1190  else if (is_bool($v)) $args[] = $v ? 'true' : 'false';
1191  else {
1192  $v = (string) @$v;
1193  $str = htmlspecialchars(str_replace(array("\r","\n"),' ',substr($v,0,$MAXSTRLEN)));
1194  if (strlen($v) > $MAXSTRLEN) $str .= '...';
1195  $args[] = $str;
1196  }
1197  }
1198  $s .= $arr['function'].'('.implode(', ',$args).')';
1199 
1200 
1201  $s .= @sprintf($fmt, $arr['line'],$arr['file'],basename($arr['file']));
1202 
1203  $s .= "\n";
1204  }
1205  if ($html) $s .= '</pre>';
1206  if ($printOrArr) print $s;
1207 
1208  return $s;
1209 }
1210 /*
1211 function _adodb_find_from($sql)
1212 {
1213 
1214  $sql = str_replace(array("\n","\r"), ' ', $sql);
1215  $charCount = strlen($sql);
1216 
1217  $inString = false;
1218  $quote = '';
1219  $parentheseCount = 0;
1220  $prevChars = '';
1221  $nextChars = '';
1222 
1223 
1224  for($i = 0; $i < $charCount; $i++) {
1225 
1226  $char = substr($sql,$i,1);
1227  $prevChars = substr($sql,0,$i);
1228  $nextChars = substr($sql,$i+1);
1229 
1230  if((($char == "'" || $char == '"' || $char == '`') && substr($prevChars,-1,1) != '\\') && $inString === false) {
1231  $quote = $char;
1232  $inString = true;
1233  }
1234 
1235  elseif((($char == "'" || $char == '"' || $char == '`') && substr($prevChars,-1,1) != '\\') && $inString === true && $quote == $char) {
1236  $quote = "";
1237  $inString = false;
1238  }
1239 
1240  elseif($char == "(" && $inString === false)
1241  $parentheseCount++;
1242 
1243  elseif($char == ")" && $inString === false && $parentheseCount > 0)
1244  $parentheseCount--;
1245 
1246  elseif($parentheseCount <= 0 && $inString === false && $char == " " && strtoupper(substr($prevChars,-5,5)) == " FROM")
1247  return $i;
1248 
1249  }
1250 }
1251 */
_adodb_getupdatesql(&$zthis, &$rs, $arrFields, $forceUpdate=false, $magicq=false, $force=2)
_adodb_column_sql_oci8(&$zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq)
_adodb_backtrace($printOrArr=true, $levels=9999, $skippy=0, $ishtml=null)
_adodb_column_sql(&$zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq, $recurse=true)
if(false) adodb_probetypes(&$array, &$types, $probe=8)
if(isset($_REQUEST['nrows'])) else $rs
Definition: server.php:94
global $ADODB_INCLUDED_LIB
_adodb_getinsertsql(&$zthis, &$rs, $arrFields, $magicq=false, $force=2)
_adodb_getmenu_gp(&$zthis, $name, $defstr='', $blank1stItem=true, $multiple=false, $size=0, $selectAttr='', $compareFields0=true)
_adodb_debug_execute(&$zthis, $sql, $inputarr)
_adodb_pageexecute_no_last_page(&$zthis, $sql, $nrows, $page, $inputarr=false, $secs2cache=0)
_array_change_key_case($an_array)
_adodb_replace(&$zthis, $table, $fieldArray, $keyCol, $autoQuote, $has_autoinc)
_adodb_getmenu(&$zthis, $name, $defstr='', $blank1stItem=true, $multiple=false, $size=0, $selectAttr='', $compareFields0=true)
adodb_transpose(&$arr, &$newarr, &$hdr, &$fobjs)
adodb_key_exists($key, &$arr, $force=2)
$sql
Definition: server.php:84
adodb_strip_order_by($sql)
_adodb_pageexecute_all_rows(&$zthis, $sql, $nrows, $page, $inputarr=false, $secs2cache=0)
_adodb_getcount(&$zthis, $sql, $inputarr=false, $secs2cache=0)