Documentation TYPO3 par Ameos |
00001 <?php 00002 /* 00003 V4.80 8 Mar 2006 (c) 2000-2006 John Lim (jlim@natsoft.com.my). All rights reserved. 00004 Released under both BSD license and Lesser GPL library license. 00005 Whenever there is any discrepancy between the two licenses, 00006 the BSD license will take precedence. 00007 Set tabs to 4 for best viewing. 00008 00009 Latest version is available at http://adodb.sourceforge.net 00010 00011 Native mssql driver. Requires mssql client. Works on Windows. 00012 To configure for Unix, see 00013 http://phpbuilder.com/columns/alberto20000919.php3 00014 00015 */ 00016 00017 // security - hide paths 00018 if (!defined('ADODB_DIR')) die(); 00019 00020 //---------------------------------------------------------------- 00021 // MSSQL returns dates with the format Oct 13 2002 or 13 Oct 2002 00022 // and this causes tons of problems because localized versions of 00023 // MSSQL will return the dates in dmy or mdy order; and also the 00024 // month strings depends on what language has been configured. The 00025 // following two variables allow you to control the localization 00026 // settings - Ugh. 00027 // 00028 // MORE LOCALIZATION INFO 00029 // ---------------------- 00030 // To configure datetime, look for and modify sqlcommn.loc, 00031 // typically found in c:\mssql\install 00032 // Also read : 00033 // http://support.microsoft.com/default.aspx?scid=kb;EN-US;q220918 00034 // Alternatively use: 00035 // CONVERT(char(12),datecol,120) 00036 //---------------------------------------------------------------- 00037 00038 00039 // has datetime converstion to YYYY-MM-DD format, and also mssql_fetch_assoc 00040 if (ADODB_PHPVER >= 0x4300) { 00041 // docs say 4.2.0, but testing shows only since 4.3.0 does it work! 00042 ini_set('mssql.datetimeconvert',0); 00043 } else { 00044 global $ADODB_mssql_mths; // array, months must be upper-case 00045 00046 00047 $ADODB_mssql_date_order = 'mdy'; 00048 $ADODB_mssql_mths = array( 00049 'JAN'=>1,'FEB'=>2,'MAR'=>3,'APR'=>4,'MAY'=>5,'JUN'=>6, 00050 'JUL'=>7,'AUG'=>8,'SEP'=>9,'OCT'=>10,'NOV'=>11,'DEC'=>12); 00051 } 00052 00053 //--------------------------------------------------------------------------- 00054 // Call this to autoset $ADODB_mssql_date_order at the beginning of your code, 00055 // just after you connect to the database. Supports mdy and dmy only. 00056 // Not required for PHP 4.2.0 and above. 00057 function AutoDetect_MSSQL_Date_Order($conn) 00058 { 00059 global $ADODB_mssql_date_order; 00060 $adate = $conn->GetOne('select getdate()'); 00061 if ($adate) { 00062 $anum = (int) $adate; 00063 if ($anum > 0) { 00064 if ($anum > 31) { 00065 //ADOConnection::outp( "MSSQL: YYYY-MM-DD date format not supported currently"); 00066 } else 00067 $ADODB_mssql_date_order = 'dmy'; 00068 } else 00069 $ADODB_mssql_date_order = 'mdy'; 00070 } 00071 } 00072 00073 class ADODB_mssql extends ADOConnection { 00074 var $databaseType = "mssql"; 00075 var $dataProvider = "mssql"; 00076 var $replaceQuote = "''"; // string to use to replace quotes 00077 var $fmtDate = "'Y-m-d'"; 00078 var $fmtTimeStamp = "'Y-m-d H:i:s'"; 00079 var $hasInsertID = true; 00080 var $substr = "substring"; 00081 var $length = 'len'; 00082 var $hasAffectedRows = true; 00083 var $metaDatabasesSQL = "select name from sysdatabases where name <> 'master'"; 00084 var $metaTablesSQL="select name,case when type='U' then 'T' else 'V' end from sysobjects where (type='U' or type='V') and (name not in ('sysallocations','syscolumns','syscomments','sysdepends','sysfilegroups','sysfiles','sysfiles1','sysforeignkeys','sysfulltextcatalogs','sysindexes','sysindexkeys','sysmembers','sysobjects','syspermissions','sysprotects','sysreferences','systypes','sysusers','sysalternates','sysconstraints','syssegments','REFERENTIAL_CONSTRAINTS','CHECK_CONSTRAINTS','CONSTRAINT_TABLE_USAGE','CONSTRAINT_COLUMN_USAGE','VIEWS','VIEW_TABLE_USAGE','VIEW_COLUMN_USAGE','SCHEMATA','TABLES','TABLE_CONSTRAINTS','TABLE_PRIVILEGES','COLUMNS','COLUMN_DOMAIN_USAGE','COLUMN_PRIVILEGES','DOMAINS','DOMAIN_CONSTRAINTS','KEY_COLUMN_USAGE','dtproperties'))"; 00085 var $metaColumnsSQL = # xtype==61 is datetime 00086 "select c.name,t.name,c.length, 00087 (case when c.xusertype=61 then 0 else c.xprec end), 00088 (case when c.xusertype=61 then 0 else c.xscale end) 00089 from syscolumns c join systypes t on t.xusertype=c.xusertype join sysobjects o on o.id=c.id where o.name='%s'"; 00090 var $hasTop = 'top'; // support mssql SELECT TOP 10 * FROM TABLE 00091 var $hasGenID = true; 00092 var $sysDate = 'convert(datetime,convert(char,GetDate(),102),102)'; 00093 var $sysTimeStamp = 'GetDate()'; 00094 var $_has_mssql_init; 00095 var $maxParameterLen = 4000; 00096 var $arrayClass = 'ADORecordSet_array_mssql'; 00097 var $uniqueSort = true; 00098 var $leftOuter = '*='; 00099 var $rightOuter = '=*'; 00100 var $ansiOuter = true; // for mssql7 or later 00101 var $poorAffectedRows = true; 00102 var $identitySQL = 'select @@IDENTITY'; // 'select SCOPE_IDENTITY'; # for mssql 2000 00103 var $uniqueOrderBy = true; 00104 var $_bindInputArray = true; 00105 00106 function ADODB_mssql() 00107 { 00108 $this->_has_mssql_init = (strnatcmp(PHP_VERSION,'4.1.0')>=0); 00109 } 00110 00111 function ServerInfo() 00112 { 00113 global $ADODB_FETCH_MODE; 00114 00115 $stmt = $this->PrepareSP('sp_server_info'); 00116 $val = 2; 00117 if ($this->fetchMode === false) { 00118 $savem = $ADODB_FETCH_MODE; 00119 $ADODB_FETCH_MODE = ADODB_FETCH_NUM; 00120 } else 00121 $savem = $this->SetFetchMode(ADODB_FETCH_NUM); 00122 00123 00124 $this->Parameter($stmt,$val,'attribute_id'); 00125 $row = $this->GetRow($stmt); 00126 00127 //$row = $this->GetRow("execute sp_server_info 2"); 00128 00129 00130 if ($this->fetchMode === false) { 00131 $ADODB_FETCH_MODE = $savem; 00132 } else 00133 $this->SetFetchMode($savem); 00134 00135 $arr['description'] = $row[2]; 00136 $arr['version'] = ADOConnection::_findvers($arr['description']); 00137 return $arr; 00138 } 00139 00140 function IfNull( $field, $ifNull ) 00141 { 00142 return " ISNULL($field, $ifNull) "; // if MS SQL Server 00143 } 00144 00145 function _insertid() 00146 { 00147 // SCOPE_IDENTITY() 00148 // Returns the last IDENTITY value inserted into an IDENTITY column in 00149 // the same scope. A scope is a module -- a stored procedure, trigger, 00150 // function, or batch. Thus, two statements are in the same scope if 00151 // they are in the same stored procedure, function, or batch. 00152 return $this->GetOne($this->identitySQL); 00153 } 00154 00155 function _affectedrows() 00156 { 00157 return $this->GetOne('select @@rowcount'); 00158 } 00159 00160 var $_dropSeqSQL = "drop table %s"; 00161 00162 function CreateSequence($seq='adodbseq',$start=1) 00163 { 00164 00165 $this->Execute('BEGIN TRANSACTION adodbseq'); 00166 $start -= 1; 00167 $this->Execute("create table $seq (id float(53))"); 00168 $ok = $this->Execute("insert into $seq with (tablock,holdlock) values($start)"); 00169 if (!$ok) { 00170 $this->Execute('ROLLBACK TRANSACTION adodbseq'); 00171 return false; 00172 } 00173 $this->Execute('COMMIT TRANSACTION adodbseq'); 00174 return true; 00175 } 00176 00177 function GenID($seq='adodbseq',$start=1) 00178 { 00179 //$this->debug=1; 00180 $this->Execute('BEGIN TRANSACTION adodbseq'); 00181 $ok = $this->Execute("update $seq with (tablock,holdlock) set id = id + 1"); 00182 if (!$ok) { 00183 $this->Execute("create table $seq (id float(53))"); 00184 $ok = $this->Execute("insert into $seq with (tablock,holdlock) values($start)"); 00185 if (!$ok) { 00186 $this->Execute('ROLLBACK TRANSACTION adodbseq'); 00187 return false; 00188 } 00189 $this->Execute('COMMIT TRANSACTION adodbseq'); 00190 return $start; 00191 } 00192 $num = $this->GetOne("select id from $seq"); 00193 $this->Execute('COMMIT TRANSACTION adodbseq'); 00194 return $num; 00195 00196 // in old implementation, pre 1.90, we returned GUID... 00197 //return $this->GetOne("SELECT CONVERT(varchar(255), NEWID()) AS 'Char'"); 00198 } 00199 00200 00201 function &SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0) 00202 { 00203 if ($nrows > 0 && $offset <= 0) { 00204 $sql = preg_replace( 00205 '/(^\s*select\s+(distinctrow|distinct)?)/i','\\1 '.$this->hasTop." $nrows ",$sql); 00206 $rs =& $this->Execute($sql,$inputarr); 00207 } else 00208 $rs =& ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache); 00209 00210 return $rs; 00211 } 00212 00213 00214 // Format date column in sql string given an input format that understands Y M D 00215 function SQLDate($fmt, $col=false) 00216 { 00217 if (!$col) $col = $this->sysTimeStamp; 00218 $s = ''; 00219 00220 $len = strlen($fmt); 00221 for ($i=0; $i < $len; $i++) { 00222 if ($s) $s .= '+'; 00223 $ch = $fmt[$i]; 00224 switch($ch) { 00225 case 'Y': 00226 case 'y': 00227 $s .= "datename(yyyy,$col)"; 00228 break; 00229 case 'M': 00230 $s .= "convert(char(3),$col,0)"; 00231 break; 00232 case 'm': 00233 $s .= "replace(str(month($col),2),' ','0')"; 00234 break; 00235 case 'Q': 00236 case 'q': 00237 $s .= "datename(quarter,$col)"; 00238 break; 00239 case 'D': 00240 case 'd': 00241 $s .= "replace(str(day($col),2),' ','0')"; 00242 break; 00243 case 'h': 00244 $s .= "substring(convert(char(14),$col,0),13,2)"; 00245 break; 00246 00247 case 'H': 00248 $s .= "replace(str(datepart(hh,$col),2),' ','0')"; 00249 break; 00250 00251 case 'i': 00252 $s .= "replace(str(datepart(mi,$col),2),' ','0')"; 00253 break; 00254 case 's': 00255 $s .= "replace(str(datepart(ss,$col),2),' ','0')"; 00256 break; 00257 case 'a': 00258 case 'A': 00259 $s .= "substring(convert(char(19),$col,0),18,2)"; 00260 break; 00261 00262 default: 00263 if ($ch == '\\') { 00264 $i++; 00265 $ch = substr($fmt,$i,1); 00266 } 00267 $s .= $this->qstr($ch); 00268 break; 00269 } 00270 } 00271 return $s; 00272 } 00273 00274 00275 function BeginTrans() 00276 { 00277 if ($this->transOff) return true; 00278 $this->transCnt += 1; 00279 $this->Execute('BEGIN TRAN'); 00280 return true; 00281 } 00282 00283 function CommitTrans($ok=true) 00284 { 00285 if ($this->transOff) return true; 00286 if (!$ok) return $this->RollbackTrans(); 00287 if ($this->transCnt) $this->transCnt -= 1; 00288 $this->Execute('COMMIT TRAN'); 00289 return true; 00290 } 00291 function RollbackTrans() 00292 { 00293 if ($this->transOff) return true; 00294 if ($this->transCnt) $this->transCnt -= 1; 00295 $this->Execute('ROLLBACK TRAN'); 00296 return true; 00297 } 00298 00299 /* 00300 Usage: 00301 00302 $this->BeginTrans(); 00303 $this->RowLock('table1,table2','table1.id=33 and table2.id=table1.id'); # lock row 33 for both tables 00304 00305 # some operation on both tables table1 and table2 00306 00307 $this->CommitTrans(); 00308 00309 See http://www.swynk.com/friends/achigrik/SQL70Locks.asp 00310 */ 00311 function RowLock($tables,$where,$flds='top 1 null as ignore') 00312 { 00313 if (!$this->transCnt) $this->BeginTrans(); 00314 return $this->GetOne("select $flds from $tables with (ROWLOCK,HOLDLOCK) where $where"); 00315 } 00316 00317 00318 function &MetaIndexes($table,$primary=false) 00319 { 00320 $table = $this->qstr($table); 00321 00322 $sql = "SELECT i.name AS ind_name, C.name AS col_name, USER_NAME(O.uid) AS Owner, c.colid, k.Keyno, 00323 CASE WHEN I.indid BETWEEN 1 AND 254 AND (I.status & 2048 = 2048 OR I.Status = 16402 AND O.XType = 'V') THEN 1 ELSE 0 END AS IsPK, 00324 CASE WHEN I.status & 2 = 2 THEN 1 ELSE 0 END AS IsUnique 00325 FROM dbo.sysobjects o INNER JOIN dbo.sysindexes I ON o.id = i.id 00326 INNER JOIN dbo.sysindexkeys K ON I.id = K.id AND I.Indid = K.Indid 00327 INNER JOIN dbo.syscolumns c ON K.id = C.id AND K.colid = C.Colid 00328 WHERE LEFT(i.name, 8) <> '_WA_Sys_' AND o.status >= 0 AND O.Name LIKE $table 00329 ORDER BY O.name, I.Name, K.keyno"; 00330 00331 global $ADODB_FETCH_MODE; 00332 $save = $ADODB_FETCH_MODE; 00333 $ADODB_FETCH_MODE = ADODB_FETCH_NUM; 00334 if ($this->fetchMode !== FALSE) { 00335 $savem = $this->SetFetchMode(FALSE); 00336 } 00337 00338 $rs = $this->Execute($sql); 00339 if (isset($savem)) { 00340 $this->SetFetchMode($savem); 00341 } 00342 $ADODB_FETCH_MODE = $save; 00343 00344 if (!is_object($rs)) { 00345 return FALSE; 00346 } 00347 00348 $indexes = array(); 00349 while ($row = $rs->FetchRow()) { 00350 if (!$primary && $row[5]) continue; 00351 00352 $indexes[$row[0]]['unique'] = $row[6]; 00353 $indexes[$row[0]]['columns'][] = $row[1]; 00354 } 00355 return $indexes; 00356 } 00357 00358 function MetaForeignKeys($table, $owner=false, $upper=false) 00359 { 00360 global $ADODB_FETCH_MODE; 00361 00362 $save = $ADODB_FETCH_MODE; 00363 $ADODB_FETCH_MODE = ADODB_FETCH_NUM; 00364 $table = $this->qstr(strtoupper($table)); 00365 00366 $sql = 00367 "select object_name(constid) as constraint_name, 00368 col_name(fkeyid, fkey) as column_name, 00369 object_name(rkeyid) as referenced_table_name, 00370 col_name(rkeyid, rkey) as referenced_column_name 00371 from sysforeignkeys 00372 where upper(object_name(fkeyid)) = $table 00373 order by constraint_name, referenced_table_name, keyno"; 00374 00375 $constraints =& $this->GetArray($sql); 00376 00377 $ADODB_FETCH_MODE = $save; 00378 00379 $arr = false; 00380 foreach($constraints as $constr) { 00381 //print_r($constr); 00382 $arr[$constr[0]][$constr[2]][] = $constr[1].'='.$constr[3]; 00383 } 00384 if (!$arr) return false; 00385 00386 $arr2 = false; 00387 00388 foreach($arr as $k => $v) { 00389 foreach($v as $a => $b) { 00390 if ($upper) $a = strtoupper($a); 00391 $arr2[$a] = $b; 00392 } 00393 } 00394 return $arr2; 00395 } 00396 00397 //From: Fernando Moreira <FMoreira@imediata.pt> 00398 function MetaDatabases() 00399 { 00400 if(@mssql_select_db("master")) { 00401 $qry=$this->metaDatabasesSQL; 00402 if($rs=@mssql_query($qry)){ 00403 $tmpAr=$ar=array(); 00404 while($tmpAr=@mssql_fetch_row($rs)) 00405 $ar[]=$tmpAr[0]; 00406 @mssql_select_db($this->database); 00407 if(sizeof($ar)) 00408 return($ar); 00409 else 00410 return(false); 00411 } else { 00412 @mssql_select_db($this->database); 00413 return(false); 00414 } 00415 } 00416 return(false); 00417 } 00418 00419 // "Stein-Aksel Basma" <basma@accelero.no> 00420 // tested with MSSQL 2000 00421 function &MetaPrimaryKeys($table) 00422 { 00423 global $ADODB_FETCH_MODE; 00424 00425 $schema = ''; 00426 $this->_findschema($table,$schema); 00427 if (!$schema) $schema = $this->database; 00428 if ($schema) $schema = "and k.table_catalog like '$schema%'"; 00429 00430 $sql = "select distinct k.column_name,ordinal_position from information_schema.key_column_usage k, 00431 information_schema.table_constraints tc 00432 where tc.constraint_name = k.constraint_name and tc.constraint_type = 00433 'PRIMARY KEY' and k.table_name = '$table' $schema order by ordinal_position "; 00434 00435 $savem = $ADODB_FETCH_MODE; 00436 $ADODB_FETCH_MODE = ADODB_FETCH_NUM; 00437 $a = $this->GetCol($sql); 00438 $ADODB_FETCH_MODE = $savem; 00439 00440 if ($a && sizeof($a)>0) return $a; 00441 $false = false; 00442 return $false; 00443 } 00444 00445 00446 function &MetaTables($ttype=false,$showSchema=false,$mask=false) 00447 { 00448 if ($mask) { 00449 $save = $this->metaTablesSQL; 00450 $mask = $this->qstr(($mask)); 00451 $this->metaTablesSQL .= " AND name like $mask"; 00452 } 00453 $ret =& ADOConnection::MetaTables($ttype,$showSchema); 00454 00455 if ($mask) { 00456 $this->metaTablesSQL = $save; 00457 } 00458 return $ret; 00459 } 00460 00461 function SelectDB($dbName) 00462 { 00463 $this->database = $dbName; 00464 $this->databaseName = $dbName; # obsolete, retained for compat with older adodb versions 00465 if ($this->_connectionID) { 00466 return @mssql_select_db($dbName); 00467 } 00468 else return false; 00469 } 00470 00471 function ErrorMsg() 00472 { 00473 if (empty($this->_errorMsg)){ 00474 $this->_errorMsg = mssql_get_last_message(); 00475 } 00476 return $this->_errorMsg; 00477 } 00478 00479 function ErrorNo() 00480 { 00481 if ($this->_logsql && $this->_errorCode !== false) return $this->_errorCode; 00482 if (empty($this->_errorMsg)) { 00483 $this->_errorMsg = mssql_get_last_message(); 00484 } 00485 $id = @mssql_query("select @@ERROR",$this->_connectionID); 00486 if (!$id) return false; 00487 $arr = mssql_fetch_array($id); 00488 @mssql_free_result($id); 00489 if (is_array($arr)) return $arr[0]; 00490 else return -1; 00491 } 00492 00493 // returns true or false 00494 function _connect($argHostname, $argUsername, $argPassword, $argDatabasename) 00495 { 00496 if (!function_exists('mssql_pconnect')) return null; 00497 $this->_connectionID = mssql_connect($argHostname,$argUsername,$argPassword); 00498 if ($this->_connectionID === false) return false; 00499 if ($argDatabasename) return $this->SelectDB($argDatabasename); 00500 return true; 00501 } 00502 00503 00504 // returns true or false 00505 function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename) 00506 { 00507 if (!function_exists('mssql_pconnect')) return null; 00508 $this->_connectionID = mssql_pconnect($argHostname,$argUsername,$argPassword); 00509 if ($this->_connectionID === false) return false; 00510 00511 // persistent connections can forget to rollback on crash, so we do it here. 00512 if ($this->autoRollback) { 00513 $cnt = $this->GetOne('select @@TRANCOUNT'); 00514 while (--$cnt >= 0) $this->Execute('ROLLBACK TRAN'); 00515 } 00516 if ($argDatabasename) return $this->SelectDB($argDatabasename); 00517 return true; 00518 } 00519 00520 function Prepare($sql) 00521 { 00522 $sqlarr = explode('?',$sql); 00523 if (sizeof($sqlarr) <= 1) return $sql; 00524 $sql2 = $sqlarr[0]; 00525 for ($i = 1, $max = sizeof($sqlarr); $i < $max; $i++) { 00526 $sql2 .= '@P'.($i-1) . $sqlarr[$i]; 00527 } 00528 return array($sql,$this->qstr($sql2),$max); 00529 } 00530 00531 function PrepareSP($sql) 00532 { 00533 if (!$this->_has_mssql_init) { 00534 ADOConnection::outp( "PrepareSP: mssql_init only available since PHP 4.1.0"); 00535 return $sql; 00536 } 00537 $stmt = mssql_init($sql,$this->_connectionID); 00538 if (!$stmt) return $sql; 00539 return array($sql,$stmt); 00540 } 00541 00542 // returns concatenated string 00543 // MSSQL requires integers to be cast as strings 00544 // automatically cast every datatype to VARCHAR(255) 00545 // @author David Rogers (introspectshun) 00546 function Concat() 00547 { 00548 $s = ""; 00549 $arr = func_get_args(); 00550 00551 // Split single record on commas, if possible 00552 if (sizeof($arr) == 1) { 00553 foreach ($arr as $arg) { 00554 $args = explode(',', $arg); 00555 } 00556 $arr = $args; 00557 } 00558 00559 array_walk($arr, create_function('&$v', '$v = "CAST(" . $v . " AS VARCHAR(255))";')); 00560 $s = implode('+',$arr); 00561 if (sizeof($arr) > 0) return "$s"; 00562 00563 return ''; 00564 } 00565 00566 /* 00567 Usage: 00568 $stmt = $db->PrepareSP('SP_RUNSOMETHING'); -- takes 2 params, @myid and @group 00569 00570 # note that the parameter does not have @ in front! 00571 $db->Parameter($stmt,$id,'myid'); 00572 $db->Parameter($stmt,$group,'group',false,64); 00573 $db->Execute($stmt); 00574 00575 @param $stmt Statement returned by Prepare() or PrepareSP(). 00576 @param $var PHP variable to bind to. Can set to null (for isNull support). 00577 @param $name Name of stored procedure variable name to bind to. 00578 @param [$isOutput] Indicates direction of parameter 0/false=IN 1=OUT 2= IN/OUT. This is ignored in oci8. 00579 @param [$maxLen] Holds an maximum length of the variable. 00580 @param [$type] The data type of $var. Legal values depend on driver. 00581 00582 See mssql_bind documentation at php.net. 00583 */ 00584 function Parameter(&$stmt, &$var, $name, $isOutput=false, $maxLen=4000, $type=false) 00585 { 00586 if (!$this->_has_mssql_init) { 00587 ADOConnection::outp( "Parameter: mssql_bind only available since PHP 4.1.0"); 00588 return false; 00589 } 00590 00591 $isNull = is_null($var); // php 4.0.4 and above... 00592 00593 if ($type === false) 00594 switch(gettype($var)) { 00595 default: 00596 case 'string': $type = SQLCHAR; break; 00597 case 'double': $type = SQLFLT8; break; 00598 case 'integer': $type = SQLINT4; break; 00599 case 'boolean': $type = SQLINT1; break; # SQLBIT not supported in 4.1.0 00600 } 00601 00602 if ($this->debug) { 00603 $prefix = ($isOutput) ? 'Out' : 'In'; 00604 $ztype = (empty($type)) ? 'false' : $type; 00605 ADOConnection::outp( "{$prefix}Parameter(\$stmt, \$php_var='$var', \$name='$name', \$maxLen=$maxLen, \$type=$ztype);"); 00606 } 00607 /* 00608 See http://phplens.com/lens/lensforum/msgs.php?id=7231 00609 00610 RETVAL is HARD CODED into php_mssql extension: 00611 The return value (a long integer value) is treated like a special OUTPUT parameter, 00612 called "RETVAL" (without the @). See the example at mssql_execute to 00613 see how it works. - type: one of this new supported PHP constants. 00614 SQLTEXT, SQLVARCHAR,SQLCHAR, SQLINT1,SQLINT2, SQLINT4, SQLBIT,SQLFLT8 00615 */ 00616 if ($name !== 'RETVAL') $name = '@'.$name; 00617 return mssql_bind($stmt[1], $name, $var, $type, $isOutput, $isNull, $maxLen); 00618 } 00619 00620 /* 00621 Unfortunately, it appears that mssql cannot handle varbinary > 255 chars 00622 So all your blobs must be of type "image". 00623 00624 Remember to set in php.ini the following... 00625 00626 ; Valid range 0 - 2147483647. Default = 4096. 00627 mssql.textlimit = 0 ; zero to pass through 00628 00629 ; Valid range 0 - 2147483647. Default = 4096. 00630 mssql.textsize = 0 ; zero to pass through 00631 */ 00632 function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB') 00633 { 00634 00635 if (strtoupper($blobtype) == 'CLOB') { 00636 $sql = "UPDATE $table SET $column='" . $val . "' WHERE $where"; 00637 return $this->Execute($sql) != false; 00638 } 00639 $sql = "UPDATE $table SET $column=0x".bin2hex($val)." WHERE $where"; 00640 return $this->Execute($sql) != false; 00641 } 00642 00643 // returns query ID if successful, otherwise false 00644 function _query($sql,$inputarr) 00645 { 00646 $this->_errorMsg = false; 00647 if (is_array($inputarr)) { 00648 00649 # bind input params with sp_executesql: 00650 # see http://www.quest-pipelines.com/newsletter-v3/0402_F.htm 00651 # works only with sql server 7 and newer 00652 if (!is_array($sql)) $sql = $this->Prepare($sql); 00653 $params = ''; 00654 $decl = ''; 00655 $i = 0; 00656 foreach($inputarr as $v) { 00657 if ($decl) { 00658 $decl .= ', '; 00659 $params .= ', '; 00660 } 00661 if (is_string($v)) { 00662 $len = strlen($v); 00663 if ($len == 0) $len = 1; 00664 00665 if ($len > 4000 ) { 00666 // NVARCHAR is max 4000 chars. Let's use NTEXT 00667 $decl .= "@P$i NTEXT"; 00668 } else { 00669 $decl .= "@P$i NVARCHAR($len)"; 00670 } 00671 00672 $params .= "@P$i=N". (strncmp($v,"'",1)==0? $v : $this->qstr($v)); 00673 } else if (is_integer($v)) { 00674 $decl .= "@P$i INT"; 00675 $params .= "@P$i=".$v; 00676 } else if (is_float($v)) { 00677 $decl .= "@P$i FLOAT"; 00678 $params .= "@P$i=".$v; 00679 } else if (is_bool($v)) { 00680 $decl .= "@P$i INT"; # Used INT just in case BIT in not supported on the user's MSSQL version. It will cast appropriately. 00681 $params .= "@P$i=".(($v)?'1':'0'); # True == 1 in MSSQL BIT fields and acceptable for storing logical true in an int field 00682 } else { 00683 $decl .= "@P$i CHAR"; # Used char because a type is required even when the value is to be NULL. 00684 $params .= "@P$i=NULL"; 00685 } 00686 $i += 1; 00687 } 00688 $decl = $this->qstr($decl); 00689 if ($this->debug) ADOConnection::outp("<font size=-1>sp_executesql N{$sql[1]},N$decl,$params</font>"); 00690 $rez = mssql_query("sp_executesql N{$sql[1]},N$decl,$params"); 00691 00692 } else if (is_array($sql)) { 00693 # PrepareSP() 00694 $rez = mssql_execute($sql[1]); 00695 00696 } else { 00697 $rez = mssql_query($sql,$this->_connectionID); 00698 } 00699 return $rez; 00700 } 00701 00702 // returns true or false 00703 function _close() 00704 { 00705 if ($this->transCnt) $this->RollbackTrans(); 00706 $rez = @mssql_close($this->_connectionID); 00707 $this->_connectionID = false; 00708 return $rez; 00709 } 00710 00711 // mssql uses a default date like Dec 30 2000 12:00AM 00712 function UnixDate($v) 00713 { 00714 return ADORecordSet_array_mssql::UnixDate($v); 00715 } 00716 00717 function UnixTimeStamp($v) 00718 { 00719 return ADORecordSet_array_mssql::UnixTimeStamp($v); 00720 } 00721 } 00722 00723 /*-------------------------------------------------------------------------------------- 00724 Class Name: Recordset 00725 --------------------------------------------------------------------------------------*/ 00726 00727 class ADORecordset_mssql extends ADORecordSet { 00728 00729 var $databaseType = "mssql"; 00730 var $canSeek = true; 00731 var $hasFetchAssoc; // see http://phplens.com/lens/lensforum/msgs.php?id=6083 00732 // _mths works only in non-localised system 00733 00734 function ADORecordset_mssql($id,$mode=false) 00735 { 00736 // freedts check... 00737 $this->hasFetchAssoc = function_exists('mssql_fetch_assoc'); 00738 00739 if ($mode === false) { 00740 global $ADODB_FETCH_MODE; 00741 $mode = $ADODB_FETCH_MODE; 00742 00743 } 00744 $this->fetchMode = $mode; 00745 return $this->ADORecordSet($id,$mode); 00746 } 00747 00748 00749 function _initrs() 00750 { 00751 GLOBAL $ADODB_COUNTRECS; 00752 $this->_numOfRows = ($ADODB_COUNTRECS)? @mssql_num_rows($this->_queryID):-1; 00753 $this->_numOfFields = @mssql_num_fields($this->_queryID); 00754 } 00755 00756 00757 //Contributed by "Sven Axelsson" <sven.axelsson@bokochwebb.se> 00758 // get next resultset - requires PHP 4.0.5 or later 00759 function NextRecordSet() 00760 { 00761 if (!mssql_next_result($this->_queryID)) return false; 00762 $this->_inited = false; 00763 $this->bind = false; 00764 $this->_currentRow = -1; 00765 $this->Init(); 00766 return true; 00767 } 00768 00769 /* Use associative array to get fields array */ 00770 function Fields($colname) 00771 { 00772 if ($this->fetchMode != ADODB_FETCH_NUM) return $this->fields[$colname]; 00773 if (!$this->bind) { 00774 $this->bind = array(); 00775 for ($i=0; $i < $this->_numOfFields; $i++) { 00776 $o = $this->FetchField($i); 00777 $this->bind[strtoupper($o->name)] = $i; 00778 } 00779 } 00780 00781 return $this->fields[$this->bind[strtoupper($colname)]]; 00782 } 00783 00784 /* Returns: an object containing field information. 00785 Get column information in the Recordset object. fetchField() can be used in order to obtain information about 00786 fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by 00787 fetchField() is retrieved. */ 00788 00789 function &FetchField($fieldOffset = -1) 00790 { 00791 if ($fieldOffset != -1) { 00792 $f = @mssql_fetch_field($this->_queryID, $fieldOffset); 00793 } 00794 else if ($fieldOffset == -1) { /* The $fieldOffset argument is not provided thus its -1 */ 00795 $f = @mssql_fetch_field($this->_queryID); 00796 } 00797 $false = false; 00798 if (empty($f)) return $false; 00799 return $f; 00800 } 00801 00802 function _seek($row) 00803 { 00804 return @mssql_data_seek($this->_queryID, $row); 00805 } 00806 00807 // speedup 00808 function MoveNext() 00809 { 00810 if ($this->EOF) return false; 00811 00812 $this->_currentRow++; 00813 00814 if ($this->fetchMode & ADODB_FETCH_ASSOC) { 00815 if ($this->fetchMode & ADODB_FETCH_NUM) { 00816 //ADODB_FETCH_BOTH mode 00817 $this->fields = @mssql_fetch_array($this->_queryID); 00818 } 00819 else { 00820 if ($this->hasFetchAssoc) {// only for PHP 4.2.0 or later 00821 $this->fields = @mssql_fetch_assoc($this->_queryID); 00822 } else { 00823 $flds = @mssql_fetch_array($this->_queryID); 00824 if (is_array($flds)) { 00825 $fassoc = array(); 00826 foreach($flds as $k => $v) { 00827 if (is_numeric($k)) continue; 00828 $fassoc[$k] = $v; 00829 } 00830 $this->fields = $fassoc; 00831 } else 00832 $this->fields = false; 00833 } 00834 } 00835 00836 if (is_array($this->fields)) { 00837 if (ADODB_ASSOC_CASE == 0) { 00838 foreach($this->fields as $k=>$v) { 00839 $this->fields[strtolower($k)] = $v; 00840 } 00841 } else if (ADODB_ASSOC_CASE == 1) { 00842 foreach($this->fields as $k=>$v) { 00843 $this->fields[strtoupper($k)] = $v; 00844 } 00845 } 00846 } 00847 } else { 00848 $this->fields = @mssql_fetch_row($this->_queryID); 00849 } 00850 if ($this->fields) return true; 00851 $this->EOF = true; 00852 00853 return false; 00854 } 00855 00856 00857 // INSERT UPDATE DELETE returns false even if no error occurs in 4.0.4 00858 // also the date format has been changed from YYYY-mm-dd to dd MMM YYYY in 4.0.4. Idiot! 00859 function _fetch($ignore_fields=false) 00860 { 00861 if ($this->fetchMode & ADODB_FETCH_ASSOC) { 00862 if ($this->fetchMode & ADODB_FETCH_NUM) { 00863 //ADODB_FETCH_BOTH mode 00864 $this->fields = @mssql_fetch_array($this->_queryID); 00865 } else { 00866 if ($this->hasFetchAssoc) // only for PHP 4.2.0 or later 00867 $this->fields = @mssql_fetch_assoc($this->_queryID); 00868 else { 00869 $this->fields = @mssql_fetch_array($this->_queryID); 00870 if (@is_array($$this->fields)) { 00871 $fassoc = array(); 00872 foreach($$this->fields as $k => $v) { 00873 if (is_integer($k)) continue; 00874 $fassoc[$k] = $v; 00875 } 00876 $this->fields = $fassoc; 00877 } 00878 } 00879 } 00880 00881 if (!$this->fields) { 00882 } else if (ADODB_ASSOC_CASE == 0) { 00883 foreach($this->fields as $k=>$v) { 00884 $this->fields[strtolower($k)] = $v; 00885 } 00886 } else if (ADODB_ASSOC_CASE == 1) { 00887 foreach($this->fields as $k=>$v) { 00888 $this->fields[strtoupper($k)] = $v; 00889 } 00890 } 00891 } else { 00892 $this->fields = @mssql_fetch_row($this->_queryID); 00893 } 00894 return $this->fields; 00895 } 00896 00897 /* close() only needs to be called if you are worried about using too much memory while your script 00898 is running. All associated result memory for the specified result identifier will automatically be freed. */ 00899 00900 function _close() 00901 { 00902 $rez = mssql_free_result($this->_queryID); 00903 $this->_queryID = false; 00904 return $rez; 00905 } 00906 // mssql uses a default date like Dec 30 2000 12:00AM 00907 function UnixDate($v) 00908 { 00909 return ADORecordSet_array_mssql::UnixDate($v); 00910 } 00911 00912 function UnixTimeStamp($v) 00913 { 00914 return ADORecordSet_array_mssql::UnixTimeStamp($v); 00915 } 00916 00917 } 00918 00919 00920 class ADORecordSet_array_mssql extends ADORecordSet_array { 00921 function ADORecordSet_array_mssql($id=-1,$mode=false) 00922 { 00923 $this->ADORecordSet_array($id,$mode); 00924 } 00925 00926 // mssql uses a default date like Dec 30 2000 12:00AM 00927 function UnixDate($v) 00928 { 00929 00930 if (is_numeric(substr($v,0,1)) && ADODB_PHPVER >= 0x4200) return parent::UnixDate($v); 00931 00932 global $ADODB_mssql_mths,$ADODB_mssql_date_order; 00933 00934 //Dec 30 2000 12:00AM 00935 if ($ADODB_mssql_date_order == 'dmy') { 00936 if (!preg_match( "|^([0-9]{1,2})[-/\. ]+([A-Za-z]{3})[-/\. ]+([0-9]{4})|" ,$v, $rr)) { 00937 return parent::UnixDate($v); 00938 } 00939 if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0; 00940 00941 $theday = $rr[1]; 00942 $themth = substr(strtoupper($rr[2]),0,3); 00943 } else { 00944 if (!preg_match( "|^([A-Za-z]{3})[-/\. ]+([0-9]{1,2})[-/\. ]+([0-9]{4})|" ,$v, $rr)) { 00945 return parent::UnixDate($v); 00946 } 00947 if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0; 00948 00949 $theday = $rr[2]; 00950 $themth = substr(strtoupper($rr[1]),0,3); 00951 } 00952 $themth = $ADODB_mssql_mths[$themth]; 00953 if ($themth <= 0) return false; 00954 // h-m-s-MM-DD-YY 00955 return mktime(0,0,0,$themth,$theday,$rr[3]); 00956 } 00957 00958 function UnixTimeStamp($v) 00959 { 00960 00961 if (is_numeric(substr($v,0,1)) && ADODB_PHPVER >= 0x4200) return parent::UnixTimeStamp($v); 00962 00963 global $ADODB_mssql_mths,$ADODB_mssql_date_order; 00964 00965 //Dec 30 2000 12:00AM 00966 if ($ADODB_mssql_date_order == 'dmy') { 00967 if (!preg_match( "|^([0-9]{1,2})[-/\. ]+([A-Za-z]{3})[-/\. ]+([0-9]{4}) +([0-9]{1,2}):([0-9]{1,2}) *([apAP]{0,1})|" 00968 ,$v, $rr)) return parent::UnixTimeStamp($v); 00969 if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0; 00970 00971 $theday = $rr[1]; 00972 $themth = substr(strtoupper($rr[2]),0,3); 00973 } else { 00974 if (!preg_match( "|^([A-Za-z]{3})[-/\. ]+([0-9]{1,2})[-/\. ]+([0-9]{4}) +([0-9]{1,2}):([0-9]{1,2}) *([apAP]{0,1})|" 00975 ,$v, $rr)) return parent::UnixTimeStamp($v); 00976 if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0; 00977 00978 $theday = $rr[2]; 00979 $themth = substr(strtoupper($rr[1]),0,3); 00980 } 00981 00982 $themth = $ADODB_mssql_mths[$themth]; 00983 if ($themth <= 0) return false; 00984 00985 switch (strtoupper($rr[6])) { 00986 case 'P': 00987 if ($rr[4]<12) $rr[4] += 12; 00988 break; 00989 case 'A': 00990 if ($rr[4]==12) $rr[4] = 0; 00991 break; 00992 default: 00993 break; 00994 } 00995 // h-m-s-MM-DD-YY 00996 return mktime($rr[4],$rr[5],0,$themth,$theday,$rr[3]); 00997 } 00998 } 00999 01000 /* 01001 Code Example 1: 01002 01003 select object_name(constid) as constraint_name, 01004 object_name(fkeyid) as table_name, 01005 col_name(fkeyid, fkey) as column_name, 01006 object_name(rkeyid) as referenced_table_name, 01007 col_name(rkeyid, rkey) as referenced_column_name 01008 from sysforeignkeys 01009 where object_name(fkeyid) = x 01010 order by constraint_name, table_name, referenced_table_name, keyno 01011 01012 Code Example 2: 01013 select constraint_name, 01014 column_name, 01015 ordinal_position 01016 from information_schema.key_column_usage 01017 where constraint_catalog = db_name() 01018 and table_name = x 01019 order by constraint_name, ordinal_position 01020 01021 http://www.databasejournal.com/scripts/article.php/1440551 01022 */ 01023 01024 ?>