source: trunk/phpgwapi/inc/adodb/drivers/adodb-mssql.inc.php @ 2

Revision 2, 27.1 KB checked in by niltonneto, 17 years ago (diff)

Removida todas as tags usadas pelo CVS ($Id, $Source).
Primeira versão no CVS externo.

  • Property svn:eol-style set to native
  • Property svn:executable set to *
Line 
1<?php
2/*
3V4.51 29 July 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.
7Set 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  To configure for Unix, see
13        http://phpbuilder.com/columns/alberto20000919.php3
14       
15*/
16
17// security - hide paths
18if (!defined('ADODB_DIR')) die();
19
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
26// settings - Ugh.
27//
28// MORE LOCALIZATION INFO
29// ----------------------
30// To configure datetime, look for and modify sqlcommn.loc,
31//      typically found in c:\mssql\install
32// Also read :
33//       http://support.microsoft.com/default.aspx?scid=kb;EN-US;q220918
34// Alternatively use:
35//         CONVERT(char(12),datecol,120)
36//----------------------------------------------------------------
37
38
39// has datetime converstion to YYYY-MM-DD format, and also mssql_fetch_assoc
40if (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);
43} else {
44global $ADODB_mssql_mths;               // array, months must be upper-case
45
46
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);
51}
52
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.
57function AutoDetect_MSSQL_Date_Order($conn)
58{
59global $ADODB_mssql_date_order;
60        $adate = $conn->GetOne('select getdate()');
61        if ($adate) {
62                $anum = (int) $adate;
63                if ($anum > 0) {
64                        if ($anum > 31) {
65                                //ADOConnection::outp( "MSSQL: YYYY-MM-DD date format not supported currently");
66                        } else
67                                $ADODB_mssql_date_order = 'dmy';
68                } else
69                        $ADODB_mssql_date_order = 'mdy';
70        }
71}
72
73class 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:sA'";
79        var $hasInsertID = true;
80        var $substr = "substring";
81        var $length = 'len';
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
91        var $hasGenID = true;
92        var $sysDate = 'convert(datetime,convert(char,GetDate(),102),102)';
93        var $sysTimeStamp = 'GetDate()';
94        var $_has_mssql_init;
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;
105       
106       
107        function ADODB_mssql()
108        {               
109                $this->_has_mssql_init = (strnatcmp(PHP_VERSION,'4.1.0')>=0);
110        }
111
112        function ServerInfo()
113        {
114        global $ADODB_FETCH_MODE;
115       
116                $stmt = $this->PrepareSP('sp_server_info');
117                $val = 2;
118                if ($this->fetchMode === false) {
119                        $savem = $ADODB_FETCH_MODE;
120                        $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
121                } else
122                        $savem = $this->SetFetchMode(ADODB_FETCH_NUM);
123               
124               
125                $this->Parameter($stmt,$val,'attribute_id');
126                $row = $this->GetRow($stmt);
127               
128                //$row = $this->GetRow("execute sp_server_info 2");
129               
130                if ($this->fetchMode === false) {
131                        $ADODB_FETCH_MODE = $savem;
132                } else
133                        $this->SetFetchMode($savem);
134               
135                $arr['description'] = $row[2];
136                $arr['version'] = ADOConnection::_findvers($arr['description']);
137                return $arr;
138        }
139       
140        function IfNull( $field, $ifNull )
141        {
142                return " ISNULL($field, $ifNull) "; // if MS SQL Server
143        }
144       
145        function _insertid()
146        {
147        // SCOPE_IDENTITY()
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);
153        }
154
155        function _affectedrows()
156        {
157                return $this->GetOne('select @@rowcount');
158        }
159
160        var $_dropSeqSQL = "drop table %s";
161       
162        function CreateSequence($seq='adodbseq',$start=1)
163        {
164                $start -= 1;
165                $this->Execute("create table $seq (id float(53))");
166                $ok = $this->Execute("insert into $seq with (tablock,holdlock) values($start)");
167                if (!$ok) {
168                                $this->Execute('ROLLBACK TRANSACTION adodbseq');
169                                return false;
170                }
171                $this->Execute('COMMIT TRANSACTION adodbseq');
172                return true;
173        }
174
175        function GenID($seq='adodbseq',$start=1)
176        {
177                //$this->debug=1;
178                $this->Execute('BEGIN TRANSACTION adodbseq');
179                $ok = $this->Execute("update $seq with (tablock,holdlock) set id = id + 1");
180                if (!$ok) {
181                        $this->Execute("create table $seq (id float(53))");
182                        $ok = $this->Execute("insert into $seq with (tablock,holdlock) values($start)");
183                        if (!$ok) {
184                                $this->Execute('ROLLBACK TRANSACTION adodbseq');
185                                return false;
186                        }
187                        $this->Execute('COMMIT TRANSACTION adodbseq');
188                        return $start;
189                }
190                $num = $this->GetOne("select id from $seq");
191                $this->Execute('COMMIT TRANSACTION adodbseq');
192                return $num;
193               
194                // in old implementation, pre 1.90, we returned GUID...
195                //return $this->GetOne("SELECT CONVERT(varchar(255), NEWID()) AS 'Char'");
196        }
197       
198
199        function &SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0)
200        {
201                if ($nrows > 0 && $offset <= 0) {
202                        $sql = preg_replace(
203                                '/(^\s*select\s+(distinctrow|distinct)?)/i','\\1 '.$this->hasTop." $nrows ",$sql);
204                        $rs =& $this->Execute($sql,$inputarr);
205                } else
206                        $rs =& ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);
207       
208                return $rs;
209        }
210       
211       
212        // Format date column in sql string given an input format that understands Y M D
213        function SQLDate($fmt, $col=false)
214        {       
215                if (!$col) $col = $this->sysTimeStamp;
216                $s = '';
217               
218                $len = strlen($fmt);
219                for ($i=0; $i < $len; $i++) {
220                        if ($s) $s .= '+';
221                        $ch = $fmt[$i];
222                        switch($ch) {
223                        case 'Y':
224                        case 'y':
225                                $s .= "datename(yyyy,$col)";
226                                break;
227                        case 'M':
228                                $s .= "convert(char(3),$col,0)";
229                                break;
230                        case 'm':
231                                $s .= "replace(str(month($col),2),' ','0')";
232                                break;
233                        case 'Q':
234                        case 'q':
235                                $s .= "datename(quarter,$col)";
236                                break;
237                        case 'D':
238                        case 'd':
239                                $s .= "replace(str(day($col),2),' ','0')";
240                                break;
241                        case 'h':
242                                $s .= "substring(convert(char(14),$col,0),13,2)";
243                                break;
244                       
245                        case 'H':
246                                $s .= "replace(str(datepart(hh,$col),2),' ','0')";
247                                break;
248                               
249                        case 'i':
250                                $s .= "replace(str(datepart(mi,$col),2),' ','0')";
251                                break;
252                        case 's':
253                                $s .= "replace(str(datepart(ss,$col),2),' ','0')";
254                                break;
255                        case 'a':
256                        case 'A':
257                                $s .= "substring(convert(char(19),$col,0),18,2)";
258                                break;
259                               
260                        default:
261                                if ($ch == '\\') {
262                                        $i++;
263                                        $ch = substr($fmt,$i,1);
264                                }
265                                $s .= $this->qstr($ch);
266                                break;
267                        }
268                }
269                return $s;
270        }
271
272       
273        function BeginTrans()
274        {
275                if ($this->transOff) return true;
276                $this->transCnt += 1;
277                $this->Execute('BEGIN TRAN');
278                return true;
279        }
280               
281        function CommitTrans($ok=true)
282        {
283                if ($this->transOff) return true;
284                if (!$ok) return $this->RollbackTrans();
285                if ($this->transCnt) $this->transCnt -= 1;
286                $this->Execute('COMMIT TRAN');
287                return true;
288        }
289        function RollbackTrans()
290        {
291                if ($this->transOff) return true;
292                if ($this->transCnt) $this->transCnt -= 1;
293                $this->Execute('ROLLBACK TRAN');
294                return true;
295        }
296       
297        /*
298                Usage:
299               
300                $this->BeginTrans();
301                $this->RowLock('table1,table2','table1.id=33 and table2.id=table1.id'); # lock row 33 for both tables
302               
303                # some operation on both tables table1 and table2
304               
305                $this->CommitTrans();
306               
307                See http://www.swynk.com/friends/achigrik/SQL70Locks.asp
308        */
309        function RowLock($tables,$where)
310        {
311                if (!$this->transCnt) $this->BeginTrans();
312                return $this->GetOne("select top 1 null as ignore from $tables with (ROWLOCK,HOLDLOCK) where $where");
313        }
314       
315        function MetaForeignKeys($table, $owner=false, $upper=false)
316        {
317        global $ADODB_FETCH_MODE;
318       
319                $save = $ADODB_FETCH_MODE;
320                $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
321                $table = $this->qstr(strtoupper($table));
322               
323                $sql =
324"select object_name(constid) as constraint_name,
325        col_name(fkeyid, fkey) as column_name,
326        object_name(rkeyid) as referenced_table_name,
327        col_name(rkeyid, rkey) as referenced_column_name
328from sysforeignkeys
329where upper(object_name(fkeyid)) = $table
330order by constraint_name, referenced_table_name, keyno";
331               
332                $constraints =& $this->GetArray($sql);
333               
334                $ADODB_FETCH_MODE = $save;
335               
336                $arr = false;
337                foreach($constraints as $constr) {
338                        //print_r($constr);
339                        $arr[$constr[0]][$constr[2]][] = $constr[1].'='.$constr[3];
340                }
341                if (!$arr) return false;
342               
343                $arr2 = false;
344               
345                foreach($arr as $k => $v) {
346                        foreach($v as $a => $b) {
347                                if ($upper) $a = strtoupper($a);
348                                $arr2[$a] = $b;
349                        }
350                }
351                return $arr2;
352        }
353
354        //From: Fernando Moreira <FMoreira@imediata.pt>
355        function MetaDatabases()
356        {
357                if(@mssql_select_db("master")) {
358                                 $qry=$this->metaDatabasesSQL;
359                                 if($rs=@mssql_query($qry)){
360                                                 $tmpAr=$ar=array();
361                                                 while($tmpAr=@mssql_fetch_row($rs))
362                                                                 $ar[]=$tmpAr[0];
363                                                @mssql_select_db($this->databaseName);
364                                                 if(sizeof($ar))
365                                                                 return($ar);
366                                                 else
367                                                                 return(false);
368                                 } else {
369                                                 @mssql_select_db($this->databaseName);
370                                                 return(false);
371                                 }
372                 }
373                 return(false);
374        }
375
376        // "Stein-Aksel Basma" <basma@accelero.no>
377        // tested with MSSQL 2000
378        function &MetaPrimaryKeys($table)
379        {
380        global $ADODB_FETCH_MODE;
381       
382                $schema = '';
383                $this->_findschema($table,$schema);
384                if (!$schema) $schema = $this->database;
385                if ($schema) $schema = "and k.table_catalog like '$schema%'";
386
387                $sql = "select distinct k.column_name,ordinal_position from information_schema.key_column_usage k,
388                information_schema.table_constraints tc
389                where tc.constraint_name = k.constraint_name and tc.constraint_type =
390                'PRIMARY KEY' and k.table_name = '$table' $schema order by ordinal_position ";
391               
392                $savem = $ADODB_FETCH_MODE;
393                $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
394                $a = $this->GetCol($sql);
395                $ADODB_FETCH_MODE = $savem;
396               
397                if ($a && sizeof($a)>0) return $a;
398                return false;     
399        }
400
401       
402        function &MetaTables($ttype=false,$showSchema=false,$mask=false)
403        {
404                if ($mask) {
405                        $save = $this->metaTablesSQL;
406                        $mask = $this->qstr(($mask));
407                        $this->metaTablesSQL .= " AND name like $mask";
408                }
409                $ret =& ADOConnection::MetaTables($ttype,$showSchema);
410               
411                if ($mask) {
412                        $this->metaTablesSQL = $save;
413                }
414                return $ret;
415        }
416 
417        function SelectDB($dbName)
418        {
419                $this->databaseName = $dbName;
420                if ($this->_connectionID) {
421                        return @mssql_select_db($dbName);               
422                }
423                else return false;     
424        }
425       
426        function ErrorMsg()
427        {
428                if (empty($this->_errorMsg)){
429                        $this->_errorMsg = mssql_get_last_message();
430                }
431                return $this->_errorMsg;
432        }
433       
434        function ErrorNo()
435        {
436                if ($this->_logsql && $this->_errorCode !== false) return $this->_errorCode;
437                if (empty($this->_errorMsg)) {
438                        $this->_errorMsg = mssql_get_last_message();
439                }
440                $id = @mssql_query("select @@ERROR",$this->_connectionID);
441                if (!$id) return false;
442                $arr = mssql_fetch_array($id);
443                @mssql_free_result($id);
444                if (is_array($arr)) return $arr[0];
445           else return -1;
446        }
447       
448        // returns true or false
449        function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)
450        {
451                if (!function_exists('mssql_pconnect')) return null;
452                $this->_connectionID = mssql_connect($argHostname,$argUsername,$argPassword);
453                if ($this->_connectionID === false) return false;
454                if ($argDatabasename) return $this->SelectDB($argDatabasename);
455                return true;   
456        }
457       
458       
459        // returns true or false
460        function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
461        {
462                if (!function_exists('mssql_pconnect')) return null;
463                $this->_connectionID = mssql_pconnect($argHostname,$argUsername,$argPassword);
464                if ($this->_connectionID === false) return false;
465               
466                // persistent connections can forget to rollback on crash, so we do it here.
467                if ($this->autoRollback) {
468                        $cnt = $this->GetOne('select @@TRANCOUNT');
469                        while (--$cnt >= 0) $this->Execute('ROLLBACK TRAN');
470                }
471                if ($argDatabasename) return $this->SelectDB($argDatabasename);
472                return true;   
473        }
474       
475        function Prepare($sql)
476        {
477                $sqlarr = explode('?',$sql);
478                if (sizeof($sqlarr) <= 1) return $sql;
479                $sql2 = $sqlarr[0];
480                for ($i = 1, $max = sizeof($sqlarr); $i < $max; $i++) {
481                        $sql2 .=  '@P'.($i-1) . $sqlarr[$i];
482                }
483                return array($sql,$this->qstr($sql2),$max);
484        }
485       
486        function PrepareSP($sql)
487        {
488                if (!$this->_has_mssql_init) {
489                        ADOConnection::outp( "PrepareSP: mssql_init only available since PHP 4.1.0");
490                        return $sql;
491                }
492                $stmt = mssql_init($sql,$this->_connectionID);
493                if (!$stmt)  return $sql;
494                return array($sql,$stmt);
495        }
496       
497        /*
498        Usage:
499                $stmt = $db->PrepareSP('SP_RUNSOMETHING'); -- takes 2 params, @myid and @group
500               
501                # note that the parameter does not have @ in front!
502                $db->Parameter($stmt,$id,'myid');
503                $db->Parameter($stmt,$group,'group',false,64);
504                $db->Execute($stmt);
505               
506                @param $stmt Statement returned by Prepare() or PrepareSP().
507                @param $var PHP variable to bind to. Can set to null (for isNull support).
508                @param $name Name of stored procedure variable name to bind to.
509                @param [$isOutput] Indicates direction of parameter 0/false=IN  1=OUT  2= IN/OUT. This is ignored in oci8.
510                @param [$maxLen] Holds an maximum length of the variable.
511                @param [$type] The data type of $var. Legal values depend on driver.
512               
513                See mssql_bind documentation at php.net.
514        */
515        function Parameter(&$stmt, &$var, $name, $isOutput=false, $maxLen=4000, $type=false)
516        {
517                if (!$this->_has_mssql_init) {
518                        ADOConnection::outp( "Parameter: mssql_bind only available since PHP 4.1.0");
519                        return $sql;
520                }
521
522                $isNull = is_null($var); // php 4.0.4 and above...
523                       
524                if ($type === false)
525                        switch(gettype($var)) {
526                        default:
527                        case 'string': $type = SQLCHAR; break;
528                        case 'double': $type = SQLFLT8; break;
529                        case 'integer': $type = SQLINT4; break;
530                        case 'boolean': $type = SQLINT1; break; # SQLBIT not supported in 4.1.0
531                        }
532               
533                if  ($this->debug) {
534                        $prefix = ($isOutput) ? 'Out' : 'In';
535                        $ztype = (empty($type)) ? 'false' : $type;
536                        ADOConnection::outp( "{$prefix}Parameter(\$stmt, \$php_var='$var', \$name='$name', \$maxLen=$maxLen, \$type=$ztype);");
537                }
538                /*
539                        See http://phplens.com/lens/lensforum/msgs.php?id=7231
540                       
541                        RETVAL is HARD CODED into php_mssql extension:
542                        The return value (a long integer value) is treated like a special OUTPUT parameter,
543                        called "RETVAL" (without the @). See the example at mssql_execute to
544                        see how it works. - type: one of this new supported PHP constants.
545                                SQLTEXT, SQLVARCHAR,SQLCHAR, SQLINT1,SQLINT2, SQLINT4, SQLBIT,SQLFLT8
546                */
547                if ($name !== 'RETVAL') $name = '@'.$name;
548                return mssql_bind($stmt[1], $name, $var, $type, $isOutput, $isNull, $maxLen);
549        }
550       
551        /*
552                Unfortunately, it appears that mssql cannot handle varbinary > 255 chars
553                So all your blobs must be of type "image".
554               
555                Remember to set in php.ini the following...
556               
557                ; Valid range 0 - 2147483647. Default = 4096.
558                mssql.textlimit = 0 ; zero to pass through
559
560                ; Valid range 0 - 2147483647. Default = 4096.
561                mssql.textsize = 0 ; zero to pass through
562        */
563        function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
564        {
565       
566                if (strtoupper($blobtype) == 'CLOB') {
567                        $sql = "UPDATE $table SET $column='" . $val . "' WHERE $where";
568                        return $this->Execute($sql) != false;
569                }
570                $sql = "UPDATE $table SET $column=0x".bin2hex($val)." WHERE $where";
571                return $this->Execute($sql) != false;
572        }
573       
574        // returns query ID if successful, otherwise false
575        function _query($sql,$inputarr)
576        {
577                $this->_errorMsg = false;
578                if (is_array($inputarr)) {
579                       
580                        # bind input params with sp_executesql:
581                        # see http://www.quest-pipelines.com/newsletter-v3/0402_F.htm
582                        # works only with sql server 7 and newer
583                        if (!is_array($sql)) $sql = $this->Prepare($sql);
584                        $params = '';
585                        $decl = '';
586                        $i = 0;
587                        foreach($inputarr as $v) {
588                                if ($decl) {
589                                        $decl .= ', ';
590                                        $params .= ', ';
591                                }       
592                                if (is_string($v)) {
593                                        $len = strlen($v);
594                                        if ($len == 0) $len = 1;
595                                       
596                                        if ($len > 4000 ) {
597                                                // NVARCHAR is max 4000 chars. Let's use NTEXT
598                                                $decl .= "@P$i NTEXT";
599                                        } else {
600                                                $decl .= "@P$i NVARCHAR($len)";
601                                        }
602
603                                        $params .= "@P$i=N". (strncmp($v,"'",1)==0? $v : $this->qstr($v));
604                                } else if (is_integer($v)) {
605                                        $decl .= "@P$i INT";
606                                        $params .= "@P$i=".$v;
607                                } else if (is_float($v)) {
608                                        $decl .= "@P$i FLOAT";
609                                        $params .= "@P$i=".$v;
610                                } else if (is_bool($v)) {
611                                        $decl .= "@P$i INT"; # Used INT just in case BIT in not supported on the user's MSSQL version. It will cast appropriately.
612                                        $params .= "@P$i=".(($v)?'1':'0'); # True == 1 in MSSQL BIT fields and acceptable for storing logical true in an int field
613                                } else {
614                                        $decl .= "@P$i CHAR"; # Used char because a type is required even when the value is to be NULL.
615                                        $params .= "@P$i=NULL";
616                                        }
617                                $i += 1;
618                        }
619                        $decl = $this->qstr($decl);
620                        if ($this->debug) ADOConnection::outp("<font size=-1>sp_executesql N{$sql[1]},N$decl,$params</font>");
621                        $rez = mssql_query("sp_executesql N{$sql[1]},N$decl,$params");
622                       
623                } else if (is_array($sql)) {
624                        # PrepareSP()
625                        $rez = mssql_execute($sql[1]);
626                       
627                } else {
628                        $rez = mssql_query($sql,$this->_connectionID);
629                }
630                return $rez;
631        }
632       
633        // returns true or false
634        function _close()
635        {
636                if ($this->transCnt) $this->RollbackTrans();
637                $rez = @mssql_close($this->_connectionID);
638                $this->_connectionID = false;
639                return $rez;
640        }
641       
642        // mssql uses a default date like Dec 30 2000 12:00AM
643        function UnixDate($v)
644        {
645                return ADORecordSet_array_mssql::UnixDate($v);
646        }
647       
648        function UnixTimeStamp($v)
649        {
650                return ADORecordSet_array_mssql::UnixTimeStamp($v);
651        }       
652}
653       
654/*--------------------------------------------------------------------------------------
655         Class Name: Recordset
656--------------------------------------------------------------------------------------*/
657
658class ADORecordset_mssql extends ADORecordSet {
659
660        var $databaseType = "mssql";
661        var $canSeek = true;
662        var $hasFetchAssoc; // see http://phplens.com/lens/lensforum/msgs.php?id=6083
663        // _mths works only in non-localised system
664       
665        function ADORecordset_mssql($id,$mode=false)
666        {
667                // freedts check...
668                $this->hasFetchAssoc = function_exists('mssql_fetch_assoc');
669
670                if ($mode === false) {
671                        global $ADODB_FETCH_MODE;
672                        $mode = $ADODB_FETCH_MODE;
673                }
674                $this->fetchMode = $mode;
675                return $this->ADORecordSet($id,$mode);
676        }
677       
678       
679        function _initrs()
680        {
681        GLOBAL $ADODB_COUNTRECS;       
682                $this->_numOfRows = ($ADODB_COUNTRECS)? @mssql_num_rows($this->_queryID):-1;
683                $this->_numOfFields = @mssql_num_fields($this->_queryID);
684        }
685       
686
687        //Contributed by "Sven Axelsson" <sven.axelsson@bokochwebb.se>
688        // get next resultset - requires PHP 4.0.5 or later
689        function NextRecordSet()
690        {
691                if (!mssql_next_result($this->_queryID)) return false;
692                $this->_inited = false;
693                $this->bind = false;
694                $this->_currentRow = -1;
695                $this->Init();
696                return true;
697        }
698
699        /* Use associative array to get fields array */
700        function Fields($colname)
701        {
702                if ($this->fetchMode != ADODB_FETCH_NUM) return $this->fields[$colname];
703                if (!$this->bind) {
704                        $this->bind = array();
705                        for ($i=0; $i < $this->_numOfFields; $i++) {
706                                $o = $this->FetchField($i);
707                                $this->bind[strtoupper($o->name)] = $i;
708                        }
709                }
710               
711                 return $this->fields[$this->bind[strtoupper($colname)]];
712        }
713       
714        /*      Returns: an object containing field information.
715                Get column information in the Recordset object. fetchField() can be used in order to obtain information about
716                fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by
717                fetchField() is retrieved.      */
718
719        function FetchField($fieldOffset = -1)
720        {
721                if ($fieldOffset != -1) {
722                        return @mssql_fetch_field($this->_queryID, $fieldOffset);
723                }
724                else if ($fieldOffset == -1) {  /*      The $fieldOffset argument is not provided thus its -1   */
725                        return @mssql_fetch_field($this->_queryID);
726                }
727                return null;
728        }
729       
730        function _seek($row)
731        {
732                return @mssql_data_seek($this->_queryID, $row);
733        }
734
735        // speedup
736        function MoveNext()
737        {
738                if ($this->EOF) return false;
739               
740                $this->_currentRow++;
741               
742                if ($this->fetchMode & ADODB_FETCH_ASSOC) {
743                        if ($this->fetchMode & ADODB_FETCH_NUM) {
744                                //ADODB_FETCH_BOTH mode
745                                $this->fields = @mssql_fetch_array($this->_queryID);
746                        }
747                        else {
748                                if ($this->hasFetchAssoc) {// only for PHP 4.2.0 or later
749                                         $this->fields = @mssql_fetch_assoc($this->_queryID);
750                                } else {
751                                        $flds = @mssql_fetch_array($this->_queryID);
752                                        if (is_array($flds)) {
753                                                $fassoc = array();
754                                                foreach($flds as $k => $v) {
755                                                        if (is_numeric($k)) continue;
756                                                        $fassoc[$k] = $v;
757                                                }
758                                                $this->fields = $fassoc;
759                                        } else
760                                                $this->fields = false;
761                                }
762                        }
763                       
764                        if (is_array($this->fields)) {
765                                if (ADODB_ASSOC_CASE == 0) {
766                                        foreach($this->fields as $k=>$v) {
767                                                $this->fields[strtolower($k)] = $v;
768                                        }
769                                } else if (ADODB_ASSOC_CASE == 1) {
770                                        foreach($this->fields as $k=>$v) {
771                                                $this->fields[strtoupper($k)] = $v;
772                                        }
773                                }
774                        }
775                } else {
776                        $this->fields = @mssql_fetch_row($this->_queryID);
777                }
778                if ($this->fields) return true;
779                $this->EOF = true;
780               
781                return false;
782        }
783
784       
785        // INSERT UPDATE DELETE returns false even if no error occurs in 4.0.4
786        // also the date format has been changed from YYYY-mm-dd to dd MMM YYYY in 4.0.4. Idiot!
787        function _fetch($ignore_fields=false)
788        {
789                if ($this->fetchMode & ADODB_FETCH_ASSOC) {
790                        if ($this->fetchMode & ADODB_FETCH_NUM) {
791                                //ADODB_FETCH_BOTH mode
792                                $this->fields = @mssql_fetch_array($this->_queryID);
793                        } else {
794                                if ($this->hasFetchAssoc) // only for PHP 4.2.0 or later
795                                        $this->fields = @mssql_fetch_assoc($this->_queryID);
796                                else {
797                                        $this->fields = @mssql_fetch_array($this->_queryID);
798                                        if (@is_array($$this->fields)) {
799                                                $fassoc = array();
800                                                foreach($$this->fields as $k => $v) {
801                                                        if (is_integer($k)) continue;
802                                                        $fassoc[$k] = $v;
803                                                }
804                                                $this->fields = $fassoc;
805                                        }
806                                }
807                        }
808                       
809                        if (!$this->fields) {
810                        } else if (ADODB_ASSOC_CASE == 0) {
811                                foreach($this->fields as $k=>$v) {
812                                        $this->fields[strtolower($k)] = $v;
813                                }
814                        } else if (ADODB_ASSOC_CASE == 1) {
815                                foreach($this->fields as $k=>$v) {
816                                        $this->fields[strtoupper($k)] = $v;
817                                }
818                        }
819                } else {
820                        $this->fields = @mssql_fetch_row($this->_queryID);
821                }
822                return $this->fields;
823        }
824       
825        /*      close() only needs to be called if you are worried about using too much memory while your script
826                is running. All associated result memory for the specified result identifier will automatically be freed.       */
827
828        function _close()
829        {
830                $rez = mssql_free_result($this->_queryID);     
831                $this->_queryID = false;
832                return $rez;
833        }
834        // mssql uses a default date like Dec 30 2000 12:00AM
835        function UnixDate($v)
836        {
837                return ADORecordSet_array_mssql::UnixDate($v);
838        }
839       
840        function UnixTimeStamp($v)
841        {
842                return ADORecordSet_array_mssql::UnixTimeStamp($v);
843        }
844       
845}
846
847
848class ADORecordSet_array_mssql extends ADORecordSet_array {
849        function ADORecordSet_array_mssql($id=-1,$mode=false)
850        {
851                $this->ADORecordSet_array($id,$mode);
852        }
853       
854                // mssql uses a default date like Dec 30 2000 12:00AM
855        function UnixDate($v)
856        {
857       
858                if (is_numeric(substr($v,0,1)) && ADODB_PHPVER >= 0x4200) return parent::UnixDate($v);
859               
860        global $ADODB_mssql_mths,$ADODB_mssql_date_order;
861       
862                //Dec 30 2000 12:00AM
863                if ($ADODB_mssql_date_order == 'dmy') {
864                        if (!preg_match( "|^([0-9]{1,2})[-/\. ]+([A-Za-z]{3})[-/\. ]+([0-9]{4})|" ,$v, $rr)) {
865                                return parent::UnixDate($v);
866                        }
867                        if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
868                       
869                        $theday = $rr[1];
870                        $themth =  substr(strtoupper($rr[2]),0,3);
871                } else {
872                        if (!preg_match( "|^([A-Za-z]{3})[-/\. ]+([0-9]{1,2})[-/\. ]+([0-9]{4})|" ,$v, $rr)) {
873                                return parent::UnixDate($v);
874                        }
875                        if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
876                       
877                        $theday = $rr[2];
878                        $themth = substr(strtoupper($rr[1]),0,3);
879                }
880                $themth = $ADODB_mssql_mths[$themth];
881                if ($themth <= 0) return false;
882                // h-m-s-MM-DD-YY
883                return  mktime(0,0,0,$themth,$theday,$rr[3]);
884        }
885       
886        function UnixTimeStamp($v)
887        {
888       
889                if (is_numeric(substr($v,0,1)) && ADODB_PHPVER >= 0x4200) return parent::UnixTimeStamp($v);
890               
891        global $ADODB_mssql_mths,$ADODB_mssql_date_order;
892       
893                //Dec 30 2000 12:00AM
894                 if ($ADODB_mssql_date_order == 'dmy') {
895                         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})|"
896                        ,$v, $rr)) return parent::UnixTimeStamp($v);
897                        if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
898               
899                        $theday = $rr[1];
900                        $themth =  substr(strtoupper($rr[2]),0,3);
901                } else {
902                        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})|"
903                        ,$v, $rr)) return parent::UnixTimeStamp($v);
904                        if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
905               
906                        $theday = $rr[2];
907                        $themth = substr(strtoupper($rr[1]),0,3);
908                }
909               
910                $themth = $ADODB_mssql_mths[$themth];
911                if ($themth <= 0) return false;
912               
913                switch (strtoupper($rr[6])) {
914                case 'P':
915                        if ($rr[4]<12) $rr[4] += 12;
916                        break;
917                case 'A':
918                        if ($rr[4]==12) $rr[4] = 0;
919                        break;
920                default:
921                        break;
922                }
923                // h-m-s-MM-DD-YY
924                return  mktime($rr[4],$rr[5],0,$themth,$theday,$rr[3]);
925        }
926}
927
928/*
929Code Example 1:
930
931select  object_name(constid) as constraint_name,
932        object_name(fkeyid) as table_name,
933        col_name(fkeyid, fkey) as column_name,
934        object_name(rkeyid) as referenced_table_name,
935        col_name(rkeyid, rkey) as referenced_column_name
936from sysforeignkeys
937where object_name(fkeyid) = x
938order by constraint_name, table_name, referenced_table_name,  keyno
939
940Code Example 2:
941select  constraint_name,
942        column_name,
943        ordinal_position
944from information_schema.key_column_usage
945where constraint_catalog = db_name()
946and table_name = x
947order by constraint_name, ordinal_position
948
949http://www.databasejournal.com/scripts/article.php/1440551
950*/
951
952?>
Note: See TracBrowser for help on using the repository browser.