dvdoug /
DB
| 1 | <?php |
||||||
| 2 | |||||||
| 3 | declare(strict_types=1); |
||||||
| 4 | /** |
||||||
| 5 | * Database Access Layer. |
||||||
| 6 | * @author Doug Wright |
||||||
| 7 | */ |
||||||
| 8 | |||||||
| 9 | namespace DVDoug\DB; |
||||||
| 10 | |||||||
| 11 | use function addslashes; |
||||||
| 12 | use function array_intersect_key; |
||||||
| 13 | use function array_map; |
||||||
| 14 | use function array_unique; |
||||||
| 15 | use function asort; |
||||||
| 16 | use function explode; |
||||||
| 17 | use function implode; |
||||||
| 18 | use function in_array; |
||||||
| 19 | use function sprintf; |
||||||
| 20 | use function strpos; |
||||||
| 21 | use function strtolower; |
||||||
| 22 | use function substr; |
||||||
| 23 | use function trim; |
||||||
| 24 | |||||||
| 25 | /** |
||||||
| 26 | * Metadata about a database column. |
||||||
| 27 | * @author Doug Wright |
||||||
| 28 | */ |
||||||
| 29 | trait DDLGeneration |
||||||
| 30 | { |
||||||
| 31 | /** |
||||||
| 32 | * Get MySQL column definition. |
||||||
| 33 | */ |
||||||
| 34 | 8 | public function getMySQLColumnDef(): string |
|||||
| 35 | { |
||||||
| 36 | 8 | $def = '`' . strtolower($this->getName()) . '` '; |
|||||
|
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||||||
| 37 | 8 | $MySQLType = $this->getMySQLType(); |
|||||
|
0 ignored issues
–
show
It seems like
getMySQLType() must be provided by classes using this trait. How about adding it as abstract method to this trait?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
| 38 | 8 | if (strpos($MySQLType, 'UNSIGNED') !== false) { |
|||||
| 39 | 4 | $unsigned = true; |
|||||
| 40 | 4 | $MySQLType = substr($MySQLType, 0, -9); |
|||||
| 41 | } else { |
||||||
| 42 | 8 | $unsigned = false; |
|||||
| 43 | } |
||||||
| 44 | |||||||
| 45 | 8 | if (in_array($MySQLType, ['ENUM', 'SET'])) { |
|||||
| 46 | 4 | $query = sprintf('SHOW COLUMNS FROM %s.%s LIKE %s', |
|||||
| 47 | 4 | $this->connection->quoteIdentifier($this->database), |
|||||
| 48 | 4 | $this->connection->quoteIdentifier($this->table), |
|||||
| 49 | 4 | $this->connection->escape($this->name)); |
|||||
| 50 | |||||||
| 51 | 4 | $statement = $this->connection->query($query); |
|||||
| 52 | 4 | $values = $statement->fetchAssoc(false)['Type']; |
|||||
| 53 | 4 | $values = explode("','", substr($values, strpos($values, '(') + 2, -2)); |
|||||
| 54 | 4 | $values = array_intersect_key($values, array_unique(array_map('strtolower', $values))); |
|||||
| 55 | 4 | asort($values); |
|||||
| 56 | |||||||
| 57 | 4 | $def .= $MySQLType; |
|||||
| 58 | 4 | $def .= '(' . implode(', ', array_map(function ($c) {return "'" . addslashes($c) . "'"; }, $values)) . ')'; |
|||||
| 59 | 8 | } elseif (in_array($MySQLType, ['CHAR', 'VARCHAR']) && $this->getLength() < 64 && $this->getDistinctValueCount() <= 16) { |
|||||
|
0 ignored issues
–
show
It seems like
getLength() must be provided by classes using this trait. How about adding it as abstract method to this trait?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
It seems like
getDistinctValueCount() must be provided by classes using this trait. How about adding it as abstract method to this trait?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
| 60 | 4 | $query = sprintf('SELECT DISTINCT %s FROM %s.%s WHERE %s IS NOT NULL ORDER BY %s ASC', |
|||||
| 61 | 4 | $this->connection->quoteIdentifier($this->name), |
|||||
| 62 | 4 | $this->connection->quoteIdentifier($this->database), |
|||||
| 63 | 4 | $this->connection->quoteIdentifier($this->table), |
|||||
| 64 | 4 | $this->connection->quoteIdentifier($this->name), |
|||||
| 65 | 4 | $this->connection->quoteIdentifier($this->name)); |
|||||
| 66 | 4 | $values = []; |
|||||
| 67 | 4 | foreach ($this->connection->query($query) as $value) { |
|||||
| 68 | 4 | $values[] = trim($value[$this->name]); |
|||||
| 69 | } |
||||||
| 70 | 4 | $values = array_intersect_key($values, array_unique(array_map('strtolower', $values))); |
|||||
| 71 | 4 | asort($values); |
|||||
| 72 | |||||||
| 73 | 4 | if ($values) { |
|||||
| 74 | 4 | $def .= 'ENUM'; |
|||||
| 75 | 4 | $def .= '(' . implode(', ', array_map(function ($c) {return "'" . addslashes($c) . "'"; }, $values)) . ')'; |
|||||
| 76 | } else { |
||||||
| 77 | 4 | $def .= $MySQLType; |
|||||
| 78 | 4 | if ($this->getLength() > 0) { |
|||||
| 79 | 4 | $def .= '(' . $this->getLength() . ')'; |
|||||
| 80 | } |
||||||
| 81 | } |
||||||
| 82 | } elseif (in_array($MySQLType, ['DATETIME', 'TIMESTAMP', 'TIME'])) { |
||||||
| 83 | $def .= $MySQLType; |
||||||
| 84 | $def .= '(' . (int) $this->getScale() . ')'; |
||||||
|
0 ignored issues
–
show
It seems like
getScale() must be provided by classes using this trait. How about adding it as abstract method to this trait?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
| 85 | } else { |
||||||
| 86 | 8 | $def .= $MySQLType; |
|||||
| 87 | |||||||
| 88 | 8 | if ($this->getScale() && !in_array($MySQLType, ['DATE'])) { |
|||||
| 89 | $def .= '(' . $this->getPrecision() . ',' . $this->getScale() . ')'; |
||||||
|
0 ignored issues
–
show
It seems like
getPrecision() must be provided by classes using this trait. How about adding it as abstract method to this trait?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
| 90 | 8 | } elseif ($this->getPrecision() && !in_array($MySQLType, ['TINYINT', 'SMALLINT', 'MEDIUMINT', 'INT', 'BIGINT'])) { |
|||||
| 91 | $def .= '(' . $this->getPrecision() . ')'; |
||||||
| 92 | 8 | } elseif ($this->getLength() > 0 && !in_array($MySQLType, ['TINYINT', 'SMALLINT', 'MEDIUMINT', 'INT', 'BIGINT'])) { |
|||||
| 93 | 4 | $def .= '(' . $this->getLength() . ')'; |
|||||
| 94 | } |
||||||
| 95 | |||||||
| 96 | 8 | if ($unsigned) { |
|||||
| 97 | 4 | $def .= ' UNSIGNED'; |
|||||
| 98 | } |
||||||
| 99 | } |
||||||
| 100 | |||||||
| 101 | 8 | if ($this->isNullable()) { |
|||||
|
0 ignored issues
–
show
It seems like
isNullable() must be provided by classes using this trait. How about adding it as abstract method to this trait?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
| 102 | 8 | $def .= ' NULL'; |
|||||
| 103 | } else { |
||||||
| 104 | 8 | $def .= ' NOT NULL'; |
|||||
| 105 | } |
||||||
| 106 | |||||||
| 107 | 8 | return $def; |
|||||
| 108 | } |
||||||
| 109 | |||||||
| 110 | /** |
||||||
| 111 | * Get Oracle column definition. |
||||||
| 112 | */ |
||||||
| 113 | 8 | public function getOracleColumnDef(): string |
|||||
| 114 | { |
||||||
| 115 | 8 | $def = '`' . strtolower($this->getName()) . '` '; |
|||||
| 116 | |||||||
| 117 | 8 | $def .= $this->getOracleType(); |
|||||
|
0 ignored issues
–
show
It seems like
getOracleType() must be provided by classes using this trait. How about adding it as abstract method to this trait?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
| 118 | |||||||
| 119 | 8 | if ($this->getScale()) { |
|||||
| 120 | $def .= '(' . $this->getPrecision() . ',' . $this->getScale() . ')'; |
||||||
| 121 | 8 | } elseif ($this->getPrecision()) { |
|||||
| 122 | 4 | $def .= '(' . $this->getPrecision() . ')'; |
|||||
| 123 | 4 | } elseif ($this->getLength()) { |
|||||
| 124 | 4 | $def .= '(' . $this->getLength() . ')'; |
|||||
| 125 | } |
||||||
| 126 | |||||||
| 127 | 8 | if ($this->isNullable()) { |
|||||
| 128 | 8 | $def .= ' NULL'; |
|||||
| 129 | } else { |
||||||
| 130 | 8 | $def .= ' NOT NULL'; |
|||||
| 131 | } |
||||||
| 132 | |||||||
| 133 | 8 | return $def; |
|||||
| 134 | } |
||||||
| 135 | } |
||||||
| 136 |