Completed
Push — master ( 0edda6...2a1c69 )
by Chris
04:06
created

SqlServer::disconnect()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 7
rs 9.4285
cc 2
eloc 4
nc 2
nop 0
1
<?php
2
namespace Darya\Database\Connection;
3
4
use Darya\Database\AbstractConnection;
5
use Darya\Database\Error;
6
use Darya\Database\Query\Translator;
7
use Darya\Database\Result;
8
use Darya\Database\Query;
9
10
/**
11
 * Darya's SQL Server (MSSQL) database interface for Windows.
12
 * 
13
 * @author Chris Andrew <[email protected]>
14
 */
15
class SqlServer extends AbstractConnection {
16
	
17
	/**
18
	 * Initiate the connection.
19
	 * 
20
	 * @return bool
21
	 */
22
	public function connect() {
23
		if ($this->connected()) {
24
			return true;
25
		}
26
		
27
		$host = $this->details['host'];
28
		
29
		if ($this->details['port']) {
30
			$host .= ', ' . $this->details['port'];
31
		}
32
		
33
		$this->connection = sqlsrv_connect($this->details['host'], array(
34
			'UID'      => $this->details['user'],
35
			'PWD'      => $this->details['pass'],
36
			'Database' => $this->details['name']
37
		));
38
		
39
		if ($this->error()) {
40
			return false;
41
		}
42
		
43
		return $this->connected = true;
44
	}
45
	
46
	/**
47
	 * Close the connection.
48
	 */
49
	public function disconnect() {
50
		if ($this->connected()) {
51
			sqlsrv_close($this->connection);
52
		}
53
		
54
		$this->connected = false;
55
	}
56
	
57
	/**
58
	 * Retrieve the query translator.
59
	 * 
60
	 * @return Translator
61
	 */
62
	public function translator() {
63
		if (!$this->translator) {
64
			$this->translator = new Translator\SqlServer;
65
		}
66
		
67
		return $this->translator;
68
	}
69
	
70
	/**
71
	 * Query the database for the last ID generated, if the given query is
72
	 * an insert query.
73
	 * 
74
	 * TODO: Use SCOPE_IDENTITY() instead?
75
	 * 
76
	 * @param string $query
77
	 * @return int
78
	 */
79
	protected function queryInsertId($query) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
80
		if (!preg_match('/^\s*INSERT\s+INTO\b/i', $query)) {
81
			return null;
82
		}
83
		
84
		$result = sqlsrv_query($this->connection, "SELECT @@IDENTITY id");
85
		list($id) = sqlsrv_fetch_array($result, SQLSRV_FETCH_NUMERIC);
86
		
87
		return $id;
88
	}
89
	
90
	/**
91
	 * Query the database for the number of rows affected by the last query.
92
	 * 
93
	 * @param string $query
94
	 * @return int
95
	 */
96
	protected function queryAffected($query) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
97
		if (preg_match('/^\s*SELECT\b/i', $query)) {
98
			return null;
99
		}
100
		
101
		$result = sqlsrv_query($this->connection, "SELECT @@ROWCOUNT affected");
102
		list($affected) = sqlsrv_fetch_array($result, SQLSRV_FETCH_NUMERIC);
103
		
104
		return $affected;
105
	}
106
	
107
	/**
108
	 * Query the database.
109
	 * 
110
	 * TODO: Also simplify this.
111
	 * 
112
	 * @param Query|string $query
113
	 * @param array        $parameters [optional]
114
	 * @return Result
115
	 */
116
	public function query($query, array $parameters = array()) {
117
		if (!$query instanceof Query) {
118
			$query = new Query($query, $parameters);
119
		}
120
		
121
		$this->connect();
122
		
123 View Code Duplication
		if (!$this->connected()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
124
			$this->lastResult = new Result($query, array(), array(), $this->error());
125
			
126
			$this->event('sqlserver.query', array($this->lastResult));
127
			
128
			return $this->lastResult;
129
		}
130
		
131
		$this->lastResult = null;
132
		
133
		$this->event('sqlserver.prequery', array($query));
134
		
135
		$mssql_result = sqlsrv_query($this->connection, $query->string, $query->parameters, array(
136
			'Scrollable' => SQLSRV_CURSOR_CLIENT_BUFFERED
137
		));
138
		
139
		$result = array(
140
			'data'      => array(),
141
			'fields'    => array(),
142
			'affected'  => null,
143
			'num_rows'  => null,
144
			'insert_id' => null
145
		);
146
		
147
		$error = $this->error();
148
		
149
		if ($mssql_result === false || $error) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
150
			$this->lastResult = new Result($query, array(), array(), $error);
151
			
152
			$this->event('sqlserver.query', array($this->lastResult));
153
			
154
			return $this->lastResult;
155
		}
156
		
157
		$result['num_rows'] = sqlsrv_num_rows($mssql_result);
158
		
159
		if ($result['num_rows']) {
160
			while ($row = sqlsrv_fetch_array($mssql_result, SQLSRV_FETCH_ASSOC)) {
161
				if (!$result['fields']) {
162
					$result['fields'] = array_keys($row);
163
				}
164
				
165
				$result['data'][] = $row;
166
			}
167
		}
168
		
169
		$result['insert_id'] = $this->queryInsertId($query);
170
		$result['affected'] = $this->queryAffected($query);
171
		
172
		$info = array(
173
			'count'     => $result['num_rows'],
174
			'fields'    => $result['fields'],
175
			'affected'  => $result['affected'],
176
			'insert_id' => $result['insert_id']
177
		);
178
		
179
		$this->lastResult = new Result($query, $result['data'], $info, $error);
180
		
181
		$this->event('sqlserver.query', array($this->lastResult));
182
		
183
		return $this->lastResult;
184
	}
185
	
186
	/**
187
	 * Retrieve error information regarding the last query or connection
188
	 * attempt.
189
	 * 
190
	 * Returns null if there is no error.
191
	 * 
192
	 * @return Error
193
	 */
194
	public function error() {
195
		$errors = sqlsrv_errors(SQLSRV_ERR_ERRORS);
196
		
197
		if (!$errors) {
198
			return null;
199
		}
200
		
201
		return new Error($errors[0]['code'], $errors[0]['message']);
202
	}
203
}
204