| [ Index ] |
PHP Cross Reference of MantisBT |
[Summary view] [Print] [Text view]
1 <?php 2 /* 3 V5.11 5 May 2010 (c) 2000-2010 John Lim (jlim#natsoft.com). All rights reserved. 4 Released under both BSD license and Lesser GPL library license. 5 Whenever there is any discrepancy between the two licenses, 6 the BSD license will take precedence. 7 Set tabs to 4 for best viewing. 8 9 Latest version is available at http://adodb.sourceforge.net 10 11 Native mssql driver. Requires mssql client. Works on Windows. 12 http://www.microsoft.com/sql/technologies/php/default.mspx 13 To configure for Unix, see 14 http://phpbuilder.com/columns/alberto20000919.php3 15 16 $stream = sqlsrv_get_field($stmt, $index, SQLSRV_SQLTYPE_STREAM(SQLSRV_ENC_BINARY)); 17 stream_filter_append($stream, "convert.iconv.ucs-2/utf-8"); // Voila, UTF-8 can be read directly from $stream 18 19 */ 20 21 // security - hide paths 22 if (!defined('ADODB_DIR')) die(); 23 24 if (!function_exists('sqlsrv_configure')) { 25 die("mssqlnative extension not installed"); 26 } 27 28 if (!function_exists('sqlsrv_set_error_handling')) { 29 function sqlsrv_set_error_handling($constant) { 30 sqlsrv_configure("WarningsReturnAsErrors", $constant); 31 } 32 } 33 if (!function_exists('sqlsrv_log_set_severity')) { 34 function sqlsrv_log_set_severity($constant) { 35 sqlsrv_configure("LogSeverity", $constant); 36 } 37 } 38 if (!function_exists('sqlsrv_log_set_subsystems')) { 39 function sqlsrv_log_set_subsystems($constant) { 40 sqlsrv_configure("LogSubsystems", $constant); 41 } 42 } 43 44 45 //---------------------------------------------------------------- 46 // MSSQL returns dates with the format Oct 13 2002 or 13 Oct 2002 47 // and this causes tons of problems because localized versions of 48 // MSSQL will return the dates in dmy or mdy order; and also the 49 // month strings depends on what language has been configured. The 50 // following two variables allow you to control the localization 51 // settings - Ugh. 52 // 53 // MORE LOCALIZATION INFO 54 // ---------------------- 55 // To configure datetime, look for and modify sqlcommn.loc, 56 // typically found in c:\mssql\install 57 // Also read : 58 // http://support.microsoft.com/default.aspx?scid=kb;EN-US;q220918 59 // Alternatively use: 60 // CONVERT(char(12),datecol,120) 61 // 62 // Also if your month is showing as month-1, 63 // e.g. Jan 13, 2002 is showing as 13/0/2002, then see 64 // http://phplens.com/lens/lensforum/msgs.php?id=7048&x=1 65 // it's a localisation problem. 66 //---------------------------------------------------------------- 67 68 69 // has datetime converstion to YYYY-MM-DD format, and also mssql_fetch_assoc 70 if (ADODB_PHPVER >= 0x4300) { 71 // docs say 4.2.0, but testing shows only since 4.3.0 does it work! 72 ini_set('mssql.datetimeconvert',0); 73 } else { 74 global $ADODB_mssql_mths; // array, months must be upper-case 75 $ADODB_mssql_date_order = 'mdy'; 76 $ADODB_mssql_mths = array( 77 'JAN'=>1,'FEB'=>2,'MAR'=>3,'APR'=>4,'MAY'=>5,'JUN'=>6, 78 'JUL'=>7,'AUG'=>8,'SEP'=>9,'OCT'=>10,'NOV'=>11,'DEC'=>12); 79 } 80 81 //--------------------------------------------------------------------------- 82 // Call this to autoset $ADODB_mssql_date_order at the beginning of your code, 83 // just after you connect to the database. Supports mdy and dmy only. 84 // Not required for PHP 4.2.0 and above. 85 function AutoDetect_MSSQL_Date_Order($conn) 86 { 87 global $ADODB_mssql_date_order; 88 $adate = $conn->GetOne('select getdate()'); 89 if ($adate) { 90 $anum = (int) $adate; 91 if ($anum > 0) { 92 if ($anum > 31) { 93 //ADOConnection::outp( "MSSQL: YYYY-MM-DD date format not supported currently"); 94 } else 95 $ADODB_mssql_date_order = 'dmy'; 96 } else 97 $ADODB_mssql_date_order = 'mdy'; 98 } 99 } 100 101 class ADODB_mssqlnative extends ADOConnection { 102 var $databaseType = "mssqlnative"; 103 var $dataProvider = "mssqlnative"; 104 var $replaceQuote = "''"; // string to use to replace quotes 105 var $fmtDate = "'Y-m-d'"; 106 var $fmtTimeStamp = "'Y-m-d H:i:s'"; 107 var $hasInsertID = true; 108 var $substr = "substring"; 109 var $length = 'len'; 110 var $hasAffectedRows = true; 111 var $poorAffectedRows = false; 112 var $metaDatabasesSQL = "select name from sys.sysdatabases where name <> 'master'"; 113 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'))"; 114 var $metaColumnsSQL = # xtype==61 is datetime 115 "select c.name,t.name,c.length, 116 (case when c.xusertype=61 then 0 else c.xprec end), 117 (case when c.xusertype=61 then 0 else c.xscale end) 118 from syscolumns c join systypes t on t.xusertype=c.xusertype join sysobjects o on o.id=c.id where o.name='%s'"; 119 var $hasTop = 'top'; // support mssql SELECT TOP 10 * FROM TABLE 120 var $hasGenID = true; 121 var $sysDate = 'convert(datetime,convert(char,GetDate(),102),102)'; 122 var $sysTimeStamp = 'GetDate()'; 123 var $maxParameterLen = 4000; 124 var $arrayClass = 'ADORecordSet_array_mssqlnative'; 125 var $uniqueSort = true; 126 var $leftOuter = '*='; 127 var $rightOuter = '=*'; 128 var $ansiOuter = true; // for mssql7 or later 129 var $identitySQL = 'select SCOPE_IDENTITY()'; // 'select SCOPE_IDENTITY'; # for mssql 2000 130 var $uniqueOrderBy = true; 131 var $_bindInputArray = true; 132 var $_dropSeqSQL = "drop table %s"; 133 134 function ADODB_mssqlnative() 135 { 136 if ($this->debug) { 137 error_log("<pre>"); 138 sqlsrv_set_error_handling( SQLSRV_ERRORS_LOG_ALL ); 139 sqlsrv_log_set_severity( SQLSRV_LOG_SEVERITY_ALL ); 140 sqlsrv_log_set_subsystems(SQLSRV_LOG_SYSTEM_ALL); 141 sqlsrv_configure('warnings_return_as_errors', 0); 142 } else { 143 sqlsrv_set_error_handling(0); 144 sqlsrv_log_set_severity(0); 145 sqlsrv_log_set_subsystems(SQLSRV_LOG_SYSTEM_ALL); 146 sqlsrv_configure('warnings_return_as_errors', 0); 147 } 148 } 149 150 function ServerInfo() 151 { 152 global $ADODB_FETCH_MODE; 153 if ($this->fetchMode === false) { 154 $savem = $ADODB_FETCH_MODE; 155 $ADODB_FETCH_MODE = ADODB_FETCH_NUM; 156 } else 157 $savem = $this->SetFetchMode(ADODB_FETCH_NUM); 158 $arrServerInfo = sqlsrv_server_info($this->_connectionID); 159 $arr['description'] = $arrServerInfo['SQLServerName'].' connected to '.$arrServerInfo['CurrentDatabase']; 160 $arr['version'] = $arrServerInfo['SQLServerVersion'];//ADOConnection::_findvers($arr['description']); 161 return $arr; 162 } 163 164 function IfNull( $field, $ifNull ) 165 { 166 return " ISNULL($field, $ifNull) "; // if MS SQL Server 167 } 168 169 function _insertid() 170 { 171 // SCOPE_IDENTITY() 172 // Returns the last IDENTITY value inserted into an IDENTITY column in 173 // the same scope. A scope is a module -- a stored procedure, trigger, 174 // function, or batch. Thus, two statements are in the same scope if 175 // they are in the same stored procedure, function, or batch. 176 return $this->GetOne($this->identitySQL); 177 } 178 179 function _affectedrows() 180 { 181 return sqlsrv_rows_affected($this->_queryID); 182 } 183 184 function CreateSequence($seq='adodbseq',$start=1) 185 { 186 if($this->debug) error_log("<hr>CreateSequence($seq,$start)"); 187 sqlsrv_begin_transaction($this->_connectionID); 188 $start -= 1; 189 $this->Execute("create table $seq (id int)");//was float(53) 190 $ok = $this->Execute("insert into $seq with (tablock,holdlock) values($start)"); 191 if (!$ok) { 192 if($this->debug) error_log("<hr>Error: ROLLBACK"); 193 sqlsrv_rollback($this->_connectionID); 194 return false; 195 } 196 sqlsrv_commit($this->_connectionID); 197 return true; 198 } 199 200 function GenID($seq='adodbseq',$start=1) 201 { 202 if($this->debug) error_log("<hr>GenID($seq,$start)"); 203 sqlsrv_begin_transaction($this->_connectionID); 204 $ok = $this->Execute("update $seq with (tablock,holdlock) set id = id + 1"); 205 if (!$ok) { 206 $this->Execute("create table $seq (id int)"); 207 $ok = $this->Execute("insert into $seq with (tablock,holdlock) values($start)"); 208 if (!$ok) { 209 if($this->debug) error_log("<hr>Error: ROLLBACK"); 210 sqlsrv_rollback($this->_connectionID); 211 return false; 212 } 213 sqlsrv_commit($this->_connectionID); 214 return $start; 215 } 216 $num = $this->GetOne("select id from $seq"); 217 sqlsrv_commit($this->_connectionID); 218 if($this->debug) error_log(" Returning: $num"); 219 return $num; 220 } 221 222 // Format date column in sql string given an input format that understands Y M D 223 function SQLDate($fmt, $col=false) 224 { 225 if (!$col) $col = $this->sysTimeStamp; 226 $s = ''; 227 228 $len = strlen($fmt); 229 for ($i=0; $i < $len; $i++) { 230 if ($s) $s .= '+'; 231 $ch = $fmt[$i]; 232 switch($ch) { 233 case 'Y': 234 case 'y': 235 $s .= "datename(yyyy,$col)"; 236 break; 237 case 'M': 238 $s .= "convert(char(3),$col,0)"; 239 break; 240 case 'm': 241 $s .= "replace(str(month($col),2),' ','0')"; 242 break; 243 case 'Q': 244 case 'q': 245 $s .= "datename(quarter,$col)"; 246 break; 247 case 'D': 248 case 'd': 249 $s .= "replace(str(day($col),2),' ','0')"; 250 break; 251 case 'h': 252 $s .= "substring(convert(char(14),$col,0),13,2)"; 253 break; 254 255 case 'H': 256 $s .= "replace(str(datepart(hh,$col),2),' ','0')"; 257 break; 258 259 case 'i': 260 $s .= "replace(str(datepart(mi,$col),2),' ','0')"; 261 break; 262 case 's': 263 $s .= "replace(str(datepart(ss,$col),2),' ','0')"; 264 break; 265 case 'a': 266 case 'A': 267 $s .= "substring(convert(char(19),$col,0),18,2)"; 268 break; 269 270 default: 271 if ($ch == '\\') { 272 $i++; 273 $ch = substr($fmt,$i,1); 274 } 275 $s .= $this->qstr($ch); 276 break; 277 } 278 } 279 return $s; 280 } 281 282 283 function BeginTrans() 284 { 285 if ($this->transOff) return true; 286 $this->transCnt += 1; 287 if ($this->debug) error_log('<hr>begin transaction'); 288 sqlsrv_begin_transaction($this->_connectionID); 289 return true; 290 } 291 292 function CommitTrans($ok=true) 293 { 294 if ($this->transOff) return true; 295 if ($this->debug) error_log('<hr>commit transaction'); 296 if (!$ok) return $this->RollbackTrans(); 297 if ($this->transCnt) $this->transCnt -= 1; 298 sqlsrv_commit($this->_connectionID); 299 return true; 300 } 301 function RollbackTrans() 302 { 303 if ($this->transOff) return true; 304 if ($this->debug) error_log('<hr>rollback transaction'); 305 if ($this->transCnt) $this->transCnt -= 1; 306 sqlsrv_rollback($this->_connectionID); 307 return true; 308 } 309 310 function SetTransactionMode( $transaction_mode ) 311 { 312 $this->_transmode = $transaction_mode; 313 if (empty($transaction_mode)) { 314 $this->Execute('SET TRANSACTION ISOLATION LEVEL READ COMMITTED'); 315 return; 316 } 317 if (!stristr($transaction_mode,'isolation')) $transaction_mode = 'ISOLATION LEVEL '.$transaction_mode; 318 $this->Execute("SET TRANSACTION ".$transaction_mode); 319 } 320 321 /* 322 Usage: 323 324 $this->BeginTrans(); 325 $this->RowLock('table1,table2','table1.id=33 and table2.id=table1.id'); # lock row 33 for both tables 326 327 # some operation on both tables table1 and table2 328 329 $this->CommitTrans(); 330 331 See http://www.swynk.com/friends/achigrik/SQL70Locks.asp 332 */ 333 function RowLock($tables,$where,$col='1 as adodbignore') 334 { 335 if ($col == '1 as adodbignore') $col = 'top 1 null as ignore'; 336 if (!$this->transCnt) $this->BeginTrans(); 337 return $this->GetOne("select $col from $tables with (ROWLOCK,HOLDLOCK) where $where"); 338 } 339 340 function SelectDB($dbName) 341 { 342 $this->database = $dbName; 343 $this->databaseName = $dbName; # obsolete, retained for compat with older adodb versions 344 if ($this->_connectionID) { 345 $rs = $this->Execute('USE '.$dbName); 346 if($rs) { 347 return true; 348 } else return false; 349 } 350 else return false; 351 } 352 353 function ErrorMsg() 354 { 355 $retErrors = sqlsrv_errors(SQLSRV_ERR_ALL); 356 if($retErrors != null) { 357 foreach($retErrors as $arrError) { 358 $this->_errorMsg .= "SQLState: ".$arrError[ 'SQLSTATE']."\n"; 359 $this->_errorMsg .= "Error Code: ".$arrError[ 'code']."\n"; 360 $this->_errorMsg .= "Message: ".$arrError[ 'message']."\n"; 361 } 362 } else { 363 $this->_errorMsg = "No errors found"; 364 } 365 return $this->_errorMsg; 366 } 367 368 function ErrorNo() 369 { 370 if ($this->_logsql && $this->_errorCode !== false) return $this->_errorCode; 371 $err = sqlsrv_errors(SQLSRV_ERR_ALL); 372 if($err[0]) return $err[0]['code']; 373 else return -1; 374 } 375 376 // returns true or false 377 function _connect($argHostname, $argUsername, $argPassword, $argDatabasename) 378 { 379 if (!function_exists('sqlsrv_connect')) return null; 380 $connectionInfo = array("Database"=>$argDatabasename,'UID'=>$argUsername,'PWD'=>$argPassword); 381 if ($this->debug) error_log("<hr>connecting... hostname: $argHostname params: ".var_export($connectionInfo,true)); 382 //if ($this->debug) error_log("<hr>_connectionID before: ".serialize($this->_connectionID)); 383 if(!($this->_connectionID = sqlsrv_connect($argHostname,$connectionInfo))) { 384 if ($this->debug) error_log( "<hr><b>errors</b>: ".print_r( sqlsrv_errors(), true)); 385 return false; 386 } 387 //if ($this->debug) error_log(" _connectionID after: ".serialize($this->_connectionID)); 388 //if ($this->debug) error_log("<hr>defined functions: <pre>".var_export(get_defined_functions(),true)."</pre>"); 389 return true; 390 } 391 392 // returns true or false 393 function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename) 394 { 395 //return null;//not implemented. NOTE: Persistent connections have no effect if PHP is used as a CGI program. (FastCGI!) 396 return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename); 397 } 398 399 function Prepare($sql) 400 { 401 $stmt = sqlsrv_prepare( $this->_connectionID, $sql); 402 if (!$stmt) return $sql; 403 return array($sql,$stmt); 404 } 405 406 // returns concatenated string 407 // MSSQL requires integers to be cast as strings 408 // automatically cast every datatype to VARCHAR(255) 409 // @author David Rogers (introspectshun) 410 function Concat() 411 { 412 $s = ""; 413 $arr = func_get_args(); 414 415 // Split single record on commas, if possible 416 if (sizeof($arr) == 1) { 417 foreach ($arr as $arg) { 418 $args = explode(',', $arg); 419 } 420 $arr = $args; 421 } 422 423 array_walk($arr, create_function('&$v', '$v = "CAST(" . $v . " AS VARCHAR(255))";')); 424 $s = implode('+',$arr); 425 if (sizeof($arr) > 0) return "$s"; 426 427 return ''; 428 } 429 430 /* 431 Unfortunately, it appears that mssql cannot handle varbinary > 255 chars 432 So all your blobs must be of type "image". 433 434 Remember to set in php.ini the following... 435 436 ; Valid range 0 - 2147483647. Default = 4096. 437 mssql.textlimit = 0 ; zero to pass through 438 439 ; Valid range 0 - 2147483647. Default = 4096. 440 mssql.textsize = 0 ; zero to pass through 441 */ 442 function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB') 443 { 444 445 if (strtoupper($blobtype) == 'CLOB') { 446 $sql = "UPDATE $table SET $column='" . $val . "' WHERE $where"; 447 return $this->Execute($sql) != false; 448 } 449 $sql = "UPDATE $table SET $column=0x".bin2hex($val)." WHERE $where"; 450 return $this->Execute($sql) != false; 451 } 452 453 // returns query ID if successful, otherwise false 454 function _query($sql,$inputarr=false) 455 { 456 $this->_errorMsg = false; 457 if (is_array($inputarr)) { 458 $rez = sqlsrv_query($this->_connectionID,$sql,$inputarr); 459 } else if (is_array($sql)) { 460 $rez = sqlsrv_query($this->_connectionID,$sql[1],$inputarr); 461 } else { 462 $rez = sqlsrv_query($this->_connectionID,$sql); 463 } 464 if ($this->debug) error_log("<hr>running query: ".var_export($sql,true)."<hr>input array: ".var_export($inputarr,true)."<hr>result: ".var_export($rez,true));//"<hr>connection: ".serialize($this->_connectionID) 465 //fix for returning true on anything besides select statements 466 if (is_array($sql)) $sql = $sql[1]; 467 $sql = ltrim($sql); 468 if(stripos($sql, 'SELECT') !== 0 && $rez !== false) { 469 if ($this->debug) error_log(" isn't a select query, returning boolean true"); 470 return true; 471 } 472 //end fix 473 if(!$rez) $rez = false; 474 return $rez; 475 } 476 477 // returns true or false 478 function _close() 479 { 480 if ($this->transCnt) $this->RollbackTrans(); 481 $rez = @sqlsrv_close($this->_connectionID); 482 $this->_connectionID = false; 483 return $rez; 484 } 485 486 // mssql uses a default date like Dec 30 2000 12:00AM 487 static function UnixDate($v) 488 { 489 return ADORecordSet_array_mssql::UnixDate($v); 490 } 491 492 static function UnixTimeStamp($v) 493 { 494 return ADORecordSet_array_mssql::UnixTimeStamp($v); 495 } 496 497 function &MetaIndexes($table,$primary=false, $owner = false) 498 { 499 $table = $this->qstr($table); 500 501 $sql = "SELECT i.name AS ind_name, C.name AS col_name, USER_NAME(O.uid) AS Owner, c.colid, k.Keyno, 502 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, 503 CASE WHEN I.status & 2 = 2 THEN 1 ELSE 0 END AS IsUnique 504 FROM dbo.sysobjects o INNER JOIN dbo.sysindexes I ON o.id = i.id 505 INNER JOIN dbo.sysindexkeys K ON I.id = K.id AND I.Indid = K.Indid 506 INNER JOIN dbo.syscolumns c ON K.id = C.id AND K.colid = C.Colid 507 WHERE LEFT(i.name, 8) <> '_WA_Sys_' AND o.status >= 0 AND O.Name LIKE $table 508 ORDER BY O.name, I.Name, K.keyno"; 509 510 global $ADODB_FETCH_MODE; 511 $save = $ADODB_FETCH_MODE; 512 $ADODB_FETCH_MODE = ADODB_FETCH_NUM; 513 if ($this->fetchMode !== FALSE) { 514 $savem = $this->SetFetchMode(FALSE); 515 } 516 517 $rs = $this->Execute($sql); 518 if (isset($savem)) { 519 $this->SetFetchMode($savem); 520 } 521 $ADODB_FETCH_MODE = $save; 522 523 if (!is_object($rs)) { 524 return FALSE; 525 } 526 527 $indexes = array(); 528 while ($row = $rs->FetchRow()) { 529 if (!$primary && $row[5]) continue; 530 531 $indexes[$row[0]]['unique'] = $row[6]; 532 $indexes[$row[0]]['columns'][] = $row[1]; 533 } 534 return $indexes; 535 } 536 537 function MetaForeignKeys($table, $owner=false, $upper=false) 538 { 539 global $ADODB_FETCH_MODE; 540 541 $save = $ADODB_FETCH_MODE; 542 $ADODB_FETCH_MODE = ADODB_FETCH_NUM; 543 $table = $this->qstr(strtoupper($table)); 544 545 $sql = 546 "select object_name(constid) as constraint_name, 547 col_name(fkeyid, fkey) as column_name, 548 object_name(rkeyid) as referenced_table_name, 549 col_name(rkeyid, rkey) as referenced_column_name 550 from sysforeignkeys 551 where upper(object_name(fkeyid)) = $table 552 order by constraint_name, referenced_table_name, keyno"; 553 554 $constraints =& $this->GetArray($sql); 555 556 $ADODB_FETCH_MODE = $save; 557 558 $arr = false; 559 foreach($constraints as $constr) { 560 //print_r($constr); 561 $arr[$constr[0]][$constr[2]][] = $constr[1].'='.$constr[3]; 562 } 563 if (!$arr) return false; 564 565 $arr2 = false; 566 567 foreach($arr as $k => $v) { 568 foreach($v as $a => $b) { 569 if ($upper) $a = strtoupper($a); 570 $arr2[$a] = $b; 571 } 572 } 573 return $arr2; 574 } 575 576 //From: Fernando Moreira <FMoreira@imediata.pt> 577 function MetaDatabases() 578 { 579 $this->SelectDB("master"); 580 $rs =& $this->Execute($this->metaDatabasesSQL); 581 $rows = $rs->GetRows(); 582 $ret = array(); 583 for($i=0;$i<count($rows);$i++) { 584 $ret[] = $rows[$i][0]; 585 } 586 $this->SelectDB($this->database); 587 if($ret) 588 return $ret; 589 else 590 return false; 591 } 592 593 // "Stein-Aksel Basma" <basma@accelero.no> 594 // tested with MSSQL 2000 595 function &MetaPrimaryKeys($table) 596 { 597 global $ADODB_FETCH_MODE; 598 599 $schema = ''; 600 $this->_findschema($table,$schema); 601 if (!$schema) $schema = $this->database; 602 if ($schema) $schema = "and k.table_catalog like '$schema%'"; 603 604 $sql = "select distinct k.column_name,ordinal_position from information_schema.key_column_usage k, 605 information_schema.table_constraints tc 606 where tc.constraint_name = k.constraint_name and tc.constraint_type = 607 'PRIMARY KEY' and k.table_name = '$table' $schema order by ordinal_position "; 608 609 $savem = $ADODB_FETCH_MODE; 610 $ADODB_FETCH_MODE = ADODB_FETCH_NUM; 611 $a = $this->GetCol($sql); 612 $ADODB_FETCH_MODE = $savem; 613 614 if ($a && sizeof($a)>0) return $a; 615 $false = false; 616 return $false; 617 } 618 619 620 function &MetaTables($ttype=false,$showSchema=false,$mask=false) 621 { 622 if ($mask) { 623 $save = $this->metaTablesSQL; 624 $mask = $this->qstr(($mask)); 625 $this->metaTablesSQL .= " AND name like $mask"; 626 } 627 $ret =& ADOConnection::MetaTables($ttype,$showSchema); 628 629 if ($mask) { 630 $this->metaTablesSQL = $save; 631 } 632 return $ret; 633 } 634 } 635 636 /*-------------------------------------------------------------------------------------- 637 Class Name: Recordset 638 --------------------------------------------------------------------------------------*/ 639 640 class ADORecordset_mssqlnative extends ADORecordSet { 641 642 var $databaseType = "mssqlnative"; 643 var $canSeek = false; 644 var $fieldOffset = 0; 645 // _mths works only in non-localised system 646 647 function ADORecordset_mssqlnative($id,$mode=false) 648 { 649 if ($mode === false) { 650 global $ADODB_FETCH_MODE; 651 $mode = $ADODB_FETCH_MODE; 652 653 } 654 $this->fetchMode = $mode; 655 return $this->ADORecordSet($id,$mode); 656 } 657 658 659 function _initrs() 660 { 661 global $ADODB_COUNTRECS; 662 if ($this->connection->debug) error_log("(before) ADODB_COUNTRECS: {$ADODB_COUNTRECS} _numOfRows: {$this->_numOfRows} _numOfFields: {$this->_numOfFields}"); 663 /*$retRowsAff = sqlsrv_rows_affected($this->_queryID);//"If you need to determine the number of rows a query will return before retrieving the actual results, appending a SELECT COUNT ... query would let you get that information, and then a call to next_result would move you to the "real" results." 664 error_log("rowsaff: ".serialize($retRowsAff)); 665 $this->_numOfRows = ($ADODB_COUNTRECS)? $retRowsAff:-1;*/ 666 $this->_numOfRows = -1;//not supported 667 $fieldmeta = sqlsrv_field_metadata($this->_queryID); 668 $this->_numOfFields = ($fieldmeta)? count($fieldmeta):-1; 669 if ($this->connection->debug) error_log("(after) _numOfRows: {$this->_numOfRows} _numOfFields: {$this->_numOfFields}"); 670 } 671 672 673 //Contributed by "Sven Axelsson" <sven.axelsson@bokochwebb.se> 674 // get next resultset - requires PHP 4.0.5 or later 675 function NextRecordSet() 676 { 677 if (!sqlsrv_next_result($this->_queryID)) return false; 678 $this->_inited = false; 679 $this->bind = false; 680 $this->_currentRow = -1; 681 $this->Init(); 682 return true; 683 } 684 685 /* Use associative array to get fields array */ 686 function Fields($colname) 687 { 688 if ($this->fetchMode != ADODB_FETCH_NUM) return $this->fields[$colname]; 689 if (!$this->bind) { 690 $this->bind = array(); 691 for ($i=0; $i < $this->_numOfFields; $i++) { 692 $o = $this->FetchField($i); 693 $this->bind[strtoupper($o->name)] = $i; 694 } 695 } 696 697 return $this->fields[$this->bind[strtoupper($colname)]]; 698 } 699 700 /* Returns: an object containing field information. 701 Get column information in the Recordset object. fetchField() can be used in order to obtain information about 702 fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by 703 fetchField() is retrieved. */ 704 705 function &FetchField($fieldOffset = -1) 706 { 707 if ($this->connection->debug) error_log("<hr>fetchfield: $fieldOffset, fetch array: <pre>".print_r($this->fields,true)."</pre> backtrace: ".adodb_backtrace(false)); 708 if ($fieldOffset != -1) $this->fieldOffset = $fieldOffset; 709 $arrKeys = array_keys($this->fields); 710 if(array_key_exists($this->fieldOffset,$arrKeys) && !array_key_exists($arrKeys[$this->fieldOffset],$this->fields)) { 711 $f = false; 712 } else { 713 $f = $this->fields[ $arrKeys[$this->fieldOffset] ]; 714 if($fieldOffset == -1) $this->fieldOffset++; 715 } 716 717 if (empty($f)) { 718 $f = false;//PHP Notice: Only variable references should be returned by reference 719 } 720 return $f; 721 } 722 723 function _seek($row) 724 { 725 return false;//There is no support for cursors in the driver at this time. All data is returned via forward-only streams. 726 } 727 728 // speedup 729 function MoveNext() 730 { 731 if ($this->connection->debug) error_log("movenext()"); 732 //if ($this->connection->debug) error_log("eof (beginning): ".$this->EOF); 733 if ($this->EOF) return false; 734 735 $this->_currentRow++; 736 if ($this->connection->debug) error_log("_currentRow: ".$this->_currentRow); 737 738 if ($this->_fetch()) return true; 739 $this->EOF = true; 740 //if ($this->connection->debug) error_log("eof (end): ".$this->EOF); 741 742 return false; 743 } 744 745 746 // INSERT UPDATE DELETE returns false even if no error occurs in 4.0.4 747 // also the date format has been changed from YYYY-mm-dd to dd MMM YYYY in 4.0.4. Idiot! 748 function _fetch($ignore_fields=false) 749 { 750 if ($this->connection->debug) error_log("_fetch()"); 751 if ($this->fetchMode & ADODB_FETCH_ASSOC) { 752 if ($this->fetchMode & ADODB_FETCH_NUM) { 753 if ($this->connection->debug) error_log("fetch mode: both"); 754 $this->fields = @sqlsrv_fetch_array($this->_queryID,SQLSRV_FETCH_BOTH); 755 } else { 756 if ($this->connection->debug) error_log("fetch mode: assoc"); 757 $this->fields = @sqlsrv_fetch_array($this->_queryID,SQLSRV_FETCH_ASSOC); 758 } 759 760 if (ADODB_ASSOC_CASE == 0) { 761 foreach($this->fields as $k=>$v) { 762 $this->fields[strtolower($k)] = $v; 763 } 764 } else if (ADODB_ASSOC_CASE == 1) { 765 foreach($this->fields as $k=>$v) { 766 $this->fields[strtoupper($k)] = $v; 767 } 768 } 769 } else { 770 if ($this->connection->debug) error_log("fetch mode: num"); 771 $this->fields = @sqlsrv_fetch_array($this->_queryID,SQLSRV_FETCH_NUMERIC); 772 } 773 if(is_array($this->fields) && array_key_exists(1,$this->fields) && !array_key_exists(0,$this->fields)) {//fix fetch numeric keys since they're not 0 based 774 $arrFixed = array(); 775 foreach($this->fields as $key=>$value) { 776 if(is_numeric($key)) { 777 $arrFixed[$key-1] = $value; 778 } else { 779 $arrFixed[$key] = $value; 780 } 781 } 782 //if($this->connection->debug) error_log("<hr>fixing non 0 based return array, old: ".print_r($this->fields,true)." new: ".print_r($arrFixed,true)); 783 $this->fields = $arrFixed; 784 } 785 if(is_array($this->fields)) { 786 foreach($this->fields as $key=>$value) { 787 if (is_object($value) && method_exists($value, 'format')) {//is DateTime object 788 $this->fields[$key] = $value->format("Y-m-d\TH:i:s\Z"); 789 } 790 } 791 } 792 if($this->fields === null) $this->fields = false; 793 if ($this->connection->debug) error_log("<hr>after _fetch, fields: <pre>".print_r($this->fields,true)." backtrace: ".adodb_backtrace(false)); 794 return $this->fields; 795 } 796 797 /* close() only needs to be called if you are worried about using too much memory while your script 798 is running. All associated result memory for the specified result identifier will automatically be freed. */ 799 function _close() 800 { 801 $rez = sqlsrv_free_stmt($this->_queryID); 802 $this->_queryID = false; 803 return $rez; 804 } 805 806 // mssql uses a default date like Dec 30 2000 12:00AM 807 static function UnixDate($v) 808 { 809 return ADORecordSet_array_mssqlnative::UnixDate($v); 810 } 811 812 static function UnixTimeStamp($v) 813 { 814 return ADORecordSet_array_mssqlnative::UnixTimeStamp($v); 815 } 816 } 817 818 819 class ADORecordSet_array_mssqlnative extends ADORecordSet_array { 820 function ADORecordSet_array_mssqlnative($id=-1,$mode=false) 821 { 822 $this->ADORecordSet_array($id,$mode); 823 } 824 825 // mssql uses a default date like Dec 30 2000 12:00AM 826 static function UnixDate($v) 827 { 828 829 if (is_numeric(substr($v,0,1)) && ADODB_PHPVER >= 0x4200) return parent::UnixDate($v); 830 831 global $ADODB_mssql_mths,$ADODB_mssql_date_order; 832 833 //Dec 30 2000 12:00AM 834 if ($ADODB_mssql_date_order == 'dmy') { 835 if (!preg_match( "|^([0-9]{1,2})[-/\. ]+([A-Za-z]{3})[-/\. ]+([0-9]{4})|" ,$v, $rr)) { 836 return parent::UnixDate($v); 837 } 838 if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0; 839 840 $theday = $rr[1]; 841 $themth = substr(strtoupper($rr[2]),0,3); 842 } else { 843 if (!preg_match( "|^([A-Za-z]{3})[-/\. ]+([0-9]{1,2})[-/\. ]+([0-9]{4})|" ,$v, $rr)) { 844 return parent::UnixDate($v); 845 } 846 if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0; 847 848 $theday = $rr[2]; 849 $themth = substr(strtoupper($rr[1]),0,3); 850 } 851 $themth = $ADODB_mssql_mths[$themth]; 852 if ($themth <= 0) return false; 853 // h-m-s-MM-DD-YY 854 return mktime(0,0,0,$themth,$theday,$rr[3]); 855 } 856 857 static function UnixTimeStamp($v) 858 { 859 860 if (is_numeric(substr($v,0,1)) && ADODB_PHPVER >= 0x4200) return parent::UnixTimeStamp($v); 861 862 global $ADODB_mssql_mths,$ADODB_mssql_date_order; 863 864 //Dec 30 2000 12:00AM 865 if ($ADODB_mssql_date_order == 'dmy') { 866 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})|" 867 ,$v, $rr)) return parent::UnixTimeStamp($v); 868 if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0; 869 870 $theday = $rr[1]; 871 $themth = substr(strtoupper($rr[2]),0,3); 872 } else { 873 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})|" 874 ,$v, $rr)) return parent::UnixTimeStamp($v); 875 if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0; 876 877 $theday = $rr[2]; 878 $themth = substr(strtoupper($rr[1]),0,3); 879 } 880 881 $themth = $ADODB_mssql_mths[$themth]; 882 if ($themth <= 0) return false; 883 884 switch (strtoupper($rr[6])) { 885 case 'P': 886 if ($rr[4]<12) $rr[4] += 12; 887 break; 888 case 'A': 889 if ($rr[4]==12) $rr[4] = 0; 890 break; 891 default: 892 break; 893 } 894 // h-m-s-MM-DD-YY 895 return mktime($rr[4],$rr[5],0,$themth,$theday,$rr[3]); 896 } 897 } 898 899 /* 900 Code Example 1: 901 902 select object_name(constid) as constraint_name, 903 object_name(fkeyid) as table_name, 904 col_name(fkeyid, fkey) as column_name, 905 object_name(rkeyid) as referenced_table_name, 906 col_name(rkeyid, rkey) as referenced_column_name 907 from sysforeignkeys 908 where object_name(fkeyid) = x 909 order by constraint_name, table_name, referenced_table_name, keyno 910 911 Code Example 2: 912 select constraint_name, 913 column_name, 914 ordinal_position 915 from information_schema.key_column_usage 916 where constraint_catalog = db_name() 917 and table_name = x 918 order by constraint_name, ordinal_position 919 920 http://www.databasejournal.com/scripts/article.php/1440551 921 */ 922 923 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Jul 28 15:48:31 2011 | Cross-referenced by PHPXref 0.7 |