3 V4.98 13 Feb 2008 (c) 2000-2008 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)
37 // Also if your month is showing as month-1,
38 // e.g. Jan 13, 2002 is showing as 13/0/2002, then see
39 // http://phplens.com/lens/lensforum/msgs.php?id=7048&x=1
40 // it's a localisation problem.
41 //----------------------------------------------------------------
44 // has datetime converstion to YYYY-MM-DD format, and also mssql_fetch_assoc
45 if (ADODB_PHPVER
>= 0x4300) {
46 // docs say 4.2.0, but testing shows only since 4.3.0 does it work!
47 ini_set('mssql.datetimeconvert',0);
49 global $ADODB_mssql_mths; // array, months must be upper-case
52 $ADODB_mssql_date_order = 'mdy';
53 $ADODB_mssql_mths = array(
54 'JAN'=>1,'FEB'=>2,'MAR'=>3,'APR'=>4,'MAY'=>5,'JUN'=>6,
55 'JUL'=>7,'AUG'=>8,'SEP'=>9,'OCT'=>10,'NOV'=>11,'DEC'=>12);
58 //---------------------------------------------------------------------------
59 // Call this to autoset $ADODB_mssql_date_order at the beginning of your code,
60 // just after you connect to the database. Supports mdy and dmy only.
61 // Not required for PHP 4.2.0 and above.
62 function AutoDetect_MSSQL_Date_Order($conn)
64 global $ADODB_mssql_date_order;
65 $adate = $conn->GetOne('select getdate()');
70 //ADOConnection::outp( "MSSQL: YYYY-MM-DD date format not supported currently");
72 $ADODB_mssql_date_order = 'dmy';
74 $ADODB_mssql_date_order = 'mdy';
78 class ADODB_mssql
extends ADOConnection
{
79 var $databaseType = "mssql";
80 var $dataProvider = "mssql";
81 var $replaceQuote = "''"; // string to use to replace quotes
82 var $fmtDate = "'Y-m-d'";
83 var $fmtTimeStamp = "'Y-m-d H:i:s'";
84 var $hasInsertID = true;
85 var $substr = "substring";
87 var $hasAffectedRows = true;
88 var $metaDatabasesSQL = "select name from sysdatabases where name <> 'master'";
89 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'))";
90 var $metaColumnsSQL = # xtype==61 is datetime
91 "select c.name,t.name,c.length,
92 (case when c.xusertype=61 then 0 else c.xprec end),
93 (case when c.xusertype=61 then 0 else c.xscale end)
94 from syscolumns c join systypes t on t.xusertype=c.xusertype join sysobjects o on o.id=c.id where o.name='%s'";
95 var $hasTop = 'top'; // support mssql SELECT TOP 10 * FROM TABLE
97 var $sysDate = 'convert(datetime,convert(char,GetDate(),102),102)';
98 var $sysTimeStamp = 'GetDate()';
100 var $maxParameterLen = 4000;
101 var $arrayClass = 'ADORecordSet_array_mssql';
102 var $uniqueSort = true;
103 var $leftOuter = '*=';
104 var $rightOuter = '=*';
105 var $ansiOuter = true; // for mssql7 or later
106 var $poorAffectedRows = true;
107 var $identitySQL = 'select SCOPE_IDENTITY()'; // 'select SCOPE_IDENTITY'; # for mssql 2000
108 var $uniqueOrderBy = true;
109 var $_bindInputArray = true;
111 function ADODB_mssql()
113 $this->_has_mssql_init
= (strnatcmp(PHP_VERSION
,'4.1.0')>=0);
116 function ServerInfo()
118 global $ADODB_FETCH_MODE;
121 if ($this->fetchMode
=== false) {
122 $savem = $ADODB_FETCH_MODE;
123 $ADODB_FETCH_MODE = ADODB_FETCH_NUM
;
125 $savem = $this->SetFetchMode(ADODB_FETCH_NUM
);
128 $stmt = $this->PrepareSP('sp_server_info');
130 $this->Parameter($stmt,$val,'attribute_id');
131 $row = $this->GetRow($stmt);
134 $row = $this->GetRow("execute sp_server_info 2");
137 if ($this->fetchMode
=== false) {
138 $ADODB_FETCH_MODE = $savem;
140 $this->SetFetchMode($savem);
142 $arr['description'] = $row[2];
143 $arr['version'] = ADOConnection
::_findvers($arr['description']);
147 function IfNull( $field, $ifNull )
149 return " ISNULL($field, $ifNull) "; // if MS SQL Server
155 // Returns the last IDENTITY value inserted into an IDENTITY column in
156 // the same scope. A scope is a module -- a stored procedure, trigger,
157 // function, or batch. Thus, two statements are in the same scope if
158 // they are in the same stored procedure, function, or batch.
159 return $this->GetOne($this->identitySQL
);
162 function _affectedrows()
164 return $this->GetOne('select @@rowcount');
167 var $_dropSeqSQL = "drop table %s";
169 function CreateSequence($seq='adodbseq',$start=1)
172 $this->Execute('BEGIN TRANSACTION adodbseq');
174 $this->Execute("create table $seq (id float(53))");
175 $ok = $this->Execute("insert into $seq with (tablock,holdlock) values($start)");
177 $this->Execute('ROLLBACK TRANSACTION adodbseq');
180 $this->Execute('COMMIT TRANSACTION adodbseq');
184 function GenID($seq='adodbseq',$start=1)
187 $this->Execute('BEGIN TRANSACTION adodbseq');
188 $ok = $this->Execute("update $seq with (tablock,holdlock) set id = id + 1");
190 $this->Execute("create table $seq (id float(53))");
191 $ok = $this->Execute("insert into $seq with (tablock,holdlock) values($start)");
193 $this->Execute('ROLLBACK TRANSACTION adodbseq');
196 $this->Execute('COMMIT TRANSACTION adodbseq');
199 $num = $this->GetOne("select id from $seq");
200 $this->Execute('COMMIT TRANSACTION adodbseq');
203 // in old implementation, pre 1.90, we returned GUID...
204 //return $this->GetOne("SELECT CONVERT(varchar(255), NEWID()) AS 'Char'");
208 function &SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0)
210 if ($nrows > 0 && $offset <= 0) {
212 '/(^\s*select\s+(distinctrow|distinct)?)/i','\\1 '.$this->hasTop
." $nrows ",$sql);
213 $rs =& $this->Execute($sql,$inputarr);
215 $rs =& ADOConnection
::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);
221 // Format date column in sql string given an input format that understands Y M D
222 function SQLDate($fmt, $col=false)
224 if (!$col) $col = $this->sysTimeStamp
;
228 for ($i=0; $i < $len; $i++
) {
234 $s .= "datename(yyyy,$col)";
237 $s .= "convert(char(3),$col,0)";
240 $s .= "replace(str(month($col),2),' ','0')";
244 $s .= "datename(quarter,$col)";
248 $s .= "replace(str(day($col),2),' ','0')";
251 $s .= "substring(convert(char(14),$col,0),13,2)";
255 $s .= "replace(str(datepart(hh,$col),2),' ','0')";
259 $s .= "replace(str(datepart(mi,$col),2),' ','0')";
262 $s .= "replace(str(datepart(ss,$col),2),' ','0')";
266 $s .= "substring(convert(char(19),$col,0),18,2)";
272 $ch = substr($fmt,$i,1);
274 $s .= $this->qstr($ch);
282 function BeginTrans()
284 if ($this->transOff
) return true;
285 $this->transCnt +
= 1;
286 $this->Execute('BEGIN TRAN');
290 function CommitTrans($ok=true)
292 if ($this->transOff
) return true;
293 if (!$ok) return $this->RollbackTrans();
294 if ($this->transCnt
) $this->transCnt
-= 1;
295 $this->Execute('COMMIT TRAN');
298 function RollbackTrans()
300 if ($this->transOff
) return true;
301 if ($this->transCnt
) $this->transCnt
-= 1;
302 $this->Execute('ROLLBACK TRAN');
306 function SetTransactionMode( $transaction_mode )
308 $this->_transmode
= $transaction_mode;
309 if (empty($transaction_mode)) {
310 $this->Execute('SET TRANSACTION ISOLATION LEVEL READ COMMITTED');
313 if (!stristr($transaction_mode,'isolation')) $transaction_mode = 'ISOLATION LEVEL '.$transaction_mode;
314 $this->Execute("SET TRANSACTION ".$transaction_mode);
321 $this->RowLock('table1,table2','table1.id=33 and table2.id=table1.id'); # lock row 33 for both tables
323 # some operation on both tables table1 and table2
325 $this->CommitTrans();
327 See http://www.swynk.com/friends/achigrik/SQL70Locks.asp
329 function RowLock($tables,$where,$flds='top 1 null as ignore')
331 if (!$this->transCnt
) $this->BeginTrans();
332 return $this->GetOne("select $flds from $tables with (ROWLOCK,HOLDLOCK) where $where");
336 function &MetaIndexes($table,$primary=false)
338 $table = $this->qstr($table);
340 $sql = "SELECT i.name AS ind_name, C.name AS col_name, USER_NAME(O.uid) AS Owner, c.colid, k.Keyno,
341 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,
342 CASE WHEN I.status & 2 = 2 THEN 1 ELSE 0 END AS IsUnique
343 FROM dbo.sysobjects o INNER JOIN dbo.sysindexes I ON o.id = i.id
344 INNER JOIN dbo.sysindexkeys K ON I.id = K.id AND I.Indid = K.Indid
345 INNER JOIN dbo.syscolumns c ON K.id = C.id AND K.colid = C.Colid
346 WHERE LEFT(i.name, 8) <> '_WA_Sys_' AND o.status >= 0 AND O.Name LIKE $table
347 ORDER BY O.name, I.Name, K.keyno";
349 global $ADODB_FETCH_MODE;
350 $save = $ADODB_FETCH_MODE;
351 $ADODB_FETCH_MODE = ADODB_FETCH_NUM
;
352 if ($this->fetchMode
!== FALSE) {
353 $savem = $this->SetFetchMode(FALSE);
356 $rs = $this->Execute($sql);
358 $this->SetFetchMode($savem);
360 $ADODB_FETCH_MODE = $save;
362 if (!is_object($rs)) {
367 while ($row = $rs->FetchRow()) {
368 if (!$primary && $row[5]) continue;
370 $indexes[$row[0]]['unique'] = $row[6];
371 $indexes[$row[0]]['columns'][] = $row[1];
376 function MetaForeignKeys($table, $owner=false, $upper=false)
378 global $ADODB_FETCH_MODE;
380 $save = $ADODB_FETCH_MODE;
381 $ADODB_FETCH_MODE = ADODB_FETCH_NUM
;
382 $table = $this->qstr(strtoupper($table));
385 "select object_name(constid) as constraint_name,
386 col_name(fkeyid, fkey) as column_name,
387 object_name(rkeyid) as referenced_table_name,
388 col_name(rkeyid, rkey) as referenced_column_name
390 where upper(object_name(fkeyid)) = $table
391 order by constraint_name, referenced_table_name, keyno";
393 $constraints =& $this->GetArray($sql);
395 $ADODB_FETCH_MODE = $save;
398 foreach($constraints as $constr) {
400 $arr[$constr[0]][$constr[2]][] = $constr[1].'='.$constr[3];
402 if (!$arr) return false;
406 foreach($arr as $k => $v) {
407 foreach($v as $a => $b) {
408 if ($upper) $a = strtoupper($a);
415 //From: Fernando Moreira <FMoreira@imediata.pt>
416 function MetaDatabases()
418 if(@mssql_select_db
("master")) {
419 $qry=$this->metaDatabasesSQL
;
420 if($rs=@mssql_query
($qry,$this->_connectionID
)){
422 while($tmpAr=@mssql_fetch_row
($rs))
424 @mssql_select_db
($this->database
);
430 @mssql_select_db
($this->database
);
437 // "Stein-Aksel Basma" <basma@accelero.no>
438 // tested with MSSQL 2000
439 function &MetaPrimaryKeys($table)
441 global $ADODB_FETCH_MODE;
444 $this->_findschema($table,$schema);
445 if (!$schema) $schema = $this->database
;
446 if ($schema) $schema = "and k.table_catalog like '$schema%'";
448 $sql = "select distinct k.column_name,ordinal_position from information_schema.key_column_usage k,
449 information_schema.table_constraints tc
450 where tc.constraint_name = k.constraint_name and tc.constraint_type =
451 'PRIMARY KEY' and k.table_name = '$table' $schema order by ordinal_position ";
453 $savem = $ADODB_FETCH_MODE;
454 $ADODB_FETCH_MODE = ADODB_FETCH_NUM
;
455 $a = $this->GetCol($sql);
456 $ADODB_FETCH_MODE = $savem;
458 if ($a && sizeof($a)>0) return $a;
464 function &MetaTables($ttype=false,$showSchema=false,$mask=false)
467 $save = $this->metaTablesSQL
;
468 $mask = $this->qstr(($mask));
469 $this->metaTablesSQL
.= " AND name like $mask";
471 $ret =& ADOConnection
::MetaTables($ttype,$showSchema);
474 $this->metaTablesSQL
= $save;
479 function SelectDB($dbName)
481 $this->database
= $dbName;
482 $this->databaseName
= $dbName; # obsolete, retained for compat with older adodb versions
483 if ($this->_connectionID
) {
484 return @mssql_select_db
($dbName);
491 if (empty($this->_errorMsg
)){
492 $this->_errorMsg
= mssql_get_last_message();
494 return $this->_errorMsg
;
499 if ($this->_logsql
&& $this->_errorCode
!== false) return $this->_errorCode
;
500 if (empty($this->_errorMsg
)) {
501 $this->_errorMsg
= mssql_get_last_message();
503 $id = @mssql_query
("select @@ERROR",$this->_connectionID
);
504 if (!$id) return false;
505 $arr = mssql_fetch_array($id);
506 @mssql_free_result
($id);
507 if (is_array($arr)) return $arr[0];
511 // returns true or false
512 function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)
514 if (!function_exists('mssql_pconnect')) return null;
515 $this->_connectionID
= mssql_connect($argHostname,$argUsername,$argPassword);
516 if ($this->_connectionID
=== false) return false;
517 if ($argDatabasename) return $this->SelectDB($argDatabasename);
522 // returns true or false
523 function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
525 if (!function_exists('mssql_pconnect')) return null;
526 $this->_connectionID
= mssql_pconnect($argHostname,$argUsername,$argPassword);
527 if ($this->_connectionID
=== false) return false;
529 // persistent connections can forget to rollback on crash, so we do it here.
530 if ($this->autoRollback
) {
531 $cnt = $this->GetOne('select @@TRANCOUNT');
532 while (--$cnt >= 0) $this->Execute('ROLLBACK TRAN');
534 if ($argDatabasename) return $this->SelectDB($argDatabasename);
538 function Prepare($sql)
540 $sqlarr = explode('?',$sql);
541 if (sizeof($sqlarr) <= 1) return $sql;
543 for ($i = 1, $max = sizeof($sqlarr); $i < $max; $i++
) {
544 $sql2 .= '@P'.($i-1) . $sqlarr[$i];
546 return array($sql,$this->qstr($sql2),$max);
549 function PrepareSP($sql)
551 if (!$this->_has_mssql_init
) {
552 ADOConnection
::outp( "PrepareSP: mssql_init only available since PHP 4.1.0");
555 $stmt = mssql_init($sql,$this->_connectionID
);
556 if (!$stmt) return $sql;
557 return array($sql,$stmt);
560 // returns concatenated string
561 // MSSQL requires integers to be cast as strings
562 // automatically cast every datatype to VARCHAR(255)
563 // @author David Rogers (introspectshun)
567 $arr = func_get_args();
569 // Split single record on commas, if possible
570 if (sizeof($arr) == 1) {
571 foreach ($arr as $arg) {
572 $args = explode(',', $arg);
577 array_walk($arr, create_function('&$v', '$v = "CAST(" . $v . " AS VARCHAR(255))";'));
578 $s = implode('+',$arr);
579 if (sizeof($arr) > 0) return "$s";
586 $stmt = $db->PrepareSP('SP_RUNSOMETHING'); -- takes 2 params, @myid and @group
588 # note that the parameter does not have @ in front!
589 $db->Parameter($stmt,$id,'myid');
590 $db->Parameter($stmt,$group,'group',false,64);
593 @param $stmt Statement returned by Prepare() or PrepareSP().
594 @param $var PHP variable to bind to. Can set to null (for isNull support).
595 @param $name Name of stored procedure variable name to bind to.
596 @param [$isOutput] Indicates direction of parameter 0/false=IN 1=OUT 2= IN/OUT. This is ignored in oci8.
597 @param [$maxLen] Holds an maximum length of the variable.
598 @param [$type] The data type of $var. Legal values depend on driver.
600 See mssql_bind documentation at php.net.
602 function Parameter(&$stmt, &$var, $name, $isOutput=false, $maxLen=4000, $type=false)
604 if (!$this->_has_mssql_init
) {
605 ADOConnection
::outp( "Parameter: mssql_bind only available since PHP 4.1.0");
609 $isNull = is_null($var); // php 4.0.4 and above...
612 switch(gettype($var)) {
614 case 'string': $type = SQLVARCHAR
; break;
615 case 'double': $type = SQLFLT8
; break;
616 case 'integer': $type = SQLINT4
; break;
617 case 'boolean': $type = SQLINT1
; break; # SQLBIT not supported in 4.1.0
621 $prefix = ($isOutput) ?
'Out' : 'In';
622 $ztype = (empty($type)) ?
'false' : $type;
623 ADOConnection
::outp( "{$prefix}Parameter(\$stmt, \$php_var='$var', \$name='$name', \$maxLen=$maxLen, \$type=$ztype);");
626 See http://phplens.com/lens/lensforum/msgs.php?id=7231
628 RETVAL is HARD CODED into php_mssql extension:
629 The return value (a long integer value) is treated like a special OUTPUT parameter,
630 called "RETVAL" (without the @). See the example at mssql_execute to
631 see how it works. - type: one of this new supported PHP constants.
632 SQLTEXT, SQLVARCHAR,SQLCHAR, SQLINT1,SQLINT2, SQLINT4, SQLBIT,SQLFLT8
634 if ($name !== 'RETVAL') $name = '@'.$name;
635 return mssql_bind($stmt[1], $name, $var, $type, $isOutput, $isNull, $maxLen);
639 Unfortunately, it appears that mssql cannot handle varbinary > 255 chars
640 So all your blobs must be of type "image".
642 Remember to set in php.ini the following...
644 ; Valid range 0 - 2147483647. Default = 4096.
645 mssql.textlimit = 0 ; zero to pass through
647 ; Valid range 0 - 2147483647. Default = 4096.
648 mssql.textsize = 0 ; zero to pass through
650 function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
653 if (strtoupper($blobtype) == 'CLOB') {
654 $sql = "UPDATE $table SET $column='" . $val . "' WHERE $where";
655 return $this->Execute($sql) != false;
657 $sql = "UPDATE $table SET $column=0x".bin2hex($val)." WHERE $where";
658 return $this->Execute($sql) != false;
661 // returns query ID if successful, otherwise false
662 function _query($sql,$inputarr)
664 $this->_errorMsg
= false;
665 if (is_array($inputarr)) {
667 # bind input params with sp_executesql:
668 # see http://www.quest-pipelines.com/newsletter-v3/0402_F.htm
669 # works only with sql server 7 and newer
670 if (!is_array($sql)) $sql = $this->Prepare($sql);
674 foreach($inputarr as $v) {
681 if ($len == 0) $len = 1;
684 // NVARCHAR is max 4000 chars. Let's use NTEXT
685 $decl .= "@P$i NTEXT";
687 $decl .= "@P$i NVARCHAR($len)";
690 $params .= "@P$i=N". (strncmp($v,"'",1)==0?
$v : $this->qstr($v));
691 } else if (is_integer($v)) {
693 $params .= "@P$i=".$v;
694 } else if (is_float($v)) {
695 $decl .= "@P$i FLOAT";
696 $params .= "@P$i=".$v;
697 } else if (is_bool($v)) {
698 $decl .= "@P$i INT"; # Used INT just in case BIT in not supported on the user's MSSQL version. It will cast appropriately.
699 $params .= "@P$i=".(($v)?
'1':'0'); # True == 1 in MSSQL BIT fields and acceptable for storing logical true in an int field
701 $decl .= "@P$i CHAR"; # Used char because a type is required even when the value is to be NULL.
702 $params .= "@P$i=NULL";
706 $decl = $this->qstr($decl);
707 if ($this->debug
) ADOConnection
::outp("<font size=-1>sp_executesql N{$sql[1]},N$decl,$params</font>");
708 $rez = mssql_query("sp_executesql N{$sql[1]},N$decl,$params", $this->_connectionID
);
710 } else if (is_array($sql)) {
712 $rez = mssql_execute($sql[1]);
715 $rez = mssql_query($sql,$this->_connectionID
);
720 // returns true or false
723 if ($this->transCnt
) $this->RollbackTrans();
724 $rez = @mssql_close
($this->_connectionID
);
725 $this->_connectionID
= false;
729 // mssql uses a default date like Dec 30 2000 12:00AM
730 function UnixDate($v)
732 return ADORecordSet_array_mssql
::UnixDate($v);
735 function UnixTimeStamp($v)
737 return ADORecordSet_array_mssql
::UnixTimeStamp($v);
741 /*--------------------------------------------------------------------------------------
742 Class Name: Recordset
743 --------------------------------------------------------------------------------------*/
745 class ADORecordset_mssql
extends ADORecordSet
{
747 var $databaseType = "mssql";
749 var $hasFetchAssoc; // see http://phplens.com/lens/lensforum/msgs.php?id=6083
750 // _mths works only in non-localised system
752 function ADORecordset_mssql($id,$mode=false)
755 $this->hasFetchAssoc
= function_exists('mssql_fetch_assoc');
757 if ($mode === false) {
758 global $ADODB_FETCH_MODE;
759 $mode = $ADODB_FETCH_MODE;
762 $this->fetchMode
= $mode;
763 return $this->ADORecordSet($id,$mode);
769 GLOBAL $ADODB_COUNTRECS;
770 $this->_numOfRows
= ($ADODB_COUNTRECS)? @mssql_num_rows
($this->_queryID
):-1;
771 $this->_numOfFields
= @mssql_num_fields
($this->_queryID
);
775 //Contributed by "Sven Axelsson" <sven.axelsson@bokochwebb.se>
776 // get next resultset - requires PHP 4.0.5 or later
777 function NextRecordSet()
779 if (!mssql_next_result($this->_queryID
)) return false;
780 $this->_inited
= false;
782 $this->_currentRow
= -1;
787 /* Use associative array to get fields array */
788 function Fields($colname)
790 if ($this->fetchMode
!= ADODB_FETCH_NUM
) return $this->fields
[$colname];
792 $this->bind
= array();
793 for ($i=0; $i < $this->_numOfFields
; $i++
) {
794 $o = $this->FetchField($i);
795 $this->bind
[strtoupper($o->name
)] = $i;
799 return $this->fields
[$this->bind
[strtoupper($colname)]];
802 /* Returns: an object containing field information.
803 Get column information in the Recordset object. fetchField() can be used in order to obtain information about
804 fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by
805 fetchField() is retrieved. */
807 function &FetchField($fieldOffset = -1)
809 if ($fieldOffset != -1) {
810 $f = @mssql_fetch_field
($this->_queryID
, $fieldOffset);
812 else if ($fieldOffset == -1) { /* The $fieldOffset argument is not provided thus its -1 */
813 $f = @mssql_fetch_field
($this->_queryID
);
816 if (empty($f)) return $false;
822 return @mssql_data_seek
($this->_queryID
, $row);
828 if ($this->EOF
) return false;
830 $this->_currentRow++
;
832 if ($this->fetchMode
& ADODB_FETCH_ASSOC
) {
833 if ($this->fetchMode
& ADODB_FETCH_NUM
) {
834 //ADODB_FETCH_BOTH mode
835 $this->fields
= @mssql_fetch_array
($this->_queryID
);
838 if ($this->hasFetchAssoc
) {// only for PHP 4.2.0 or later
839 $this->fields
= @mssql_fetch_assoc
($this->_queryID
);
841 $flds = @mssql_fetch_array
($this->_queryID
);
842 if (is_array($flds)) {
844 foreach($flds as $k => $v) {
845 if (is_numeric($k)) continue;
848 $this->fields
= $fassoc;
850 $this->fields
= false;
854 if (is_array($this->fields
)) {
855 if (ADODB_ASSOC_CASE
== 0) {
856 foreach($this->fields
as $k=>$v) {
857 $this->fields
[strtolower($k)] = $v;
859 } else if (ADODB_ASSOC_CASE
== 1) {
860 foreach($this->fields
as $k=>$v) {
861 $this->fields
[strtoupper($k)] = $v;
866 $this->fields
= @mssql_fetch_row
($this->_queryID
);
868 if ($this->fields
) return true;
875 // INSERT UPDATE DELETE returns false even if no error occurs in 4.0.4
876 // also the date format has been changed from YYYY-mm-dd to dd MMM YYYY in 4.0.4. Idiot!
877 function _fetch($ignore_fields=false)
879 if ($this->fetchMode
& ADODB_FETCH_ASSOC
) {
880 if ($this->fetchMode
& ADODB_FETCH_NUM
) {
881 //ADODB_FETCH_BOTH mode
882 $this->fields
= @mssql_fetch_array
($this->_queryID
);
884 if ($this->hasFetchAssoc
) // only for PHP 4.2.0 or later
885 $this->fields
= @mssql_fetch_assoc
($this->_queryID
);
887 $this->fields
= @mssql_fetch_array
($this->_queryID
);
888 if (@is_array
($
$this->fields
)) {
890 foreach($
$this->fields
as $k => $v) {
891 if (is_integer($k)) continue;
894 $this->fields
= $fassoc;
899 if (!$this->fields
) {
900 } else if (ADODB_ASSOC_CASE
== 0) {
901 foreach($this->fields
as $k=>$v) {
902 $this->fields
[strtolower($k)] = $v;
904 } else if (ADODB_ASSOC_CASE
== 1) {
905 foreach($this->fields
as $k=>$v) {
906 $this->fields
[strtoupper($k)] = $v;
910 $this->fields
= @mssql_fetch_row
($this->_queryID
);
912 return $this->fields
;
915 /* close() only needs to be called if you are worried about using too much memory while your script
916 is running. All associated result memory for the specified result identifier will automatically be freed. */
920 $rez = mssql_free_result($this->_queryID
);
921 $this->_queryID
= false;
924 // mssql uses a default date like Dec 30 2000 12:00AM
925 function UnixDate($v)
927 return ADORecordSet_array_mssql
::UnixDate($v);
930 function UnixTimeStamp($v)
932 return ADORecordSet_array_mssql
::UnixTimeStamp($v);
938 class ADORecordSet_array_mssql
extends ADORecordSet_array
{
939 function ADORecordSet_array_mssql($id=-1,$mode=false)
941 $this->ADORecordSet_array($id,$mode);
944 // mssql uses a default date like Dec 30 2000 12:00AM
945 function UnixDate($v)
948 if (is_numeric(substr($v,0,1)) && ADODB_PHPVER
>= 0x4200) return parent
::UnixDate($v);
950 global $ADODB_mssql_mths,$ADODB_mssql_date_order;
952 //Dec 30 2000 12:00AM
953 if ($ADODB_mssql_date_order == 'dmy') {
954 if (!preg_match( "|^([0-9]{1,2})[-/\. ]+([A-Za-z]{3})[-/\. ]+([0-9]{4})|" ,$v, $rr)) {
955 return parent
::UnixDate($v);
957 if ($rr[3] <= TIMESTAMP_FIRST_YEAR
) return 0;
960 $themth = substr(strtoupper($rr[2]),0,3);
962 if (!preg_match( "|^([A-Za-z]{3})[-/\. ]+([0-9]{1,2})[-/\. ]+([0-9]{4})|" ,$v, $rr)) {
963 return parent
::UnixDate($v);
965 if ($rr[3] <= TIMESTAMP_FIRST_YEAR
) return 0;
968 $themth = substr(strtoupper($rr[1]),0,3);
970 $themth = $ADODB_mssql_mths[$themth];
971 if ($themth <= 0) return false;
973 return mktime(0,0,0,$themth,$theday,$rr[3]);
976 function UnixTimeStamp($v)
979 if (is_numeric(substr($v,0,1)) && ADODB_PHPVER
>= 0x4200) return parent
::UnixTimeStamp($v);
981 global $ADODB_mssql_mths,$ADODB_mssql_date_order;
983 //Dec 30 2000 12:00AM
984 if ($ADODB_mssql_date_order == 'dmy') {
985 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})|"
986 ,$v, $rr)) return parent
::UnixTimeStamp($v);
987 if ($rr[3] <= TIMESTAMP_FIRST_YEAR
) return 0;
990 $themth = substr(strtoupper($rr[2]),0,3);
992 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})|"
993 ,$v, $rr)) return parent
::UnixTimeStamp($v);
994 if ($rr[3] <= TIMESTAMP_FIRST_YEAR
) return 0;
997 $themth = substr(strtoupper($rr[1]),0,3);
1000 $themth = $ADODB_mssql_mths[$themth];
1001 if ($themth <= 0) return false;
1003 switch (strtoupper($rr[6])) {
1005 if ($rr[4]<12) $rr[4] +
= 12;
1008 if ($rr[4]==12) $rr[4] = 0;
1014 return mktime($rr[4],$rr[5],0,$themth,$theday,$rr[3]);
1021 select object_name(constid) as constraint_name,
1022 object_name(fkeyid) as table_name,
1023 col_name(fkeyid, fkey) as column_name,
1024 object_name(rkeyid) as referenced_table_name,
1025 col_name(rkeyid, rkey) as referenced_column_name
1027 where object_name(fkeyid) = x
1028 order by constraint_name, table_name, referenced_table_name, keyno
1031 select constraint_name,
1034 from information_schema.key_column_usage
1035 where constraint_catalog = db_name()
1037 order by constraint_name, ordinal_position
1039 http://www.databasejournal.com/scripts/article.php/1440551