Documentation TYPO3 par Ameos |
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.80 8 Mar 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 // fix by alexander zhukov, alex#unipack.ru, because count(*) and 'order by' fails 00329 // with mssql, access and postgresql. Also a good speedup optimization - skips sorting! 00330 // also see http://phplens.com/lens/lensforum/msgs.php?id=12752 00331 if (preg_match('/\sORDER\s+BY\s*\(/i',$rewritesql)) 00332 $rewritesql = preg_replace('/(\sORDER\s+BY\s.*)/is','',$rewritesql); 00333 else 00334 $rewritesql = preg_replace('/(\sORDER\s+BY\s[^)]*)/is','',$rewritesql); 00335 00336 } 00337 00338 if (isset($rewritesql) && $rewritesql != $sql) { 00339 if ($secs2cache) { 00340 // we only use half the time of secs2cache because the count can quickly 00341 // become inaccurate if new records are added 00342 $qryRecs = $zthis->CacheGetOne($secs2cache/2,$rewritesql,$inputarr); 00343 00344 } else { 00345 $qryRecs = $zthis->GetOne($rewritesql,$inputarr); 00346 } 00347 if ($qryRecs !== false) return $qryRecs; 00348 } 00349 //-------------------------------------------- 00350 // query rewrite failed - so try slower way... 00351 00352 00353 // strip off unneeded ORDER BY if no UNION 00354 if (preg_match('/\s*UNION\s*/is', $sql)) $rewritesql = $sql; 00355 else $rewritesql = preg_replace('/(\sORDER\s+BY\s.*)/is','',$sql); 00356 00357 $rstest = &$zthis->Execute($rewritesql,$inputarr); 00358 if (!$rstest) $rstest = $zthis->Execute($sql,$inputarr); 00359 00360 if ($rstest) { 00361 $qryRecs = $rstest->RecordCount(); 00362 if ($qryRecs == -1) { 00363 global $ADODB_EXTENSION; 00364 // some databases will return -1 on MoveLast() - change to MoveNext() 00365 if ($ADODB_EXTENSION) { 00366 while(!$rstest->EOF) { 00367 adodb_movenext($rstest); 00368 } 00369 } else { 00370 while(!$rstest->EOF) { 00371 $rstest->MoveNext(); 00372 } 00373 } 00374 $qryRecs = $rstest->_currentRow; 00375 } 00376 $rstest->Close(); 00377 if ($qryRecs == -1) return 0; 00378 } 00379 00380 return $qryRecs; 00381 } 00382 00383 /* 00384 Code originally from "Cornel G" <conyg@fx.ro> 00385 00386 This code might not work with SQL that has UNION in it 00387 00388 Also if you are using CachePageExecute(), there is a strong possibility that 00389 data will get out of synch. use CachePageExecute() only with tables that 00390 rarely change. 00391 */ 00392 function &_adodb_pageexecute_all_rows(&$zthis, $sql, $nrows, $page, 00393 $inputarr=false, $secs2cache=0) 00394 { 00395 $atfirstpage = false; 00396 $atlastpage = false; 00397 $lastpageno=1; 00398 00399 // If an invalid nrows is supplied, 00400 // we assume a default value of 10 rows per page 00401 if (!isset($nrows) || $nrows <= 0) $nrows = 10; 00402 00403 $qryRecs = false; //count records for no offset 00404 00405 $qryRecs = _adodb_getcount($zthis,$sql,$inputarr,$secs2cache); 00406 $lastpageno = (int) ceil($qryRecs / $nrows); 00407 $zthis->_maxRecordCount = $qryRecs; 00408 00409 00410 00411 // ***** Here we check whether $page is the last page or 00412 // whether we are trying to retrieve 00413 // a page number greater than the last page number. 00414 if ($page >= $lastpageno) { 00415 $page = $lastpageno; 00416 $atlastpage = true; 00417 } 00418 00419 // If page number <= 1, then we are at the first page 00420 if (empty($page) || $page <= 1) { 00421 $page = 1; 00422 $atfirstpage = true; 00423 } 00424 00425 // We get the data we want 00426 $offset = $nrows * ($page-1); 00427 if ($secs2cache > 0) 00428 $rsreturn = &$zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $offset, $inputarr); 00429 else 00430 $rsreturn = &$zthis->SelectLimit($sql, $nrows, $offset, $inputarr, $secs2cache); 00431 00432 00433 // Before returning the RecordSet, we set the pagination properties we need 00434 if ($rsreturn) { 00435 $rsreturn->_maxRecordCount = $qryRecs; 00436 $rsreturn->rowsPerPage = $nrows; 00437 $rsreturn->AbsolutePage($page); 00438 $rsreturn->AtFirstPage($atfirstpage); 00439 $rsreturn->AtLastPage($atlastpage); 00440 $rsreturn->LastPageNo($lastpageno); 00441 } 00442 return $rsreturn; 00443 } 00444 00445 // Iván Oliva version 00446 function &_adodb_pageexecute_no_last_page(&$zthis, $sql, $nrows, $page, $inputarr=false, $secs2cache=0) 00447 { 00448 00449 $atfirstpage = false; 00450 $atlastpage = false; 00451 00452 if (!isset($page) || $page <= 1) { // If page number <= 1, then we are at the first page 00453 $page = 1; 00454 $atfirstpage = true; 00455 } 00456 if ($nrows <= 0) $nrows = 10; // If an invalid nrows is supplied, we assume a default value of 10 rows per page 00457 00458 // ***** Here we check whether $page is the last page or whether we are trying to retrieve a page number greater than 00459 // the last page number. 00460 $pagecounter = $page + 1; 00461 $pagecounteroffset = ($pagecounter * $nrows) - $nrows; 00462 if ($secs2cache>0) $rstest = &$zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $pagecounteroffset, $inputarr); 00463 else $rstest = &$zthis->SelectLimit($sql, $nrows, $pagecounteroffset, $inputarr, $secs2cache); 00464 if ($rstest) { 00465 while ($rstest && $rstest->EOF && $pagecounter>0) { 00466 $atlastpage = true; 00467 $pagecounter--; 00468 $pagecounteroffset = $nrows * ($pagecounter - 1); 00469 $rstest->Close(); 00470 if ($secs2cache>0) $rstest = &$zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $pagecounteroffset, $inputarr); 00471 else $rstest = &$zthis->SelectLimit($sql, $nrows, $pagecounteroffset, $inputarr, $secs2cache); 00472 } 00473 if ($rstest) $rstest->Close(); 00474 } 00475 if ($atlastpage) { // If we are at the last page or beyond it, we are going to retrieve it 00476 $page = $pagecounter; 00477 if ($page == 1) $atfirstpage = true; // We have to do this again in case the last page is the same as the first 00478 //... page, that is, the recordset has only 1 page. 00479 } 00480 00481 // We get the data we want 00482 $offset = $nrows * ($page-1); 00483 if ($secs2cache > 0) $rsreturn = &$zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $offset, $inputarr); 00484 else $rsreturn = &$zthis->SelectLimit($sql, $nrows, $offset, $inputarr, $secs2cache); 00485 00486 // Before returning the RecordSet, we set the pagination properties we need 00487 if ($rsreturn) { 00488 $rsreturn->rowsPerPage = $nrows; 00489 $rsreturn->AbsolutePage($page); 00490 $rsreturn->AtFirstPage($atfirstpage); 00491 $rsreturn->AtLastPage($atlastpage); 00492 } 00493 return $rsreturn; 00494 } 00495 00496 function _adodb_getupdatesql(&$zthis,&$rs, $arrFields,$forceUpdate=false,$magicq=false,$force=2) 00497 { 00498 if (!$rs) { 00499 printf(ADODB_BAD_RS,'GetUpdateSQL'); 00500 return false; 00501 } 00502 00503 $fieldUpdatedCount = 0; 00504 $arrFields = _array_change_key_case($arrFields); 00505 00506 $hasnumeric = isset($rs->fields[0]); 00507 $setFields = ''; 00508 00509 // Loop through all of the fields in the recordset 00510 for ($i=0, $max=$rs->FieldCount(); $i < $max; $i++) { 00511 // Get the field from the recordset 00512 $field = $rs->FetchField($i); 00513 00514 // If the recordset field is one 00515 // of the fields passed in then process. 00516 $upperfname = strtoupper($field->name); 00517 if (adodb_key_exists($upperfname,$arrFields,$force)) { 00518 00519 // If the existing field value in the recordset 00520 // is different from the value passed in then 00521 // go ahead and append the field name and new value to 00522 // the update query. 00523 00524 if ($hasnumeric) $val = $rs->fields[$i]; 00525 else if (isset($rs->fields[$upperfname])) $val = $rs->fields[$upperfname]; 00526 else if (isset($rs->fields[$field->name])) $val = $rs->fields[$field->name]; 00527 else if (isset($rs->fields[strtolower($upperfname)])) $val = $rs->fields[strtolower($upperfname)]; 00528 else $val = ''; 00529 00530 00531 if ($forceUpdate || strcmp($val, $arrFields[$upperfname])) { 00532 // Set the counter for the number of fields that will be updated. 00533 $fieldUpdatedCount++; 00534 00535 // Based on the datatype of the field 00536 // Format the value properly for the database 00537 $type = $rs->MetaType($field->type); 00538 00539 00540 if ($type == 'null') { 00541 $type = 'C'; 00542 } 00543 00544 if (strpos($upperfname,' ') !== false) 00545 $fnameq = $zthis->nameQuote.$upperfname.$zthis->nameQuote; 00546 else 00547 $fnameq = $upperfname; 00548 00549 00550 // is_null requires php 4.0.4 00551 //********************************************************// 00552 if (is_null($arrFields[$upperfname]) 00553 || (empty($arrFields[$upperfname]) && strlen($arrFields[$upperfname]) == 0) 00554 || $arrFields[$upperfname] === 'null' 00555 ) 00556 { 00557 switch ($force) { 00558 00559 //case 0: 00560 // //Ignore empty values. This is allready handled in "adodb_key_exists" function. 00561 //break; 00562 00563 case 1: 00564 //Set null 00565 $setFields .= $field->name . " = null, "; 00566 break; 00567 00568 case 2: 00569 //Set empty 00570 $arrFields[$upperfname] = ""; 00571 $setFields .= _adodb_column_sql($zthis, 'U', $type, $upperfname, $fnameq,$arrFields, $magicq); 00572 break; 00573 default: 00574 case 3: 00575 //Set the value that was given in array, so you can give both null and empty values 00576 if (is_null($arrFields[$upperfname]) || $arrFields[$upperfname] === 'null') { 00577 $setFields .= $field->name . " = null, "; 00578 } else { 00579 $setFields .= _adodb_column_sql($zthis, 'U', $type, $upperfname, $fnameq,$arrFields, $magicq); 00580 } 00581 break; 00582 } 00583 //********************************************************// 00584 } else { 00585 //we do this so each driver can customize the sql for 00586 //DB specific column types. 00587 //Oracle needs BLOB types to be handled with a returning clause 00588 //postgres has special needs as well 00589 $setFields .= _adodb_column_sql($zthis, 'U', $type, $upperfname, $fnameq, 00590 $arrFields, $magicq); 00591 } 00592 } 00593 } 00594 } 00595 00596 // If there were any modified fields then build the rest of the update query. 00597 if ($fieldUpdatedCount > 0 || $forceUpdate) { 00598 // Get the table name from the existing query. 00599 if (!empty($rs->tableName)) $tableName = $rs->tableName; 00600 else { 00601 preg_match("/FROM\s+".ADODB_TABLE_REGEX."/is", $rs->sql, $tableName); 00602 $tableName = $tableName[1]; 00603 } 00604 // Get the full where clause excluding the word "WHERE" from 00605 // the existing query. 00606 preg_match('/\sWHERE\s(.*)/is', $rs->sql, $whereClause); 00607 00608 $discard = false; 00609 // not a good hack, improvements? 00610 if ($whereClause) { 00611 #var_dump($whereClause); 00612 if (preg_match('/\s(ORDER\s.*)/is', $whereClause[1], $discard)); 00613 else if (preg_match('/\s(LIMIT\s.*)/is', $whereClause[1], $discard)); 00614 else if (preg_match('/\s(FOR UPDATE.*)/is', $whereClause[1], $discard)); 00615 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 00616 } else 00617 $whereClause = array(false,false); 00618 00619 if ($discard) 00620 $whereClause[1] = substr($whereClause[1], 0, strlen($whereClause[1]) - strlen($discard[1])); 00621 00622 $sql = 'UPDATE '.$tableName.' SET '.substr($setFields, 0, -2); 00623 if (strlen($whereClause[1]) > 0) 00624 $sql .= ' WHERE '.$whereClause[1]; 00625 00626 return $sql; 00627 00628 } else { 00629 return false; 00630 } 00631 } 00632 00633 function adodb_key_exists($key, &$arr,$force=2) 00634 { 00635 if ($force<=0) { 00636 // the following is the old behaviour where null or empty fields are ignored 00637 return (!empty($arr[$key])) || (isset($arr[$key]) && strlen($arr[$key])>0); 00638 } 00639 00640 if (isset($arr[$key])) return true; 00641 ## null check below 00642 if (ADODB_PHPVER >= 0x4010) return array_key_exists($key,$arr); 00643 return false; 00644 } 00645 00653 function _adodb_getinsertsql(&$zthis,&$rs,$arrFields,$magicq=false,$force=2) 00654 { 00655 static $cacheRS = false; 00656 static $cacheSig = 0; 00657 static $cacheCols; 00658 00659 $tableName = ''; 00660 $values = ''; 00661 $fields = ''; 00662 $recordSet = null; 00663 $arrFields = _array_change_key_case($arrFields); 00664 $fieldInsertedCount = 0; 00665 00666 if (is_string($rs)) { 00667 //ok we have a table name 00668 //try and get the column info ourself. 00669 $tableName = $rs; 00670 00671 //we need an object for the recordSet 00672 //because we have to call MetaType. 00673 //php can't do a $rsclass::MetaType() 00674 $rsclass = $zthis->rsPrefix.$zthis->databaseType; 00675 $recordSet = new $rsclass(-1,$zthis->fetchMode); 00676 $recordSet->connection = &$zthis; 00677 00678 if (is_string($cacheRS) && $cacheRS == $rs) { 00679 $columns =& $cacheCols; 00680 } else { 00681 $columns = $zthis->MetaColumns( $tableName ); 00682 $cacheRS = $tableName; 00683 $cacheCols = $columns; 00684 } 00685 } else if (is_subclass_of($rs, 'adorecordset')) { 00686 if (isset($rs->insertSig) && is_integer($cacheRS) && $cacheRS == $rs->insertSig) { 00687 $columns =& $cacheCols; 00688 } else { 00689 for ($i=0, $max=$rs->FieldCount(); $i < $max; $i++) 00690 $columns[] = $rs->FetchField($i); 00691 $cacheRS = $cacheSig; 00692 $cacheCols = $columns; 00693 $rs->insertSig = $cacheSig++; 00694 } 00695 $recordSet =& $rs; 00696 00697 } else { 00698 printf(ADODB_BAD_RS,'GetInsertSQL'); 00699 return false; 00700 } 00701 00702 // Loop through all of the fields in the recordset 00703 foreach( $columns as $field ) { 00704 $upperfname = strtoupper($field->name); 00705 if (adodb_key_exists($upperfname,$arrFields,$force)) { 00706 $bad = false; 00707 if (strpos($upperfname,' ') !== false) 00708 $fnameq = $zthis->nameQuote.$upperfname.$zthis->nameQuote; 00709 else 00710 $fnameq = $upperfname; 00711 00712 $type = $recordSet->MetaType($field->type); 00713 00714 /********************************************************/ 00715 if (is_null($arrFields[$upperfname]) 00716 || (empty($arrFields[$upperfname]) && strlen($arrFields[$upperfname]) == 0) 00717 || $arrFields[$upperfname] === 'null' 00718 ) 00719 { 00720 switch ($force) { 00721 00722 case 0: // we must always set null if missing 00723 $bad = true; 00724 break; 00725 00726 case 1: 00727 $values .= "null, "; 00728 break; 00729 00730 case 2: 00731 //Set empty 00732 $arrFields[$upperfname] = ""; 00733 $values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq,$arrFields, $magicq); 00734 break; 00735 00736 default: 00737 case 3: 00738 //Set the value that was given in array, so you can give both null and empty values 00739 if (is_null($arrFields[$upperfname]) || $arrFields[$upperfname] === 'null') { 00740 $values .= "null, "; 00741 } else { 00742 $values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq, $arrFields, $magicq); 00743 } 00744 break; 00745 } // switch 00746 00747 /*********************************************************/ 00748 } else { 00749 //we do this so each driver can customize the sql for 00750 //DB specific column types. 00751 //Oracle needs BLOB types to be handled with a returning clause 00752 //postgres has special needs as well 00753 $values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq, 00754 $arrFields, $magicq); 00755 } 00756 00757 if ($bad) continue; 00758 // Set the counter for the number of fields that will be inserted. 00759 $fieldInsertedCount++; 00760 00761 00762 // Get the name of the fields to insert 00763 $fields .= $fnameq . ", "; 00764 } 00765 } 00766 00767 00768 // If there were any inserted fields then build the rest of the insert query. 00769 if ($fieldInsertedCount <= 0) return false; 00770 00771 // Get the table name from the existing query. 00772 if (!$tableName) { 00773 if (!empty($rs->tableName)) $tableName = $rs->tableName; 00774 else if (preg_match("/FROM\s+".ADODB_TABLE_REGEX."/is", $rs->sql, $tableName)) 00775 $tableName = $tableName[1]; 00776 else 00777 return false; 00778 } 00779 00780 // Strip off the comma and space on the end of both the fields 00781 // and their values. 00782 $fields = substr($fields, 0, -2); 00783 $values = substr($values, 0, -2); 00784 00785 // Append the fields and their values to the insert query. 00786 return 'INSERT INTO '.$zthis->nameQuote.$tableName.$zthis->nameQuote.' ( '.$fields.' ) VALUES ( '.$values.' )'; 00787 } 00788 00789 00805 function _adodb_column_sql_oci8(&$zthis,$action, $type, $fname, $fnameq, $arrFields, $magicq) 00806 { 00807 $sql = ''; 00808 00809 // Based on the datatype of the field 00810 // Format the value properly for the database 00811 switch($type) { 00812 case 'B': 00813 //in order to handle Blobs correctly, we need 00814 //to do some magic for Oracle 00815 00816 //we need to create a new descriptor to handle 00817 //this properly 00818 if (!empty($zthis->hasReturningInto)) { 00819 if ($action == 'I') { 00820 $sql = 'empty_blob(), '; 00821 } else { 00822 $sql = $fnameq. '=empty_blob(), '; 00823 } 00824 //add the variable to the returning clause array 00825 //so the user can build this later in 00826 //case they want to add more to it 00827 $zthis->_returningArray[$fname] = ':xx'.$fname.'xx'; 00828 } else if (empty($arrFields[$fname])){ 00829 if ($action == 'I') { 00830 $sql = 'empty_blob(), '; 00831 } else { 00832 $sql = $fnameq. '=empty_blob(), '; 00833 } 00834 } else { 00835 //this is to maintain compatibility 00836 //with older adodb versions. 00837 $sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq,false); 00838 } 00839 break; 00840 00841 case "X": 00842 //we need to do some more magic here for long variables 00843 //to handle these correctly in oracle. 00844 00845 //create a safe bind var name 00846 //to avoid conflicts w/ dupes. 00847 if (!empty($zthis->hasReturningInto)) { 00848 if ($action == 'I') { 00849 $sql = ':xx'.$fname.'xx, '; 00850 } else { 00851 $sql = $fnameq.'=:xx'.$fname.'xx, '; 00852 } 00853 //add the variable to the returning clause array 00854 //so the user can build this later in 00855 //case they want to add more to it 00856 $zthis->_returningArray[$fname] = ':xx'.$fname.'xx'; 00857 } else { 00858 //this is to maintain compatibility 00859 //with older adodb versions. 00860 $sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq,false); 00861 } 00862 break; 00863 00864 default: 00865 $sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq,false); 00866 break; 00867 } 00868 00869 return $sql; 00870 } 00871 00872 function _adodb_column_sql(&$zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq, $recurse=true) 00873 { 00874 00875 if ($recurse) { 00876 switch($zthis->dataProvider) { 00877 case 'postgres': 00878 if ($type == 'L') $type = 'C'; 00879 break; 00880 case 'oci8': 00881 return _adodb_column_sql_oci8($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq); 00882 00883 } 00884 } 00885 00886 switch($type) { 00887 case "C": 00888 case "X": 00889 case 'B': 00890 $val = $zthis->qstr($arrFields[$fname],$magicq); 00891 break; 00892 00893 case "D": 00894 $val = $zthis->DBDate($arrFields[$fname]); 00895 break; 00896 00897 case "T": 00898 $val = $zthis->DBTimeStamp($arrFields[$fname]); 00899 break; 00900 00901 default: 00902 $val = $arrFields[$fname]; 00903 if (empty($val)) $val = '0'; 00904 break; 00905 } 00906 00907 if ($action == 'I') return $val . ", "; 00908 00909 00910 return $fnameq . "=" . $val . ", "; 00911 00912 } 00913 00914 00915 00916 function _adodb_debug_execute(&$zthis, $sql, $inputarr) 00917 { 00918 $ss = ''; 00919 if ($inputarr) { 00920 foreach($inputarr as $kk=>$vv) { 00921 if (is_string($vv) && strlen($vv)>64) $vv = substr($vv,0,64).'...'; 00922 $ss .= "($kk=>'$vv') "; 00923 } 00924 $ss = "[ $ss ]"; 00925 } 00926 $sqlTxt = is_array($sql) ? $sql[0] : $sql; 00927 /*str_replace(', ','##1#__^LF',is_array($sql) ? $sql[0] : $sql); 00928 $sqlTxt = str_replace(',',', ',$sqlTxt); 00929 $sqlTxt = str_replace('##1#__^LF', ', ' ,$sqlTxt); 00930 */ 00931 // check if running from browser or command-line 00932 $inBrowser = isset($_SERVER['HTTP_USER_AGENT']); 00933 00934 $dbt = $zthis->databaseType; 00935 if (isset($zthis->dsnType)) $dbt .= '-'.$zthis->dsnType; 00936 if ($inBrowser) { 00937 if ($ss) { 00938 $ss = '<code>'.htmlspecialchars($ss).'</code>'; 00939 } 00940 if ($zthis->debug === -1) 00941 ADOConnection::outp( "<br />\n($dbt): ".htmlspecialchars($sqlTxt)." $ss\n<br />\n",false); 00942 else 00943 ADOConnection::outp( "<hr />\n($dbt): ".htmlspecialchars($sqlTxt)." $ss\n<hr />\n",false); 00944 } else { 00945 ADOConnection::outp("-----\n($dbt): ".$sqlTxt."\n-----\n",false); 00946 } 00947 00948 $qID = $zthis->_query($sql,$inputarr); 00949 00950 /* 00951 Alexios Fakios notes that ErrorMsg() must be called before ErrorNo() for mssql 00952 because ErrorNo() calls Execute('SELECT @ERROR'), causing recursion 00953 */ 00954 if ($zthis->databaseType == 'mssql') { 00955 // ErrorNo is a slow function call in mssql, and not reliable in PHP 4.0.6 00956 if($emsg = $zthis->ErrorMsg()) { 00957 if ($err = $zthis->ErrorNo()) ADOConnection::outp($err.': '.$emsg); 00958 } 00959 } else if (!$qID) { 00960 ADOConnection::outp($zthis->ErrorNo() .': '. $zthis->ErrorMsg()); 00961 } 00962 00963 if ($zthis->debug === 99) _adodb_backtrace(true,9999,2); 00964 return $qID; 00965 } 00966 00967 # pretty print the debug_backtrace function 00968 function _adodb_backtrace($printOrArr=true,$levels=9999,$skippy=0) 00969 { 00970 if (!function_exists('debug_backtrace')) return ''; 00971 00972 $html = (isset($_SERVER['HTTP_USER_AGENT'])); 00973 $fmt = ($html) ? "</font><font color=#808080 size=-1> %% line %4d, file: <a href=\"file:/%s\">%s</a></font>" : "%% line %4d, file: %s"; 00974 00975 $MAXSTRLEN = 128; 00976 00977 $s = ($html) ? '<pre align=left>' : ''; 00978 00979 if (is_array($printOrArr)) $traceArr = $printOrArr; 00980 else $traceArr = debug_backtrace(); 00981 array_shift($traceArr); 00982 array_shift($traceArr); 00983 $tabs = sizeof($traceArr)-2; 00984 00985 foreach ($traceArr as $arr) { 00986 if ($skippy) {$skippy -= 1; continue;} 00987 $levels -= 1; 00988 if ($levels < 0) break; 00989 00990 $args = array(); 00991 for ($i=0; $i < $tabs; $i++) $s .= ($html) ? ' ' : "\t"; 00992 $tabs -= 1; 00993 if ($html) $s .= '<font face="Courier New,Courier">'; 00994 if (isset($arr['class'])) $s .= $arr['class'].'.'; 00995 if (isset($arr['args'])) 00996 foreach($arr['args'] as $v) { 00997 if (is_null($v)) $args[] = 'null'; 00998 else if (is_array($v)) $args[] = 'Array['.sizeof($v).']'; 00999 else if (is_object($v)) $args[] = 'Object:'.get_class($v); 01000 else if (is_bool($v)) $args[] = $v ? 'true' : 'false'; 01001 else { 01002 $v = (string) @$v; 01003 $str = htmlspecialchars(substr($v,0,$MAXSTRLEN)); 01004 if (strlen($v) > $MAXSTRLEN) $str .= '...'; 01005 $args[] = $str; 01006 } 01007 } 01008 $s .= $arr['function'].'('.implode(', ',$args).')'; 01009 01010 01011 $s .= @sprintf($fmt, $arr['line'],$arr['file'],basename($arr['file'])); 01012 01013 $s .= "\n"; 01014 } 01015 if ($html) $s .= '</pre>'; 01016 if ($printOrArr) print $s; 01017 01018 return $s; 01019 } 01020 01021 ?>