"TYPO3 4.0.1: typo3_src-4.0.1/typo3/sysext/adodb/adodb/adodb-lib.inc.php Source File", "datetime" => "Sat Dec 2 19:22:24 2006", "date" => "2 Dec 2006", "doxygenversion" => "1.4.6", "projectname" => "TYPO3 4.0.1", "projectnumber" => "4.0.1" ); get_header($doxygen_vars); ?>

adodb-lib.inc.php

00001 <?php
00002 
00003 // security - hide paths
00004 if (!defined('ADODB_DIR')) die();
00005 
00006 global $ADODB_INCLUDED_LIB;
00007 $ADODB_INCLUDED_LIB = 1;
00008 
00009 /* 
00010  @version V4.90 8 June 2006 (c) 2000-2006 John Lim (jlim\@natsoft.com.my). All rights reserved.
00011   Released under both BSD license and Lesser GPL library license. 
00012   Whenever there is any discrepancy between the two licenses, 
00013   the BSD license will take precedence. See License.txt. 
00014   Set tabs to 4 for best viewing.
00015   
00016   Less commonly used functions are placed here to reduce size of adodb.inc.php. 
00017 */ 
00018 
00019 
00020 // Force key to upper. 
00021 // See also http://www.php.net/manual/en/function.array-change-key-case.php
00022 function _array_change_key_case($an_array)
00023 {
00024         if (is_array($an_array)) {
00025                 $new_array = array();
00026                 foreach($an_array as $key=>$value)
00027                         $new_array[strtoupper($key)] = $value;
00028 
00029                 return $new_array;
00030    }
00031 
00032         return $an_array;
00033 }
00034 
00035 function _adodb_replace(&$zthis, $table, $fieldArray, $keyCol, $autoQuote, $has_autoinc)
00036 {
00037                 if (count($fieldArray) == 0) return 0;
00038                 $first = true;
00039                 $uSet = '';
00040                 
00041                 if (!is_array($keyCol)) {
00042                         $keyCol = array($keyCol);
00043                 }
00044                 foreach($fieldArray as $k => $v) {
00045                         if ($autoQuote && !is_numeric($v) and strncmp($v,"'",1) !== 0 and strcasecmp($v,'null')!=0) {
00046                                 $v = $zthis->qstr($v);
00047                                 $fieldArray[$k] = $v;
00048                         }
00049                         if (in_array($k,$keyCol)) continue; // skip UPDATE if is key
00050                         
00051                         if ($first) {
00052                                 $first = false;                 
00053                                 $uSet = "$k=$v";
00054                         } else
00055                                 $uSet .= ",$k=$v";
00056                 }
00057                  
00058                 $where = false;
00059                 foreach ($keyCol as $v) {
00060                         if (isset($fieldArray[$v])) {
00061                                 if ($where) $where .= ' and '.$v.'='.$fieldArray[$v];
00062                                 else $where = $v.'='.$fieldArray[$v];
00063                         }
00064                 }
00065                 
00066                 if ($uSet && $where) {
00067                         $update = "UPDATE $table SET $uSet WHERE $where";
00068 
00069                         $rs = $zthis->Execute($update);
00070                         
00071                         
00072                         if ($rs) {
00073                                 if ($zthis->poorAffectedRows) {
00074                                 /*
00075                                  The Select count(*) wipes out any errors that the update would have returned. 
00076                                 http://phplens.com/lens/lensforum/msgs.php?id=5696
00077                                 */
00078                                         if ($zthis->ErrorNo()<>0) return 0;
00079                                         
00080                                 # affected_rows == 0 if update field values identical to old values
00081                                 # for mysql - which is silly. 
00082                         
00083                                         $cnt = $zthis->GetOne("select count(*) from $table where $where");
00084                                         if ($cnt > 0) return 1; // record already exists
00085                                 } else {
00086                                         if (($zthis->Affected_Rows()>0)) return 1;
00087                                 }
00088                         } else
00089                                 return 0;
00090                 }
00091                 
00092         //      print "<p>Error=".$this->ErrorNo().'<p>';
00093                 $first = true;
00094                 foreach($fieldArray as $k => $v) {
00095                         if ($has_autoinc && in_array($k,$keyCol)) continue; // skip autoinc col
00096                         
00097                         if ($first) {
00098                                 $first = false;                 
00099                                 $iCols = "$k";
00100                                 $iVals = "$v";
00101                         } else {
00102                                 $iCols .= ",$k";
00103                                 $iVals .= ",$v";
00104                         }                               
00105                 }
00106                 $insert = "INSERT INTO $table ($iCols) VALUES ($iVals)"; 
00107                 $rs = $zthis->Execute($insert);
00108                 return ($rs) ? 2 : 0;
00109 }
00110 
00111 // Requires $ADODB_FETCH_MODE = ADODB_FETCH_NUM
00112 function _adodb_getmenu(&$zthis, $name,$defstr='',$blank1stItem=true,$multiple=false,
00113                         $size=0, $selectAttr='',$compareFields0=true)
00114 {
00115         $hasvalue = false;
00116 
00117         if ($multiple or is_array($defstr)) {
00118                 if ($size==0) $size=5;
00119                 $attr = ' multiple size="'.$size.'"';
00120                 if (!strpos($name,'[]')) $name .= '[]';
00121         } else if ($size) $attr = ' size="'.$size.'"';
00122         else $attr ='';
00123         
00124         $s = '<select name="'.$name.'"'.$attr.' '.$selectAttr.'>';
00125         if ($blank1stItem) 
00126                 if (is_string($blank1stItem))  {
00127                         $barr = explode(':',$blank1stItem);
00128                         if (sizeof($barr) == 1) $barr[] = '';
00129                         $s .= "\n<option value=\"".$barr[0]."\">".$barr[1]."</option>";
00130                 } else $s .= "\n<option></option>";
00131 
00132         if ($zthis->FieldCount() > 1) $hasvalue=true;
00133         else $compareFields0 = true;
00134         
00135         $value = '';
00136     $optgroup = null;
00137     $firstgroup = true;
00138     $fieldsize = $zthis->FieldCount();
00139         while(!$zthis->EOF) {
00140                 $zval = rtrim(reset($zthis->fields));
00141 
00142                 if ($blank1stItem && $zval=="") {
00143                         $zthis->MoveNext();
00144                         continue;
00145                 }
00146 
00147         if ($fieldsize > 1) {
00148                         if (isset($zthis->fields[1]))
00149                                 $zval2 = rtrim($zthis->fields[1]);
00150                         else
00151                                 $zval2 = rtrim(next($zthis->fields));
00152                 }
00153                 $selected = ($compareFields0) ? $zval : $zval2;
00154                 
00155         $group = '';
00156                 if ($fieldsize > 2) {
00157             $group = rtrim($zthis->fields[2]);
00158         }
00159  
00160         if ($optgroup != $group) {
00161             $optgroup = $group;
00162             if ($firstgroup) {
00163                 $firstgroup = false;
00164                 $s .="\n<optgroup label='". htmlspecialchars($group) ."'>";
00165             } else {
00166                 $s .="\n</optgroup>";
00167                 $s .="\n<optgroup label='". htmlspecialchars($group) ."'>";
00168             }
00169                 }
00170         
00171                 if ($hasvalue) 
00172                         $value = " value='".htmlspecialchars($zval2)."'";
00173                 
00174                 if (is_array($defstr))  {
00175                         
00176                         if (in_array($selected,$defstr)) 
00177                                 $s .= "\n<option selected='selected'$value>".htmlspecialchars($zval).'</option>';
00178                         else 
00179                                 $s .= "\n<option".$value.'>'.htmlspecialchars($zval).'</option>';
00180                 }
00181                 else {
00182                         if (strcasecmp($selected,$defstr)==0) 
00183                                 $s .= "\n<option selected='selected'$value>".htmlspecialchars($zval).'</option>';
00184                         else
00185                                 $s .= "\n<option".$value.'>'.htmlspecialchars($zval).'</option>';
00186                 }
00187                 $zthis->MoveNext();
00188         } // while
00189         
00190     // closing last optgroup
00191     if($optgroup != null) {
00192         $s .= "\n</optgroup>";
00193         }
00194         return $s ."\n</select>\n";
00195 }
00196 
00197 // Requires $ADODB_FETCH_MODE = ADODB_FETCH_NUM
00198 function _adodb_getmenu_gp(&$zthis, $name,$defstr='',$blank1stItem=true,$multiple=false,
00199                         $size=0, $selectAttr='',$compareFields0=true)
00200 {
00201         $hasvalue = false;
00202 
00203         if ($multiple or is_array($defstr)) {
00204                 if ($size==0) $size=5;
00205                 $attr = ' multiple size="'.$size.'"';
00206                 if (!strpos($name,'[]')) $name .= '[]';
00207         } else if ($size) $attr = ' size="'.$size.'"';
00208         else $attr ='';
00209         
00210         $s = '<select name="'.$name.'"'.$attr.' '.$selectAttr.'>';
00211         if ($blank1stItem) 
00212                 if (is_string($blank1stItem))  {
00213                         $barr = explode(':',$blank1stItem);
00214                         if (sizeof($barr) == 1) $barr[] = '';
00215                         $s .= "\n<option value=\"".$barr[0]."\">".$barr[1]."</option>";
00216                 } else $s .= "\n<option></option>";
00217 
00218         if ($zthis->FieldCount() > 1) $hasvalue=true;
00219         else $compareFields0 = true;
00220         
00221         $value = '';
00222     $optgroup = null;
00223     $firstgroup = true;
00224     $fieldsize = sizeof($zthis->fields);
00225         while(!$zthis->EOF) {
00226                 $zval = rtrim(reset($zthis->fields));
00227 
00228                 if ($blank1stItem && $zval=="") {
00229                         $zthis->MoveNext();
00230                         continue;
00231                 }
00232 
00233         if ($fieldsize > 1) {
00234                         if (isset($zthis->fields[1]))
00235                                 $zval2 = rtrim($zthis->fields[1]);
00236                         else
00237                                 $zval2 = rtrim(next($zthis->fields));
00238                 }
00239                 $selected = ($compareFields0) ? $zval : $zval2;
00240                 
00241         $group = '';
00242                 if (isset($zthis->fields[2])) {
00243             $group = rtrim($zthis->fields[2]);
00244         }
00245  
00246         if ($optgroup != $group) {
00247             $optgroup = $group;
00248             if ($firstgroup) {
00249                 $firstgroup = false;
00250                 $s .="\n<optgroup label='". htmlspecialchars($group) ."'>";
00251             } else {
00252                 $s .="\n</optgroup>";
00253                 $s .="\n<optgroup label='". htmlspecialchars($group) ."'>";
00254             }
00255                 }
00256         
00257                 if ($hasvalue) 
00258                         $value = " value='".htmlspecialchars($zval2)."'";
00259                 
00260                 if (is_array($defstr))  {
00261                         
00262                         if (in_array($selected,$defstr)) 
00263                                 $s .= "\n<option selected='selected'$value>".htmlspecialchars($zval).'</option>';
00264                         else 
00265                                 $s .= "\n<option".$value.'>'.htmlspecialchars($zval).'</option>';
00266                 }
00267                 else {
00268                         if (strcasecmp($selected,$defstr)==0) 
00269                                 $s .= "\n<option selected='selected'$value>".htmlspecialchars($zval).'</option>';
00270                         else
00271                                 $s .= "\n<option".$value.'>'.htmlspecialchars($zval).'</option>';
00272                 }
00273                 $zthis->MoveNext();
00274         } // while
00275         
00276     // closing last optgroup
00277     if($optgroup != null) {
00278         $s .= "\n</optgroup>";
00279         }
00280         return $s ."\n</select>\n";
00281 }
00282 
00283 
00284 /*
00285         Count the number of records this sql statement will return by using
00286         query rewriting heuristics...
00287         
00288         Does not work with UNIONs, except with postgresql and oracle.
00289         
00290         Usage:
00291         
00292         $conn->Connect(...);
00293         $cnt = _adodb_getcount($conn, $sql);
00294         
00295 */
00296 function _adodb_getcount(&$zthis, $sql,$inputarr=false,$secs2cache=0) 
00297 {
00298         $qryRecs = 0;
00299         
00300          if (preg_match("/^\s*SELECT\s+DISTINCT/is", $sql) || 
00301                 preg_match('/\s+GROUP\s+BY\s+/is',$sql) || 
00302                 preg_match('/\s+UNION\s+/is',$sql)) {
00303                 // ok, has SELECT DISTINCT or GROUP BY so see if we can use a table alias
00304                 // but this is only supported by oracle and postgresql...
00305                 if ($zthis->dataProvider == 'oci8') {
00306                         
00307                         $rewritesql = preg_replace('/(\sORDER\s+BY\s.*)/is','',$sql);
00308                         
00309                         // Allow Oracle hints to be used for query optimization, Chris Wrye
00310                         if (preg_match('#/\\*+.*?\\*\\/#', $sql, $hint)) {
00311                                 $rewritesql = "SELECT ".$hint[0]." COUNT(*) FROM (".$rewritesql.")"; 
00312                         } else
00313                                 $rewritesql = "SELECT COUNT(*) FROM (".$rewritesql.")"; 
00314                         
00315                 } else if (strncmp($zthis->databaseType,'postgres',8) == 0)  {
00316                         
00317                         $info = $zthis->ServerInfo();
00318                         if (substr($info['version'],0,3) >= 7.1) { // good till version 999
00319                                 $rewritesql = preg_replace('/(\sORDER\s+BY\s[^)]*)/is','',$sql);
00320                                 $rewritesql = "SELECT COUNT(*) FROM ($rewritesql) _ADODB_ALIAS_";
00321                         }
00322                 }
00323         } else {
00324                 // now replace SELECT ... FROM with SELECT COUNT(*) FROM
00325                 $rewritesql = preg_replace(
00326                                         '/^\s*SELECT\s.*\s+FROM\s/Uis','SELECT COUNT(*) FROM ',$sql);
00327 
00328                 
00329                 
00330                 // fix by alexander zhukov, alex#unipack.ru, because count(*) and 'order by' fails 
00331                 // with mssql, access and postgresql. Also a good speedup optimization - skips sorting!
00332                 // also see http://phplens.com/lens/lensforum/msgs.php?id=12752
00333                 if (preg_match('/\sORDER\s+BY\s*\(/i',$rewritesql))
00334                         $rewritesql = preg_replace('/(\sORDER\s+BY\s.*)/is','',$rewritesql);
00335                 else
00336                         $rewritesql = preg_replace('/(\sORDER\s+BY\s[^)]*)/is','',$rewritesql);
00337         }
00338         
00339         
00340         
00341         if (isset($rewritesql) && $rewritesql != $sql) {
00342                 if (preg_match('/\sLIMIT\s+[0-9]+/i',$sql,$limitarr)) $rewritesql .= $limitarr[1];
00343                  
00344                 if ($secs2cache) {
00345                         // we only use half the time of secs2cache because the count can quickly
00346                         // become inaccurate if new records are added
00347                         $qryRecs = $zthis->CacheGetOne($secs2cache/2,$rewritesql,$inputarr);
00348                         
00349                 } else {
00350                         $qryRecs = $zthis->GetOne($rewritesql,$inputarr);
00351                 }
00352                 if ($qryRecs !== false) return $qryRecs;
00353         }
00354         //--------------------------------------------
00355         // query rewrite failed - so try slower way...
00356         
00357         
00358         // strip off unneeded ORDER BY if no UNION
00359         if (preg_match('/\s*UNION\s*/is', $sql)) $rewritesql = $sql;
00360         else $rewritesql = preg_replace('/(\sORDER\s+BY\s.*)/is','',$sql); 
00361         
00362         if (preg_match('/\sLIMIT\s+[0-9]+/i',$sql,$limitarr)) $rewritesql .= $limitarr[0];
00363                 
00364         $rstest = &$zthis->Execute($rewritesql,$inputarr);
00365         if (!$rstest) $rstest = $zthis->Execute($sql,$inputarr);
00366         
00367         if ($rstest) {
00368                         $qryRecs = $rstest->RecordCount();
00369                 if ($qryRecs == -1) { 
00370                 global $ADODB_EXTENSION;
00371                 // some databases will return -1 on MoveLast() - change to MoveNext()
00372                         if ($ADODB_EXTENSION) {
00373                                 while(!$rstest->EOF) {
00374                                         adodb_movenext($rstest);
00375                                 }
00376                         } else {
00377                                 while(!$rstest->EOF) {
00378                                         $rstest->MoveNext();
00379                                 }
00380                         }
00381                         $qryRecs = $rstest->_currentRow;
00382                 }
00383                 $rstest->Close();
00384                 if ($qryRecs == -1) return 0;
00385         }
00386         
00387         return $qryRecs;
00388 }
00389 
00390 /*
00391         Code originally from "Cornel G" <conyg@fx.ro>
00392 
00393         This code might not work with SQL that has UNION in it  
00394         
00395         Also if you are using CachePageExecute(), there is a strong possibility that
00396         data will get out of synch. use CachePageExecute() only with tables that
00397         rarely change.
00398 */
00399 function &_adodb_pageexecute_all_rows(&$zthis, $sql, $nrows, $page, 
00400                                                 $inputarr=false, $secs2cache=0) 
00401 {
00402         $atfirstpage = false;
00403         $atlastpage = false;
00404         $lastpageno=1;
00405 
00406         // If an invalid nrows is supplied, 
00407         // we assume a default value of 10 rows per page
00408         if (!isset($nrows) || $nrows <= 0) $nrows = 10;
00409 
00410         $qryRecs = false; //count records for no offset
00411         
00412         $qryRecs = _adodb_getcount($zthis,$sql,$inputarr,$secs2cache);
00413         $lastpageno = (int) ceil($qryRecs / $nrows);
00414         $zthis->_maxRecordCount = $qryRecs;
00415         
00416 
00417 
00418         // ***** Here we check whether $page is the last page or 
00419         // whether we are trying to retrieve 
00420         // a page number greater than the last page number.
00421         if ($page >= $lastpageno) {
00422                 $page = $lastpageno;
00423                 $atlastpage = true;
00424         }
00425         
00426         // If page number <= 1, then we are at the first page
00427         if (empty($page) || $page <= 1) {       
00428                 $page = 1;
00429                 $atfirstpage = true;
00430         }
00431         
00432         // We get the data we want
00433         $offset = $nrows * ($page-1);
00434         if ($secs2cache > 0) 
00435                 $rsreturn = &$zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $offset, $inputarr);
00436         else 
00437                 $rsreturn = &$zthis->SelectLimit($sql, $nrows, $offset, $inputarr, $secs2cache);
00438 
00439         
00440         // Before returning the RecordSet, we set the pagination properties we need
00441         if ($rsreturn) {
00442                 $rsreturn->_maxRecordCount = $qryRecs;
00443                 $rsreturn->rowsPerPage = $nrows;
00444                 $rsreturn->AbsolutePage($page);
00445                 $rsreturn->AtFirstPage($atfirstpage);
00446                 $rsreturn->AtLastPage($atlastpage);
00447                 $rsreturn->LastPageNo($lastpageno);
00448         }
00449         return $rsreturn;
00450 }
00451 
00452 // Iván Oliva version
00453 function &_adodb_pageexecute_no_last_page(&$zthis, $sql, $nrows, $page, $inputarr=false, $secs2cache=0) 
00454 {
00455 
00456         $atfirstpage = false;
00457         $atlastpage = false;
00458         
00459         if (!isset($page) || $page <= 1) {      // If page number <= 1, then we are at the first page
00460                 $page = 1;
00461                 $atfirstpage = true;
00462         }
00463         if ($nrows <= 0) $nrows = 10;   // If an invalid nrows is supplied, we assume a default value of 10 rows per page
00464         
00465         // ***** Here we check whether $page is the last page or whether we are trying to retrieve a page number greater than 
00466         // the last page number.
00467         $pagecounter = $page + 1;
00468         $pagecounteroffset = ($pagecounter * $nrows) - $nrows;
00469         if ($secs2cache>0) $rstest = &$zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $pagecounteroffset, $inputarr);
00470         else $rstest = &$zthis->SelectLimit($sql, $nrows, $pagecounteroffset, $inputarr, $secs2cache);
00471         if ($rstest) {
00472                 while ($rstest && $rstest->EOF && $pagecounter>0) {
00473                         $atlastpage = true;
00474                         $pagecounter--;
00475                         $pagecounteroffset = $nrows * ($pagecounter - 1);
00476                         $rstest->Close();
00477                         if ($secs2cache>0) $rstest = &$zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $pagecounteroffset, $inputarr);
00478                         else $rstest = &$zthis->SelectLimit($sql, $nrows, $pagecounteroffset, $inputarr, $secs2cache);
00479                 }
00480                 if ($rstest) $rstest->Close();
00481         }
00482         if ($atlastpage) {      // If we are at the last page or beyond it, we are going to retrieve it
00483                 $page = $pagecounter;
00484                 if ($page == 1) $atfirstpage = true;    // We have to do this again in case the last page is the same as the first
00485                         //... page, that is, the recordset has only 1 page.
00486         }
00487         
00488         // We get the data we want
00489         $offset = $nrows * ($page-1);
00490         if ($secs2cache > 0) $rsreturn = &$zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $offset, $inputarr);
00491         else $rsreturn = &$zthis->SelectLimit($sql, $nrows, $offset, $inputarr, $secs2cache);
00492         
00493         // Before returning the RecordSet, we set the pagination properties we need
00494         if ($rsreturn) {
00495                 $rsreturn->rowsPerPage = $nrows;
00496                 $rsreturn->AbsolutePage($page);
00497                 $rsreturn->AtFirstPage($atfirstpage);
00498                 $rsreturn->AtLastPage($atlastpage);
00499         }
00500         return $rsreturn;
00501 }
00502 
00503 function _adodb_getupdatesql(&$zthis,&$rs, $arrFields,$forceUpdate=false,$magicq=false,$force=2)
00504 {
00505                 if (!$rs) {
00506                         printf(ADODB_BAD_RS,'GetUpdateSQL');
00507                         return false;
00508                 }
00509         
00510                 $fieldUpdatedCount = 0;
00511                 $arrFields = _array_change_key_case($arrFields);
00512 
00513                 $hasnumeric = isset($rs->fields[0]);
00514                 $setFields = '';
00515                 
00516                 // Loop through all of the fields in the recordset
00517                 for ($i=0, $max=$rs->FieldCount(); $i < $max; $i++) {
00518                         // Get the field from the recordset
00519                         $field = $rs->FetchField($i);
00520 
00521                         // If the recordset field is one
00522                         // of the fields passed in then process.
00523                         $upperfname = strtoupper($field->name);
00524                         if (adodb_key_exists($upperfname,$arrFields,$force)) {
00525                                 
00526                                 // If the existing field value in the recordset
00527                                 // is different from the value passed in then
00528                                 // go ahead and append the field name and new value to
00529                                 // the update query.
00530                                 
00531                                 if ($hasnumeric) $val = $rs->fields[$i];
00532                                 else if (isset($rs->fields[$upperfname])) $val = $rs->fields[$upperfname];
00533                                 else if (isset($rs->fields[$field->name])) $val =  $rs->fields[$field->name];
00534                                 else if (isset($rs->fields[strtolower($upperfname)])) $val =  $rs->fields[strtolower($upperfname)];
00535                                 else $val = '';
00536                                 
00537                         
00538                                 if ($forceUpdate || strcmp($val, $arrFields[$upperfname])) {
00539                                         // Set the counter for the number of fields that will be updated.
00540                                         $fieldUpdatedCount++;
00541 
00542                                         // Based on the datatype of the field
00543                                         // Format the value properly for the database
00544                                         $type = $rs->MetaType($field->type);
00545                                                 
00546 
00547                                         if ($type == 'null') {
00548                                                 $type = 'C';
00549                                         }
00550                                         
00551                                         if (strpos($upperfname,' ') !== false)
00552                                                 $fnameq = $zthis->nameQuote.$upperfname.$zthis->nameQuote;
00553                                         else
00554                                                 $fnameq = $upperfname;
00555                                         
00556                                         
00557                 // is_null requires php 4.0.4
00558                 //********************************************************//
00559                 if (is_null($arrFields[$upperfname])
00560                                         || (empty($arrFields[$upperfname]) && strlen($arrFields[$upperfname]) == 0)
00561                     || $arrFields[$upperfname] === 'null'
00562                     )
00563                 {
00564                     switch ($force) {
00565 
00566                         //case 0:
00567                         //    //Ignore empty values. This is allready handled in "adodb_key_exists" function.
00568                         //break;
00569 
00570                         case 1:
00571                             //Set null
00572                             $setFields .= $field->name . " = null, ";
00573                         break;
00574                                                         
00575                         case 2:
00576                             //Set empty
00577                             $arrFields[$upperfname] = "";
00578                             $setFields .= _adodb_column_sql($zthis, 'U', $type, $upperfname, $fnameq,$arrFields, $magicq);
00579                         break;
00580                                                 default:
00581                         case 3:
00582                             //Set the value that was given in array, so you can give both null and empty values
00583                             if (is_null($arrFields[$upperfname]) || $arrFields[$upperfname] === 'null') {
00584                                 $setFields .= $field->name . " = null, ";
00585                             } else {
00586                                 $setFields .= _adodb_column_sql($zthis, 'U', $type, $upperfname, $fnameq,$arrFields, $magicq);
00587                             }
00588                         break;
00589                     }
00590                 //********************************************************//
00591                 } else {
00592                                                 //we do this so each driver can customize the sql for
00593                                                 //DB specific column types. 
00594                                                 //Oracle needs BLOB types to be handled with a returning clause
00595                                                 //postgres has special needs as well
00596                                                 $setFields .= _adodb_column_sql($zthis, 'U', $type, $upperfname, $fnameq,
00597                                                                                                                   $arrFields, $magicq);
00598                                         }
00599                                 }
00600                         }
00601                 }
00602 
00603                 // If there were any modified fields then build the rest of the update query.
00604                 if ($fieldUpdatedCount > 0 || $forceUpdate) {
00605                                         // Get the table name from the existing query.
00606                         if (!empty($rs->tableName)) $tableName = $rs->tableName;
00607                         else {
00608                                 preg_match("/FROM\s+".ADODB_TABLE_REGEX."/is", $rs->sql, $tableName);
00609                                 $tableName = $tableName[1];
00610                         }
00611                         // Get the full where clause excluding the word "WHERE" from
00612                         // the existing query.
00613                         preg_match('/\sWHERE\s(.*)/is', $rs->sql, $whereClause);
00614                         
00615                         $discard = false;
00616                         // not a good hack, improvements?
00617                         if ($whereClause) {
00618                         #var_dump($whereClause);
00619                                 if (preg_match('/\s(ORDER\s.*)/is', $whereClause[1], $discard));
00620                                 else if (preg_match('/\s(LIMIT\s.*)/is', $whereClause[1], $discard));
00621                                 else if (preg_match('/\s(FOR UPDATE.*)/is', $whereClause[1], $discard));
00622                                 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
00623                         } else
00624                                 $whereClause = array(false,false);
00625                                 
00626                         if ($discard)
00627                                 $whereClause[1] = substr($whereClause[1], 0, strlen($whereClause[1]) - strlen($discard[1]));
00628                         
00629                         $sql = 'UPDATE '.$tableName.' SET '.substr($setFields, 0, -2);
00630                         if (strlen($whereClause[1]) > 0) 
00631                                 $sql .= ' WHERE '.$whereClause[1];
00632 
00633                         return $sql;
00634 
00635                 } else {
00636                         return false;
00637         }
00638 }
00639 
00640 function adodb_key_exists($key, &$arr,$force=2)
00641 {
00642         if ($force<=0) {
00643                 // the following is the old behaviour where null or empty fields are ignored
00644                 return (!empty($arr[$key])) || (isset($arr[$key]) && strlen($arr[$key])>0);
00645         }
00646 
00647         if (isset($arr[$key])) return true;
00648         ## null check below
00649         if (ADODB_PHPVER >= 0x4010) return array_key_exists($key,$arr);
00650         return false;
00651 }
00652 
00660 function _adodb_getinsertsql(&$zthis,&$rs,$arrFields,$magicq=false,$force=2)
00661 {
00662 static $cacheRS = false;
00663 static $cacheSig = 0;
00664 static $cacheCols;
00665 
00666         $tableName = '';
00667         $values = '';
00668         $fields = '';
00669         $recordSet = null;
00670         $arrFields = _array_change_key_case($arrFields);
00671         $fieldInsertedCount = 0;
00672         
00673         if (is_string($rs)) {
00674                 //ok we have a table name
00675                 //try and get the column info ourself.
00676                 $tableName = $rs;                       
00677         
00678                 //we need an object for the recordSet
00679                 //because we have to call MetaType.
00680                 //php can't do a $rsclass::MetaType()
00681                 $rsclass = $zthis->rsPrefix.$zthis->databaseType;
00682                 $recordSet = new $rsclass(-1,$zthis->fetchMode);
00683                 $recordSet->connection = &$zthis;
00684                 
00685                 if (is_string($cacheRS) && $cacheRS == $rs) {
00686                         $columns =& $cacheCols;
00687                 } else {
00688                         $columns = $zthis->MetaColumns( $tableName );
00689                         $cacheRS = $tableName;
00690                         $cacheCols = $columns;
00691                 }
00692         } else if (is_subclass_of($rs, 'adorecordset')) {
00693                 if (isset($rs->insertSig) && is_integer($cacheRS) && $cacheRS == $rs->insertSig) {
00694                         $columns =& $cacheCols;
00695                 } else {
00696                         for ($i=0, $max=$rs->FieldCount(); $i < $max; $i++) 
00697                                 $columns[] = $rs->FetchField($i);
00698                         $cacheRS = $cacheSig;
00699                         $cacheCols = $columns;
00700                         $rs->insertSig = $cacheSig++;
00701                 }
00702                 $recordSet =& $rs;
00703         
00704         } else {
00705                 printf(ADODB_BAD_RS,'GetInsertSQL');
00706                 return false;
00707         }
00708 
00709         // Loop through all of the fields in the recordset
00710         foreach( $columns as $field ) { 
00711                 $upperfname = strtoupper($field->name);
00712                 if (adodb_key_exists($upperfname,$arrFields,$force)) {
00713                         $bad = false;
00714                         if (strpos($upperfname,' ') !== false)
00715                                 $fnameq = $zthis->nameQuote.$upperfname.$zthis->nameQuote;
00716                         else
00717                                 $fnameq = $upperfname;
00718                         
00719                         $type = $recordSet->MetaType($field->type);
00720                         
00721             /********************************************************/
00722             if (is_null($arrFields[$upperfname])
00723                 || (empty($arrFields[$upperfname]) && strlen($arrFields[$upperfname]) == 0)
00724                 || $arrFields[$upperfname] === 'null'
00725                                 )
00726                {
00727                     switch ($force) {
00728 
00729                         case 0: // we must always set null if missing
00730                                                         $bad = true;
00731                                                         break;
00732                                                         
00733                         case 1:
00734                             $values  .= "null, ";
00735                         break;
00736                 
00737                         case 2:
00738                             //Set empty
00739                             $arrFields[$upperfname] = "";
00740                             $values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq,$arrFields, $magicq);
00741                         break;
00742 
00743                                                 default:
00744                         case 3:
00745                             //Set the value that was given in array, so you can give both null and empty values
00746                                                         if (is_null($arrFields[$upperfname]) || $arrFields[$upperfname] === 'null') { 
00747                                                                 $values  .= "null, ";
00748                                                         } else {
00749                                         $values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq, $arrFields, $magicq);
00750                                         }
00751                                 break;
00752                         } // switch
00753 
00754             /*********************************************************/
00755                         } else {
00756                                 //we do this so each driver can customize the sql for
00757                                 //DB specific column types. 
00758                                 //Oracle needs BLOB types to be handled with a returning clause
00759                                 //postgres has special needs as well
00760                                 $values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq,
00761                                                                                            $arrFields, $magicq);
00762                         }
00763                         
00764                         if ($bad) continue;
00765                         // Set the counter for the number of fields that will be inserted.
00766                         $fieldInsertedCount++;
00767                         
00768                         
00769                         // Get the name of the fields to insert
00770                         $fields .= $fnameq . ", ";
00771                 }
00772         }
00773 
00774 
00775         // If there were any inserted fields then build the rest of the insert query.
00776         if ($fieldInsertedCount <= 0)  return false;
00777         
00778         // Get the table name from the existing query.
00779         if (!$tableName) {
00780                 if (!empty($rs->tableName)) $tableName = $rs->tableName;
00781                 else if (preg_match("/FROM\s+".ADODB_TABLE_REGEX."/is", $rs->sql, $tableName))
00782                         $tableName = $tableName[1];
00783                 else 
00784                         return false;
00785         }               
00786 
00787         // Strip off the comma and space on the end of both the fields
00788         // and their values.
00789         $fields = substr($fields, 0, -2);
00790         $values = substr($values, 0, -2);
00791 
00792         // Append the fields and their values to the insert query.
00793         return 'INSERT INTO '.$zthis->nameQuote.$tableName.$zthis->nameQuote.' ( '.$fields.' ) VALUES ( '.$values.' )';
00794 }
00795 
00796 
00812 function _adodb_column_sql_oci8(&$zthis,$action, $type, $fname, $fnameq, $arrFields, $magicq) 
00813 {
00814     $sql = '';
00815     
00816     // Based on the datatype of the field
00817     // Format the value properly for the database
00818     switch($type) {
00819     case 'B':
00820         //in order to handle Blobs correctly, we need
00821         //to do some magic for Oracle
00822 
00823         //we need to create a new descriptor to handle 
00824         //this properly
00825         if (!empty($zthis->hasReturningInto)) {
00826             if ($action == 'I') {
00827                 $sql = 'empty_blob(), ';
00828             } else {
00829                 $sql = $fnameq. '=empty_blob(), ';
00830             }
00831             //add the variable to the returning clause array
00832             //so the user can build this later in
00833             //case they want to add more to it
00834             $zthis->_returningArray[$fname] = ':xx'.$fname.'xx';
00835         } else if (empty($arrFields[$fname])){
00836             if ($action == 'I') {
00837                 $sql = 'empty_blob(), ';
00838             } else {
00839                 $sql = $fnameq. '=empty_blob(), ';
00840             }            
00841         } else {
00842             //this is to maintain compatibility
00843             //with older adodb versions.
00844             $sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq,false);
00845         }
00846         break;
00847 
00848     case "X":
00849         //we need to do some more magic here for long variables
00850         //to handle these correctly in oracle.
00851 
00852         //create a safe bind var name
00853         //to avoid conflicts w/ dupes.
00854        if (!empty($zthis->hasReturningInto)) {
00855             if ($action == 'I') {
00856                 $sql = ':xx'.$fname.'xx, ';                
00857             } else {
00858                 $sql = $fnameq.'=:xx'.$fname.'xx, ';
00859             }
00860             //add the variable to the returning clause array
00861             //so the user can build this later in
00862             //case they want to add more to it
00863             $zthis->_returningArray[$fname] = ':xx'.$fname.'xx';
00864         } else {
00865             //this is to maintain compatibility
00866             //with older adodb versions.
00867             $sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq,false);
00868         }            
00869         break;
00870         
00871     default:
00872         $sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq,  $arrFields, $magicq,false);
00873         break;
00874     }
00875     
00876     return $sql;
00877 }    
00878         
00879 function _adodb_column_sql(&$zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq, $recurse=true) 
00880 {
00881 
00882         if ($recurse) {
00883                 switch($zthis->dataProvider)  {
00884                 case 'postgres':
00885                         if ($type == 'L') $type = 'C';
00886                         break;
00887                 case 'oci8':
00888                         return _adodb_column_sql_oci8($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq);
00889                         
00890                 }
00891         }
00892                 
00893         switch($type) {
00894                 case "C":
00895                 case "X":
00896                 case 'B':
00897                         $val = $zthis->qstr($arrFields[$fname],$magicq);
00898                         break;
00899 
00900                 case "D":
00901                         $val = $zthis->DBDate($arrFields[$fname]);
00902                         break;
00903 
00904                 case "T":
00905                         $val = $zthis->DBTimeStamp($arrFields[$fname]);
00906                         break;
00907 
00908                 default:
00909                         $val = $arrFields[$fname];
00910                         if (empty($val)) $val = '0';
00911                         break;
00912         }
00913 
00914         if ($action == 'I') return $val . ", ";
00915         
00916         
00917         return $fnameq . "=" . $val  . ", ";
00918         
00919 }
00920 
00921 
00922 
00923 function _adodb_debug_execute(&$zthis, $sql, $inputarr)
00924 {
00925         $ss = '';
00926         if ($inputarr) {
00927                 foreach($inputarr as $kk=>$vv) {
00928                         if (is_string($vv) && strlen($vv)>64) $vv = substr($vv,0,64).'...';
00929                         $ss .= "($kk=>'$vv') ";
00930                 }
00931                 $ss = "[ $ss ]";
00932         }
00933         $sqlTxt = is_array($sql) ? $sql[0] : $sql;
00934         /*str_replace(', ','##1#__^LF',is_array($sql) ? $sql[0] : $sql);
00935         $sqlTxt = str_replace(',',', ',$sqlTxt);
00936         $sqlTxt = str_replace('##1#__^LF', ', ' ,$sqlTxt);
00937         */
00938         // check if running from browser or command-line
00939         $inBrowser = isset($_SERVER['HTTP_USER_AGENT']);
00940         
00941         $dbt = $zthis->databaseType;
00942         if (isset($zthis->dsnType)) $dbt .= '-'.$zthis->dsnType;
00943         if ($inBrowser) {
00944                 if ($ss) {
00945                         $ss = '<code>'.htmlspecialchars($ss).'</code>';
00946                 }
00947                 if ($zthis->debug === -1)
00948                         ADOConnection::outp( "<br />\n($dbt): ".htmlspecialchars($sqlTxt)." &nbsp; $ss\n<br />\n",false);
00949                 else 
00950                         ADOConnection::outp( "<hr />\n($dbt): ".htmlspecialchars($sqlTxt)." &nbsp; $ss\n<hr />\n",false);
00951         } else {
00952                 ADOConnection::outp("-----\n($dbt): ".$sqlTxt."\n-----\n",false);
00953         }
00954 
00955         $qID = $zthis->_query($sql,$inputarr);
00956         
00957         /* 
00958                 Alexios Fakios notes that ErrorMsg() must be called before ErrorNo() for mssql
00959                 because ErrorNo() calls Execute('SELECT @ERROR'), causing recursion
00960         */
00961         if ($zthis->databaseType == 'mssql') { 
00962         // ErrorNo is a slow function call in mssql, and not reliable in PHP 4.0.6
00963                 if($emsg = $zthis->ErrorMsg()) {
00964                         if ($err = $zthis->ErrorNo()) ADOConnection::outp($err.': '.$emsg);
00965                 }
00966         } else if (!$qID) {
00967                 ADOConnection::outp($zthis->ErrorNo() .': '. $zthis->ErrorMsg());
00968         }
00969         
00970         if ($zthis->debug === 99) _adodb_backtrace(true,9999,2);
00971         return $qID;
00972 }
00973 
00974 # pretty print the debug_backtrace function
00975 function _adodb_backtrace($printOrArr=true,$levels=9999,$skippy=0)
00976 {
00977         if (!function_exists('debug_backtrace')) return '';
00978          
00979         $html =  (isset($_SERVER['HTTP_USER_AGENT']));
00980         $fmt =  ($html) ? "</font><font color=#808080 size=-1> %% line %4d, file: <a href=\"file:/%s\">%s</a></font>" : "%% line %4d, file: %s";
00981 
00982         $MAXSTRLEN = 128;
00983 
00984         $s = ($html) ? '<pre align=left>' : '';
00985         
00986         if (is_array($printOrArr)) $traceArr = $printOrArr;
00987         else $traceArr = debug_backtrace();
00988         array_shift($traceArr);
00989         array_shift($traceArr);
00990         $tabs = sizeof($traceArr)-2;
00991         
00992         foreach ($traceArr as $arr) {
00993                 if ($skippy) {$skippy -= 1; continue;}
00994                 $levels -= 1;
00995                 if ($levels < 0) break;
00996                 
00997                 $args = array();
00998                 for ($i=0; $i < $tabs; $i++) $s .=  ($html) ? ' &nbsp; ' : "\t";
00999                 $tabs -= 1;
01000                 if ($html) $s .= '<font face="Courier New,Courier">';
01001                 if (isset($arr['class'])) $s .= $arr['class'].'.';
01002                 if (isset($arr['args']))
01003                  foreach($arr['args'] as $v) {
01004                         if (is_null($v)) $args[] = 'null';
01005                         else if (is_array($v)) $args[] = 'Array['.sizeof($v).']';
01006                         else if (is_object($v)) $args[] = 'Object:'.get_class($v);
01007                         else if (is_bool($v)) $args[] = $v ? 'true' : 'false';
01008                         else {
01009                                 $v = (string) @$v;
01010                                 $str = htmlspecialchars(substr($v,0,$MAXSTRLEN));
01011                                 if (strlen($v) > $MAXSTRLEN) $str .= '...';
01012                                 $args[] = $str;
01013                         }
01014                 }
01015                 $s .= $arr['function'].'('.implode(', ',$args).')';
01016                 
01017                 
01018                 $s .= @sprintf($fmt, $arr['line'],$arr['file'],basename($arr['file']));
01019                         
01020                 $s .= "\n";
01021         }       
01022         if ($html) $s .= '</pre>';
01023         if ($printOrArr) print $s;
01024         
01025         return $s;
01026 }
01027 /*
01028 function _adodb_find_from($sql) 
01029 {
01030 
01031         $sql = str_replace(array("\n","\r"), ' ', $sql);
01032         $charCount = strlen($sql);
01033         
01034         $inString = false;
01035         $quote = '';
01036         $parentheseCount = 0;
01037         $prevChars = '';
01038         $nextChars = '';
01039         
01040 
01041         for($i = 0; $i < $charCount; $i++) {
01042 
01043         $char = substr($sql,$i,1);
01044             $prevChars = substr($sql,0,$i);
01045         $nextChars = substr($sql,$i+1);
01046 
01047                 if((($char == "'" || $char == '"' || $char == '`') && substr($prevChars,-1,1) != '\\') && $inString === false) {
01048                         $quote = $char;
01049                         $inString = true;
01050                 }
01051 
01052                 elseif((($char == "'" || $char == '"' || $char == '`') && substr($prevChars,-1,1) != '\\') && $inString === true && $quote == $char) {
01053                         $quote = "";
01054                         $inString = false;
01055                 }
01056 
01057                 elseif($char == "(" && $inString === false)
01058                         $parentheseCount++;
01059 
01060                 elseif($char == ")" && $inString === false && $parentheseCount > 0)
01061                         $parentheseCount--;
01062 
01063                 elseif($parentheseCount <= 0 && $inString === false && $char == " " && strtoupper(substr($prevChars,-5,5)) == " FROM")
01064                         return $i;
01065 
01066         }
01067 }
01068 */
01069 
01070 ?>