Completed
Push — master ( 20edd5...7d7f4e )
by smiley
02:32
created

PostgreSQLDriver::connect()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 31
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 31
rs 8.8571
c 0
b 0
f 0
cc 3
eloc 17
nc 3
nop 0
1
<?php
2
/**
3
 * Class PostgreSQLDriver
4
 *
5
 * @filesource   PostgreSQLDriver.php
6
 * @created      21.02.2016
7
 * @package      chillerlan\Database\Drivers\PostgreSQL
8
 * @author       Smiley <[email protected]>
9
 * @copyright    2016 Smiley
10
 * @license      MIT
11
 */
12
13
namespace chillerlan\Database\Drivers;
14
15
use chillerlan\Database\DBResult;
16
17
class PostgreSQLDriver extends DBDriverAbstract{
18
19
	protected $dialect = 'pgsql';
20
	protected $quotes = ['"', '"'];
21
22
	/**
23
	 * Holds the database resource object
24
	 *
25
	 * @var resource
26
	 */
27
	protected $db;
28
29
	/**
30
	 * Establishes a database connection and returns the connection object
31
	 *
32
	 * @return \chillerlan\Database\Drivers\DBDriverInterface
33
	 * @throws \chillerlan\Database\Drivers\DBDriverException
34
	 */
35
	public function connect():DBDriverInterface{
36
37
		if(gettype($this->db) === 'resource'){
38
			return $this;
39
		}
40
41
		// i am an ugly duckling. fix me please.
42
43
		$options = [
44
			'--client_encoding='.$this->options->pgsql_charset,
45
		];
46
47
		$conn_str = [
48
			'host=\''.$this->options->host.'\'',
49
			'port=\''.(int)$this->options->port.'\'',
50
			'dbname=\''.$this->options->database.'\'',
51
			'user=\''.$this->options->username.'\'',
52
			'password=\''.$this->options->password.'\'',
53
			'options=\''.implode(' ', $options).'\'',
54
		];
55
56
		try{
57
			$this->db = pg_connect(implode(' ', $conn_str));
58
59
			return $this;
60
		}
61
		catch(\Exception $e){
62
			throw new DBDriverException('db error: [PostgreSQLDriver]: '.$e->getMessage());
63
		}
64
65
	}
66
67
	/**
68
	 * Closes a database connection
69
	 *
70
	 * @return bool
71
	 */
72
	public function disconnect():bool{
73
		return pg_close($this->db);
74
	}
75
76
	/**
77
	 * Returns info about the used php client
78
	 *
79
	 * @return string php's database client string
80
	 */
81
	public function getClientInfo():string{
82
		$ver = pg_version($this->db);
83
84
		return 'PostgreSQL '.$ver['client'].' ('.$ver['client_encoding'].')';
85
	}
86
87
	/**
88
	 * Returns info about the database server
89
	 *
90
	 * @return string database's serverinfo string
91
	 */
92
	public function getServerInfo():string{
93
		$ver = pg_version($this->db);
94
95
		return 'PostgreSQL '.$ver['server'].' ('.$ver['server_encoding'].', date style: '.$ver['DateStyle'].', time zone: '.$ver['TimeZone'].')';
96
	}
97
98
	/**
99
	 * @param $data
100
	 *
101
	 * @return string
102
	 */
103
	public function escape($data){
104
		return pg_escape_string($this->db, $data);
105
	}
106
107
	/**
108
	 * @param             $result
109
	 * @param string|null $index
110
	 * @param bool        $assoc
111
	 *
112
	 * @return bool|\chillerlan\Database\DBResult
113
	 */
114
	protected function __getResult($result, string $index = null, bool $assoc = true){
115
116
		if(is_bool($result)){
117
			return $result; // @codeCoverageIgnore
118
		}
119
120
		$out = new DBResult(null, $this->source_encoding, $this->dest_encoding);
121
		$i   = 0;
122
123
		while($row = call_user_func_array($assoc ? 'pg_fetch_assoc' : 'pg_fetch_row', [$result])){
124
			$key = $i;
125
126
			$j = 0;
127
			foreach($row as $k => $item){
128
				// https://gitter.im/arenanet/api-cdi?at=594326ba31f589c64fafe554
129
				$t = pg_field_type($result, $j);
130
131
				switch(true){
132
					case $t === 'bool':
133
						$row[$k] = $item === 't'; break;
0 ignored issues
show
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
134
					case in_array($t, ['int2', 'int4', 'int8']):
135
						$row[$k] = (int)$item; break;
0 ignored issues
show
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
136
					case in_array($t, ['float4', 'float8']):
137
						$row[$k] = (float)$item; break;
0 ignored issues
show
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
138
				}
139
140
				$j++;
141
			}
142
143
			if($assoc && !empty($index)){
144
				$key = $row[$index];
145
			}
146
147
			$out[$key] = $row;
148
			$i++;
149
		}
150
151
		pg_free_result($result);
152
153
		return $i === 0 ? true : $out;
154
	}
155
156
	/**
157
	 * @param string      $sql
158
	 * @param string|null $index
159
	 * @param bool        $assoc
160
	 *
161
	 * @return bool|\chillerlan\Database\DBResult
162
	 */
163
	protected function __raw(string $sql, string $index = null, bool $assoc = true){
164
		return $this->__getResult(pg_query($sql), $index, $assoc);
165
	}
166
167
	/**
168
	 * @param string      $sql
169
	 * @param array       $values
170
	 * @param string|null $index
171
	 * @param bool        $assoc
172
	 *
173
	 * @return bool|\chillerlan\Database\DBResult
174
	 */
175
	protected function __prepared(string $sql, array $values = [], string $index = null, bool $assoc = true){
176
		pg_prepare($this->db, '', $this->replaceParams($sql));
177
178
		return $this->__getResult(pg_execute($this->db, '', $values), $index, $assoc);
179
	}
180
181
	/**
182
	 * @param string $sql
183
	 * @param array  $values
184
	 *
185
	 * @return bool
186
	 */
187 View Code Duplication
	protected function __multi(string $sql, array $values){
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...
188
		pg_prepare($this->db, '', $this->replaceParams($sql));
189
190
		foreach($values as $row){
191
			pg_execute($this->db, '', $row);
192
		}
193
194
		return true;
195
	}
196
197
	/**
198
	 * @param string $sql
199
	 * @param array  $data
200
	 * @param        $callback
201
	 *
202
	 * @return bool
203
	 */
204 View Code Duplication
	protected function __multi_callback(string $sql, array $data, $callback){
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...
205
		pg_prepare($this->db, '', $this->replaceParams($sql));
206
207
		foreach($data as $row){
208
			pg_execute($this->db, '', call_user_func_array($callback, [$row]));
209
		}
210
211
		return true;
212
	}
213
214
	/**
215
	 * @param string $sql
216
	 *
217
	 * @return string
218
	 */
219
	protected function replaceParams(string $sql):string{
220
		$i = 0;
221
222
		return preg_replace_callback('/(\?)/', function() use (&$i){
223
			return '$'.++$i;
224
		}, $sql);
225
	}
226
227
}
228