Documentation TYPO3 par Ameos

adodb-mssql.inc.php

00001 <?php
00002 /* 
00003 V4.80 8 Mar 2006  (c) 2000-2006 John Lim (jlim@natsoft.com.my). All rights reserved.
00004   Released under both BSD license and Lesser GPL library license. 
00005   Whenever there is any discrepancy between the two licenses, 
00006   the BSD license will take precedence. 
00007 Set tabs to 4 for best viewing.
00008   
00009   Latest version is available at http://adodb.sourceforge.net
00010   
00011   Native mssql driver. Requires mssql client. Works on Windows. 
00012   To configure for Unix, see 
00013         http://phpbuilder.com/columns/alberto20000919.php3
00014         
00015 */
00016 
00017 // security - hide paths
00018 if (!defined('ADODB_DIR')) die();
00019 
00020 //----------------------------------------------------------------
00021 // MSSQL returns dates with the format Oct 13 2002 or 13 Oct 2002
00022 // and this causes tons of problems because localized versions of 
00023 // MSSQL will return the dates in dmy or  mdy order; and also the 
00024 // month strings depends on what language has been configured. The 
00025 // following two variables allow you to control the localization
00026 // settings - Ugh.
00027 //
00028 // MORE LOCALIZATION INFO
00029 // ----------------------
00030 // To configure datetime, look for and modify sqlcommn.loc, 
00031 //      typically found in c:\mssql\install
00032 // Also read :
00033 //       http://support.microsoft.com/default.aspx?scid=kb;EN-US;q220918
00034 // Alternatively use:
00035 //         CONVERT(char(12),datecol,120)
00036 //----------------------------------------------------------------
00037 
00038 
00039 // has datetime converstion to YYYY-MM-DD format, and also mssql_fetch_assoc
00040 if (ADODB_PHPVER >= 0x4300) {
00041 // docs say 4.2.0, but testing shows only since 4.3.0 does it work!
00042         ini_set('mssql.datetimeconvert',0); 
00043 } else {
00044 global $ADODB_mssql_mths;               // array, months must be upper-case
00045 
00046 
00047         $ADODB_mssql_date_order = 'mdy'; 
00048         $ADODB_mssql_mths = array(
00049                 'JAN'=>1,'FEB'=>2,'MAR'=>3,'APR'=>4,'MAY'=>5,'JUN'=>6,
00050                 'JUL'=>7,'AUG'=>8,'SEP'=>9,'OCT'=>10,'NOV'=>11,'DEC'=>12);
00051 }
00052 
00053 //---------------------------------------------------------------------------
00054 // Call this to autoset $ADODB_mssql_date_order at the beginning of your code,
00055 // just after you connect to the database. Supports mdy and dmy only.
00056 // Not required for PHP 4.2.0 and above.
00057 function AutoDetect_MSSQL_Date_Order($conn)
00058 {
00059 global $ADODB_mssql_date_order;
00060         $adate = $conn->GetOne('select getdate()');
00061         if ($adate) {
00062                 $anum = (int) $adate;
00063                 if ($anum > 0) {
00064                         if ($anum > 31) {
00065                                 //ADOConnection::outp( "MSSQL: YYYY-MM-DD date format not supported currently");
00066                         } else
00067                                 $ADODB_mssql_date_order = 'dmy';
00068                 } else
00069                         $ADODB_mssql_date_order = 'mdy';
00070         }
00071 }
00072 
00073 class ADODB_mssql extends ADOConnection {
00074         var $databaseType = "mssql";    
00075         var $dataProvider = "mssql";
00076         var $replaceQuote = "''"; // string to use to replace quotes
00077         var $fmtDate = "'Y-m-d'";
00078         var $fmtTimeStamp = "'Y-m-d H:i:s'";
00079         var $hasInsertID = true;
00080         var $substr = "substring";
00081         var $length = 'len';
00082         var $hasAffectedRows = true;
00083         var $metaDatabasesSQL = "select name from sysdatabases where name <> 'master'";
00084         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'))";
00085         var $metaColumnsSQL = # xtype==61 is datetime
00086 "select c.name,t.name,c.length,
00087         (case when c.xusertype=61 then 0 else c.xprec end),
00088         (case when c.xusertype=61 then 0 else c.xscale end) 
00089         from syscolumns c join systypes t on t.xusertype=c.xusertype join sysobjects o on o.id=c.id where o.name='%s'";
00090         var $hasTop = 'top';            // support mssql SELECT TOP 10 * FROM TABLE
00091         var $hasGenID = true;
00092         var $sysDate = 'convert(datetime,convert(char,GetDate(),102),102)';
00093         var $sysTimeStamp = 'GetDate()';
00094         var $_has_mssql_init;
00095         var $maxParameterLen = 4000;
00096         var $arrayClass = 'ADORecordSet_array_mssql';
00097         var $uniqueSort = true;
00098         var $leftOuter = '*=';
00099         var $rightOuter = '=*';
00100         var $ansiOuter = true; // for mssql7 or later
00101         var $poorAffectedRows = true;
00102         var $identitySQL = 'select @@IDENTITY'; // 'select SCOPE_IDENTITY'; # for mssql 2000
00103         var $uniqueOrderBy = true;
00104         var $_bindInputArray = true;
00105         
00106         function ADODB_mssql() 
00107         {               
00108                 $this->_has_mssql_init = (strnatcmp(PHP_VERSION,'4.1.0')>=0);
00109         }
00110 
00111         function ServerInfo()
00112         {
00113         global $ADODB_FETCH_MODE;
00114         
00115                 $stmt = $this->PrepareSP('sp_server_info');
00116                 $val = 2;
00117                 if ($this->fetchMode === false) {
00118                         $savem = $ADODB_FETCH_MODE;
00119                         $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
00120                 } else 
00121                         $savem = $this->SetFetchMode(ADODB_FETCH_NUM);
00122                 
00123                 
00124                 $this->Parameter($stmt,$val,'attribute_id');
00125                 $row = $this->GetRow($stmt);
00126                 
00127                 //$row = $this->GetRow("execute sp_server_info 2");
00128                 
00129                 
00130                 if ($this->fetchMode === false) {
00131                         $ADODB_FETCH_MODE = $savem;
00132                 } else
00133                         $this->SetFetchMode($savem);
00134                 
00135                 $arr['description'] = $row[2];
00136                 $arr['version'] = ADOConnection::_findvers($arr['description']);
00137                 return $arr;
00138         }
00139         
00140         function IfNull( $field, $ifNull ) 
00141         {
00142                 return " ISNULL($field, $ifNull) "; // if MS SQL Server
00143         }
00144         
00145         function _insertid()
00146         {
00147         // SCOPE_IDENTITY()
00148         // Returns the last IDENTITY value inserted into an IDENTITY column in 
00149         // the same scope. A scope is a module -- a stored procedure, trigger, 
00150         // function, or batch. Thus, two statements are in the same scope if 
00151         // they are in the same stored procedure, function, or batch.
00152                         return $this->GetOne($this->identitySQL);
00153         }
00154 
00155         function _affectedrows()
00156         {
00157                 return $this->GetOne('select @@rowcount');
00158         }
00159 
00160         var $_dropSeqSQL = "drop table %s";
00161         
00162         function CreateSequence($seq='adodbseq',$start=1)
00163         {
00164                 
00165                 $this->Execute('BEGIN TRANSACTION adodbseq');
00166                 $start -= 1;
00167                 $this->Execute("create table $seq (id float(53))");
00168                 $ok = $this->Execute("insert into $seq with (tablock,holdlock) values($start)");
00169                 if (!$ok) {
00170                                 $this->Execute('ROLLBACK TRANSACTION adodbseq');
00171                                 return false;
00172                 }
00173                 $this->Execute('COMMIT TRANSACTION adodbseq'); 
00174                 return true;
00175         }
00176 
00177         function GenID($seq='adodbseq',$start=1)
00178         {
00179                 //$this->debug=1;
00180                 $this->Execute('BEGIN TRANSACTION adodbseq');
00181                 $ok = $this->Execute("update $seq with (tablock,holdlock) set id = id + 1");
00182                 if (!$ok) {
00183                         $this->Execute("create table $seq (id float(53))");
00184                         $ok = $this->Execute("insert into $seq with (tablock,holdlock) values($start)");
00185                         if (!$ok) {
00186                                 $this->Execute('ROLLBACK TRANSACTION adodbseq');
00187                                 return false;
00188                         }
00189                         $this->Execute('COMMIT TRANSACTION adodbseq'); 
00190                         return $start;
00191                 }
00192                 $num = $this->GetOne("select id from $seq");
00193                 $this->Execute('COMMIT TRANSACTION adodbseq'); 
00194                 return $num;
00195                 
00196                 // in old implementation, pre 1.90, we returned GUID...
00197                 //return $this->GetOne("SELECT CONVERT(varchar(255), NEWID()) AS 'Char'");
00198         }
00199         
00200 
00201         function &SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0)
00202         {
00203                 if ($nrows > 0 && $offset <= 0) {
00204                         $sql = preg_replace(
00205                                 '/(^\s*select\s+(distinctrow|distinct)?)/i','\\1 '.$this->hasTop." $nrows ",$sql);
00206                         $rs =& $this->Execute($sql,$inputarr);
00207                 } else
00208                         $rs =& ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);
00209         
00210                 return $rs;
00211         }
00212         
00213         
00214         // Format date column in sql string given an input format that understands Y M D
00215         function SQLDate($fmt, $col=false)
00216         {       
00217                 if (!$col) $col = $this->sysTimeStamp;
00218                 $s = '';
00219                 
00220                 $len = strlen($fmt);
00221                 for ($i=0; $i < $len; $i++) {
00222                         if ($s) $s .= '+';
00223                         $ch = $fmt[$i];
00224                         switch($ch) {
00225                         case 'Y':
00226                         case 'y':
00227                                 $s .= "datename(yyyy,$col)";
00228                                 break;
00229                         case 'M':
00230                                 $s .= "convert(char(3),$col,0)";
00231                                 break;
00232                         case 'm':
00233                                 $s .= "replace(str(month($col),2),' ','0')";
00234                                 break;
00235                         case 'Q':
00236                         case 'q':
00237                                 $s .= "datename(quarter,$col)";
00238                                 break;
00239                         case 'D':
00240                         case 'd':
00241                                 $s .= "replace(str(day($col),2),' ','0')";
00242                                 break;
00243                         case 'h':
00244                                 $s .= "substring(convert(char(14),$col,0),13,2)";
00245                                 break;
00246                         
00247                         case 'H':
00248                                 $s .= "replace(str(datepart(hh,$col),2),' ','0')";
00249                                 break;
00250                                 
00251                         case 'i':
00252                                 $s .= "replace(str(datepart(mi,$col),2),' ','0')";
00253                                 break;
00254                         case 's':
00255                                 $s .= "replace(str(datepart(ss,$col),2),' ','0')";
00256                                 break;
00257                         case 'a':
00258                         case 'A':
00259                                 $s .= "substring(convert(char(19),$col,0),18,2)";
00260                                 break;
00261                                 
00262                         default:
00263                                 if ($ch == '\\') {
00264                                         $i++;
00265                                         $ch = substr($fmt,$i,1);
00266                                 }
00267                                 $s .= $this->qstr($ch);
00268                                 break;
00269                         }
00270                 }
00271                 return $s;
00272         }
00273 
00274         
00275         function BeginTrans()
00276         {
00277                 if ($this->transOff) return true; 
00278                 $this->transCnt += 1;
00279                 $this->Execute('BEGIN TRAN');
00280                 return true;
00281         }
00282                 
00283         function CommitTrans($ok=true) 
00284         { 
00285                 if ($this->transOff) return true; 
00286                 if (!$ok) return $this->RollbackTrans();
00287                 if ($this->transCnt) $this->transCnt -= 1;
00288                 $this->Execute('COMMIT TRAN');
00289                 return true;
00290         }
00291         function RollbackTrans()
00292         {
00293                 if ($this->transOff) return true; 
00294                 if ($this->transCnt) $this->transCnt -= 1;
00295                 $this->Execute('ROLLBACK TRAN');
00296                 return true;
00297         }
00298         
00299         /*
00300                 Usage:
00301                 
00302                 $this->BeginTrans();
00303                 $this->RowLock('table1,table2','table1.id=33 and table2.id=table1.id'); # lock row 33 for both tables
00304                 
00305                 # some operation on both tables table1 and table2
00306                 
00307                 $this->CommitTrans();
00308                 
00309                 See http://www.swynk.com/friends/achigrik/SQL70Locks.asp
00310         */
00311         function RowLock($tables,$where,$flds='top 1 null as ignore') 
00312         {
00313                 if (!$this->transCnt) $this->BeginTrans();
00314                 return $this->GetOne("select $flds from $tables with (ROWLOCK,HOLDLOCK) where $where");
00315         }
00316         
00317         
00318         function &MetaIndexes($table,$primary=false)
00319         {
00320                 $table = $this->qstr($table);
00321 
00322                 $sql = "SELECT i.name AS ind_name, C.name AS col_name, USER_NAME(O.uid) AS Owner, c.colid, k.Keyno, 
00323                         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,
00324                         CASE WHEN I.status & 2 = 2 THEN 1 ELSE 0 END AS IsUnique
00325                         FROM dbo.sysobjects o INNER JOIN dbo.sysindexes I ON o.id = i.id 
00326                         INNER JOIN dbo.sysindexkeys K ON I.id = K.id AND I.Indid = K.Indid 
00327                         INNER JOIN dbo.syscolumns c ON K.id = C.id AND K.colid = C.Colid
00328                         WHERE LEFT(i.name, 8) <> '_WA_Sys_' AND o.status >= 0 AND O.Name LIKE $table
00329                         ORDER BY O.name, I.Name, K.keyno";
00330 
00331                 global $ADODB_FETCH_MODE;
00332                 $save = $ADODB_FETCH_MODE;
00333         $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
00334         if ($this->fetchMode !== FALSE) {
00335                 $savem = $this->SetFetchMode(FALSE);
00336         }
00337         
00338         $rs = $this->Execute($sql);
00339         if (isset($savem)) {
00340                 $this->SetFetchMode($savem);
00341         }
00342         $ADODB_FETCH_MODE = $save;
00343 
00344         if (!is_object($rs)) {
00345                 return FALSE;
00346         }
00347 
00348                 $indexes = array();
00349                 while ($row = $rs->FetchRow()) {
00350                         if (!$primary && $row[5]) continue;
00351                         
00352             $indexes[$row[0]]['unique'] = $row[6];
00353             $indexes[$row[0]]['columns'][] = $row[1];
00354         }
00355         return $indexes;
00356         }
00357         
00358         function MetaForeignKeys($table, $owner=false, $upper=false)
00359         {
00360         global $ADODB_FETCH_MODE;
00361         
00362                 $save = $ADODB_FETCH_MODE;
00363                 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
00364                 $table = $this->qstr(strtoupper($table));
00365                 
00366                 $sql = 
00367 "select object_name(constid) as constraint_name,
00368         col_name(fkeyid, fkey) as column_name,
00369         object_name(rkeyid) as referenced_table_name,
00370         col_name(rkeyid, rkey) as referenced_column_name
00371 from sysforeignkeys
00372 where upper(object_name(fkeyid)) = $table
00373 order by constraint_name, referenced_table_name, keyno";
00374                 
00375                 $constraints =& $this->GetArray($sql);
00376                 
00377                 $ADODB_FETCH_MODE = $save;
00378                 
00379                 $arr = false;
00380                 foreach($constraints as $constr) {
00381                         //print_r($constr);
00382                         $arr[$constr[0]][$constr[2]][] = $constr[1].'='.$constr[3]; 
00383                 }
00384                 if (!$arr) return false;
00385                 
00386                 $arr2 = false;
00387                 
00388                 foreach($arr as $k => $v) {
00389                         foreach($v as $a => $b) {
00390                                 if ($upper) $a = strtoupper($a);
00391                                 $arr2[$a] = $b;
00392                         }
00393                 }
00394                 return $arr2;
00395         }
00396 
00397         //From: Fernando Moreira <FMoreira@imediata.pt>
00398         function MetaDatabases() 
00399         { 
00400                 if(@mssql_select_db("master")) { 
00401                                  $qry=$this->metaDatabasesSQL; 
00402                                  if($rs=@mssql_query($qry)){ 
00403                                                  $tmpAr=$ar=array(); 
00404                                                  while($tmpAr=@mssql_fetch_row($rs)) 
00405                                                                  $ar[]=$tmpAr[0]; 
00406                                                 @mssql_select_db($this->database); 
00407                                                  if(sizeof($ar)) 
00408                                                                  return($ar); 
00409                                                  else 
00410                                                                  return(false); 
00411                                  } else { 
00412                                                  @mssql_select_db($this->database); 
00413                                                  return(false); 
00414                                  } 
00415                  } 
00416                  return(false); 
00417         } 
00418 
00419         // "Stein-Aksel Basma" <basma@accelero.no>
00420         // tested with MSSQL 2000
00421         function &MetaPrimaryKeys($table)
00422         {
00423         global $ADODB_FETCH_MODE;
00424         
00425                 $schema = '';
00426                 $this->_findschema($table,$schema);
00427                 if (!$schema) $schema = $this->database;
00428                 if ($schema) $schema = "and k.table_catalog like '$schema%'"; 
00429 
00430                 $sql = "select distinct k.column_name,ordinal_position from information_schema.key_column_usage k,
00431                 information_schema.table_constraints tc 
00432                 where tc.constraint_name = k.constraint_name and tc.constraint_type =
00433                 'PRIMARY KEY' and k.table_name = '$table' $schema order by ordinal_position ";
00434                 
00435                 $savem = $ADODB_FETCH_MODE;
00436                 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
00437                 $a = $this->GetCol($sql);
00438                 $ADODB_FETCH_MODE = $savem;
00439                 
00440                 if ($a && sizeof($a)>0) return $a;
00441                 $false = false;
00442                 return $false;    
00443         }
00444 
00445         
00446         function &MetaTables($ttype=false,$showSchema=false,$mask=false) 
00447         {
00448                 if ($mask) {
00449                         $save = $this->metaTablesSQL;
00450                         $mask = $this->qstr(($mask));
00451                         $this->metaTablesSQL .= " AND name like $mask";
00452                 }
00453                 $ret =& ADOConnection::MetaTables($ttype,$showSchema);
00454                 
00455                 if ($mask) {
00456                         $this->metaTablesSQL = $save;
00457                 }
00458                 return $ret;
00459         }
00460  
00461         function SelectDB($dbName) 
00462         {
00463                 $this->database = $dbName;
00464                 $this->databaseName = $dbName; # obsolete, retained for compat with older adodb versions
00465                 if ($this->_connectionID) {
00466                         return @mssql_select_db($dbName);               
00467                 }
00468                 else return false;      
00469         }
00470         
00471         function ErrorMsg() 
00472         {
00473                 if (empty($this->_errorMsg)){
00474                         $this->_errorMsg = mssql_get_last_message();
00475                 }
00476                 return $this->_errorMsg;
00477         }
00478         
00479         function ErrorNo() 
00480         {
00481                 if ($this->_logsql && $this->_errorCode !== false) return $this->_errorCode;
00482                 if (empty($this->_errorMsg)) {
00483                         $this->_errorMsg = mssql_get_last_message();
00484                 }
00485                 $id = @mssql_query("select @@ERROR",$this->_connectionID);
00486                 if (!$id) return false;
00487                 $arr = mssql_fetch_array($id);
00488                 @mssql_free_result($id);
00489                 if (is_array($arr)) return $arr[0];
00490            else return -1;
00491         }
00492         
00493         // returns true or false
00494         function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)
00495         {
00496                 if (!function_exists('mssql_pconnect')) return null;
00497                 $this->_connectionID = mssql_connect($argHostname,$argUsername,$argPassword);
00498                 if ($this->_connectionID === false) return false;
00499                 if ($argDatabasename) return $this->SelectDB($argDatabasename);
00500                 return true;    
00501         }
00502         
00503         
00504         // returns true or false
00505         function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
00506         {
00507                 if (!function_exists('mssql_pconnect')) return null;
00508                 $this->_connectionID = mssql_pconnect($argHostname,$argUsername,$argPassword);
00509                 if ($this->_connectionID === false) return false;
00510                 
00511                 // persistent connections can forget to rollback on crash, so we do it here.
00512                 if ($this->autoRollback) {
00513                         $cnt = $this->GetOne('select @@TRANCOUNT');
00514                         while (--$cnt >= 0) $this->Execute('ROLLBACK TRAN'); 
00515                 }
00516                 if ($argDatabasename) return $this->SelectDB($argDatabasename);
00517                 return true;    
00518         }
00519         
00520         function Prepare($sql)
00521         {
00522                 $sqlarr = explode('?',$sql);
00523                 if (sizeof($sqlarr) <= 1) return $sql;
00524                 $sql2 = $sqlarr[0];
00525                 for ($i = 1, $max = sizeof($sqlarr); $i < $max; $i++) {
00526                         $sql2 .=  '@P'.($i-1) . $sqlarr[$i];
00527                 } 
00528                 return array($sql,$this->qstr($sql2),$max);
00529         }
00530         
00531         function PrepareSP($sql)
00532         {
00533                 if (!$this->_has_mssql_init) {
00534                         ADOConnection::outp( "PrepareSP: mssql_init only available since PHP 4.1.0");
00535                         return $sql;
00536                 }
00537                 $stmt = mssql_init($sql,$this->_connectionID);
00538                 if (!$stmt)  return $sql;
00539                 return array($sql,$stmt);
00540         }
00541         
00542         // returns concatenated string
00543     // MSSQL requires integers to be cast as strings
00544     // automatically cast every datatype to VARCHAR(255)
00545     // @author David Rogers (introspectshun)
00546     function Concat()
00547     {
00548             $s = "";
00549             $arr = func_get_args();
00550 
00551             // Split single record on commas, if possible
00552             if (sizeof($arr) == 1) {
00553                 foreach ($arr as $arg) {
00554                     $args = explode(',', $arg);
00555                 }
00556                 $arr = $args;
00557             }
00558 
00559             array_walk($arr, create_function('&$v', '$v = "CAST(" . $v . " AS VARCHAR(255))";'));
00560             $s = implode('+',$arr);
00561             if (sizeof($arr) > 0) return "$s";
00562             
00563                         return '';
00564     }
00565         
00566         /* 
00567         Usage:
00568                 $stmt = $db->PrepareSP('SP_RUNSOMETHING'); -- takes 2 params, @myid and @group
00569                 
00570                 # note that the parameter does not have @ in front!
00571                 $db->Parameter($stmt,$id,'myid');
00572                 $db->Parameter($stmt,$group,'group',false,64);
00573                 $db->Execute($stmt);
00574                 
00575                 @param $stmt Statement returned by Prepare() or PrepareSP().
00576                 @param $var PHP variable to bind to. Can set to null (for isNull support).
00577                 @param $name Name of stored procedure variable name to bind to.
00578                 @param [$isOutput] Indicates direction of parameter 0/false=IN  1=OUT  2= IN/OUT. This is ignored in oci8.
00579                 @param [$maxLen] Holds an maximum length of the variable.
00580                 @param [$type] The data type of $var. Legal values depend on driver.
00581                 
00582                 See mssql_bind documentation at php.net.
00583         */
00584         function Parameter(&$stmt, &$var, $name, $isOutput=false, $maxLen=4000, $type=false)
00585         {
00586                 if (!$this->_has_mssql_init) {
00587                         ADOConnection::outp( "Parameter: mssql_bind only available since PHP 4.1.0");
00588                         return false;
00589                 }
00590 
00591                 $isNull = is_null($var); // php 4.0.4 and above...
00592                         
00593                 if ($type === false) 
00594                         switch(gettype($var)) {
00595                         default:
00596                         case 'string': $type = SQLCHAR; break;
00597                         case 'double': $type = SQLFLT8; break;
00598                         case 'integer': $type = SQLINT4; break;
00599                         case 'boolean': $type = SQLINT1; break; # SQLBIT not supported in 4.1.0
00600                         }
00601                 
00602                 if  ($this->debug) {
00603                         $prefix = ($isOutput) ? 'Out' : 'In';
00604                         $ztype = (empty($type)) ? 'false' : $type;
00605                         ADOConnection::outp( "{$prefix}Parameter(\$stmt, \$php_var='$var', \$name='$name', \$maxLen=$maxLen, \$type=$ztype);");
00606                 }
00607                 /*
00608                         See http://phplens.com/lens/lensforum/msgs.php?id=7231
00609                         
00610                         RETVAL is HARD CODED into php_mssql extension:
00611                         The return value (a long integer value) is treated like a special OUTPUT parameter, 
00612                         called "RETVAL" (without the @). See the example at mssql_execute to 
00613                         see how it works. - type: one of this new supported PHP constants. 
00614                                 SQLTEXT, SQLVARCHAR,SQLCHAR, SQLINT1,SQLINT2, SQLINT4, SQLBIT,SQLFLT8 
00615                 */
00616                 if ($name !== 'RETVAL') $name = '@'.$name;
00617                 return mssql_bind($stmt[1], $name, $var, $type, $isOutput, $isNull, $maxLen);
00618         }
00619         
00620         /* 
00621                 Unfortunately, it appears that mssql cannot handle varbinary > 255 chars
00622                 So all your blobs must be of type "image".
00623                 
00624                 Remember to set in php.ini the following...
00625                 
00626                 ; Valid range 0 - 2147483647. Default = 4096. 
00627                 mssql.textlimit = 0 ; zero to pass through 
00628 
00629                 ; Valid range 0 - 2147483647. Default = 4096. 
00630                 mssql.textsize = 0 ; zero to pass through 
00631         */
00632         function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
00633         {
00634         
00635                 if (strtoupper($blobtype) == 'CLOB') {
00636                         $sql = "UPDATE $table SET $column='" . $val . "' WHERE $where";
00637                         return $this->Execute($sql) != false;
00638                 }
00639                 $sql = "UPDATE $table SET $column=0x".bin2hex($val)." WHERE $where";
00640                 return $this->Execute($sql) != false;
00641         }
00642         
00643         // returns query ID if successful, otherwise false
00644         function _query($sql,$inputarr)
00645         {
00646                 $this->_errorMsg = false;
00647                 if (is_array($inputarr)) {
00648                         
00649                         # bind input params with sp_executesql: 
00650                         # see http://www.quest-pipelines.com/newsletter-v3/0402_F.htm
00651                         # works only with sql server 7 and newer
00652                         if (!is_array($sql)) $sql = $this->Prepare($sql);
00653                         $params = '';
00654                         $decl = '';
00655                         $i = 0;
00656                         foreach($inputarr as $v) {
00657                                 if ($decl) {
00658                                         $decl .= ', ';
00659                                         $params .= ', ';
00660                                 }       
00661                                 if (is_string($v)) {
00662                                         $len = strlen($v);
00663                                         if ($len == 0) $len = 1;
00664                                         
00665                                         if ($len > 4000 ) {
00666                                                 // NVARCHAR is max 4000 chars. Let's use NTEXT
00667                                                 $decl .= "@P$i NTEXT";
00668                                         } else {
00669                                                 $decl .= "@P$i NVARCHAR($len)";
00670                                         }
00671 
00672                                         $params .= "@P$i=N". (strncmp($v,"'",1)==0? $v : $this->qstr($v));
00673                                 } else if (is_integer($v)) {
00674                                         $decl .= "@P$i INT";
00675                                         $params .= "@P$i=".$v;
00676                                 } else if (is_float($v)) {
00677                                         $decl .= "@P$i FLOAT";
00678                                         $params .= "@P$i=".$v;
00679                                 } else if (is_bool($v)) {
00680                                         $decl .= "@P$i INT"; # Used INT just in case BIT in not supported on the user's MSSQL version. It will cast appropriately.
00681                                         $params .= "@P$i=".(($v)?'1':'0'); # True == 1 in MSSQL BIT fields and acceptable for storing logical true in an int field
00682                                 } else {
00683                                         $decl .= "@P$i CHAR"; # Used char because a type is required even when the value is to be NULL.
00684                                         $params .= "@P$i=NULL";
00685                                         }
00686                                 $i += 1;
00687                         }
00688                         $decl = $this->qstr($decl);
00689                         if ($this->debug) ADOConnection::outp("<font size=-1>sp_executesql N{$sql[1]},N$decl,$params</font>");
00690                         $rez = mssql_query("sp_executesql N{$sql[1]},N$decl,$params");
00691                         
00692                 } else if (is_array($sql)) {
00693                         # PrepareSP()
00694                         $rez = mssql_execute($sql[1]);
00695                         
00696                 } else {
00697                         $rez = mssql_query($sql,$this->_connectionID);
00698                 }
00699                 return $rez;
00700         }
00701         
00702         // returns true or false
00703         function _close()
00704         { 
00705                 if ($this->transCnt) $this->RollbackTrans();
00706                 $rez = @mssql_close($this->_connectionID);
00707                 $this->_connectionID = false;
00708                 return $rez;
00709         }
00710         
00711         // mssql uses a default date like Dec 30 2000 12:00AM
00712         function UnixDate($v)
00713         {
00714                 return ADORecordSet_array_mssql::UnixDate($v);
00715         }
00716         
00717         function UnixTimeStamp($v)
00718         {
00719                 return ADORecordSet_array_mssql::UnixTimeStamp($v);
00720         }       
00721 }
00722         
00723 /*--------------------------------------------------------------------------------------
00724          Class Name: Recordset
00725 --------------------------------------------------------------------------------------*/
00726 
00727 class ADORecordset_mssql extends ADORecordSet { 
00728 
00729         var $databaseType = "mssql";
00730         var $canSeek = true;
00731         var $hasFetchAssoc; // see http://phplens.com/lens/lensforum/msgs.php?id=6083
00732         // _mths works only in non-localised system
00733         
00734         function ADORecordset_mssql($id,$mode=false)
00735         {
00736                 // freedts check...
00737                 $this->hasFetchAssoc = function_exists('mssql_fetch_assoc');
00738 
00739                 if ($mode === false) { 
00740                         global $ADODB_FETCH_MODE;
00741                         $mode = $ADODB_FETCH_MODE;
00742 
00743                 }
00744                 $this->fetchMode = $mode;
00745                 return $this->ADORecordSet($id,$mode);
00746         }
00747         
00748         
00749         function _initrs()
00750         {
00751         GLOBAL $ADODB_COUNTRECS;        
00752                 $this->_numOfRows = ($ADODB_COUNTRECS)? @mssql_num_rows($this->_queryID):-1;
00753                 $this->_numOfFields = @mssql_num_fields($this->_queryID);
00754         }
00755         
00756 
00757         //Contributed by "Sven Axelsson" <sven.axelsson@bokochwebb.se>
00758         // get next resultset - requires PHP 4.0.5 or later
00759         function NextRecordSet()
00760         {
00761                 if (!mssql_next_result($this->_queryID)) return false;
00762                 $this->_inited = false;
00763                 $this->bind = false;
00764                 $this->_currentRow = -1;
00765                 $this->Init();
00766                 return true;
00767         }
00768 
00769         /* Use associative array to get fields array */
00770         function Fields($colname)
00771         {
00772                 if ($this->fetchMode != ADODB_FETCH_NUM) return $this->fields[$colname];
00773                 if (!$this->bind) {
00774                         $this->bind = array();
00775                         for ($i=0; $i < $this->_numOfFields; $i++) {
00776                                 $o = $this->FetchField($i);
00777                                 $this->bind[strtoupper($o->name)] = $i;
00778                         }
00779                 }
00780                 
00781                  return $this->fields[$this->bind[strtoupper($colname)]];
00782         }
00783         
00784         /*      Returns: an object containing field information. 
00785                 Get column information in the Recordset object. fetchField() can be used in order to obtain information about
00786                 fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by
00787                 fetchField() is retrieved.      */
00788 
00789         function &FetchField($fieldOffset = -1) 
00790         {
00791                 if ($fieldOffset != -1) {
00792                         $f = @mssql_fetch_field($this->_queryID, $fieldOffset);
00793                 }
00794                 else if ($fieldOffset == -1) {  /*      The $fieldOffset argument is not provided thus its -1   */
00795                         $f = @mssql_fetch_field($this->_queryID);
00796                 }
00797                 $false = false;
00798                 if (empty($f)) return $false;
00799                 return $f;
00800         }
00801         
00802         function _seek($row) 
00803         {
00804                 return @mssql_data_seek($this->_queryID, $row);
00805         }
00806 
00807         // speedup
00808         function MoveNext() 
00809         {
00810                 if ($this->EOF) return false;
00811                 
00812                 $this->_currentRow++;
00813                 
00814                 if ($this->fetchMode & ADODB_FETCH_ASSOC) {
00815                         if ($this->fetchMode & ADODB_FETCH_NUM) {
00816                                 //ADODB_FETCH_BOTH mode
00817                                 $this->fields = @mssql_fetch_array($this->_queryID);
00818                         }
00819                         else {
00820                                 if ($this->hasFetchAssoc) {// only for PHP 4.2.0 or later
00821                                          $this->fields = @mssql_fetch_assoc($this->_queryID);
00822                                 } else {
00823                                         $flds = @mssql_fetch_array($this->_queryID);
00824                                         if (is_array($flds)) {
00825                                                 $fassoc = array();
00826                                                 foreach($flds as $k => $v) {
00827                                                         if (is_numeric($k)) continue;
00828                                                         $fassoc[$k] = $v;
00829                                                 }
00830                                                 $this->fields = $fassoc;
00831                                         } else
00832                                                 $this->fields = false;
00833                                 }
00834                         }
00835                         
00836                         if (is_array($this->fields)) {
00837                                 if (ADODB_ASSOC_CASE == 0) {
00838                                         foreach($this->fields as $k=>$v) {
00839                                                 $this->fields[strtolower($k)] = $v;
00840                                         }
00841                                 } else if (ADODB_ASSOC_CASE == 1) {
00842                                         foreach($this->fields as $k=>$v) {
00843                                                 $this->fields[strtoupper($k)] = $v;
00844                                         }
00845                                 }
00846                         }
00847                 } else {
00848                         $this->fields = @mssql_fetch_row($this->_queryID);
00849                 }
00850                 if ($this->fields) return true;
00851                 $this->EOF = true;
00852                 
00853                 return false;
00854         }
00855 
00856         
00857         // INSERT UPDATE DELETE returns false even if no error occurs in 4.0.4
00858         // also the date format has been changed from YYYY-mm-dd to dd MMM YYYY in 4.0.4. Idiot!
00859         function _fetch($ignore_fields=false) 
00860         {
00861                 if ($this->fetchMode & ADODB_FETCH_ASSOC) {
00862                         if ($this->fetchMode & ADODB_FETCH_NUM) {
00863                                 //ADODB_FETCH_BOTH mode
00864                                 $this->fields = @mssql_fetch_array($this->_queryID);
00865                         } else {
00866                                 if ($this->hasFetchAssoc) // only for PHP 4.2.0 or later
00867                                         $this->fields = @mssql_fetch_assoc($this->_queryID);
00868                                 else {
00869                                         $this->fields = @mssql_fetch_array($this->_queryID);
00870                                         if (@is_array($$this->fields)) {
00871                                                 $fassoc = array();
00872                                                 foreach($$this->fields as $k => $v) {
00873                                                         if (is_integer($k)) continue;
00874                                                         $fassoc[$k] = $v;
00875                                                 }
00876                                                 $this->fields = $fassoc;
00877                                         }
00878                                 }
00879                         }
00880                         
00881                         if (!$this->fields) {
00882                         } else if (ADODB_ASSOC_CASE == 0) {
00883                                 foreach($this->fields as $k=>$v) {
00884                                         $this->fields[strtolower($k)] = $v;
00885                                 }
00886                         } else if (ADODB_ASSOC_CASE == 1) {
00887                                 foreach($this->fields as $k=>$v) {
00888                                         $this->fields[strtoupper($k)] = $v;
00889                                 }
00890                         }
00891                 } else {
00892                         $this->fields = @mssql_fetch_row($this->_queryID);
00893                 }
00894                 return $this->fields;
00895         }
00896         
00897         /*      close() only needs to be called if you are worried about using too much memory while your script
00898                 is running. All associated result memory for the specified result identifier will automatically be freed.       */
00899 
00900         function _close() 
00901         {
00902                 $rez = mssql_free_result($this->_queryID);      
00903                 $this->_queryID = false;
00904                 return $rez;
00905         }
00906         // mssql uses a default date like Dec 30 2000 12:00AM
00907         function UnixDate($v)
00908         {
00909                 return ADORecordSet_array_mssql::UnixDate($v);
00910         }
00911         
00912         function UnixTimeStamp($v)
00913         {
00914                 return ADORecordSet_array_mssql::UnixTimeStamp($v);
00915         }
00916         
00917 }
00918 
00919 
00920 class ADORecordSet_array_mssql extends ADORecordSet_array {
00921         function ADORecordSet_array_mssql($id=-1,$mode=false) 
00922         {
00923                 $this->ADORecordSet_array($id,$mode);
00924         }
00925         
00926                 // mssql uses a default date like Dec 30 2000 12:00AM
00927         function UnixDate($v)
00928         {
00929         
00930                 if (is_numeric(substr($v,0,1)) && ADODB_PHPVER >= 0x4200) return parent::UnixDate($v);
00931                 
00932         global $ADODB_mssql_mths,$ADODB_mssql_date_order;
00933         
00934                 //Dec 30 2000 12:00AM 
00935                 if ($ADODB_mssql_date_order == 'dmy') {
00936                         if (!preg_match( "|^([0-9]{1,2})[-/\. ]+([A-Za-z]{3})[-/\. ]+([0-9]{4})|" ,$v, $rr)) {
00937                                 return parent::UnixDate($v);
00938                         }
00939                         if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
00940                         
00941                         $theday = $rr[1];
00942                         $themth =  substr(strtoupper($rr[2]),0,3);
00943                 } else {
00944                         if (!preg_match( "|^([A-Za-z]{3})[-/\. ]+([0-9]{1,2})[-/\. ]+([0-9]{4})|" ,$v, $rr)) {
00945                                 return parent::UnixDate($v);
00946                         }
00947                         if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
00948                         
00949                         $theday = $rr[2];
00950                         $themth = substr(strtoupper($rr[1]),0,3);
00951                 }
00952                 $themth = $ADODB_mssql_mths[$themth];
00953                 if ($themth <= 0) return false;
00954                 // h-m-s-MM-DD-YY
00955                 return  mktime(0,0,0,$themth,$theday,$rr[3]);
00956         }
00957         
00958         function UnixTimeStamp($v)
00959         {
00960         
00961                 if (is_numeric(substr($v,0,1)) && ADODB_PHPVER >= 0x4200) return parent::UnixTimeStamp($v);
00962                 
00963         global $ADODB_mssql_mths,$ADODB_mssql_date_order;
00964         
00965                 //Dec 30 2000 12:00AM
00966                  if ($ADODB_mssql_date_order == 'dmy') {
00967                          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})|"
00968                         ,$v, $rr)) return parent::UnixTimeStamp($v);
00969                         if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
00970                 
00971                         $theday = $rr[1];
00972                         $themth =  substr(strtoupper($rr[2]),0,3);
00973                 } else {
00974                         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})|"
00975                         ,$v, $rr)) return parent::UnixTimeStamp($v);
00976                         if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
00977                 
00978                         $theday = $rr[2];
00979                         $themth = substr(strtoupper($rr[1]),0,3);
00980                 }
00981                 
00982                 $themth = $ADODB_mssql_mths[$themth];
00983                 if ($themth <= 0) return false;
00984                 
00985                 switch (strtoupper($rr[6])) {
00986                 case 'P':
00987                         if ($rr[4]<12) $rr[4] += 12;
00988                         break;
00989                 case 'A':
00990                         if ($rr[4]==12) $rr[4] = 0;
00991                         break;
00992                 default:
00993                         break;
00994                 }
00995                 // h-m-s-MM-DD-YY
00996                 return  mktime($rr[4],$rr[5],0,$themth,$theday,$rr[3]);
00997         }
00998 }
00999 
01000 /*
01001 Code Example 1:
01002 
01003 select  object_name(constid) as constraint_name,
01004         object_name(fkeyid) as table_name, 
01005         col_name(fkeyid, fkey) as column_name,
01006         object_name(rkeyid) as referenced_table_name,
01007         col_name(rkeyid, rkey) as referenced_column_name
01008 from sysforeignkeys
01009 where object_name(fkeyid) = x
01010 order by constraint_name, table_name, referenced_table_name,  keyno
01011 
01012 Code Example 2:
01013 select  constraint_name,
01014         column_name,
01015         ordinal_position
01016 from information_schema.key_column_usage
01017 where constraint_catalog = db_name()
01018 and table_name = x
01019 order by constraint_name, ordinal_position
01020 
01021 http://www.databasejournal.com/scripts/article.php/1440551
01022 */
01023 
01024 ?>


Généré par Le spécialiste TYPO3 avec  doxygen 1.4.6