3 V4.92a 29 Aug 2006 (c) 2000-2006 John Lim (jlim#natsoft.com.my). 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.
9 Latest version is available at http://adodb.sourceforge.net
11 Native mssql driver. Requires mssql client. Works on Windows.
12 To configure for Unix, see
13 http://phpbuilder.com/columns/alberto20000919.php3
17 // security - hide paths
18 if (!defined('ADODB_DIR')) die();
20 //----------------------------------------------------------------
21 // MSSQL returns dates with the format Oct 13 2002 or 13 Oct 2002
22 // and this causes tons of problems because localized versions of
23 // MSSQL will return the dates in dmy or mdy order; and also the
24 // month strings depends on what language has been configured. The
25 // following two variables allow you to control the localization
28 // MORE LOCALIZATION INFO
29 // ----------------------
30 // To configure datetime, look for and modify sqlcommn.loc,
31 // typically found in c:\mssql\install
33 // http://support.microsoft.com/default.aspx?scid=kb;EN-US;q220918
35 // CONVERT(char(12),datecol,120)
36 //----------------------------------------------------------------
39 // has datetime converstion to YYYY-MM-DD format, and also mssql_fetch_assoc
40 if (ADODB_PHPVER
>= 0x4300) {
41 // docs say 4.2.0, but testing shows only since 4.3.0 does it work!
42 ini_set('mssql.datetimeconvert',0);
44 global $ADODB_mssql_mths; // array, months must be upper-case
47 $ADODB_mssql_date_order = 'mdy';
48 $ADODB_mssql_mths = array(
49 'JAN'=>1,'FEB'=>2,'MAR'=>3,'APR'=>4,'MAY'=>5,'JUN'=>6,
50 'JUL'=>7,'AUG'=>8,'SEP'=>9,'OCT'=>10,'NOV'=>11,'DEC'=>12);
53 //---------------------------------------------------------------------------
54 // Call this to autoset $ADODB_mssql_date_order at the beginning of your code,
55 // just after you connect to the database. Supports mdy and dmy only.
56 // Not required for PHP 4.2.0 and above.
57 function AutoDetect_MSSQL_Date_Order($conn)
59 global $ADODB_mssql_date_order;
60 $adate = $conn->GetOne('select getdate()');
65 //ADOConnection::outp( "MSSQL: YYYY-MM-DD date format not supported currently");
67 $ADODB_mssql_date_order = 'dmy';
69 $ADODB_mssql_date_order = 'mdy';
73 class ADODB_mssql
extends ADOConnection
{
74 var $databaseType = "mssql";
75 var $dataProvider = "mssql";
76 var $replaceQuote = "''"; // string to use to replace quotes
77 var $fmtDate = "'Y-m-d'";
78 var $fmtTimeStamp = "'Y-m-d H:i:s'";
79 var $hasInsertID = true;
80 var $substr = "substring";
82 var $hasAffectedRows = true;
83 var $metaDatabasesSQL = "select name from sysdatabases where name <> 'master'";
84 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'))";
85 var $metaColumnsSQL = # xtype==61 is datetime
86 "select c.name,t.name,c.length,
87 (case when c.xusertype=61 then 0 else c.xprec end),
88 (case when c.xusertype=61 then 0 else c.xscale end)
89 from syscolumns c join systypes t on t.xusertype=c.xusertype join sysobjects o on o.id=c.id where o.name='%s'";
90 var $hasTop = 'top'; // support mssql SELECT TOP 10 * FROM TABLE
92 var $sysDate = 'convert(datetime,convert(char,GetDate(),102),102)';
93 var $sysTimeStamp = 'GetDate()';
95 var $maxParameterLen = 4000;
96 var $arrayClass = 'ADORecordSet_array_mssql';
97 var $uniqueSort = true;
98 var $leftOuter = '*=';
99 var $rightOuter = '=*';
100 var $ansiOuter = true; // for mssql7 or later
101 var $poorAffectedRows = true;
102 var $identitySQL = 'select @@IDENTITY'; // 'select SCOPE_IDENTITY'; # for mssql 2000
103 var $uniqueOrderBy = true;
104 var $_bindInputArray = true;
106 function ADODB_mssql()
108 $this->_has_mssql_init
= (strnatcmp(PHP_VERSION
,'4.1.0')>=0);
111 function ServerInfo()
113 global $ADODB_FETCH_MODE;
115 $stmt = $this->PrepareSP('sp_server_info');
117 if ($this->fetchMode
=== false) {
118 $savem = $ADODB_FETCH_MODE;
119 $ADODB_FETCH_MODE = ADODB_FETCH_NUM
;
121 $savem = $this->SetFetchMode(ADODB_FETCH_NUM
);
124 $this->Parameter($stmt,$val,'attribute_id');
125 $row = $this->GetRow($stmt);
127 //$row = $this->GetRow("execute sp_server_info 2");
130 if ($this->fetchMode
=== false) {
131 $ADODB_FETCH_MODE = $savem;
133 $this->SetFetchMode($savem);
135 $arr['description'] = $row[2];
136 $arr['version'] = ADOConnection
::_findvers($arr['description']);
140 function IfNull( $field, $ifNull )
142 return " ISNULL($field, $ifNull) "; // if MS SQL Server
148 // Returns the last IDENTITY value inserted into an IDENTITY column in
149 // the same scope. A scope is a module -- a stored procedure, trigger,
150 // function, or batch. Thus, two statements are in the same scope if
151 // they are in the same stored procedure, function, or batch.
152 return $this->GetOne($this->identitySQL
);
155 function _affectedrows()
157 return $this->GetOne('select @@rowcount');
160 var $_dropSeqSQL = "drop table %s";
162 function CreateSequence($seq='adodbseq',$start=1)
165 $this->Execute('BEGIN TRANSACTION adodbseq');
167 $this->Execute("create table $seq (id float(53))");
168 $ok = $this->Execute("insert into $seq with (tablock,holdlock) values($start)");
170 $this->Execute('ROLLBACK TRANSACTION adodbseq');
173 $this->Execute('COMMIT TRANSACTION adodbseq');
177 function GenID($seq='adodbseq',$start=1)
180 $this->Execute('BEGIN TRANSACTION adodbseq');
181 $ok = $this->Execute("update $seq with (tablock,holdlock) set id = id + 1");
183 $this->Execute("create table $seq (id float(53))");
184 $ok = $this->Execute("insert into $seq with (tablock,holdlock) values($start)");
186 $this->Execute('ROLLBACK TRANSACTION adodbseq');
189 $this->Execute('COMMIT TRANSACTION adodbseq');
192 $num = $this->GetOne("select id from $seq");
193 $this->Execute('COMMIT TRANSACTION adodbseq');
196 // in old implementation, pre 1.90, we returned GUID...
197 //return $this->GetOne("SELECT CONVERT(varchar(255), NEWID()) AS 'Char'");
201 function &SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0)
203 if ($nrows > 0 && $offset <= 0) {
205 '/(^\s*select\s+(distinctrow|distinct)?)/i','\\1 '.$this->hasTop
." $nrows ",$sql);
206 $rs =& $this->Execute($sql,$inputarr);
208 $rs =& ADOConnection
::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);
214 // Format date column in sql string given an input format that understands Y M D
215 function SQLDate($fmt, $col=false)
217 if (!$col) $col = $this->sysTimeStamp
;
221 for ($i=0; $i < $len; $i++
) {
227 $s .= "datename(yyyy,$col)";
230 $s .= "convert(char(3),$col,0)";
233 $s .= "replace(str(month($col),2),' ','0')";
237 $s .= "datename(quarter,$col)";
241 $s .= "replace(str(day($col),2),' ','0')";
244 $s .= "substring(convert(char(14),$col,0),13,2)";
248 $s .= "replace(str(datepart(hh,$col),2),' ','0')";
252 $s .= "replace(str(datepart(mi,$col),2),' ','0')";
255 $s .= "replace(str(datepart(ss,$col),2),' ','0')";
259 $s .= "substring(convert(char(19),$col,0),18,2)";
265 $ch = substr($fmt,$i,1);
267 $s .= $this->qstr($ch);
275 function BeginTrans()
277 if ($this->transOff
) return true;
278 $this->transCnt +
= 1;
279 $this->Execute('BEGIN TRAN');
283 function CommitTrans($ok=true)
285 if ($this->transOff
) return true;
286 if (!$ok) return $this->RollbackTrans();
287 if ($this->transCnt
) $this->transCnt
-= 1;
288 $this->Execute('COMMIT TRAN');
291 function RollbackTrans()
293 if ($this->transOff
) return true;
294 if ($this->transCnt
) $this->transCnt
-= 1;
295 $this->Execute('ROLLBACK TRAN');
299 function SetTransactionMode( $transaction_mode )
301 $this->_transmode
= $transaction_mode;
302 if (empty($transaction_mode)) {
303 $this->Execute('SET TRANSACTION ISOLATION LEVEL READ COMMITTED');
306 if (!stristr($transaction_mode,'isolation')) $transaction_mode = 'ISOLATION LEVEL '.$transaction_mode;
307 $this->Execute("SET TRANSACTION ".$transaction_mode);
314 $this->RowLock('table1,table2','table1.id=33 and table2.id=table1.id'); # lock row 33 for both tables
316 # some operation on both tables table1 and table2
318 $this->CommitTrans();
320 See http://www.swynk.com/friends/achigrik/SQL70Locks.asp
322 function RowLock($tables,$where,$flds='top 1 null as ignore')
324 if (!$this->transCnt
) $this->BeginTrans();
325 return $this->GetOne("select $flds from $tables with (ROWLOCK,HOLDLOCK) where $where");
329 function &MetaIndexes($table,$primary=false)
331 $table = $this->qstr($table);
333 $sql = "SELECT i.name AS ind_name, C.name AS col_name, USER_NAME(O.uid) AS Owner, c.colid, k.Keyno,
334 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,
335 CASE WHEN I.status & 2 = 2 THEN 1 ELSE 0 END AS IsUnique
336 FROM dbo.sysobjects o INNER JOIN dbo.sysindexes I ON o.id = i.id
337 INNER JOIN dbo.sysindexkeys K ON I.id = K.id AND I.Indid = K.Indid
338 INNER JOIN dbo.syscolumns c ON K.id = C.id AND K.colid = C.Colid
339 WHERE LEFT(i.name, 8) <> '_WA_Sys_' AND o.status >= 0 AND O.Name LIKE $table
340 ORDER BY O.name, I.Name, K.keyno";
342 global $ADODB_FETCH_MODE;
343 $save = $ADODB_FETCH_MODE;
344 $ADODB_FETCH_MODE = ADODB_FETCH_NUM
;
345 if ($this->fetchMode
!== FALSE) {
346 $savem = $this->SetFetchMode(FALSE);
349 $rs = $this->Execute($sql);
351 $this->SetFetchMode($savem);
353 $ADODB_FETCH_MODE = $save;
355 if (!is_object($rs)) {
360 while ($row = $rs->FetchRow()) {
361 if (!$primary && $row[5]) continue;
363 $indexes[$row[0]]['unique'] = $row[6];
364 $indexes[$row[0]]['columns'][] = $row[1];
369 function MetaForeignKeys($table, $owner=false, $upper=false)
371 global $ADODB_FETCH_MODE;
373 $save = $ADODB_FETCH_MODE;
374 $ADODB_FETCH_MODE = ADODB_FETCH_NUM
;
375 $table = $this->qstr(strtoupper($table));
378 "select object_name(constid) as constraint_name,
379 col_name(fkeyid, fkey) as column_name,
380 object_name(rkeyid) as referenced_table_name,
381 col_name(rkeyid, rkey) as referenced_column_name
383 where upper(object_name(fkeyid)) = $table
384 order by constraint_name, referenced_table_name, keyno";
386 $constraints =& $this->GetArray($sql);
388 $ADODB_FETCH_MODE = $save;
391 foreach($constraints as $constr) {
393 $arr[$constr[0]][$constr[2]][] = $constr[1].'='.$constr[3];
395 if (!$arr) return false;
399 foreach($arr as $k => $v) {
400 foreach($v as $a => $b) {
401 if ($upper) $a = strtoupper($a);
408 //From: Fernando Moreira <FMoreira@imediata.pt>
409 function MetaDatabases()
411 if(@mssql_select_db
("master")) {
412 $qry=$this->metaDatabasesSQL
;
413 if($rs=@mssql_query
($qry)){
415 while($tmpAr=@mssql_fetch_row
($rs))
417 @mssql_select_db
($this->database
);
423 @mssql_select_db
($this->database
);
430 // "Stein-Aksel Basma" <basma@accelero.no>
431 // tested with MSSQL 2000
432 function &MetaPrimaryKeys($table)
434 global $ADODB_FETCH_MODE;
437 $this->_findschema($table,$schema);
438 if (!$schema) $schema = $this->database
;
439 if ($schema) $schema = "and k.table_catalog like '$schema%'";
441 $sql = "select distinct k.column_name,ordinal_position from information_schema.key_column_usage k,
442 information_schema.table_constraints tc
443 where tc.constraint_name = k.constraint_name and tc.constraint_type =
444 'PRIMARY KEY' and k.table_name = '$table' $schema order by ordinal_position ";
446 $savem = $ADODB_FETCH_MODE;
447 $ADODB_FETCH_MODE = ADODB_FETCH_NUM
;
448 $a = $this->GetCol($sql);
449 $ADODB_FETCH_MODE = $savem;
451 if ($a && sizeof($a)>0) return $a;
457 function &MetaTables($ttype=false,$showSchema=false,$mask=false)
460 $save = $this->metaTablesSQL
;
461 $mask = $this->qstr(($mask));
462 $this->metaTablesSQL
.= " AND name like $mask";
464 $ret =& ADOConnection
::MetaTables($ttype,$showSchema);
467 $this->metaTablesSQL
= $save;
472 function SelectDB($dbName)
474 $this->database
= $dbName;
475 $this->databaseName
= $dbName; # obsolete, retained for compat with older adodb versions
476 if ($this->_connectionID
) {
477 return @mssql_select_db
($dbName);
484 if (empty($this->_errorMsg
)){
485 $this->_errorMsg
= mssql_get_last_message();
487 return $this->_errorMsg
;
492 if ($this->_logsql
&& $this->_errorCode
!== false) return $this->_errorCode
;
493 if (empty($this->_errorMsg
)) {
494 $this->_errorMsg
= mssql_get_last_message();
496 $id = @mssql_query
("select @@ERROR",$this->_connectionID
);
497 if (!$id) return false;
498 $arr = mssql_fetch_array($id);
499 @mssql_free_result
($id);
500 if (is_array($arr)) return $arr[0];
504 // returns true or false
505 function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)
507 if (!function_exists('mssql_pconnect')) return null;
508 $this->_connectionID
= mssql_connect($argHostname,$argUsername,$argPassword);
509 if ($this->_connectionID
=== false) return false;
510 if ($argDatabasename) return $this->SelectDB($argDatabasename);
515 // returns true or false
516 function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
518 if (!function_exists('mssql_pconnect')) return null;
519 $this->_connectionID
= mssql_pconnect($argHostname,$argUsername,$argPassword);
520 if ($this->_connectionID
=== false) return false;
522 // persistent connections can forget to rollback on crash, so we do it here.
523 if ($this->autoRollback
) {
524 $cnt = $this->GetOne('select @@TRANCOUNT');
525 while (--$cnt >= 0) $this->Execute('ROLLBACK TRAN');
527 if ($argDatabasename) return $this->SelectDB($argDatabasename);
531 function Prepare($sql)
533 $sqlarr = explode('?',$sql);
534 if (sizeof($sqlarr) <= 1) return $sql;
536 for ($i = 1, $max = sizeof($sqlarr); $i < $max; $i++
) {
537 $sql2 .= '@P'.($i-1) . $sqlarr[$i];
539 return array($sql,$this->qstr($sql2),$max);
542 function PrepareSP($sql)
544 if (!$this->_has_mssql_init
) {
545 ADOConnection
::outp( "PrepareSP: mssql_init only available since PHP 4.1.0");
548 $stmt = mssql_init($sql,$this->_connectionID
);
549 if (!$stmt) return $sql;
550 return array($sql,$stmt);
553 // returns concatenated string
554 // MSSQL requires integers to be cast as strings
555 // automatically cast every datatype to VARCHAR(255)
556 // @author David Rogers (introspectshun)
560 $arr = func_get_args();
562 // Split single record on commas, if possible
563 if (sizeof($arr) == 1) {
564 foreach ($arr as $arg) {
565 $args = explode(',', $arg);
570 array_walk($arr, create_function('&$v', '$v = "CAST(" . $v . " AS VARCHAR(255))";'));
571 $s = implode('+',$arr);
572 if (sizeof($arr) > 0) return "$s";
579 $stmt = $db->PrepareSP('SP_RUNSOMETHING'); -- takes 2 params, @myid and @group
581 # note that the parameter does not have @ in front!
582 $db->Parameter($stmt,$id,'myid');
583 $db->Parameter($stmt,$group,'group',false,64);
586 @param $stmt Statement returned by Prepare() or PrepareSP().
587 @param $var PHP variable to bind to. Can set to null (for isNull support).
588 @param $name Name of stored procedure variable name to bind to.
589 @param [$isOutput] Indicates direction of parameter 0/false=IN 1=OUT 2= IN/OUT. This is ignored in oci8.
590 @param [$maxLen] Holds an maximum length of the variable.
591 @param [$type] The data type of $var. Legal values depend on driver.
593 See mssql_bind documentation at php.net.
595 function Parameter(&$stmt, &$var, $name, $isOutput=false, $maxLen=4000, $type=false)
597 if (!$this->_has_mssql_init
) {
598 ADOConnection
::outp( "Parameter: mssql_bind only available since PHP 4.1.0");
602 $isNull = is_null($var); // php 4.0.4 and above...
605 switch(gettype($var)) {
607 case 'string': $type = SQLCHAR
; break;
608 case 'double': $type = SQLFLT8
; break;
609 case 'integer': $type = SQLINT4
; break;
610 case 'boolean': $type = SQLINT1
; break; # SQLBIT not supported in 4.1.0
614 $prefix = ($isOutput) ?
'Out' : 'In';
615 $ztype = (empty($type)) ?
'false' : $type;
616 ADOConnection
::outp( "{$prefix}Parameter(\$stmt, \$php_var='$var', \$name='$name', \$maxLen=$maxLen, \$type=$ztype);");
619 See http://phplens.com/lens/lensforum/msgs.php?id=7231
621 RETVAL is HARD CODED into php_mssql extension:
622 The return value (a long integer value) is treated like a special OUTPUT parameter,
623 called "RETVAL" (without the @). See the example at mssql_execute to
624 see how it works. - type: one of this new supported PHP constants.
625 SQLTEXT, SQLVARCHAR,SQLCHAR, SQLINT1,SQLINT2, SQLINT4, SQLBIT,SQLFLT8
627 if ($name !== 'RETVAL') $name = '@'.$name;
628 return mssql_bind($stmt[1], $name, $var, $type, $isOutput, $isNull, $maxLen);
632 Unfortunately, it appears that mssql cannot handle varbinary > 255 chars
633 So all your blobs must be of type "image".
635 Remember to set in php.ini the following...
637 ; Valid range 0 - 2147483647. Default = 4096.
638 mssql.textlimit = 0 ; zero to pass through
640 ; Valid range 0 - 2147483647. Default = 4096.
641 mssql.textsize = 0 ; zero to pass through
643 function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
646 if (strtoupper($blobtype) == 'CLOB') {
647 $sql = "UPDATE $table SET $column='" . $val . "' WHERE $where";
648 return $this->Execute($sql) != false;
650 $sql = "UPDATE $table SET $column=0x".bin2hex($val)." WHERE $where";
651 return $this->Execute($sql) != false;
654 // returns query ID if successful, otherwise false
655 function _query($sql,$inputarr)
657 $this->_errorMsg
= false;
658 if (is_array($inputarr)) {
660 # bind input params with sp_executesql:
661 # see http://www.quest-pipelines.com/newsletter-v3/0402_F.htm
662 # works only with sql server 7 and newer
663 if (!is_array($sql)) $sql = $this->Prepare($sql);
667 foreach($inputarr as $v) {
674 if ($len == 0) $len = 1;
677 // NVARCHAR is max 4000 chars. Let's use NTEXT
678 $decl .= "@P$i NTEXT";
680 $decl .= "@P$i NVARCHAR($len)";
683 $params .= "@P$i=N". (strncmp($v,"'",1)==0?
$v : $this->qstr($v));
684 } else if (is_integer($v)) {
686 $params .= "@P$i=".$v;
687 } else if (is_float($v)) {
688 $decl .= "@P$i FLOAT";
689 $params .= "@P$i=".$v;
690 } else if (is_bool($v)) {
691 $decl .= "@P$i INT"; # Used INT just in case BIT in not supported on the user's MSSQL version. It will cast appropriately.
692 $params .= "@P$i=".(($v)?
'1':'0'); # True == 1 in MSSQL BIT fields and acceptable for storing logical true in an int field
694 $decl .= "@P$i CHAR"; # Used char because a type is required even when the value is to be NULL.
695 $params .= "@P$i=NULL";
699 $decl = $this->qstr($decl);
700 if ($this->debug
) ADOConnection
::outp("<font size=-1>sp_executesql N{$sql[1]},N$decl,$params</font>");
701 $rez = mssql_query("sp_executesql N{$sql[1]},N$decl,$params");
703 } else if (is_array($sql)) {
705 $rez = mssql_execute($sql[1]);
708 $rez = mssql_query($sql,$this->_connectionID
);
713 // returns true or false
716 if ($this->transCnt
) $this->RollbackTrans();
717 $rez = @mssql_close
($this->_connectionID
);
718 $this->_connectionID
= false;
722 // mssql uses a default date like Dec 30 2000 12:00AM
723 function UnixDate($v)
725 return ADORecordSet_array_mssql
::UnixDate($v);
728 function UnixTimeStamp($v)
730 return ADORecordSet_array_mssql
::UnixTimeStamp($v);
734 /*--------------------------------------------------------------------------------------
735 Class Name: Recordset
736 --------------------------------------------------------------------------------------*/
738 class ADORecordset_mssql
extends ADORecordSet
{
740 var $databaseType = "mssql";
742 var $hasFetchAssoc; // see http://phplens.com/lens/lensforum/msgs.php?id=6083
743 // _mths works only in non-localised system
745 function ADORecordset_mssql($id,$mode=false)
748 $this->hasFetchAssoc
= function_exists('mssql_fetch_assoc');
750 if ($mode === false) {
751 global $ADODB_FETCH_MODE;
752 $mode = $ADODB_FETCH_MODE;
755 $this->fetchMode
= $mode;
756 return $this->ADORecordSet($id,$mode);
762 GLOBAL $ADODB_COUNTRECS;
763 $this->_numOfRows
= ($ADODB_COUNTRECS)? @mssql_num_rows
($this->_queryID
):-1;
764 $this->_numOfFields
= @mssql_num_fields
($this->_queryID
);
768 //Contributed by "Sven Axelsson" <sven.axelsson@bokochwebb.se>
769 // get next resultset - requires PHP 4.0.5 or later
770 function NextRecordSet()
772 if (!mssql_next_result($this->_queryID
)) return false;
773 $this->_inited
= false;
775 $this->_currentRow
= -1;
780 /* Use associative array to get fields array */
781 function Fields($colname)
783 if ($this->fetchMode
!= ADODB_FETCH_NUM
) return $this->fields
[$colname];
785 $this->bind
= array();
786 for ($i=0; $i < $this->_numOfFields
; $i++
) {
787 $o = $this->FetchField($i);
788 $this->bind
[strtoupper($o->name
)] = $i;
792 return $this->fields
[$this->bind
[strtoupper($colname)]];
795 /* Returns: an object containing field information.
796 Get column information in the Recordset object. fetchField() can be used in order to obtain information about
797 fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by
798 fetchField() is retrieved. */
800 function &FetchField($fieldOffset = -1)
802 if ($fieldOffset != -1) {
803 $f = @mssql_fetch_field
($this->_queryID
, $fieldOffset);
805 else if ($fieldOffset == -1) { /* The $fieldOffset argument is not provided thus its -1 */
806 $f = @mssql_fetch_field
($this->_queryID
);
809 if (empty($f)) return $false;
815 return @mssql_data_seek
($this->_queryID
, $row);
821 if ($this->EOF
) return false;
823 $this->_currentRow++
;
825 if ($this->fetchMode
& ADODB_FETCH_ASSOC
) {
826 if ($this->fetchMode
& ADODB_FETCH_NUM
) {
827 //ADODB_FETCH_BOTH mode
828 $this->fields
= @mssql_fetch_array
($this->_queryID
);
831 if ($this->hasFetchAssoc
) {// only for PHP 4.2.0 or later
832 $this->fields
= @mssql_fetch_assoc
($this->_queryID
);
834 $flds = @mssql_fetch_array
($this->_queryID
);
835 if (is_array($flds)) {
837 foreach($flds as $k => $v) {
838 if (is_numeric($k)) continue;
841 $this->fields
= $fassoc;
843 $this->fields
= false;
847 if (is_array($this->fields
)) {
848 if (ADODB_ASSOC_CASE
== 0) {
849 foreach($this->fields
as $k=>$v) {
850 $this->fields
[strtolower($k)] = $v;
852 } else if (ADODB_ASSOC_CASE
== 1) {
853 foreach($this->fields
as $k=>$v) {
854 $this->fields
[strtoupper($k)] = $v;
859 $this->fields
= @mssql_fetch_row
($this->_queryID
);
861 if ($this->fields
) return true;
868 // INSERT UPDATE DELETE returns false even if no error occurs in 4.0.4
869 // also the date format has been changed from YYYY-mm-dd to dd MMM YYYY in 4.0.4. Idiot!
870 function _fetch($ignore_fields=false)
872 if ($this->fetchMode
& ADODB_FETCH_ASSOC
) {
873 if ($this->fetchMode
& ADODB_FETCH_NUM
) {
874 //ADODB_FETCH_BOTH mode
875 $this->fields
= @mssql_fetch_array
($this->_queryID
);
877 if ($this->hasFetchAssoc
) // only for PHP 4.2.0 or later
878 $this->fields
= @mssql_fetch_assoc
($this->_queryID
);
880 $this->fields
= @mssql_fetch_array
($this->_queryID
);
881 if (@is_array
($
$this->fields
)) {
883 foreach($
$this->fields
as $k => $v) {
884 if (is_integer($k)) continue;
887 $this->fields
= $fassoc;
892 if (!$this->fields
) {
893 } else if (ADODB_ASSOC_CASE
== 0) {
894 foreach($this->fields
as $k=>$v) {
895 $this->fields
[strtolower($k)] = $v;
897 } else if (ADODB_ASSOC_CASE
== 1) {
898 foreach($this->fields
as $k=>$v) {
899 $this->fields
[strtoupper($k)] = $v;
903 $this->fields
= @mssql_fetch_row
($this->_queryID
);
905 return $this->fields
;
908 /* close() only needs to be called if you are worried about using too much memory while your script
909 is running. All associated result memory for the specified result identifier will automatically be freed. */
913 $rez = mssql_free_result($this->_queryID
);
914 $this->_queryID
= false;
917 // mssql uses a default date like Dec 30 2000 12:00AM
918 function UnixDate($v)
920 return ADORecordSet_array_mssql
::UnixDate($v);
923 function UnixTimeStamp($v)
925 return ADORecordSet_array_mssql
::UnixTimeStamp($v);
931 class ADORecordSet_array_mssql
extends ADORecordSet_array
{
932 function ADORecordSet_array_mssql($id=-1,$mode=false)
934 $this->ADORecordSet_array($id,$mode);
937 // mssql uses a default date like Dec 30 2000 12:00AM
938 function UnixDate($v)
941 if (is_numeric(substr($v,0,1)) && ADODB_PHPVER
>= 0x4200) return parent
::UnixDate($v);
943 global $ADODB_mssql_mths,$ADODB_mssql_date_order;
945 //Dec 30 2000 12:00AM
946 if ($ADODB_mssql_date_order == 'dmy') {
947 if (!preg_match( "|^([0-9]{1,2})[-/\. ]+([A-Za-z]{3})[-/\. ]+([0-9]{4})|" ,$v, $rr)) {
948 return parent
::UnixDate($v);
950 if ($rr[3] <= TIMESTAMP_FIRST_YEAR
) return 0;
953 $themth = substr(strtoupper($rr[2]),0,3);
955 if (!preg_match( "|^([A-Za-z]{3})[-/\. ]+([0-9]{1,2})[-/\. ]+([0-9]{4})|" ,$v, $rr)) {
956 return parent
::UnixDate($v);
958 if ($rr[3] <= TIMESTAMP_FIRST_YEAR
) return 0;
961 $themth = substr(strtoupper($rr[1]),0,3);
963 $themth = $ADODB_mssql_mths[$themth];
964 if ($themth <= 0) return false;
966 return mktime(0,0,0,$themth,$theday,$rr[3]);
969 function UnixTimeStamp($v)
972 if (is_numeric(substr($v,0,1)) && ADODB_PHPVER
>= 0x4200) return parent
::UnixTimeStamp($v);
974 global $ADODB_mssql_mths,$ADODB_mssql_date_order;
976 //Dec 30 2000 12:00AM
977 if ($ADODB_mssql_date_order == 'dmy') {
978 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})|"
979 ,$v, $rr)) return parent
::UnixTimeStamp($v);
980 if ($rr[3] <= TIMESTAMP_FIRST_YEAR
) return 0;
983 $themth = substr(strtoupper($rr[2]),0,3);
985 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})|"
986 ,$v, $rr)) return parent
::UnixTimeStamp($v);
987 if ($rr[3] <= TIMESTAMP_FIRST_YEAR
) return 0;
990 $themth = substr(strtoupper($rr[1]),0,3);
993 $themth = $ADODB_mssql_mths[$themth];
994 if ($themth <= 0) return false;
996 switch (strtoupper($rr[6])) {
998 if ($rr[4]<12) $rr[4] +
= 12;
1001 if ($rr[4]==12) $rr[4] = 0;
1007 return mktime($rr[4],$rr[5],0,$themth,$theday,$rr[3]);
1014 select object_name(constid) as constraint_name,
1015 object_name(fkeyid) as table_name,
1016 col_name(fkeyid, fkey) as column_name,
1017 object_name(rkeyid) as referenced_table_name,
1018 col_name(rkeyid, rkey) as referenced_column_name
1020 where object_name(fkeyid) = x
1021 order by constraint_name, table_name, referenced_table_name, keyno
1024 select constraint_name,
1027 from information_schema.key_column_usage
1028 where constraint_catalog = db_name()
1030 order by constraint_name, ordinal_position
1032 http://www.databasejournal.com/scripts/article.php/1440551