2 // security - hide paths
3 if (!defined('ADODB_DIR')) die();
5 global $ADODB_INCLUDED_LIB;
6 $ADODB_INCLUDED_LIB = 1;
9 @version V5.19 23-Apr-2014 (c) 2000-2014 John Lim (jlim#natsoft.com). All rights reserved.
10 Released under both BSD license and Lesser GPL library license.
11 Whenever there is any discrepancy between the two licenses,
12 the BSD license will take precedence. See License.txt.
13 Set tabs to 4 for best viewing.
15 Less commonly used functions are placed here to reduce size of adodb.inc.php.
18 function adodb_strip_order_by($sql)
20 $rez = preg_match('/(\sORDER\s+BY\s(?:[^)](?!limit))*)(?:\sLIMIT\s+[0-9]+)?/is', $sql, $arr);
22 if (strpos($arr[1], '(') !== false) {
23 $at = strpos($sql, $arr[1]);
25 for ($i=$at, $max=strlen($sql); $i < $max; $i++) {
29 } elseif($ch == ')') {
36 $sql = substr($sql,0,$at).substr($sql,$i);
38 $sql = str_replace($arr[1], '', $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*/ 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];
456 $rstest = $zthis->CacheExecute($secs2cache,$rewritesql,$inputarr);
457 if (!$rstest) $rstest = $zthis->CacheExecute($secs2cache,$sql,$inputarr);
459 $rstest = $zthis->Execute($rewritesql,$inputarr);
460 if (!$rstest) $rstest = $zthis->Execute($sql,$inputarr);
463 $qryRecs = $rstest->RecordCount();
464 if ($qryRecs == -1) {
465 global $ADODB_EXTENSION;
466 // some databases will return -1 on MoveLast() - change to MoveNext()
467 if ($ADODB_EXTENSION) {
468 while(!$rstest->EOF) {
469 adodb_movenext($rstest);
472 while(!$rstest->EOF) {
476 $qryRecs = $rstest->_currentRow;
479 if ($qryRecs == -1) return 0;
485 Code originally from "Cornel G" <conyg@fx.ro>
487 This code might not work with SQL that has UNION in it
489 Also if you are using CachePageExecute(), there is a strong possibility that
490 data will get out of synch. use CachePageExecute() only with tables that
493 function _adodb_pageexecute_all_rows(&$zthis, $sql, $nrows, $page,
494 $inputarr=false, $secs2cache=0)
496 $atfirstpage = false;
500 // If an invalid nrows is supplied,
501 // we assume a default value of 10 rows per page
502 if (!isset($nrows) || $nrows <= 0) $nrows = 10;
504 $qryRecs = false; //count records for no offset
506 $qryRecs = _adodb_getcount($zthis,$sql,$inputarr,$secs2cache);
507 $lastpageno = (int) ceil($qryRecs / $nrows);
508 $zthis->_maxRecordCount = $qryRecs;
512 // ***** Here we check whether $page is the last page or
513 // whether we are trying to retrieve
514 // a page number greater than the last page number.
515 if ($page >= $lastpageno) {
520 // If page number <= 1, then we are at the first page
521 if (empty($page) || $page <= 1) {
526 // We get the data we want
527 $offset = $nrows * ($page-1);
529 $rsreturn = $zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $offset, $inputarr);
531 $rsreturn = $zthis->SelectLimit($sql, $nrows, $offset, $inputarr, $secs2cache);
534 // Before returning the RecordSet, we set the pagination properties we need
536 $rsreturn->_maxRecordCount = $qryRecs;
537 $rsreturn->rowsPerPage = $nrows;
538 $rsreturn->AbsolutePage($page);
539 $rsreturn->AtFirstPage($atfirstpage);
540 $rsreturn->AtLastPage($atlastpage);
541 $rsreturn->LastPageNo($lastpageno);
546 // Iván Oliva version
547 function _adodb_pageexecute_no_last_page(&$zthis, $sql, $nrows, $page, $inputarr=false, $secs2cache=0)
550 $atfirstpage = false;
553 if (!isset($page) || $page <= 1) { // If page number <= 1, then we are at the first page
557 if ($nrows <= 0) $nrows = 10; // If an invalid nrows is supplied, we assume a default value of 10 rows per page
559 // ***** Here we check whether $page is the last page or whether we are trying to retrieve a page number greater than
560 // the last page number.
561 $pagecounter = $page + 1;
562 $pagecounteroffset = ($pagecounter * $nrows) - $nrows;
563 if ($secs2cache>0) $rstest = $zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $pagecounteroffset, $inputarr);
564 else $rstest = $zthis->SelectLimit($sql, $nrows, $pagecounteroffset, $inputarr, $secs2cache);
566 while ($rstest && $rstest->EOF && $pagecounter>0) {
569 $pagecounteroffset = $nrows * ($pagecounter - 1);
571 if ($secs2cache>0) $rstest = $zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $pagecounteroffset, $inputarr);
572 else $rstest = $zthis->SelectLimit($sql, $nrows, $pagecounteroffset, $inputarr, $secs2cache);
574 if ($rstest) $rstest->Close();
576 if ($atlastpage) { // If we are at the last page or beyond it, we are going to retrieve it
577 $page = $pagecounter;
578 if ($page == 1) $atfirstpage = true; // We have to do this again in case the last page is the same as the first
579 //... page, that is, the recordset has only 1 page.
582 // We get the data we want
583 $offset = $nrows * ($page-1);
584 if ($secs2cache > 0) $rsreturn = $zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $offset, $inputarr);
585 else $rsreturn = $zthis->SelectLimit($sql, $nrows, $offset, $inputarr, $secs2cache);
587 // Before returning the RecordSet, we set the pagination properties we need
589 $rsreturn->rowsPerPage = $nrows;
590 $rsreturn->AbsolutePage($page);
591 $rsreturn->AtFirstPage($atfirstpage);
592 $rsreturn->AtLastPage($atlastpage);
597 function _adodb_getupdatesql(&$zthis,&$rs, $arrFields,$forceUpdate=false,$magicq=false,$force=2)
599 global $ADODB_QUOTE_FIELDNAMES;
602 printf(ADODB_BAD_RS,'GetUpdateSQL');
606 $fieldUpdatedCount = 0;
607 $arrFields = _array_change_key_case($arrFields);
609 $hasnumeric = isset($rs->fields[0]);
612 // Loop through all of the fields in the recordset
613 for ($i=0, $max=$rs->FieldCount(); $i < $max; $i++) {
614 // Get the field from the recordset
615 $field = $rs->FetchField($i);
617 // If the recordset field is one
618 // of the fields passed in then process.
619 $upperfname = strtoupper($field->name);
620 if (adodb_key_exists($upperfname,$arrFields,$force)) {
622 // If the existing field value in the recordset
623 // is different from the value passed in then
624 // go ahead and append the field name and new value to
627 if ($hasnumeric) $val = $rs->fields[$i];
628 else if (isset($rs->fields[$upperfname])) $val = $rs->fields[$upperfname];
629 else if (isset($rs->fields[$field->name])) $val = $rs->fields[$field->name];
630 else if (isset($rs->fields[strtolower($upperfname)])) $val = $rs->fields[strtolower($upperfname)];
634 if ($forceUpdate || strcmp($val, $arrFields[$upperfname])) {
635 // Set the counter for the number of fields that will be updated.
636 $fieldUpdatedCount++;
638 // Based on the datatype of the field
639 // Format the value properly for the database
640 $type = $rs->MetaType($field->type);
643 if ($type == 'null') {
647 if ((strpos($upperfname,' ') !== false) || ($ADODB_QUOTE_FIELDNAMES)) {
648 switch ($ADODB_QUOTE_FIELDNAMES) {
650 $fnameq = $zthis->nameQuote.strtolower($field->name).$zthis->nameQuote;break;
652 $fnameq = $zthis->nameQuote.$field->name.$zthis->nameQuote;break;
655 $fnameq = $zthis->nameQuote.$upperfname.$zthis->nameQuote;break;
658 $fnameq = $upperfname;
660 //********************************************************//
661 if (is_null($arrFields[$upperfname])
662 || (empty($arrFields[$upperfname]) && strlen($arrFields[$upperfname]) == 0)
663 || $arrFields[$upperfname] === $zthis->null2null
669 // //Ignore empty values. This is allready handled in "adodb_key_exists" function.
674 $setFields .= $field->name . " = null, ";
679 $arrFields[$upperfname] = "";
680 $setFields .= _adodb_column_sql($zthis, 'U', $type, $upperfname, $fnameq,$arrFields, $magicq);
684 //Set the value that was given in array, so you can give both null and empty values
685 if (is_null($arrFields[$upperfname]) || $arrFields[$upperfname] === $zthis->null2null) {
686 $setFields .= $field->name . " = null, ";
688 $setFields .= _adodb_column_sql($zthis, 'U', $type, $upperfname, $fnameq,$arrFields, $magicq);
692 //********************************************************//
694 //we do this so each driver can customize the sql for
695 //DB specific column types.
696 //Oracle needs BLOB types to be handled with a returning clause
697 //postgres has special needs as well
698 $setFields .= _adodb_column_sql($zthis, 'U', $type, $upperfname, $fnameq,
699 $arrFields, $magicq);
705 // If there were any modified fields then build the rest of the update query.
706 if ($fieldUpdatedCount > 0 || $forceUpdate) {
707 // Get the table name from the existing query.
708 if (!empty($rs->tableName)) $tableName = $rs->tableName;
710 preg_match("/FROM\s+".ADODB_TABLE_REGEX."/is", $rs->sql, $tableName);
711 $tableName = $tableName[1];
713 // Get the full where clause excluding the word "WHERE" from
714 // the existing query.
715 preg_match('/\sWHERE\s(.*)/is', $rs->sql, $whereClause);
718 // not a good hack, improvements?
720 #var_dump($whereClause);
721 if (preg_match('/\s(ORDER\s.*)/is', $whereClause[1], $discard));
722 else if (preg_match('/\s(LIMIT\s.*)/is', $whereClause[1], $discard));
723 else if (preg_match('/\s(FOR UPDATE.*)/is', $whereClause[1], $discard));
724 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
726 $whereClause = array(false,false);
729 $whereClause[1] = substr($whereClause[1], 0, strlen($whereClause[1]) - strlen($discard[1]));
731 $sql = 'UPDATE '.$tableName.' SET '.substr($setFields, 0, -2);
732 if (strlen($whereClause[1]) > 0)
733 $sql .= ' WHERE '.$whereClause[1];
742 function adodb_key_exists($key, &$arr,$force=2)
745 // the following is the old behaviour where null or empty fields are ignored
746 return (!empty($arr[$key])) || (isset($arr[$key]) && strlen($arr[$key])>0);
749 if (isset($arr[$key])) return true;
751 if (ADODB_PHPVER >= 0x4010) return array_key_exists($key,$arr);
756 * There is a special case of this function for the oci8 driver.
757 * The proper way to handle an insert w/ a blob in oracle requires
758 * a returning clause with bind variables and a descriptor blob.
762 function _adodb_getinsertsql(&$zthis,&$rs,$arrFields,$magicq=false,$force=2)
764 static $cacheRS = false;
765 static $cacheSig = 0;
767 global $ADODB_QUOTE_FIELDNAMES;
773 $arrFields = _array_change_key_case($arrFields);
774 $fieldInsertedCount = 0;
776 if (is_string($rs)) {
777 //ok we have a table name
778 //try and get the column info ourself.
781 //we need an object for the recordSet
782 //because we have to call MetaType.
783 //php can't do a $rsclass::MetaType()
784 $rsclass = $zthis->rsPrefix.$zthis->databaseType;
785 $recordSet = new $rsclass(-1,$zthis->fetchMode);
786 $recordSet->connection = $zthis;
788 if (is_string($cacheRS) && $cacheRS == $rs) {
789 $columns = $cacheCols;
791 $columns = $zthis->MetaColumns( $tableName );
792 $cacheRS = $tableName;
793 $cacheCols = $columns;
795 } else if (is_subclass_of($rs, 'adorecordset')) {
796 if (isset($rs->insertSig) && is_integer($cacheRS) && $cacheRS == $rs->insertSig) {
797 $columns = $cacheCols;
799 for ($i=0, $max=$rs->FieldCount(); $i < $max; $i++)
800 $columns[] = $rs->FetchField($i);
801 $cacheRS = $cacheSig;
802 $cacheCols = $columns;
803 $rs->insertSig = $cacheSig++;
808 printf(ADODB_BAD_RS,'GetInsertSQL');
812 // Loop through all of the fields in the recordset
813 foreach( $columns as $field ) {
814 $upperfname = strtoupper($field->name);
815 if (adodb_key_exists($upperfname,$arrFields,$force)) {
817 if ((strpos($upperfname,' ') !== false) || ($ADODB_QUOTE_FIELDNAMES)) {
818 switch ($ADODB_QUOTE_FIELDNAMES) {
820 $fnameq = $zthis->nameQuote.strtolower($field->name).$zthis->nameQuote;break;
822 $fnameq = $zthis->nameQuote.$field->name.$zthis->nameQuote;break;
825 $fnameq = $zthis->nameQuote.$upperfname.$zthis->nameQuote;break;
828 $fnameq = $upperfname;
830 $type = $recordSet->MetaType($field->type);
832 /********************************************************/
833 if (is_null($arrFields[$upperfname])
834 || (empty($arrFields[$upperfname]) && strlen($arrFields[$upperfname]) == 0)
835 || $arrFields[$upperfname] === $zthis->null2null
840 case 0: // we must always set null if missing
850 $arrFields[$upperfname] = "";
851 $values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq,$arrFields, $magicq);
856 //Set the value that was given in array, so you can give both null and empty values
857 if (is_null($arrFields[$upperfname]) || $arrFields[$upperfname] === $zthis->null2null) {
860 $values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq, $arrFields, $magicq);
865 /*********************************************************/
867 //we do this so each driver can customize the sql for
868 //DB specific column types.
869 //Oracle needs BLOB types to be handled with a returning clause
870 //postgres has special needs as well
871 $values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq,
872 $arrFields, $magicq);
876 // Set the counter for the number of fields that will be inserted.
877 $fieldInsertedCount++;
880 // Get the name of the fields to insert
881 $fields .= $fnameq . ", ";
886 // If there were any inserted fields then build the rest of the insert query.
887 if ($fieldInsertedCount <= 0) return false;
889 // Get the table name from the existing query.
891 if (!empty($rs->tableName)) $tableName = $rs->tableName;
892 else if (preg_match("/FROM\s+".ADODB_TABLE_REGEX."/is", $rs->sql, $tableName))
893 $tableName = $tableName[1];
898 // Strip off the comma and space on the end of both the fields
900 $fields = substr($fields, 0, -2);
901 $values = substr($values, 0, -2);
903 // Append the fields and their values to the insert query.
904 return 'INSERT INTO '.$tableName.' ( '.$fields.' ) VALUES ( '.$values.' )';
909 * This private method is used to help construct
910 * the update/sql which is generated by GetInsertSQL and GetUpdateSQL.
911 * It handles the string construction of 1 column -> sql string based on
912 * the column type. We want to do 'safe' handling of BLOBs
914 * @param string the type of sql we are trying to create
916 * @param string column data type from the db::MetaType() method
917 * @param string the column name
918 * @param array the column value
923 function _adodb_column_sql_oci8(&$zthis,$action, $type, $fname, $fnameq, $arrFields, $magicq)
927 // Based on the datatype of the field
928 // Format the value properly for the database
931 //in order to handle Blobs correctly, we need
932 //to do some magic for Oracle
934 //we need to create a new descriptor to handle
936 if (!empty($zthis->hasReturningInto)) {
937 if ($action == 'I') {
938 $sql = 'empty_blob(), ';
940 $sql = $fnameq. '=empty_blob(), ';
942 //add the variable to the returning clause array
943 //so the user can build this later in
944 //case they want to add more to it
945 $zthis->_returningArray[$fname] = ':xx'.$fname.'xx';
946 } else if (empty($arrFields[$fname])){
947 if ($action == 'I') {
948 $sql = 'empty_blob(), ';
950 $sql = $fnameq. '=empty_blob(), ';
953 //this is to maintain compatibility
954 //with older adodb versions.
955 $sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq,false);
960 //we need to do some more magic here for long variables
961 //to handle these correctly in oracle.
963 //create a safe bind var name
964 //to avoid conflicts w/ dupes.
965 if (!empty($zthis->hasReturningInto)) {
966 if ($action == 'I') {
967 $sql = ':xx'.$fname.'xx, ';
969 $sql = $fnameq.'=:xx'.$fname.'xx, ';
971 //add the variable to the returning clause array
972 //so the user can build this later in
973 //case they want to add more to it
974 $zthis->_returningArray[$fname] = ':xx'.$fname.'xx';
976 //this is to maintain compatibility
977 //with older adodb versions.
978 $sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq,false);
983 $sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq,false);
990 function _adodb_column_sql(&$zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq, $recurse=true)
994 switch($zthis->dataProvider) {
996 if ($type == 'L') $type = 'C';
999 return _adodb_column_sql_oci8($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq);
1008 $val = $zthis->qstr($arrFields[$fname],$magicq);
1012 $val = $zthis->DBDate($arrFields[$fname]);
1016 $val = $zthis->DBTimeStamp($arrFields[$fname]);
1020 $val = $arrFields[$fname];
1021 if (!is_numeric($val)) $val = str_replace(',', '.', (float)$val);
1026 $val = $arrFields[$fname];
1027 if (!is_numeric($val)) $val = (integer) $val;
1031 $val = str_replace(array("'"," ","("),"",$arrFields[$fname]); // basic sql injection defence
1032 if (empty($val)) $val = '0';
1036 if ($action == 'I') return $val . ", ";
1039 return $fnameq . "=" . $val . ", ";
1045 function _adodb_debug_execute(&$zthis, $sql, $inputarr)
1049 foreach($inputarr as $kk=>$vv) {
1050 if (is_string($vv) && strlen($vv)>64) $vv = substr($vv,0,64).'...';
1051 if (is_null($vv)) $ss .= "($kk=>null) ";
1052 else $ss .= "($kk=>'$vv') ";
1056 $sqlTxt = is_array($sql) ? $sql[0] : $sql;
1057 /*str_replace(', ','##1#__^LF',is_array($sql) ? $sql[0] : $sql);
1058 $sqlTxt = str_replace(',',', ',$sqlTxt);
1059 $sqlTxt = str_replace('##1#__^LF', ', ' ,$sqlTxt);
1061 // check if running from browser or command-line
1062 $inBrowser = isset($_SERVER['HTTP_USER_AGENT']);
1064 $dbt = $zthis->databaseType;
1065 if (isset($zthis->dsnType)) $dbt .= '-'.$zthis->dsnType;
1068 $ss = '<code>'.htmlspecialchars($ss).'</code>';
1070 if ($zthis->debug === -1)
1071 ADOConnection::outp( "<br>\n($dbt): ".htmlspecialchars($sqlTxt)." $ss\n<br>\n",false);
1072 else if ($zthis->debug !== -99)
1073 ADOConnection::outp( "<hr>\n($dbt): ".htmlspecialchars($sqlTxt)." $ss\n<hr>\n",false);
1076 if ($zthis->debug !== -99)
1077 ADOConnection::outp("-----<hr>\n($dbt): ".$sqlTxt." $ss\n-----<hr>\n",false);
1080 $qID = $zthis->_query($sql,$inputarr);
1083 Alexios Fakios notes that ErrorMsg() must be called before ErrorNo() for mssql
1084 because ErrorNo() calls Execute('SELECT @ERROR'), causing recursion
1086 if ($zthis->databaseType == 'mssql') {
1087 // ErrorNo is a slow function call in mssql, and not reliable in PHP 4.0.6
1089 if($emsg = $zthis->ErrorMsg()) {
1090 if ($err = $zthis->ErrorNo()) {
1091 if ($zthis->debug === -99)
1092 ADOConnection::outp( "<hr>\n($dbt): ".htmlspecialchars($sqlTxt)." $ss\n<hr>\n",false);
1094 ADOConnection::outp($err.': '.$emsg);
1099 if ($zthis->debug === -99)
1100 if ($inBrowser) ADOConnection::outp( "<hr>\n($dbt): ".htmlspecialchars($sqlTxt)." $ss\n<hr>\n",false);
1101 else ADOConnection::outp("-----<hr>\n($dbt): ".$sqlTxt."$ss\n-----<hr>\n",false);
1103 ADOConnection::outp($zthis->ErrorNo() .': '. $zthis->ErrorMsg());
1106 if ($zthis->debug === 99) _adodb_backtrace(true,9999,2);
1110 # pretty print the debug_backtrace function
1111 function _adodb_backtrace($printOrArr=true,$levels=9999,$skippy=0,$ishtml=null)
1113 if (!function_exists('debug_backtrace')) return '';
1115 if ($ishtml === null) $html = (isset($_SERVER['HTTP_USER_AGENT']));
1116 else $html = $ishtml;
1118 $fmt = ($html) ? "</font><font color=#808080 size=-1> %% line %4d, file: <a href=\"file:/%s\">%s</a></font>" : "%% line %4d, file: %s";
1122 $s = ($html) ? '<pre align=left>' : '';
1124 if (is_array($printOrArr)) $traceArr = $printOrArr;
1125 else $traceArr = debug_backtrace();
1126 array_shift($traceArr);
1127 array_shift($traceArr);
1128 $tabs = sizeof($traceArr)-2;
1130 foreach ($traceArr as $arr) {
1131 if ($skippy) {$skippy -= 1; continue;}
1133 if ($levels < 0) break;
1136 for ($i=0; $i < $tabs; $i++) $s .= ($html) ? ' ' : "\t";
1138 if ($html) $s .= '<font face="Courier New,Courier">';
1139 if (isset($arr['class'])) $s .= $arr['class'].'.';
1140 if (isset($arr['args']))
1141 foreach($arr['args'] as $v) {
1142 if (is_null($v)) $args[] = 'null';
1143 else if (is_array($v)) $args[] = 'Array['.sizeof($v).']';
1144 else if (is_object($v)) $args[] = 'Object:'.get_class($v);
1145 else if (is_bool($v)) $args[] = $v ? 'true' : 'false';
1148 $str = htmlspecialchars(str_replace(array("\r","\n"),' ',substr($v,0,$MAXSTRLEN)));
1149 if (strlen($v) > $MAXSTRLEN) $str .= '...';
1153 $s .= $arr['function'].'('.implode(', ',$args).')';
1156 $s .= @sprintf($fmt, $arr['line'],$arr['file'],basename($arr['file']));
1160 if ($html) $s .= '</pre>';
1161 if ($printOrArr) print $s;
1166 function _adodb_find_from($sql)
1169 $sql = str_replace(array("\n","\r"), ' ', $sql);
1170 $charCount = strlen($sql);
1174 $parentheseCount = 0;
1179 for($i = 0; $i < $charCount; $i++) {
1181 $char = substr($sql,$i,1);
1182 $prevChars = substr($sql,0,$i);
1183 $nextChars = substr($sql,$i+1);
1185 if((($char == "'" || $char == '"' || $char == '`') && substr($prevChars,-1,1) != '\\') && $inString === false) {
1190 elseif((($char == "'" || $char == '"' || $char == '`') && substr($prevChars,-1,1) != '\\') && $inString === true && $quote == $char) {
1195 elseif($char == "(" && $inString === false)
1198 elseif($char == ")" && $inString === false && $parentheseCount > 0)
1201 elseif($parentheseCount <= 0 && $inString === false && $char == " " && strtoupper(substr($prevChars,-5,5)) == " FROM")