3 // security - hide paths
4 if (!defined('ADODB_DIR')) die();
6 global $ADODB_INCLUDED_LIB;
7 $ADODB_INCLUDED_LIB = 1;
10 @version V4.98 13 Feb 2008 (c) 2000-2008 John Lim (jlim\@natsoft.com.my). All rights reserved.
11 Released under both BSD license and Lesser GPL library license.
12 Whenever there is any discrepancy between the two licenses,
13 the BSD license will take precedence. See License.txt.
14 Set tabs to 4 for best viewing.
16 Less commonly used functions are placed here to reduce size of adodb.inc.php.
19 function adodb_strip_order_by($sql)
21 $rez = preg_match('/(\sORDER\s+BY\s[^)]*)/is',$sql,$arr);
23 if (strpos($arr[0],'(') !== false) {
24 $at = strpos($sql,$arr[0]);
26 for ($i=$at, $max=strlen($sql); $i < $max; $i++
) {
30 } elseif($ch == ')') {
37 $sql = substr($sql,0,$at).substr($sql,$i);
39 $sql = str_replace($arr[0], '', $sql);
44 $sql = 'select * from (select a from b order by a(b),b(c) desc)';
45 $sql = '(select * from abc order by 1)';
46 die(adodb_strip_order_by($sql));
49 function adodb_probetypes(&$array,&$types,$probe=8)
51 // probe and guess the type
53 if ($probe > sizeof($array)) $max = sizeof($array);
57 for ($j=0;$j < $max; $j++
) {
64 if (isset($types[$i]) && $types[$i]=='C') continue;
66 //print " ($i ".$types[$i]. "$v) ";
69 if (!preg_match('/^[+-]{0,1}[0-9\.]+$/',$v)) {
70 $types[$i] = 'C'; // once C, always C
75 // If empty string, we presume is character
76 // test for integer for 1st row only
77 // after that it is up to testing other rows to prove
78 // that it is not an integer
79 if (strlen($v) == 0) $types[$i] = 'C';
80 if (strpos($v,'.') !== false) $types[$i] = 'N';
81 else $types[$i] = 'I';
85 if (strpos($v,'.') !== false) $types[$i] = 'N';
92 function adodb_transpose(&$arr, &$newarr, &$hdr, &$fobjs)
94 $oldX = sizeof(reset($arr));
99 $hdr = array('Fields');
100 for ($y = 0; $y < $oldY; $y++
) {
101 $hdr[] = $arr[$y][0];
106 for ($x = $startx; $x < $oldX; $x++
) {
109 $newarr[] = array($o->name
);
113 for ($y = 0; $y < $oldY; $y++
) {
114 $newarr[$x-$startx][] = $arr[$y][$x];
119 // Force key to upper.
120 // See also http://www.php.net/manual/en/function.array-change-key-case.php
121 function _array_change_key_case($an_array)
123 if (is_array($an_array)) {
124 $new_array = array();
125 foreach($an_array as $key=>$value)
126 $new_array[strtoupper($key)] = $value;
134 function _adodb_replace(&$zthis, $table, $fieldArray, $keyCol, $autoQuote, $has_autoinc)
136 if (count($fieldArray) == 0) return 0;
140 if (!is_array($keyCol)) {
141 $keyCol = array($keyCol);
143 foreach($fieldArray as $k => $v) {
146 $fieldArray[$k] = $v;
147 } else if ($autoQuote && !is_numeric($v) /*and strncmp($v,"'",1) !== 0 -- sql injection risk*/ and strcasecmp($v,$zthis->null2null
)!=0) {
148 $v = $zthis->qstr($v);
149 $fieldArray[$k] = $v;
151 if (in_array($k,$keyCol)) continue; // skip UPDATE if is key
161 foreach ($keyCol as $v) {
162 if (isset($fieldArray[$v])) {
163 if ($where) $where .= ' and '.$v.'='.$fieldArray[$v];
164 else $where = $v.'='.$fieldArray[$v];
168 if ($uSet && $where) {
169 $update = "UPDATE $table SET $uSet WHERE $where";
171 $rs = $zthis->Execute($update);
175 if ($zthis->poorAffectedRows
) {
177 The Select count(*) wipes out any errors that the update would have returned.
178 http://phplens.com/lens/lensforum/msgs.php?id=5696
180 if ($zthis->ErrorNo()<>0) return 0;
182 # affected_rows == 0 if update field values identical to old values
183 # for mysql - which is silly.
185 $cnt = $zthis->GetOne("select count(*) from $table where $where");
186 if ($cnt > 0) return 1; // record already exists
188 if (($zthis->Affected_Rows()>0)) return 1;
194 // print "<p>Error=".$this->ErrorNo().'<p>';
196 foreach($fieldArray as $k => $v) {
197 if ($has_autoinc && in_array($k,$keyCol)) continue; // skip autoinc col
208 $insert = "INSERT INTO $table ($iCols) VALUES ($iVals)";
209 $rs = $zthis->Execute($insert);
210 return ($rs) ?
2 : 0;
213 // Requires $ADODB_FETCH_MODE = ADODB_FETCH_NUM
214 function _adodb_getmenu(&$zthis, $name,$defstr='',$blank1stItem=true,$multiple=false,
215 $size=0, $selectAttr='',$compareFields0=true)
219 if ($multiple or is_array($defstr)) {
220 if ($size==0) $size=5;
221 $attr = ' multiple size="'.$size.'"';
222 if (!strpos($name,'[]')) $name .= '[]';
223 } else if ($size) $attr = ' size="'.$size.'"';
226 $s = '<select name="'.$name.'"'.$attr.' '.$selectAttr.'>';
228 if (is_string($blank1stItem)) {
229 $barr = explode(':',$blank1stItem);
230 if (sizeof($barr) == 1) $barr[] = '';
231 $s .= "\n<option value=\"".$barr[0]."\">".$barr[1]."</option>";
232 } else $s .= "\n<option></option>";
234 if ($zthis->FieldCount() > 1) $hasvalue=true;
235 else $compareFields0 = true;
240 $fieldsize = $zthis->FieldCount();
241 while(!$zthis->EOF
) {
242 $zval = rtrim(reset($zthis->fields
));
244 if ($blank1stItem && $zval=="") {
249 if ($fieldsize > 1) {
250 if (isset($zthis->fields
[1]))
251 $zval2 = rtrim($zthis->fields
[1]);
253 $zval2 = rtrim(next($zthis->fields
));
255 $selected = ($compareFields0) ?
$zval : $zval2;
258 if ($fieldsize > 2) {
259 $group = rtrim($zthis->fields
[2]);
262 if ($optgroup != $group) {
266 $s .="\n<optgroup label='". htmlspecialchars($group) ."'>";
268 $s .="\n</optgroup>";
269 $s .="\n<optgroup label='". htmlspecialchars($group) ."'>";
274 $value = " value='".htmlspecialchars($zval2)."'";
276 if (is_array($defstr)) {
278 if (in_array($selected,$defstr))
279 $s .= "\n<option selected='selected'$value>".htmlspecialchars($zval).'</option>';
281 $s .= "\n<option".$value.'>'.htmlspecialchars($zval).'</option>';
284 if (strcasecmp($selected,$defstr)==0)
285 $s .= "\n<option selected='selected'$value>".htmlspecialchars($zval).'</option>';
287 $s .= "\n<option".$value.'>'.htmlspecialchars($zval).'</option>';
292 // closing last optgroup
293 if($optgroup != null) {
294 $s .= "\n</optgroup>";
296 return $s ."\n</select>\n";
299 // Requires $ADODB_FETCH_MODE = ADODB_FETCH_NUM
300 function _adodb_getmenu_gp(&$zthis, $name,$defstr='',$blank1stItem=true,$multiple=false,
301 $size=0, $selectAttr='',$compareFields0=true)
305 if ($multiple or is_array($defstr)) {
306 if ($size==0) $size=5;
307 $attr = ' multiple size="'.$size.'"';
308 if (!strpos($name,'[]')) $name .= '[]';
309 } else if ($size) $attr = ' size="'.$size.'"';
312 $s = '<select name="'.$name.'"'.$attr.' '.$selectAttr.'>';
314 if (is_string($blank1stItem)) {
315 $barr = explode(':',$blank1stItem);
316 if (sizeof($barr) == 1) $barr[] = '';
317 $s .= "\n<option value=\"".$barr[0]."\">".$barr[1]."</option>";
318 } else $s .= "\n<option></option>";
320 if ($zthis->FieldCount() > 1) $hasvalue=true;
321 else $compareFields0 = true;
326 $fieldsize = sizeof($zthis->fields
);
327 while(!$zthis->EOF
) {
328 $zval = rtrim(reset($zthis->fields
));
330 if ($blank1stItem && $zval=="") {
335 if ($fieldsize > 1) {
336 if (isset($zthis->fields
[1]))
337 $zval2 = rtrim($zthis->fields
[1]);
339 $zval2 = rtrim(next($zthis->fields
));
341 $selected = ($compareFields0) ?
$zval : $zval2;
344 if (isset($zthis->fields
[2])) {
345 $group = rtrim($zthis->fields
[2]);
348 if ($optgroup != $group) {
352 $s .="\n<optgroup label='". htmlspecialchars($group) ."'>";
354 $s .="\n</optgroup>";
355 $s .="\n<optgroup label='". htmlspecialchars($group) ."'>";
360 $value = " value='".htmlspecialchars($zval2)."'";
362 if (is_array($defstr)) {
364 if (in_array($selected,$defstr))
365 $s .= "\n<option selected='selected'$value>".htmlspecialchars($zval).'</option>';
367 $s .= "\n<option".$value.'>'.htmlspecialchars($zval).'</option>';
370 if (strcasecmp($selected,$defstr)==0)
371 $s .= "\n<option selected='selected'$value>".htmlspecialchars($zval).'</option>';
373 $s .= "\n<option".$value.'>'.htmlspecialchars($zval).'</option>';
378 // closing last optgroup
379 if($optgroup != null) {
380 $s .= "\n</optgroup>";
382 return $s ."\n</select>\n";
387 Count the number of records this sql statement will return by using
388 query rewriting heuristics...
390 Does not work with UNIONs, except with postgresql and oracle.
395 $cnt = _adodb_getcount($conn, $sql);
398 function _adodb_getcount(&$zthis, $sql,$inputarr=false,$secs2cache=0)
402 if (!empty($zthis->_nestedSQL
) ||
preg_match("/^\s*SELECT\s+DISTINCT/is", $sql) ||
403 preg_match('/\s+GROUP\s+BY\s+/is',$sql) ||
404 preg_match('/\s+UNION\s+/is',$sql)) {
406 $rewritesql = adodb_strip_order_by($sql);
408 // ok, has SELECT DISTINCT or GROUP BY so see if we can use a table alias
409 // but this is only supported by oracle and postgresql...
410 if ($zthis->dataProvider
== 'oci8') {
411 // Allow Oracle hints to be used for query optimization, Chris Wrye
412 if (preg_match('#/\\*+.*?\\*\\/#', $sql, $hint)) {
413 $rewritesql = "SELECT ".$hint[0]." COUNT(*) FROM (".$rewritesql.")";
415 $rewritesql = "SELECT COUNT(*) FROM (".$rewritesql.")";
417 } else if (strncmp($zthis->databaseType
,'postgres',8) == 0 ||
strncmp($zthis->databaseType
,'mysql',5) == 0) {
418 $rewritesql = "SELECT COUNT(*) FROM ($rewritesql) _ADODB_ALIAS_";
420 $rewritesql = "SELECT COUNT(*) FROM ($rewritesql) ";
423 // now replace SELECT ... FROM with SELECT COUNT(*) FROM
424 $rewritesql = preg_replace(
425 '/^\s*SELECT\s.*\s+FROM\s/Uis','SELECT COUNT(*) FROM ',$sql);
426 // fix by alexander zhukov, alex#unipack.ru, because count(*) and 'order by' fails
427 // with mssql, access and postgresql. Also a good speedup optimization - skips sorting!
428 // also see http://phplens.com/lens/lensforum/msgs.php?id=12752
429 $rewritesql = adodb_strip_order_by($rewritesql);
432 if (isset($rewritesql) && $rewritesql != $sql) {
433 if (preg_match('/\sLIMIT\s+[0-9]+/i',$sql,$limitarr)) $rewritesql .= $limitarr[0];
436 // we only use half the time of secs2cache because the count can quickly
437 // become inaccurate if new records are added
438 $qryRecs = $zthis->CacheGetOne($secs2cache/2,$rewritesql,$inputarr);
441 $qryRecs = $zthis->GetOne($rewritesql,$inputarr);
443 if ($qryRecs !== false) return $qryRecs;
445 //--------------------------------------------
446 // query rewrite failed - so try slower way...
449 // strip off unneeded ORDER BY if no UNION
450 if (preg_match('/\s*UNION\s*/is', $sql)) $rewritesql = $sql;
451 else $rewritesql = $rewritesql = adodb_strip_order_by($sql);
453 if (preg_match('/\sLIMIT\s+[0-9]+/i',$sql,$limitarr)) $rewritesql .= $limitarr[0];
455 $rstest = &$zthis->Execute($rewritesql,$inputarr);
456 if (!$rstest) $rstest = $zthis->Execute($sql,$inputarr);
459 $qryRecs = $rstest->RecordCount();
460 if ($qryRecs == -1) {
461 global $ADODB_EXTENSION;
462 // some databases will return -1 on MoveLast() - change to MoveNext()
463 if ($ADODB_EXTENSION) {
464 while(!$rstest->EOF
) {
465 adodb_movenext($rstest);
468 while(!$rstest->EOF
) {
472 $qryRecs = $rstest->_currentRow
;
475 if ($qryRecs == -1) return 0;
481 Code originally from "Cornel G" <conyg@fx.ro>
483 This code might not work with SQL that has UNION in it
485 Also if you are using CachePageExecute(), there is a strong possibility that
486 data will get out of synch. use CachePageExecute() only with tables that
489 function &_adodb_pageexecute_all_rows(&$zthis, $sql, $nrows, $page,
490 $inputarr=false, $secs2cache=0)
492 $atfirstpage = false;
496 // If an invalid nrows is supplied,
497 // we assume a default value of 10 rows per page
498 if (!isset($nrows) ||
$nrows <= 0) $nrows = 10;
500 $qryRecs = false; //count records for no offset
502 $qryRecs = _adodb_getcount($zthis,$sql,$inputarr,$secs2cache);
503 $lastpageno = (int) ceil($qryRecs / $nrows);
504 $zthis->_maxRecordCount
= $qryRecs;
508 // ***** Here we check whether $page is the last page or
509 // whether we are trying to retrieve
510 // a page number greater than the last page number.
511 if ($page >= $lastpageno) {
516 // If page number <= 1, then we are at the first page
517 if (empty($page) ||
$page <= 1) {
522 // We get the data we want
523 $offset = $nrows * ($page-1);
525 $rsreturn = &$zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $offset, $inputarr);
527 $rsreturn = &$zthis->SelectLimit($sql, $nrows, $offset, $inputarr, $secs2cache);
530 // Before returning the RecordSet, we set the pagination properties we need
532 $rsreturn->_maxRecordCount
= $qryRecs;
533 $rsreturn->rowsPerPage
= $nrows;
534 $rsreturn->AbsolutePage($page);
535 $rsreturn->AtFirstPage($atfirstpage);
536 $rsreturn->AtLastPage($atlastpage);
537 $rsreturn->LastPageNo($lastpageno);
542 // Iván Oliva version
543 function &_adodb_pageexecute_no_last_page(&$zthis, $sql, $nrows, $page, $inputarr=false, $secs2cache=0)
546 $atfirstpage = false;
549 if (!isset($page) ||
$page <= 1) { // If page number <= 1, then we are at the first page
553 if ($nrows <= 0) $nrows = 10; // If an invalid nrows is supplied, we assume a default value of 10 rows per page
555 // ***** Here we check whether $page is the last page or whether we are trying to retrieve a page number greater than
556 // the last page number.
557 $pagecounter = $page +
1;
558 $pagecounteroffset = ($pagecounter * $nrows) - $nrows;
559 if ($secs2cache>0) $rstest = &$zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $pagecounteroffset, $inputarr);
560 else $rstest = &$zthis->SelectLimit($sql, $nrows, $pagecounteroffset, $inputarr, $secs2cache);
562 while ($rstest && $rstest->EOF
&& $pagecounter>0) {
565 $pagecounteroffset = $nrows * ($pagecounter - 1);
567 if ($secs2cache>0) $rstest = &$zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $pagecounteroffset, $inputarr);
568 else $rstest = &$zthis->SelectLimit($sql, $nrows, $pagecounteroffset, $inputarr, $secs2cache);
570 if ($rstest) $rstest->Close();
572 if ($atlastpage) { // If we are at the last page or beyond it, we are going to retrieve it
573 $page = $pagecounter;
574 if ($page == 1) $atfirstpage = true; // We have to do this again in case the last page is the same as the first
575 //... page, that is, the recordset has only 1 page.
578 // We get the data we want
579 $offset = $nrows * ($page-1);
580 if ($secs2cache > 0) $rsreturn = &$zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $offset, $inputarr);
581 else $rsreturn = &$zthis->SelectLimit($sql, $nrows, $offset, $inputarr, $secs2cache);
583 // Before returning the RecordSet, we set the pagination properties we need
585 $rsreturn->rowsPerPage
= $nrows;
586 $rsreturn->AbsolutePage($page);
587 $rsreturn->AtFirstPage($atfirstpage);
588 $rsreturn->AtLastPage($atlastpage);
593 function _adodb_getupdatesql(&$zthis,&$rs, $arrFields,$forceUpdate=false,$magicq=false,$force=2)
595 global $ADODB_QUOTE_FIELDNAMES;
598 printf(ADODB_BAD_RS
,'GetUpdateSQL');
602 $fieldUpdatedCount = 0;
603 $arrFields = _array_change_key_case($arrFields);
605 $hasnumeric = isset($rs->fields
[0]);
608 // Loop through all of the fields in the recordset
609 for ($i=0, $max=$rs->FieldCount(); $i < $max; $i++
) {
610 // Get the field from the recordset
611 $field = $rs->FetchField($i);
613 // If the recordset field is one
614 // of the fields passed in then process.
615 $upperfname = strtoupper($field->name
);
616 if (adodb_key_exists($upperfname,$arrFields,$force)) {
618 // If the existing field value in the recordset
619 // is different from the value passed in then
620 // go ahead and append the field name and new value to
623 if ($hasnumeric) $val = $rs->fields
[$i];
624 else if (isset($rs->fields
[$upperfname])) $val = $rs->fields
[$upperfname];
625 else if (isset($rs->fields
[$field->name
])) $val = $rs->fields
[$field->name
];
626 else if (isset($rs->fields
[strtolower($upperfname)])) $val = $rs->fields
[strtolower($upperfname)];
630 if ($forceUpdate ||
strcmp($val, $arrFields[$upperfname])) {
631 // Set the counter for the number of fields that will be updated.
632 $fieldUpdatedCount++
;
634 // Based on the datatype of the field
635 // Format the value properly for the database
636 $type = $rs->MetaType($field->type
);
639 if ($type == 'null') {
643 if ((strpos($upperfname,' ') !== false) ||
($ADODB_QUOTE_FIELDNAMES))
644 $fnameq = $zthis->nameQuote
.$upperfname.$zthis->nameQuote
;
646 $fnameq = $upperfname;
649 // is_null requires php 4.0.4
650 //********************************************************//
651 if (is_null($arrFields[$upperfname])
652 ||
(empty($arrFields[$upperfname]) && strlen($arrFields[$upperfname]) == 0)
653 ||
$arrFields[$upperfname] === $zthis->null2null
659 // //Ignore empty values. This is allready handled in "adodb_key_exists" function.
664 $setFields .= $field->name
. " = null, ";
669 $arrFields[$upperfname] = "";
670 $setFields .= _adodb_column_sql($zthis, 'U', $type, $upperfname, $fnameq,$arrFields, $magicq);
674 //Set the value that was given in array, so you can give both null and empty values
675 if (is_null($arrFields[$upperfname]) ||
$arrFields[$upperfname] === $zthis->null2null
) {
676 $setFields .= $field->name
. " = null, ";
678 $setFields .= _adodb_column_sql($zthis, 'U', $type, $upperfname, $fnameq,$arrFields, $magicq);
682 //********************************************************//
684 //we do this so each driver can customize the sql for
685 //DB specific column types.
686 //Oracle needs BLOB types to be handled with a returning clause
687 //postgres has special needs as well
688 $setFields .= _adodb_column_sql($zthis, 'U', $type, $upperfname, $fnameq,
689 $arrFields, $magicq);
695 // If there were any modified fields then build the rest of the update query.
696 if ($fieldUpdatedCount > 0 ||
$forceUpdate) {
697 // Get the table name from the existing query.
698 if (!empty($rs->tableName
)) $tableName = $rs->tableName
;
700 preg_match("/FROM\s+".ADODB_TABLE_REGEX
."/is", $rs->sql
, $tableName);
701 $tableName = $tableName[1];
703 // Get the full where clause excluding the word "WHERE" from
704 // the existing query.
705 preg_match('/\sWHERE\s(.*)/is', $rs->sql
, $whereClause);
708 // not a good hack, improvements?
710 #var_dump($whereClause);
711 if (preg_match('/\s(ORDER\s.*)/is', $whereClause[1], $discard));
712 else if (preg_match('/\s(LIMIT\s.*)/is', $whereClause[1], $discard));
713 else if (preg_match('/\s(FOR UPDATE.*)/is', $whereClause[1], $discard));
714 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
716 $whereClause = array(false,false);
719 $whereClause[1] = substr($whereClause[1], 0, strlen($whereClause[1]) - strlen($discard[1]));
721 $sql = 'UPDATE '.$tableName.' SET '.substr($setFields, 0, -2);
722 if (strlen($whereClause[1]) > 0)
723 $sql .= ' WHERE '.$whereClause[1];
732 function adodb_key_exists($key, &$arr,$force=2)
735 // the following is the old behaviour where null or empty fields are ignored
736 return (!empty($arr[$key])) ||
(isset($arr[$key]) && strlen($arr[$key])>0);
739 if (isset($arr[$key])) return true;
741 if (ADODB_PHPVER
>= 0x4010) return array_key_exists($key,$arr);
746 * There is a special case of this function for the oci8 driver.
747 * The proper way to handle an insert w/ a blob in oracle requires
748 * a returning clause with bind variables and a descriptor blob.
752 function _adodb_getinsertsql(&$zthis,&$rs,$arrFields,$magicq=false,$force=2)
754 static $cacheRS = false;
755 static $cacheSig = 0;
757 global $ADODB_QUOTE_FIELDNAMES;
763 $arrFields = _array_change_key_case($arrFields);
764 $fieldInsertedCount = 0;
766 if (is_string($rs)) {
767 //ok we have a table name
768 //try and get the column info ourself.
771 //we need an object for the recordSet
772 //because we have to call MetaType.
773 //php can't do a $rsclass::MetaType()
774 $rsclass = $zthis->rsPrefix
.$zthis->databaseType
;
775 $recordSet = new $rsclass(-1,$zthis->fetchMode
);
776 $recordSet->connection
= &$zthis;
778 if (is_string($cacheRS) && $cacheRS == $rs) {
779 $columns =& $cacheCols;
781 $columns = $zthis->MetaColumns( $tableName );
782 $cacheRS = $tableName;
783 $cacheCols = $columns;
785 } else if (is_subclass_of($rs, 'adorecordset')) {
786 if (isset($rs->insertSig
) && is_integer($cacheRS) && $cacheRS == $rs->insertSig
) {
787 $columns =& $cacheCols;
789 for ($i=0, $max=$rs->FieldCount(); $i < $max; $i++
)
790 $columns[] = $rs->FetchField($i);
791 $cacheRS = $cacheSig;
792 $cacheCols = $columns;
793 $rs->insertSig
= $cacheSig++
;
798 printf(ADODB_BAD_RS
,'GetInsertSQL');
802 // Loop through all of the fields in the recordset
803 foreach( $columns as $field ) {
804 $upperfname = strtoupper($field->name
);
805 if (adodb_key_exists($upperfname,$arrFields,$force)) {
807 if ((strpos($upperfname,' ') !== false) ||
($ADODB_QUOTE_FIELDNAMES))
808 $fnameq = $zthis->nameQuote
.$upperfname.$zthis->nameQuote
;
810 $fnameq = $upperfname;
812 $type = $recordSet->MetaType($field->type
);
814 /********************************************************/
815 if (is_null($arrFields[$upperfname])
816 ||
(empty($arrFields[$upperfname]) && strlen($arrFields[$upperfname]) == 0)
817 ||
$arrFields[$upperfname] === $zthis->null2null
822 case 0: // we must always set null if missing
832 $arrFields[$upperfname] = "";
833 $values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq,$arrFields, $magicq);
838 //Set the value that was given in array, so you can give both null and empty values
839 if (is_null($arrFields[$upperfname]) ||
$arrFields[$upperfname] === $zthis->null2null
) {
842 $values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq, $arrFields, $magicq);
847 /*********************************************************/
849 //we do this so each driver can customize the sql for
850 //DB specific column types.
851 //Oracle needs BLOB types to be handled with a returning clause
852 //postgres has special needs as well
853 $values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq,
854 $arrFields, $magicq);
858 // Set the counter for the number of fields that will be inserted.
859 $fieldInsertedCount++
;
862 // Get the name of the fields to insert
863 $fields .= $fnameq . ", ";
868 // If there were any inserted fields then build the rest of the insert query.
869 if ($fieldInsertedCount <= 0) return false;
871 // Get the table name from the existing query.
873 if (!empty($rs->tableName
)) $tableName = $rs->tableName
;
874 else if (preg_match("/FROM\s+".ADODB_TABLE_REGEX
."/is", $rs->sql
, $tableName))
875 $tableName = $tableName[1];
880 // Strip off the comma and space on the end of both the fields
882 $fields = substr($fields, 0, -2);
883 $values = substr($values, 0, -2);
885 // Append the fields and their values to the insert query.
886 return 'INSERT INTO '.$tableName.' ( '.$fields.' ) VALUES ( '.$values.' )';
891 * This private method is used to help construct
892 * the update/sql which is generated by GetInsertSQL and GetUpdateSQL.
893 * It handles the string construction of 1 column -> sql string based on
894 * the column type. We want to do 'safe' handling of BLOBs
896 * @param string the type of sql we are trying to create
898 * @param string column data type from the db::MetaType() method
899 * @param string the column name
900 * @param array the column value
905 function _adodb_column_sql_oci8(&$zthis,$action, $type, $fname, $fnameq, $arrFields, $magicq)
909 // Based on the datatype of the field
910 // Format the value properly for the database
913 //in order to handle Blobs correctly, we need
914 //to do some magic for Oracle
916 //we need to create a new descriptor to handle
918 if (!empty($zthis->hasReturningInto
)) {
919 if ($action == 'I') {
920 $sql = 'empty_blob(), ';
922 $sql = $fnameq. '=empty_blob(), ';
924 //add the variable to the returning clause array
925 //so the user can build this later in
926 //case they want to add more to it
927 $zthis->_returningArray
[$fname] = ':xx'.$fname.'xx';
928 } else if (empty($arrFields[$fname])){
929 if ($action == 'I') {
930 $sql = 'empty_blob(), ';
932 $sql = $fnameq. '=empty_blob(), ';
935 //this is to maintain compatibility
936 //with older adodb versions.
937 $sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq,false);
942 //we need to do some more magic here for long variables
943 //to handle these correctly in oracle.
945 //create a safe bind var name
946 //to avoid conflicts w/ dupes.
947 if (!empty($zthis->hasReturningInto
)) {
948 if ($action == 'I') {
949 $sql = ':xx'.$fname.'xx, ';
951 $sql = $fnameq.'=:xx'.$fname.'xx, ';
953 //add the variable to the returning clause array
954 //so the user can build this later in
955 //case they want to add more to it
956 $zthis->_returningArray
[$fname] = ':xx'.$fname.'xx';
958 //this is to maintain compatibility
959 //with older adodb versions.
960 $sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq,false);
965 $sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq,false);
972 function _adodb_column_sql(&$zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq, $recurse=true)
976 switch($zthis->dataProvider
) {
978 if ($type == 'L') $type = 'C';
981 return _adodb_column_sql_oci8($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq);
990 $val = $zthis->qstr($arrFields[$fname],$magicq);
994 $val = $zthis->DBDate($arrFields[$fname]);
998 $val = $zthis->DBTimeStamp($arrFields[$fname]);
1001 case "F": //Floating point number // Moodle added
1003 $val = $arrFields[$fname];
1004 if (!is_numeric($val)) $val = str_replace(',', '.', (float)$val);
1007 case "L": //Integer field suitable for storing booleans (0 or 1) // Moodle added
1010 $val = $arrFields[$fname];
1011 if (!is_numeric($val)) $val = (integer) $val;
1015 $val = str_replace(array("'"," ","("),"",$arrFields[$fname]); // basic sql injection defence
1016 if (empty($val)) $val = '0';
1020 if ($action == 'I') return $val . ", ";
1023 return $fnameq . "=" . $val . ", ";
1029 function _adodb_debug_execute(&$zthis, $sql, $inputarr)
1033 foreach($inputarr as $kk=>$vv) {
1034 if (is_string($vv) && strlen($vv)>64) $vv = substr($vv,0,64).'...';
1035 if (is_null($vv)) $ss .= "($kk=>null) ";
1036 else $ss .= "($kk=>'$vv') ";
1040 $sqlTxt = is_array($sql) ?
$sql[0] : $sql;
1041 /*str_replace(', ','##1#__^LF',is_array($sql) ? $sql[0] : $sql);
1042 $sqlTxt = str_replace(',',', ',$sqlTxt);
1043 $sqlTxt = str_replace('##1#__^LF', ', ' ,$sqlTxt);
1045 // check if running from browser or command-line
1046 $inBrowser = isset($_SERVER['HTTP_USER_AGENT']);
1048 $dbt = $zthis->databaseType
;
1049 if (isset($zthis->dsnType
)) $dbt .= '-'.$zthis->dsnType
;
1052 $ss = '<code>'.htmlspecialchars($ss).'</code>';
1054 if ($zthis->debug
=== -1)
1055 ADOConnection
::outp( "<br />\n($dbt): ".htmlspecialchars($sqlTxt)." $ss\n<br />\n",false);
1057 ADOConnection
::outp( "<hr />\n($dbt): ".htmlspecialchars($sqlTxt)." $ss\n<hr />\n",false);
1059 ADOConnection
::outp("-----\n($dbt): ".$sqlTxt."\n-----\n",false);
1062 $qID = $zthis->_query($sql,$inputarr);
1065 Alexios Fakios notes that ErrorMsg() must be called before ErrorNo() for mssql
1066 because ErrorNo() calls Execute('SELECT @ERROR'), causing recursion
1068 if ($zthis->databaseType
== 'mssql') {
1069 // ErrorNo is a slow function call in mssql, and not reliable in PHP 4.0.6
1070 if($emsg = $zthis->ErrorMsg()) {
1071 if ($err = $zthis->ErrorNo()) ADOConnection
::outp($err.': '.$emsg);
1074 ADOConnection
::outp($zthis->ErrorNo() .': '. $zthis->ErrorMsg());
1077 if ($zthis->debug
=== 99) _adodb_backtrace(true,9999,2);
1081 # pretty print the debug_backtrace function
1082 function _adodb_backtrace($printOrArr=true,$levels=9999,$skippy=0)
1084 if (!function_exists('debug_backtrace')) return '';
1086 $html = (isset($_SERVER['HTTP_USER_AGENT']));
1087 // moodle change start - see readme_moodle.txt
1088 $fmt = ($html) ?
"</font><font color=\"#808080\" size=\"-1\"> %% line %4d, file: <a href=\"file:/%s\">%s</a></font>" : "%% line %4d, file: %s";
1089 // moodle change end
1093 // moodle change start - see readme_moodle.txt
1094 $s = ($html) ?
'<pre align="left">' : '';
1095 // moodle change end
1097 if (is_array($printOrArr)) $traceArr = $printOrArr;
1098 else $traceArr = debug_backtrace();
1099 array_shift($traceArr);
1100 array_shift($traceArr);
1101 $tabs = sizeof($traceArr)-2;
1103 foreach ($traceArr as $arr) {
1104 if ($skippy) {$skippy -= 1; continue;}
1106 if ($levels < 0) break;
1109 for ($i=0; $i < $tabs; $i++
) $s .= ($html) ?
' ' : "\t";
1111 if ($html) $s .= '<font face="Courier New,Courier">';
1112 if (isset($arr['class'])) $s .= $arr['class'].'.';
1113 if (isset($arr['args']))
1114 foreach($arr['args'] as $v) {
1115 if (is_null($v)) $args[] = 'null';
1116 else if (is_array($v)) $args[] = 'Array['.sizeof($v).']';
1117 else if (is_object($v)) $args[] = 'Object:'.get_class($v);
1118 else if (is_bool($v)) $args[] = $v ?
'true' : 'false';
1121 $str = htmlspecialchars(substr($v,0,$MAXSTRLEN));
1122 if (strlen($v) > $MAXSTRLEN) $str .= '...';
1126 $s .= $arr['function'].'('.implode(', ',$args).')';
1129 $s .= @sprintf
($fmt, $arr['line'],$arr['file'],basename($arr['file']));
1133 if ($html) $s .= '</pre>';
1134 if ($printOrArr) print $s;
1139 function _adodb_find_from($sql)
1142 $sql = str_replace(array("\n","\r"), ' ', $sql);
1143 $charCount = strlen($sql);
1147 $parentheseCount = 0;
1152 for($i = 0; $i < $charCount; $i++) {
1154 $char = substr($sql,$i,1);
1155 $prevChars = substr($sql,0,$i);
1156 $nextChars = substr($sql,$i+1);
1158 if((($char == "'" || $char == '"' || $char == '`') && substr($prevChars,-1,1) != '\\') && $inString === false) {
1163 elseif((($char == "'" || $char == '"' || $char == '`') && substr($prevChars,-1,1) != '\\') && $inString === true && $quote == $char) {
1168 elseif($char == "(" && $inString === false)
1171 elseif($char == ")" && $inString === false && $parentheseCount > 0)
1174 elseif($parentheseCount <= 0 && $inString === false && $char == " " && strtoupper(substr($prevChars,-5,5)) == " FROM")