Completed
Push — master ( b141fe...2d6784 )
by smiley
02:06
created

CreateTable::sql()   C

Complexity

Conditions 8
Paths 37

Size

Total Lines 34
Code Lines 19

Duplication

Lines 9
Ratio 26.47 %

Importance

Changes 0
Metric Value
dl 9
loc 34
rs 5.3846
c 0
b 0
f 0
cc 8
eloc 19
nc 37
nop 0
1
<?php
2
/**
3
 * Class CreateTable
4
 *
5
 * @filesource   CreateTable.php
6
 * @created      03.06.2017
7
 * @package      chillerlan\Database\Query\Dialects\MySQL
8
 * @author       Smiley <[email protected]>
9
 * @copyright    2017 Smiley
10
 * @license      MIT
11
 */
12
13
namespace chillerlan\Database\Query\Dialects\MySQL;
14
15
use chillerlan\Database\Query\CreateTableAbstract;
16
use chillerlan\Database\Query\QueryException;
17
18
/**
19
 * @link https://dev.mysql.com/doc/refman/5.7/en/create-table.html
20
 */
21
class CreateTable extends CreateTableAbstract{
22
23
	/**
24
	 * @return string
25
	 * @throws \chillerlan\Database\Query\QueryException
26
	 */
27
	public function sql():string{
28
29
		if(empty($this->name)){
30
			throw new QueryException('no name specified');
31
		}
32
33
		$sql = 'CREATE ';
34
		$sql .= $this->temp ? 'TEMPORARY ' : '';
35
		$sql .= 'TABLE ';
36
		$sql .= $this->ifNotExists ? 'IF NOT EXISTS ' : '';
37
		$sql .= $this->quote($this->name);
38
39 View Code Duplication
		if(!empty($this->cols)){
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...
40
			$sql .= ' ('.PHP_EOL."\t".implode(','.PHP_EOL."\t", $this->cols);
41
42
			if($this->primaryKey){
43
				$sql .=','.PHP_EOL."\t".'PRIMARY KEY ('.$this->quote($this->primaryKey).')';
44
			}
45
46
			$sql .= PHP_EOL.')';
47
		}
48
49
		if(!empty($this->collate)){
50
			list($charset) = explode('_', $this->collate);
51
52
			$sql .= PHP_EOL.'CHARACTER SET '.$charset;
53
54
			if($charset !== $this->collate){
55
				$sql .= ' COLLATE '.$this->collate;
56
			}
57
		}
58
59
		return $sql;
60
	}
61
62
	/**
63
	 * @param string      $name
64
	 * @param string      $type
65
	 * @param null        $length
66
	 * @param string|null $attribute
67
	 * @param string|null $collation
68
	 * @param bool|null   $isNull
69
	 * @param string|null $defaultType
70
	 * @param null        $defaultValue
71
	 * @param string|null $extra
72
	 *
73
	 * @return string
74
	 */
75
	protected function fieldspec(
76
		string $name,
77
		string $type,
78
		$length = null,
79
		string $attribute = null,
80
		string $collation = null,
81
		bool $isNull = null,
82
		string $defaultType = null,
83
		$defaultValue = null,
84
		string $extra = null
85
	){
86
		$name = trim($name);
87
		$type = strtoupper(trim($type));
88
89
		$field = ['`'.$name.'`'];
90
91
		// @todo: whitelist types?
92
		$nolengthtypes = ['DATE', 'TINYBLOB', 'TINYTEXT', 'BLOB', 'TEXT', 'MEDIUMBLOB',
93
		                  'MEDIUMTEXT', 'LONGBLOB', 'LONGTEXT', 'SERIAL', 'BOOLEAN', 'UUID'];
94
95
		$field[] = (is_int($length) || is_string($length) && count(explode(',', $length)) === 2) && !in_array($type, $nolengthtypes)
96
			? $type.'('. $length . ')'
97
			: $type;
98
99
		if($attribute){
0 ignored issues
show
Bug Best Practice introduced by
The expression $attribute of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
100
			$field[] = strtoupper($attribute);
101
		}
102
103
		$collationtypes = ['TINYTEXT', 'TEXT', 'MEDIUMTEXT', 'LONGTEXT', 'VARCHAR', 'CHAR', 'ENUM', 'SET'];
104
		if($collation && in_array($type, $collationtypes)){
0 ignored issues
show
Bug Best Practice introduced by
The expression $collation of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
105
			list($charset) = explode('_', $collation);
106
107
			$field[] = 'CHARACTER SET '.$charset;
108
109
			if($charset !== $collation){
110
				$field[] = 'COLLATE '.$collation;
111
			}
112
113
		}
114
115
		if(is_bool($isNull)){
116
			$field[] = $isNull ? 'NULL' : 'NOT NULL';
117
		}
118
119
		$defaultType = strtoupper($defaultType);
120
121
		if($defaultType === 'USER_DEFINED'){
122
123
			switch(true){
124
				case $type === 'TIMESTAMP' && intval($defaultValue) === 0:
125
					$field[] = 'DEFAULT 0';
126
					break;
127 View Code Duplication
				case $type === 'BIT':
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...
128
					$field[] = 'DEFAULT b\''.preg_replace('/[^01]/', '0', $defaultValue).'\'';
129
					break;
130 View Code Duplication
				case $type === 'BOOLEAN':
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...
131
					$field[] = 'DEFAULT '.preg_match('/^1|T|TRUE|YES$/i', $defaultValue) ? 'TRUE' : 'FALSE';
132
					break;
133
				case $type === 'BINARY' || $type === 'VARBINARY':
134
					$field[] = 'DEFAULT 0x'.$defaultValue;
135
					break;
136 View Code Duplication
				case strtoupper($defaultValue) === 'NULL' && $isNull === true:
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...
137
					$field[] = 'DEFAULT NULL';
138
					break;
139
				default:
140
					$field[] = 'DEFAULT '.(is_int($defaultValue) || is_float($defaultValue) ? $defaultValue : '\''.$defaultValue.'\'') ;
141
			}
142
143
		}
144 View Code Duplication
		else if($defaultType === 'CURRENT_TIMESTAMP'){
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...
145
			$field[] = 'DEFAULT CURRENT_TIMESTAMP';
146
		}
147
		else if($defaultType === 'NULL' && $isNull === true){
148
			$field[] = 'DEFAULT NULL';
149
		}
150
151
152
		if($extra){
0 ignored issues
show
Bug Best Practice introduced by
The expression $extra of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
153
			$field[] = $extra;
154
		}
155
156
		return implode(' ', $field);
157
	}
158
159
}
160