3 V4.22 15 Apr 2004 (c) 2000-2004 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://php.weblogs.com/
11 Native mssql driver. Requires mssql client. Works on Windows.
12 To configure for Unix, see
13 http://phpbuilder.com/columns/alberto20000919.php3
17 //----------------------------------------------------------------
18 // MSSQL returns dates with the format Oct 13 2002 or 13 Oct 2002
19 // and this causes tons of problems because localized versions of
20 // MSSQL will return the dates in dmy or mdy order; and also the
21 // month strings depends on what language has been configured. The
22 // following two variables allow you to control the localization
25 // MORE LOCALIZATION INFO
26 // ----------------------
27 // To configure datetime, look for and modify sqlcommn.loc,
28 // typically found in c:\mssql\install
30 // http://support.microsoft.com/default.aspx?scid=kb;EN-US;q220918
32 // CONVERT(char(12),datecol,120)
33 //----------------------------------------------------------------
35 // has datetime converstion to YYYY-MM-DD format, and also mssql_fetch_assoc
36 if (ADODB_PHPVER >= 0x4300) {
37 // docs say 4.2.0, but testing shows only since 4.3.0 does it work!
38 @ini_set('mssql.datetimeconvert', 0);
40 global $ADODB_mssql_mths; // array, months must be upper-case
42 $ADODB_mssql_date_order = 'mdy';
43 $ADODB_mssql_mths = array(
44 'JAN' => 1, 'FEB' => 2, 'MAR' => 3, 'APR' => 4, 'MAY' => 5, 'JUN' => 6,
45 'JUL' => 7, 'AUG' => 8, 'SEP' => 9, 'OCT' => 10, 'NOV' => 11, 'DEC' => 12);
48 //---------------------------------------------------------------------------
49 // Call this to autoset $ADODB_mssql_date_order at the beginning of your code,
50 // just after you connect to the database. Supports mdy and dmy only.
51 // Not required for PHP 4.2.0 and above.
52 function AutoDetect_MSSQL_Date_Order($conn)
54 global $ADODB_mssql_date_order;
55 $adate = $conn->GetOne('select getdate()');
60 //ADOConnection::outp( "MSSQL: YYYY-MM-DD date format not supported currently");
62 $ADODB_mssql_date_order = 'dmy';
64 $ADODB_mssql_date_order = 'mdy';
68 class ADODB_mssql extends ADOConnection
70 var $databaseType = "mssql";
71 var $dataProvider = "mssql";
72 var $replaceQuote = "''"; // string to use to replace quotes
73 var $fmtDate = "'Y-m-d'";
74 var $fmtTimeStamp = "'Y-m-d h:i:sA'";
75 var $hasInsertID = true;
76 var $substr = "substring";
78 var $upperCase = 'upper';
79 var $hasAffectedRows = true;
80 var $metaDatabasesSQL = "select name from sysdatabases where name <> 'master'";
81 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'))";
82 var $metaColumnsSQL = # xtype==61 is datetime
83 "select c.name,t.name,c.length,
84 (case when c.xusertype=61 then 0 else c.xprec end),
85 (case when c.xusertype=61 then 0 else c.xscale end)
86 from syscolumns c join systypes t on t.xusertype=c.xusertype join sysobjects o on o.id=c.id where o.name='%s'";
87 var $hasTop = 'top'; // support mssql SELECT TOP 10 * FROM TABLE
89 var $sysDate = 'convert(datetime,convert(char,GetDate(),102),102)';
90 var $sysTimeStamp = 'GetDate()';
92 var $maxParameterLen = 4000;
93 var $arrayClass = 'ADORecordSet_array_mssql';
94 var $uniqueSort = true;
95 var $leftOuter = '*=';
96 var $rightOuter = '=*';
97 var $ansiOuter = true; // for mssql7 or later
98 var $poorAffectedRows = true;
99 var $identitySQL = 'select @@IDENTITY'; // 'select SCOPE_IDENTITY'; # for mssql 2000
100 var $uniqueOrderBy = true;
101 var $_bindInputArray = true;
103 function ADODB_mssql()
105 $this->_has_mssql_init = (strnatcmp(PHP_VERSION, '4.1.0') >= 0);
108 function ServerInfo()
110 global $ADODB_FETCH_MODE;
112 $stmt = $this->PrepareSP('sp_server_info');
114 if ($this->fetchMode === false) {
115 $savem = $ADODB_FETCH_MODE;
116 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
118 $savem = $this->SetFetchMode(ADODB_FETCH_NUM);
120 $this->Parameter($stmt, $val, 'attribute_id');
121 $row = $this->GetRow($stmt);
123 //$row = $this->GetRow("execute sp_server_info 2");
125 if ($this->fetchMode === false) {
126 $ADODB_FETCH_MODE = $savem;
128 $this->SetFetchMode($savem);
130 $arr['description'] = $row[2];
131 $arr['version'] = ADOConnection::_findvers($arr['description']);
135 function IfNull($field, $ifNull)
137 return " ISNULL($field, $ifNull) "; // if MS SQL Server
143 // Returns the last IDENTITY value inserted into an IDENTITY column in
144 // the same scope. A scope is a module -- a stored procedure, trigger,
145 // function, or batch. Thus, two statements are in the same scope if
146 // they are in the same stored procedure, function, or batch.
147 return $this->GetOne($this->identitySQL);
150 function _affectedrows()
152 return $this->GetOne('select @@rowcount');
155 var $_dropSeqSQL = "drop table %s";
157 function CreateSequence($seq = 'adodbseq', $start = 1)
160 $this->Execute("create table $seq (id float(53))");
161 $ok = $this->Execute("insert into $seq with (tablock,holdlock) values($start)");
163 $this->Execute('ROLLBACK TRANSACTION adodbseq');
166 $this->Execute('COMMIT TRANSACTION adodbseq');
170 function GenID($seq = 'adodbseq', $start = 1)
173 $this->Execute('BEGIN TRANSACTION adodbseq');
174 $ok = $this->Execute("update $seq with (tablock,holdlock) set id = id + 1");
176 $this->Execute("create table $seq (id float(53))");
177 $ok = $this->Execute("insert into $seq with (tablock,holdlock) values($start)");
179 $this->Execute('ROLLBACK TRANSACTION adodbseq');
182 $this->Execute('COMMIT TRANSACTION adodbseq');
185 $num = $this->GetOne("select id from $seq");
186 $this->Execute('COMMIT TRANSACTION adodbseq');
189 // in old implementation, pre 1.90, we returned GUID...
190 //return $this->GetOne("SELECT CONVERT(varchar(255), NEWID()) AS 'Char'");
193 function &SelectLimit($sql, $nrows = -1, $offset = -1, $inputarr = false, $secs2cache = 0)
195 if ($nrows > 0 && $offset <= 0) {
197 '/(^\s*select\s+(distinctrow|distinct)?)/i', '\\1 ' . $this->hasTop . " $nrows ", $sql);
198 $rs =& $this->Execute($sql, $inputarr);
200 $rs =& ADOConnection::SelectLimit($sql, $nrows, $offset, $inputarr, $secs2cache);
205 // Format date column in sql string given an input format that understands Y M D
206 function SQLDate($fmt, $col = false)
208 if (!$col) $col = $this->sysTimeStamp;
212 for ($i = 0; $i < $len; $i++) {
218 $s .= "datename(yyyy,$col)";
221 $s .= "convert(char(3),$col,0)";
224 $s .= "replace(str(month($col),2),' ','0')";
228 $s .= "datename(quarter,$col)";
232 $s .= "replace(str(day($col),2),' ','0')";
235 $s .= "substring(convert(char(14),$col,0),13,2)";
239 $s .= "replace(str(datepart(hh,$col),2),' ','0')";
243 $s .= "replace(str(datepart(mi,$col),2),' ','0')";
246 $s .= "replace(str(datepart(ss,$col),2),' ','0')";
250 $s .= "substring(convert(char(19),$col,0),18,2)";
256 $ch = substr($fmt, $i, 1);
258 $s .= $this->qstr($ch);
265 function BeginTrans()
267 if ($this->transOff) return true;
268 $this->transCnt += 1;
269 $this->Execute('BEGIN TRAN');
273 function CommitTrans($ok = true)
275 if ($this->transOff) return true;
276 if (!$ok) return $this->RollbackTrans();
277 if ($this->transCnt) $this->transCnt -= 1;
278 $this->Execute('COMMIT TRAN');
282 function RollbackTrans()
284 if ($this->transOff) return true;
285 if ($this->transCnt) $this->transCnt -= 1;
286 $this->Execute('ROLLBACK TRAN');
294 $this->RowLock('table1,table2','table1.id=33 and table2.id=table1.id'); # lock row 33 for both tables
296 # some operation on both tables table1 and table2
298 $this->CommitTrans();
300 See http://www.swynk.com/friends/achigrik/SQL70Locks.asp
302 function RowLock($tables, $where)
304 if (!$this->transCnt) $this->BeginTrans();
305 return $this->GetOne("select top 1 null as ignore from $tables with (ROWLOCK,HOLDLOCK) where $where");
308 function MetaForeignKeys($table, $owner = false, $upper = false)
310 global $ADODB_FETCH_MODE;
312 $save = $ADODB_FETCH_MODE;
313 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
314 $table = $this->qstr(strtoupper($table));
317 "select object_name(constid) as constraint_name,
318 col_name(fkeyid, fkey) as column_name,
319 object_name(rkeyid) as referenced_table_name,
320 col_name(rkeyid, rkey) as referenced_column_name
322 where upper(object_name(fkeyid)) = $table
323 order by constraint_name, referenced_table_name, keyno";
325 $constraints =& $this->GetArray($sql);
327 $ADODB_FETCH_MODE = $save;
330 foreach ($constraints as $constr) {
332 $arr[$constr[0]][$constr[2]][] = $constr[1] . '=' . $constr[3];
334 if (!$arr) return false;
338 foreach ($arr as $k => $v) {
339 foreach ($v as $a => $b) {
340 if ($upper) $a = strtoupper($a);
347 //From: Fernando Moreira <FMoreira@imediata.pt>
348 function MetaDatabases()
350 if (@mssql_select_db("master")) {
351 $qry = $this->metaDatabasesSQL;
352 if ($rs = @mssql_query($qry)) {
353 $tmpAr = $ar = array();
354 while ($tmpAr = @mssql_fetch_row($rs))
356 @mssql_select_db($this->databaseName);
362 @mssql_select_db($this->databaseName);
369 // "Stein-Aksel Basma" <basma@accelero.no>
370 // tested with MSSQL 2000
371 function MetaPrimaryKeys($table)
373 $sql = "select k.column_name from information_schema.key_column_usage k,
374 information_schema.table_constraints tc
375 where tc.constraint_name = k.constraint_name and tc.constraint_type =
376 'PRIMARY KEY' and k.table_name = '$table'";
378 $a = $this->GetCol($sql);
379 if ($a && sizeof($a) > 0) return $a;
383 function &MetaTables($ttype = false, $showSchema = false, $mask = false)
386 $save = $this->metaTablesSQL;
387 $mask = $this->qstr(($mask));
388 $this->metaTablesSQL .= " AND name like $mask";
390 $ret =& ADOConnection::MetaTables($ttype, $showSchema);
393 $this->metaTablesSQL = $save;
398 function SelectDB($dbName)
400 $this->databaseName = $dbName;
401 if ($this->_connectionID) {
402 return @mssql_select_db($dbName);
408 if (empty($this->_errorMsg)) {
409 $this->_errorMsg = mssql_get_last_message();
411 return $this->_errorMsg;
416 if ($this->_logsql && $this->_errorCode !== false) return $this->_errorCode;
417 if (empty($this->_errorMsg)) {
418 $this->_errorMsg = mssql_get_last_message();
420 $id = @mssql_query("select @@ERROR", $this->_connectionID);
421 if (!$id) return false;
422 $arr = mssql_fetch_array($id);
423 @mssql_free_result($id);
424 if (is_array($arr)) return $arr[0];
428 // returns true or false
429 function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)
431 if (!function_exists('mssql_pconnect')) return false;
432 $this->_connectionID = mssql_connect($argHostname, $argUsername, $argPassword);
433 if ($this->_connectionID === false) return false;
434 if ($argDatabasename) return $this->SelectDB($argDatabasename);
438 // returns true or false
439 function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
441 if (!function_exists('mssql_pconnect')) return false;
442 $this->_connectionID = mssql_pconnect($argHostname, $argUsername, $argPassword);
443 if ($this->_connectionID === false) return false;
445 // persistent connections can forget to rollback on crash, so we do it here.
446 if ($this->autoRollback) {
447 $cnt = $this->GetOne('select @@TRANCOUNT');
448 while (--$cnt >= 0) $this->Execute('ROLLBACK TRAN');
450 if ($argDatabasename) return $this->SelectDB($argDatabasename);
454 function Prepare($sql)
456 $sqlarr = explode('?', $sql);
457 if (sizeof($sqlarr) <= 1) return $sql;
459 for ($i = 1, $max = sizeof($sqlarr); $i < $max; $i++) {
460 $sql2 .= '@P' . ($i - 1) . $sqlarr[$i];
462 return array($sql, $this->qstr($sql2), $max);
465 function PrepareSP($sql)
467 if (!$this->_has_mssql_init) {
468 ADOConnection::outp("PrepareSP: mssql_init only available since PHP 4.1.0");
471 $stmt = mssql_init($sql, $this->_connectionID);
472 if (!$stmt) return $sql;
473 return array($sql, $stmt);
478 $stmt = $db->PrepareSP('SP_RUNSOMETHING'); -- takes 2 params, @myid and @group
480 # note that the parameter does not have @ in front!
481 $db->Parameter($stmt,$id,'myid');
482 $db->Parameter($stmt,$group,'group',false,64);
485 @param $stmt Statement returned by Prepare() or PrepareSP().
486 @param $var PHP variable to bind to. Can set to null (for isNull support).
487 @param $name Name of stored procedure variable name to bind to.
488 @param [$isOutput] Indicates direction of parameter 0/false=IN 1=OUT 2= IN/OUT. This is ignored in oci8.
489 @param [$maxLen] Holds an maximum length of the variable.
490 @param [$type] The data type of $var. Legal values depend on driver.
492 See mssql_bind documentation at php.net.
494 function Parameter(&$stmt, &$var, $name, $isOutput = false, $maxLen = 4000, $type = false)
496 if (!$this->_has_mssql_init) {
497 ADOConnection::outp("Parameter: mssql_bind only available since PHP 4.1.0");
501 $isNull = is_null($var); // php 4.0.4 and above...
504 switch (gettype($var)) {
517 break; # SQLBIT not supported in 4.1.0
521 $prefix = ($isOutput) ? 'Out' : 'In';
522 $ztype = (empty($type)) ? 'false' : $type;
523 ADOConnection::outp("{$prefix}Parameter(\$stmt, \$php_var='$var', \$name='$name', \$maxLen=$maxLen, \$type=$ztype);");
526 See http://phplens.com/lens/lensforum/msgs.php?id=7231
528 RETVAL is HARD CODED into php_mssql extension:
529 The return value (a long integer value) is treated like a special OUTPUT parameter,
530 called "RETVAL" (without the @). See the example at mssql_execute to
531 see how it works. - type: one of this new supported PHP constants.
532 SQLTEXT, SQLVARCHAR,SQLCHAR, SQLINT1,SQLINT2, SQLINT4, SQLBIT,SQLFLT8
534 if ($name !== 'RETVAL') $name = '@' . $name;
535 return mssql_bind($stmt[1], $name, $var, $type, $isOutput, $isNull, $maxLen);
539 Unfortunately, it appears that mssql cannot handle varbinary > 255 chars
540 So all your blobs must be of type "image".
542 Remember to set in php.ini the following...
544 ; Valid range 0 - 2147483647. Default = 4096.
545 mssql.textlimit = 0 ; zero to pass through
547 ; Valid range 0 - 2147483647. Default = 4096.
548 mssql.textsize = 0 ; zero to pass through
550 function UpdateBlob($table, $column, $val, $where, $blobtype = 'BLOB')
552 $sql = "UPDATE $table SET $column=0x" . bin2hex($val) . " WHERE $where";
553 return $this->Execute($sql) != false;
556 // returns query ID if successful, otherwise false
557 function _query($sql, $inputarr)
559 $this->_errorMsg = false;
560 if (is_array($inputarr)) {
562 # bind input params with sp_executesql:
563 # see http://www.quest-pipelines.com/newsletter-v3/0402_F.htm
564 # works only with sql server 7 and newer
565 if (!is_array($sql)) $sql = $this->Prepare($sql);
569 foreach ($inputarr as $v) {
576 if ($len == 0) $len = 1;
579 // NVARCHAR is max 4000 chars. Let's use NTEXT
580 $decl .= "@P$i NTEXT";
582 $decl .= "@P$i NVARCHAR($len)";
585 $params .= "@P$i=N" . (strncmp($v, "'", 1) == 0 ? $v : $this->qstr($v));
586 } elseif (is_integer($v)) {
588 $params .= "@P$i=" . $v;
590 $decl .= "@P$i FLOAT";
591 $params .= "@P$i=" . $v;
595 $decl = $this->qstr($decl);
596 if ($this->debug) ADOConnection::outp("<font size=-1>sp_executesql N{$sql[1]},N$decl,$params</font>");
597 $rez = mssql_query("sp_executesql N{$sql[1]},N$decl,$params");
599 } elseif (is_array($sql)) {
601 $rez = mssql_execute($sql[1]);
604 $rez = mssql_query($sql, $this->_connectionID);
609 // returns true or false
612 if ($this->transCnt) $this->RollbackTrans();
613 $rez = @mssql_close($this->_connectionID);
614 $this->_connectionID = false;
618 // mssql uses a default date like Dec 30 2000 12:00AM
619 function UnixDate($v)
621 return ADORecordSet_array_mssql::UnixDate($v);
624 function UnixTimeStamp($v)
626 return ADORecordSet_array_mssql::UnixTimeStamp($v);
630 /*--------------------------------------------------------------------------------------
631 Class Name: Recordset
632 --------------------------------------------------------------------------------------*/
634 class ADORecordset_mssql extends ADORecordSet
637 var $databaseType = "mssql";
639 var $hasFetchAssoc; // see http://phplens.com/lens/lensforum/msgs.php?id=6083
640 // _mths works only in non-localised system
642 function ADORecordset_mssql($id, $mode = false)
645 $this->hasFetchAssoc = function_exists('mssql_fetch_assoc');
647 if ($mode === false) {
648 global $ADODB_FETCH_MODE;
649 $mode = $ADODB_FETCH_MODE;
651 $this->fetchMode = $mode;
652 return $this->ADORecordSet($id, $mode);
658 GLOBAL $ADODB_COUNTRECS;
659 $this->_numOfRows = ($ADODB_COUNTRECS) ? @mssql_num_rows($this->_queryID) : -1;
660 $this->_numOfFields = @mssql_num_fields($this->_queryID);
664 //Contributed by "Sven Axelsson" <sven.axelsson@bokochwebb.se>
665 // get next resultset - requires PHP 4.0.5 or later
666 function NextRecordSet()
668 if (!mssql_next_result($this->_queryID)) return false;
669 $this->_inited = false;
671 $this->_currentRow = -1;
676 /* Use associative array to get fields array */
677 function Fields($colname)
679 if ($this->fetchMode != ADODB_FETCH_NUM) return $this->fields[$colname];
681 $this->bind = array();
682 for ($i = 0; $i < $this->_numOfFields; $i++) {
683 $o = $this->FetchField($i);
684 $this->bind[strtoupper($o->name)] = $i;
688 return $this->fields[$this->bind[strtoupper($colname)]];
691 /* Returns: an object containing field information.
692 Get column information in the Recordset object. fetchField() can be used in order to obtain information about
693 fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by
694 fetchField() is retrieved. */
696 function FetchField($fieldOffset = -1)
698 if ($fieldOffset != -1) {
699 return @mssql_fetch_field($this->_queryID, $fieldOffset);
700 } else if ($fieldOffset == -1) { /* The $fieldOffset argument is not provided thus its -1 */
701 return @mssql_fetch_field($this->_queryID);
708 return @mssql_data_seek($this->_queryID, $row);
714 if ($this->EOF) return false;
716 $this->_currentRow++;
718 if ($this->fetchMode & ADODB_FETCH_ASSOC) {
719 if ($this->fetchMode & ADODB_FETCH_NUM) {
720 //ADODB_FETCH_BOTH mode
721 $this->fields = @mssql_fetch_array($this->_queryID);
723 if ($this->hasFetchAssoc) { // only for PHP 4.2.0 or later
724 $this->fields = @mssql_fetch_assoc($this->_queryID);
726 $flds = @mssql_fetch_array($this->_queryID);
727 if (is_array($flds)) {
729 foreach ($flds as $k => $v) {
730 if (is_numeric($k)) continue;
733 $this->fields = $fassoc;
735 $this->fields = false;
739 if (is_array($this->fields)) {
740 if (ADODB_ASSOC_CASE == 0) {
741 foreach ($this->fields as $k => $v) {
742 $this->fields[strtolower($k)] = $v;
744 } elseif (ADODB_ASSOC_CASE == 1) {
745 foreach ($this->fields as $k => $v) {
746 $this->fields[strtoupper($k)] = $v;
751 $this->fields = @mssql_fetch_row($this->_queryID);
753 if ($this->fields) return true;
760 // INSERT UPDATE DELETE returns false even if no error occurs in 4.0.4
761 // also the date format has been changed from YYYY-mm-dd to dd MMM YYYY in 4.0.4. Idiot!
762 function _fetch($ignore_fields = false)
764 if ($this->fetchMode & ADODB_FETCH_ASSOC) {
765 if ($this->fetchMode & ADODB_FETCH_NUM) {
766 //ADODB_FETCH_BOTH mode
767 $this->fields = @mssql_fetch_array($this->_queryID);
769 if ($this->hasFetchAssoc) // only for PHP 4.2.0 or later
770 $this->fields = @mssql_fetch_assoc($this->_queryID);
772 $this->fields = @mssql_fetch_array($this->_queryID);
773 if (is_array($$this->fields)) {
775 foreach ($$this->fields as $k => $v) {
776 if (is_integer($k)) continue;
779 $this->fields = $fassoc;
784 if (!$this->fields) {
785 } elseif (ADODB_ASSOC_CASE == 0) {
786 foreach ($this->fields as $k => $v) {
787 $this->fields[strtolower($k)] = $v;
789 } elseif (ADODB_ASSOC_CASE == 1) {
790 foreach ($this->fields as $k => $v) {
791 $this->fields[strtoupper($k)] = $v;
795 $this->fields = @mssql_fetch_row($this->_queryID);
797 return $this->fields;
800 /* close() only needs to be called if you are worried about using too much memory while your script
801 is running. All associated result memory for the specified result identifier will automatically be freed. */
805 $rez = mssql_free_result($this->_queryID);
806 $this->_queryID = false;
810 // mssql uses a default date like Dec 30 2000 12:00AM
811 function UnixDate($v)
813 return ADORecordSet_array_mssql::UnixDate($v);
816 function UnixTimeStamp($v)
818 return ADORecordSet_array_mssql::UnixTimeStamp($v);
824 class ADORecordSet_array_mssql extends ADORecordSet_array
826 function ADORecordSet_array_mssql($id = -1, $mode = false)
828 $this->ADORecordSet_array($id, $mode);
831 // mssql uses a default date like Dec 30 2000 12:00AM
832 function UnixDate($v)
835 if (is_numeric(substr($v, 0, 1)) && ADODB_PHPVER >= 0x4200) return parent::UnixDate($v);
837 global $ADODB_mssql_mths, $ADODB_mssql_date_order;
839 //Dec 30 2000 12:00AM
840 if ($ADODB_mssql_date_order == 'dmy') {
841 if (!preg_match("|^([0-9]{1,2})[-/\. ]+([A-Za-z]{3})[-/\. ]+([0-9]{4})|", $v, $rr)) {
842 return parent::UnixDate($v);
844 if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
847 $themth = substr(strtoupper($rr[2]), 0, 3);
849 if (!preg_match("|^([A-Za-z]{3})[-/\. ]+([0-9]{1,2})[-/\. ]+([0-9]{4})|", $v, $rr)) {
850 return parent::UnixDate($v);
852 if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
855 $themth = substr(strtoupper($rr[1]), 0, 3);
857 $themth = $ADODB_mssql_mths[$themth];
858 if ($themth <= 0) return false;
860 return mktime(0, 0, 0, $themth, $theday, $rr[3]);
863 function UnixTimeStamp($v)
866 if (is_numeric(substr($v, 0, 1)) && ADODB_PHPVER >= 0x4200) return parent::UnixTimeStamp($v);
868 global $ADODB_mssql_mths, $ADODB_mssql_date_order;
870 //Dec 30 2000 12:00AM
871 if ($ADODB_mssql_date_order == 'dmy') {
872 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})|"
874 ) return parent::UnixTimeStamp($v);
875 if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
878 $themth = substr(strtoupper($rr[2]), 0, 3);
880 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})|"
882 ) return parent::UnixTimeStamp($v);
883 if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
886 $themth = substr(strtoupper($rr[1]), 0, 3);
889 $themth = $ADODB_mssql_mths[$themth];
890 if ($themth <= 0) return false;
892 switch (strtoupper($rr[6])) {
894 if ($rr[4] < 12) $rr[4] += 12;
897 if ($rr[4] == 12) $rr[4] = 0;
903 return mktime($rr[4], $rr[5], 0, $themth, $theday, $rr[3]);
910 select object_name(constid) as constraint_name,
911 object_name(fkeyid) as table_name,
912 col_name(fkeyid, fkey) as column_name,
913 object_name(rkeyid) as referenced_table_name,
914 col_name(rkeyid, rkey) as referenced_column_name
916 where object_name(fkeyid) = x
917 order by constraint_name, table_name, referenced_table_name, keyno
920 select constraint_name,
923 from information_schema.key_column_usage
924 where constraint_catalog = db_name()
926 order by constraint_name, ordinal_position
928 http://www.databasejournal.com/scripts/article.php/1440551