|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 /* 00003 V5.14 8 Sept 2011 (c) 2000-2011 John Lim (jlim#natsoft.com). 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 MSSQL support via ODBC. Requires ODBC. Works on Windows and Unix. 00012 For Unix configuration, see http://phpbuilder.com/columns/alberto20000919.php3 00013 */ 00014 00015 // security - hide paths 00016 if (!defined('ADODB_DIR')) die(); 00017 00018 if (!defined('_ADODB_ODBC_LAYER')) { 00019 include(ADODB_DIR."/drivers/adodb-odbc.inc.php"); 00020 } 00021 00022 00023 class ADODB_odbc_mssql extends ADODB_odbc { 00024 var $databaseType = 'odbc_mssql'; 00025 var $fmtDate = "'Y-m-d'"; 00026 var $fmtTimeStamp = "'Y-m-d H:i:s'"; 00027 var $_bindInputArray = true; 00028 var $metaDatabasesSQL = "select name from sysdatabases where name <> 'master'"; 00029 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'))"; 00030 var $metaColumnsSQL = "select c.name,t.name,c.length from syscolumns c join systypes t on t.xusertype=c.xusertype join sysobjects o on o.id=c.id where o.name='%s'"; 00031 var $hasTop = 'top'; // support mssql/interbase SELECT TOP 10 * FROM TABLE 00032 var $sysDate = 'GetDate()'; 00033 var $sysTimeStamp = 'GetDate()'; 00034 var $leftOuter = '*='; 00035 var $rightOuter = '=*'; 00036 var $substr = 'substring'; 00037 var $length = 'len'; 00038 var $ansiOuter = true; // for mssql7 or later 00039 var $identitySQL = 'select SCOPE_IDENTITY()'; // 'select SCOPE_IDENTITY'; # for mssql 2000 00040 var $hasInsertID = true; 00041 var $connectStmt = 'SET CONCAT_NULL_YIELDS_NULL OFF'; # When SET CONCAT_NULL_YIELDS_NULL is ON, 00042 # concatenating a null value with a string yields a NULL result 00043 00044 function ADODB_odbc_mssql() 00045 { 00046 $this->ADODB_odbc(); 00047 //$this->curmode = SQL_CUR_USE_ODBC; 00048 } 00049 00050 // crashes php... 00051 function ServerInfo() 00052 { 00053 global $ADODB_FETCH_MODE; 00054 $save = $ADODB_FETCH_MODE; 00055 $ADODB_FETCH_MODE = ADODB_FETCH_NUM; 00056 $row = $this->GetRow("execute sp_server_info 2"); 00057 $ADODB_FETCH_MODE = $save; 00058 if (!is_array($row)) return false; 00059 $arr['description'] = $row[2]; 00060 $arr['version'] = ADOConnection::_findvers($arr['description']); 00061 return $arr; 00062 } 00063 00064 function IfNull( $field, $ifNull ) 00065 { 00066 return " ISNULL($field, $ifNull) "; // if MS SQL Server 00067 } 00068 00069 function _insertid() 00070 { 00071 // SCOPE_IDENTITY() 00072 // Returns the last IDENTITY value inserted into an IDENTITY column in 00073 // the same scope. A scope is a module -- a stored procedure, trigger, 00074 // function, or batch. Thus, two statements are in the same scope if 00075 // they are in the same stored procedure, function, or batch. 00076 return $this->GetOne($this->identitySQL); 00077 } 00078 00079 00080 function MetaForeignKeys($table, $owner=false, $upper=false) 00081 { 00082 global $ADODB_FETCH_MODE; 00083 00084 $save = $ADODB_FETCH_MODE; 00085 $ADODB_FETCH_MODE = ADODB_FETCH_NUM; 00086 $table = $this->qstr(strtoupper($table)); 00087 00088 $sql = 00089 "select object_name(constid) as constraint_name, 00090 col_name(fkeyid, fkey) as column_name, 00091 object_name(rkeyid) as referenced_table_name, 00092 col_name(rkeyid, rkey) as referenced_column_name 00093 from sysforeignkeys 00094 where upper(object_name(fkeyid)) = $table 00095 order by constraint_name, referenced_table_name, keyno"; 00096 00097 $constraints = $this->GetArray($sql); 00098 00099 $ADODB_FETCH_MODE = $save; 00100 00101 $arr = false; 00102 foreach($constraints as $constr) { 00103 //print_r($constr); 00104 $arr[$constr[0]][$constr[2]][] = $constr[1].'='.$constr[3]; 00105 } 00106 if (!$arr) return false; 00107 00108 $arr2 = false; 00109 00110 foreach($arr as $k => $v) { 00111 foreach($v as $a => $b) { 00112 if ($upper) $a = strtoupper($a); 00113 $arr2[$a] = $b; 00114 } 00115 } 00116 return $arr2; 00117 } 00118 00119 function MetaTables($ttype=false,$showSchema=false,$mask=false) 00120 { 00121 if ($mask) {$this->debug=1; 00122 $save = $this->metaTablesSQL; 00123 $mask = $this->qstr($mask); 00124 $this->metaTablesSQL .= " AND name like $mask"; 00125 } 00126 $ret = ADOConnection::MetaTables($ttype,$showSchema); 00127 00128 if ($mask) { 00129 $this->metaTablesSQL = $save; 00130 } 00131 return $ret; 00132 } 00133 00134 function MetaColumns($table, $normalize=true) 00135 { 00136 $arr = ADOConnection::MetaColumns($table); 00137 return $arr; 00138 } 00139 00140 00141 function MetaIndexes($table,$primary=false, $owner=false) 00142 { 00143 $table = $this->qstr($table); 00144 00145 $sql = "SELECT i.name AS ind_name, C.name AS col_name, USER_NAME(O.uid) AS Owner, c.colid, k.Keyno, 00146 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, 00147 CASE WHEN I.status & 2 = 2 THEN 1 ELSE 0 END AS IsUnique 00148 FROM dbo.sysobjects o INNER JOIN dbo.sysindexes I ON o.id = i.id 00149 INNER JOIN dbo.sysindexkeys K ON I.id = K.id AND I.Indid = K.Indid 00150 INNER JOIN dbo.syscolumns c ON K.id = C.id AND K.colid = C.Colid 00151 WHERE LEFT(i.name, 8) <> '_WA_Sys_' AND o.status >= 0 AND O.Name LIKE $table 00152 ORDER BY O.name, I.Name, K.keyno"; 00153 00154 global $ADODB_FETCH_MODE; 00155 $save = $ADODB_FETCH_MODE; 00156 $ADODB_FETCH_MODE = ADODB_FETCH_NUM; 00157 if ($this->fetchMode !== FALSE) { 00158 $savem = $this->SetFetchMode(FALSE); 00159 } 00160 00161 $rs = $this->Execute($sql); 00162 if (isset($savem)) { 00163 $this->SetFetchMode($savem); 00164 } 00165 $ADODB_FETCH_MODE = $save; 00166 00167 if (!is_object($rs)) { 00168 return FALSE; 00169 } 00170 00171 $indexes = array(); 00172 while ($row = $rs->FetchRow()) { 00173 if (!$primary && $row[5]) continue; 00174 00175 $indexes[$row[0]]['unique'] = $row[6]; 00176 $indexes[$row[0]]['columns'][] = $row[1]; 00177 } 00178 return $indexes; 00179 } 00180 00181 function _query($sql,$inputarr=false) 00182 { 00183 if (is_string($sql)) $sql = str_replace('||','+',$sql); 00184 return ADODB_odbc::_query($sql,$inputarr); 00185 } 00186 00187 function SetTransactionMode( $transaction_mode ) 00188 { 00189 $this->_transmode = $transaction_mode; 00190 if (empty($transaction_mode)) { 00191 $this->Execute('SET TRANSACTION ISOLATION LEVEL READ COMMITTED'); 00192 return; 00193 } 00194 if (!stristr($transaction_mode,'isolation')) $transaction_mode = 'ISOLATION LEVEL '.$transaction_mode; 00195 $this->Execute("SET TRANSACTION ".$transaction_mode); 00196 } 00197 00198 // "Stein-Aksel Basma" <basma@accelero.no> 00199 // tested with MSSQL 2000 00200 function MetaPrimaryKeys($table) 00201 { 00202 global $ADODB_FETCH_MODE; 00203 00204 $schema = ''; 00205 $this->_findschema($table,$schema); 00206 //if (!$schema) $schema = $this->database; 00207 if ($schema) $schema = "and k.table_catalog like '$schema%'"; 00208 00209 $sql = "select distinct k.column_name,ordinal_position from information_schema.key_column_usage k, 00210 information_schema.table_constraints tc 00211 where tc.constraint_name = k.constraint_name and tc.constraint_type = 00212 'PRIMARY KEY' and k.table_name = '$table' $schema order by ordinal_position "; 00213 00214 $savem = $ADODB_FETCH_MODE; 00215 $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC; 00216 $a = $this->GetCol($sql); 00217 $ADODB_FETCH_MODE = $savem; 00218 00219 if ($a && sizeof($a)>0) return $a; 00220 $false = false; 00221 return $false; 00222 } 00223 00224 function SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0) 00225 { 00226 if ($nrows > 0 && $offset <= 0) { 00227 $sql = preg_replace( 00228 '/(^\s*select\s+(distinctrow|distinct)?)/i','\\1 '.$this->hasTop." $nrows ",$sql); 00229 $rs = $this->Execute($sql,$inputarr); 00230 } else 00231 $rs = ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache); 00232 00233 return $rs; 00234 } 00235 00236 // Format date column in sql string given an input format that understands Y M D 00237 function SQLDate($fmt, $col=false) 00238 { 00239 if (!$col) $col = $this->sysTimeStamp; 00240 $s = ''; 00241 00242 $len = strlen($fmt); 00243 for ($i=0; $i < $len; $i++) { 00244 if ($s) $s .= '+'; 00245 $ch = $fmt[$i]; 00246 switch($ch) { 00247 case 'Y': 00248 case 'y': 00249 $s .= "datename(yyyy,$col)"; 00250 break; 00251 case 'M': 00252 $s .= "convert(char(3),$col,0)"; 00253 break; 00254 case 'm': 00255 $s .= "replace(str(month($col),2),' ','0')"; 00256 break; 00257 case 'Q': 00258 case 'q': 00259 $s .= "datename(quarter,$col)"; 00260 break; 00261 case 'D': 00262 case 'd': 00263 $s .= "replace(str(day($col),2),' ','0')"; 00264 break; 00265 case 'h': 00266 $s .= "substring(convert(char(14),$col,0),13,2)"; 00267 break; 00268 00269 case 'H': 00270 $s .= "replace(str(datepart(hh,$col),2),' ','0')"; 00271 break; 00272 00273 case 'i': 00274 $s .= "replace(str(datepart(mi,$col),2),' ','0')"; 00275 break; 00276 case 's': 00277 $s .= "replace(str(datepart(ss,$col),2),' ','0')"; 00278 break; 00279 case 'a': 00280 case 'A': 00281 $s .= "substring(convert(char(19),$col,0),18,2)"; 00282 break; 00283 00284 default: 00285 if ($ch == '\\') { 00286 $i++; 00287 $ch = substr($fmt,$i,1); 00288 } 00289 $s .= $this->qstr($ch); 00290 break; 00291 } 00292 } 00293 return $s; 00294 } 00295 00296 } 00297 00298 class ADORecordSet_odbc_mssql extends ADORecordSet_odbc { 00299 00300 var $databaseType = 'odbc_mssql'; 00301 00302 function ADORecordSet_odbc_mssql($id,$mode=false) 00303 { 00304 return $this->ADORecordSet_odbc($id,$mode); 00305 } 00306 } 00307 ?>