PostgreSQL::__getResult()   B
last analyzed

Complexity

Conditions 11
Paths 23

Size

Total Lines 42
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 22
nc 23
nop 3
dl 0
loc 42
rs 7.3166
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Class PostgreSQL
4
 *
5
 * @filesource   PostgreSQL.php
6
 * @created      28.06.2017
7
 * @package      chillerlan\Database\Drivers
8
 * @author       Smiley <[email protected]>
9
 * @copyright    2017 Smiley
10
 * @license      MIT
11
 *
12
 * @noinspection PhpComposerExtensionStubsInspection
13
 */
14
15
namespace chillerlan\Database\Drivers;
16
17
use chillerlan\Database\{
18
	Dialects\Postgres, Result
19
};
20
21
/**
22
 * @property resource $db
23
 */
24
class PostgreSQL extends DriverAbstract{
25
26
	protected string $dialect = Postgres::class;
27
28
	/** @inheritdoc */
29
	public function connect():DriverInterface{
30
31
		if(gettype($this->db) === 'resource'){
32
			return $this;
33
		}
34
35
		// i am an ugly duckling. fix me please.
36
37
		$options = [
38
			'--client_encoding='.$this->options->pgsql_charset,
39
		];
40
41
		$conn_str = [
42
			'host=\''.$this->options->host.'\'',
43
			'port=\''.(int)$this->options->port.'\'',
44
			'dbname=\''.$this->options->database.'\'',
45
			'user=\''.$this->options->username.'\'',
46
			'password=\''.$this->options->password.'\'',
47
			'options=\''.implode(' ', $options).'\'',
48
		];
49
50
		try{
51
			$this->db = pg_connect(implode(' ', $conn_str));
52
53
			return $this;
54
		}
55
		catch(\Exception $e){
56
			throw new DriverException('db error: [PostgreSQL]: '.$e->getMessage());
57
		}
58
59
	}
60
61
	/** @inheritdoc */
62
	public function disconnect():bool{
63
64
		if(gettype($this->db) === 'resource'){
65
			return pg_close($this->db);
66
		}
67
68
		return true;
69
	}
70
71
	/** @inheritdoc */
72
	public function getClientInfo():string{
73
		$ver = pg_version($this->db);
74
75
		return 'PostgreSQL '.$ver['client'].' ('.$ver['client_encoding'].')';
76
	}
77
78
	/** @inheritdoc */
79
	public function getServerInfo():?string{
80
		$ver = pg_version($this->db);
81
82
		return 'PostgreSQL '.$ver['server'].' ('.$ver['server_encoding'].', date style: '.$ver['DateStyle'].', time zone: '.$ver['TimeZone'].')';
83
	}
84
85
	/** @inheritdoc */
86
	protected function __escape(string $data):string{
87
		return '\''.pg_escape_string($this->db, $data).'\''; // emulate PDO
88
	}
89
90
	/**
91
	 * @param             $result
92
	 * @param string|null $index
93
	 * @param bool        $assoc
94
	 *
95
	 * @return bool|\chillerlan\Database\Result
96
	 */
97
	protected function __getResult($result, string $index = null, bool $assoc = null){
98
99
		if(is_bool($result)){
100
			return $result; // @codeCoverageIgnore
101
		}
102
103
		$out = new Result(null, $this->convert_encoding_src, $this->convert_encoding_dest);
104
		$i   = 0;
105
106
		while($row = call_user_func_array($assoc === true ? 'pg_fetch_assoc' : 'pg_fetch_row', [$result])){
107
			$key = $i;
108
109
			$j = 0;
110
			foreach($row as $k => $item){
111
				// https://gitter.im/arenanet/api-cdi?at=594326ba31f589c64fafe554
112
				$fieldType = pg_field_type($result, $j);
113
114
				if($fieldType === 'bool'){
115
					$row[$k] = $item === 't';
116
				}
117
				elseif(in_array($fieldType, ['int2', 'int4', 'int8'], true)){
118
					$row[$k] = (int)$item;
119
120
				}
121
				elseif(in_array($fieldType, ['float4', 'float8'], true)){
122
					$row[$k] = (float)$item; // @codeCoverageIgnore
123
				}
124
125
				$j++;
126
			}
127
128
			if($assoc && !empty($index)){
129
				$key = $row[$index];
130
			}
131
132
			$out[$key] = $row;
133
			$i++;
134
		}
135
136
		pg_free_result($result);
137
138
		return $i === 0 ? true : $out;
139
	}
140
141
	/** @inheritdoc */
142
	protected function raw_query(string $sql, string $index = null, bool $assoc = null){
143
		return $this->__getResult(pg_query($sql), $index, $assoc);
0 ignored issues
show
Bug introduced by
$sql of type string is incompatible with the type resource expected by parameter $connection of pg_query(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

143
		return $this->__getResult(pg_query(/** @scrutinizer ignore-type */ $sql), $index, $assoc);
Loading history...
Bug introduced by
The call to pg_query() has too few arguments starting with query. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

143
		return $this->__getResult(/** @scrutinizer ignore-call */ pg_query($sql), $index, $assoc);

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
144
	}
145
146
	/** @inheritdoc */
147
	protected function prepared_query(string $sql, array $values = null, string $index = null, bool $assoc = null){
148
		pg_prepare($this->db, '', $this->replaceParams($sql));
149
150
		return $this->__getResult(pg_execute($this->db, '', $values), $index, $assoc);
0 ignored issues
show
Bug introduced by
It seems like $values can also be of type null; however, parameter $params of pg_execute() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

150
		return $this->__getResult(pg_execute($this->db, '', /** @scrutinizer ignore-type */ $values), $index, $assoc);
Loading history...
151
	}
152
153
	/** @inheritdoc */
154
	protected function multi_query(string $sql, array $values){
155
		pg_prepare($this->db, '', $this->replaceParams($sql));
156
157
		foreach($values as $row){
158
			pg_execute($this->db, '', $row);
159
		}
160
161
		return true;
162
	}
163
164
	/** @inheritdoc */
165
	protected function multi_callback_query(string $sql, iterable $data, $callback){
166
		pg_prepare($this->db, '', $this->replaceParams($sql));
167
168
		foreach($data as $k => $row){
169
			pg_execute($this->db, '', call_user_func_array($callback, [$row, $k]));
170
		}
171
172
		return true;
173
	}
174
175
	/** @inheritdoc */
176
	protected function replaceParams(string $sql):string{
177
		$i = 0;
178
179
		return preg_replace_callback('/(\?)/', function() use (&$i){
180
			return '$'.++$i;
181
		}, $sql);
182
	}
183
184
}
185