MySQL::fieldspec()   F
last analyzed

Complexity

Conditions 25
Paths 2880

Size

Total Lines 71
Code Lines 44

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 25
eloc 44
nc 2880
nop 9
dl 0
loc 71
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

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:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/**
3
 * Class MySQL
4
 *
5
 * @filesource   MySQL.php
6
 * @created      11.01.2018
7
 * @package      chillerlan\Database\Dialects
8
 * @author       Smiley <[email protected]>
9
 * @copyright    2018 Smiley
10
 * @license      MIT
11
 */
12
13
namespace chillerlan\Database\Dialects;
14
15
class MySQL extends DialectAbstract{
16
17
	protected array $quotes = ['`', '`'];
18
	protected string $charset = 'utf8mb4_bin';
19
20
	/** @inheritdoc */
21
	public function insert(string $table, array $fields, string $onConflict = null, string $conflictTarget = null):array{
22
		$onConflict = strtoupper($onConflict);
0 ignored issues
show
Bug introduced by
It seems like $onConflict can also be of type null; however, parameter $string of strtoupper() does only seem to accept string, 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

22
		$onConflict = strtoupper(/** @scrutinizer ignore-type */ $onConflict);
Loading history...
23
24
		switch($onConflict){
25
			case 'IGNORE':
26
				$sql = ['INSERT IGNORE'];
27
				break;
28
			case 'REPLACE':
29
				$sql = ['REPLACE'];
30
				break;
31
			default:
32
				$sql = ['INSERT'];
33
		}
34
35
		$sql[] = 'INTO';
36
		$sql[] = $this->quote($table);
37
		$sql[] = '('.$this->quotes[0].implode($this->quotes[1].', '.$this->quotes[0], $fields).$this->quotes[1].')';
38
		$sql[] = 'VALUES';
39
		$sql[] = '('.implode(',', array_fill(0, count($fields), '?')).')';
40
41
		return $sql;
42
	}
43
44
	/** @inheritdoc */
45
	public function createDatabase(string $dbname, bool $ifNotExists = null, string $collate = null):array {
46
		$collate = $collate ?? $this->charset;
47
48
		$sql[] = 'CREATE DATABASE';
0 ignored issues
show
Comprehensibility Best Practice introduced by
$sql was never initialized. Although not strictly required by PHP, it is generally a good practice to add $sql = array(); before regardless.
Loading history...
49
50
		if($ifNotExists){
51
			$sql[] = 'IF NOT EXISTS';
52
		}
53
54
		$sql[] = $this->quote($dbname);
55
56
		if(!empty($collate)){
57
			[$charset] = explode('_', $collate);
58
59
			$sql[] = 'CHARACTER SET';
60
			$sql[] = $charset;
61
62
			if($collate !== $charset){
63
				$sql[] = 'COLLATE';
64
				$sql[] = $collate;
65
			}
66
67
		}
68
69
		return $sql;
70
	}
71
72
	/** @inheritdoc */
73
	public function createTable(string $table, array $cols, string $primaryKey = null, bool $ifNotExists = null, bool $temp = null, string $dir = null):array {
74
		$sql = ['CREATE'];
75
76
		if($temp){
77
			$sql[] = 'TEMPORARY';
78
		}
79
80
		$sql[] = 'TABLE' ;
81
82
		if($ifNotExists){
83
			$sql[] =  'IF NOT EXISTS' ;
84
		}
85
86
		$sql[] =  $this->quote($table);
87
88
		if(!empty($cols)){
89
			$sql[] = '(';
90
			$sql[] = implode(', ', $cols);
91
92
			if(!empty($primaryKey)){
93
				$sql[] = ', PRIMARY KEY (';
94
				$sql[] = $this->quote($primaryKey);
95
				$sql[] =  ')';
96
			}
97
98
			$sql[] = ')';
99
		}
100
101
		if(!empty($this->charset)){
102
			[$charset] = explode('_', $this->charset);
103
104
			$sql[] = 'CHARACTER SET';
105
			$sql[] = $charset;
106
107
			if($charset !== $this->charset){
108
				$sql[] = 'COLLATE';
109
				$sql[] = $this->charset;
110
			}
111
112
		}
113
114
		return $sql;
115
	}
116
117
	/** @inheritdoc */
118
	public function fieldspec(string $name, string $type, $length = null, string $attribute = null, string $collation = null, bool $isNull = null, string $defaultType = null, $defaultValue = null, string $extra = null):string {
119
		$type = strtoupper(trim($type));
120
		$defaultType = strtoupper($defaultType);
0 ignored issues
show
Bug introduced by
It seems like $defaultType can also be of type null; however, parameter $string of strtoupper() does only seem to accept string, 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

120
		$defaultType = strtoupper(/** @scrutinizer ignore-type */ $defaultType);
Loading history...
121
122
123
		$field = [$this->quote(trim($name))];
124
125
		// @todo: whitelist types?
126
		$nolengthtypes = ['DATE', 'TINYBLOB', 'TINYTEXT', 'BLOB', 'TEXT', 'MEDIUMBLOB',
127
		                  'MEDIUMTEXT', 'LONGBLOB', 'LONGTEXT', 'SERIAL', 'BOOLEAN', 'UUID'];
128
129
		$field[] = (is_int($length) || (is_string($length) && count(explode(',', $length)) === 2)) && !in_array($type, $nolengthtypes, true)
130
			? $type.'('. $length . ')'
131
			: $type;
132
133
		if($attribute){
134
			$field[] = strtoupper($attribute);
135
		}
136
137
		$collationtypes = ['TINYTEXT', 'TEXT', 'MEDIUMTEXT', 'LONGTEXT', 'VARCHAR', 'CHAR', 'ENUM', 'SET'];
138
		if($collation && in_array($type, $collationtypes, true)){
139
			[$charset] = explode('_', $collation);
140
141
			$field[] = 'CHARACTER SET '.$charset;
142
143
			if($charset !== $collation){
144
				$field[] = 'COLLATE '.$collation;
145
			}
146
147
		}
148
149
		if($isNull !== null){
150
			$field[] = $isNull ? 'NULL' : 'NOT NULL';
151
		}
152
153
		if($defaultType === 'USER_DEFINED'){
154
155
			switch(true){
156
				case $type === 'TIMESTAMP' && intval($defaultValue) === 0:
157
					$field[] = 'DEFAULT 0';
158
					break;
159
				case $type === 'BIT':
160
					$field[] = 'DEFAULT b\''.preg_replace('/[^01]/', '0', $defaultValue).'\'';
161
					break;
162
				case $type === 'BOOLEAN':
163
					$field[] = 'DEFAULT '.(preg_match('/^1|T|TRUE|YES$/i', $defaultValue) ? 'TRUE' : 'FALSE');
164
					break;
165
				case $type === 'BINARY' || $type === 'VARBINARY':
166
					$field[] = 'DEFAULT 0x'.$defaultValue;
167
					break;
168
				case strtoupper($defaultValue) === 'NULL' && $isNull === true:
169
					$field[] = 'DEFAULT NULL';
170
					break;
171
				default:
172
					$field[] = 'DEFAULT \''.$defaultValue.'\'';
173
			}
174
175
		}
176
		else if($defaultType === 'CURRENT_TIMESTAMP'){
177
			$field[] = 'DEFAULT CURRENT_TIMESTAMP';
178
		}
179
		else if($defaultType === 'NULL' && $isNull === true){
180
			$field[] = 'DEFAULT NULL';
181
		}
182
183
184
		if($extra){
185
			$field[] = $extra;
186
		}
187
188
		return implode(' ', $field);
189
	}
190
191
	/** @inheritdoc */
192
	public function showDatabases():array{
193
		return ['SHOW DATABASES'];
194
	}
195
196
	/** @inheritdoc */
197
	public function showTables(string $database = null, string $pattern = null, string $where = null):array{
198
		return ['SHOW TABLES'];
199
	}
200
201
	/** @inheritdoc */
202
	public function showCreateTable(string $table):array{
203
		$sql = ['SHOW CREATE TABLE'];
204
		$sql[] = $this->quote($table);
205
206
		return $sql;
207
	}
208
209
}
210