1<?php
2/**
3 * Microsoft SQL Server ADO driver.
4 *
5 * Requires ADO and MSSQL client. Works only on MS Windows.
6 *
7 * This file is part of ADOdb, a Database Abstraction Layer library for PHP.
8 *
9 * @package ADOdb
10 * @link https://adodb.org Project's web site and documentation
11 * @link https://github.com/ADOdb/ADOdb Source code and issue tracker
12 *
13 * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause
14 * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option,
15 * any later version. This means you can use it in proprietary products.
16 * See the LICENSE.md file distributed with this source code for details.
17 * @license BSD-3-Clause
18 * @license LGPL-2.1-or-later
19 *
20 * @copyright 2000-2013 John Lim
21 * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community
22 */
23
24// security - hide paths
25if (!defined('ADODB_DIR')) die();
26
27if (!defined('_ADODB_ADO_LAYER')) {
28	include_once(ADODB_DIR . "/drivers/adodb-ado5.inc.php");
29}
30
31
32class  ADODB_ado_mssql extends ADODB_ado {
33	var $databaseType = 'ado_mssql';
34	var $hasTop = 'top';
35	var $hasInsertID = true;
36	var $sysDate = 'convert(datetime,convert(char,GetDate(),102),102)';
37	var $sysTimeStamp = 'GetDate()';
38	var $leftOuter = '*=';
39	var $rightOuter = '=*';
40	var $ansiOuter = true; // for mssql7 or later
41	var $substr = "substring";
42	var $length = 'len';
43	var $_dropSeqSQL = "drop table %s";
44
45	//var $_inTransaction = 1; // always open recordsets, so no transaction problems.
46
47	protected function _insertID($table = '', $column = '')
48	{
49			return $this->GetOne('select SCOPE_IDENTITY()');
50	}
51
52	function _affectedrows()
53	{
54			return $this->GetOne('select @@rowcount');
55	}
56
57	function SetTransactionMode( $transaction_mode )
58	{
59		$this->_transmode  = $transaction_mode;
60		if (empty($transaction_mode)) {
61			$this->Execute('SET TRANSACTION ISOLATION LEVEL READ COMMITTED');
62			return;
63		}
64		if (!stristr($transaction_mode,'isolation')) $transaction_mode = 'ISOLATION LEVEL '.$transaction_mode;
65		$this->Execute("SET TRANSACTION ".$transaction_mode);
66	}
67
68	function qStr($s, $magic_quotes=false)
69	{
70		$s = ADOConnection::qStr($s);
71		return str_replace("\0", "\\\\000", $s);
72	}
73
74	function MetaColumns($table, $normalize=true)
75	{
76		$table = strtoupper($table);
77		$arr= array();
78		$dbc = $this->_connectionID;
79
80		$osoptions = array();
81		$osoptions[0] = null;
82		$osoptions[1] = null;
83		$osoptions[2] = $table;
84		$osoptions[3] = null;
85
86		$adors=@$dbc->OpenSchema(4, $osoptions);//tables
87
88		if ($adors){
89			while (!$adors->EOF){
90				$fld = new ADOFieldObject();
91				$c = $adors->Fields(3);
92				$fld->name = $c->Value;
93				$fld->type = 'CHAR'; // cannot discover type in ADO!
94				$fld->max_length = -1;
95				$arr[strtoupper($fld->name)]=$fld;
96
97				$adors->MoveNext();
98			}
99			$adors->Close();
100		}
101		$false = false;
102		return empty($arr) ? $false : $arr;
103	}
104
105	function CreateSequence($seq='adodbseq',$start=1)
106	{
107
108		$this->Execute('BEGIN TRANSACTION adodbseq');
109		$start -= 1;
110		$this->Execute("create table $seq (id float(53))");
111		$ok = $this->Execute("insert into $seq with (tablock,holdlock) values($start)");
112		if (!$ok) {
113				$this->Execute('ROLLBACK TRANSACTION adodbseq');
114				return false;
115		}
116		$this->Execute('COMMIT TRANSACTION adodbseq');
117		return true;
118	}
119
120	function GenID($seq='adodbseq',$start=1)
121	{
122		//$this->debug=1;
123		$this->Execute('BEGIN TRANSACTION adodbseq');
124		$ok = $this->Execute("update $seq with (tablock,holdlock) set id = id + 1");
125		if (!$ok) {
126			$this->Execute("create table $seq (id float(53))");
127			$ok = $this->Execute("insert into $seq with (tablock,holdlock) values($start)");
128			if (!$ok) {
129				$this->Execute('ROLLBACK TRANSACTION adodbseq');
130				return false;
131			}
132			$this->Execute('COMMIT TRANSACTION adodbseq');
133			return $start;
134		}
135		$num = $this->GetOne("select id from $seq");
136		$this->Execute('COMMIT TRANSACTION adodbseq');
137		return $num;
138
139		// in old implementation, pre 1.90, we returned GUID...
140		//return $this->GetOne("SELECT CONVERT(varchar(255), NEWID()) AS 'Char'");
141	}
142
143} // end class
144
145class ADORecordSet_ado_mssql extends ADORecordSet_ado {
146
147	var $databaseType = 'ado_mssql';
148
149}
150