3 * SQL data types definition
6 declare(strict_types
=1);
10 use PhpMyAdmin\Query\Compatibility
;
13 use function _pgettext
;
14 use function array_diff
;
15 use function array_merge
;
16 use function array_values
;
17 use function htmlspecialchars
;
18 use function in_array
;
19 use function mb_strtoupper
;
22 use function strncasecmp
;
25 * Class holding type definitions for MySQL and MariaDB.
29 public function __construct(private DatabaseInterface
$dbi)
34 * Returns list of unary operators.
38 public function getUnaryOperators(): array
40 return ['IS NULL', 'IS NOT NULL', "= ''", "!= ''"];
44 * Check whether operator is unary.
46 * @param string $op operator name
48 public function isUnaryOperator(string $op): bool
50 return in_array($op, $this->getUnaryOperators(), true);
54 * Returns list of operators checking for NULL.
58 public function getNullOperators(): array
60 return ['IS NULL', 'IS NOT NULL'];
64 * ENUM search operators
68 public function getEnumOperators(): array
74 * TEXT search operators
78 public function getTextOperators(): array
100 * Number search operators
104 public function getNumberOperators(): array
125 * UUID search operators
129 public function getUUIDOperators(): array
131 return ['=', '!=', 'LIKE', 'LIKE %...%', 'NOT LIKE', 'NOT LIKE %...%', 'IN (...)', 'NOT IN (...)'];
135 * Returns operators for given type
137 * @param string $type Type of field
138 * @param bool $null Whether field can be NULL
142 public function getTypeOperators(string $type, bool $null): array
145 $class = $this->getTypeClass($type);
147 if (strncasecmp($type, 'enum', 4) == 0) {
148 $ret = array_merge($ret, $this->getEnumOperators());
149 } elseif ($class === 'CHAR') {
150 $ret = array_merge($ret, $this->getTextOperators());
151 } elseif ($class === 'UUID') {
152 $ret = array_merge($ret, $this->getUUIDOperators());
154 $ret = array_merge($ret, $this->getNumberOperators());
158 return array_merge($ret, $this->getNullOperators());
165 * Returns operators for given type as html options
167 * @param string $type Type of field
168 * @param bool $null Whether field can be NULL
169 * @param string|null $selectedOperator Option to be selected
171 * @return string Generated Html
173 public function getTypeOperatorsHtml(string $type, bool $null, string|
null $selectedOperator = null): string
177 foreach ($this->getTypeOperators($type, $null) as $fc) {
178 $selected = $selectedOperator !== null && $selectedOperator === $fc ?
' selected="selected"' : '';
180 $html .= '<option value="' . htmlspecialchars($fc) . '"'
182 . htmlspecialchars($fc) . '</option>';
189 * Returns the data type description.
191 * @param string $type The data type to get a description.
193 public function getTypeDescription(string $type): string
195 return match (mb_strtoupper($type)) {
196 'TINYINT' => __('A 1-byte integer, signed range is -128 to 127, unsigned range is 0 to 255'),
197 'SMALLINT' => __('A 2-byte integer, signed range is -32,768 to 32,767, unsigned range is 0 to 65,535'),
199 'A 3-byte integer, signed range is -8,388,608 to 8,388,607, unsigned range is 0 to 16,777,215',
202 'A 4-byte integer, signed range is ' .
203 '-2,147,483,648 to 2,147,483,647, unsigned range is 0 to ' .
207 'An 8-byte integer, signed range is -9,223,372,036,854,775,808 ' .
208 'to 9,223,372,036,854,775,807, unsigned range is 0 to ' .
209 '18,446,744,073,709,551,615',
212 'A fixed-point number (M, D) - the maximum number of digits (M) ' .
213 'is 65 (default 10), the maximum number of decimals (D) is 30 ' .
217 'A small floating-point number, allowable values are ' .
218 '-3.402823466E+38 to -1.175494351E-38, 0, and 1.175494351E-38 to ' .
222 'A double-precision floating-point number, allowable values are ' .
223 '-1.7976931348623157E+308 to -2.2250738585072014E-308, 0, and ' .
224 '2.2250738585072014E-308 to 1.7976931348623157E+308',
226 'REAL' => __('Synonym for DOUBLE (exception: in REAL_AS_FLOAT SQL mode it is a synonym for FLOAT)'),
227 'BIT' => __('A bit-field type (M), storing M of bits per value (default is 1, maximum is 64)'),
229 'A synonym for TINYINT(1), a value of zero is considered false, nonzero values are considered true',
231 'SERIAL' => __('An alias for BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE'),
233 __('A date, supported range is %1$s to %2$s'),
237 'DATETIME' => sprintf(
238 __('A date and time combination, supported range is %1$s to %2$s'),
239 '1000-01-01 00:00:00',
240 '9999-12-31 23:59:59',
243 'A timestamp, range is 1970-01-01 00:00:01 UTC to 2038-01-09 ' .
244 '03:14:07 UTC, stored as the number of seconds since the epoch ' .
245 '(1970-01-01 00:00:00 UTC)',
248 __('A time, range is %1$s to %2$s'),
253 'A year in four-digit (4, default) or two-digit (2) format, the ' .
254 'allowable values are 70 (1970) to 69 (2069) or 1901 to 2155 and ' .
258 'A fixed-length (0-255, default 1) string that is always ' .
259 'right-padded with spaces to the specified length when stored',
261 'VARCHAR' => sprintf(
263 'A variable-length (%s) string, the effective maximum length is subject to the maximum row size',
268 'A TEXT column with a maximum length of 255 (2^8 - 1) characters, ' .
269 'stored with a one-byte prefix indicating the length of the value ' .
273 'A TEXT column with a maximum length of 65,535 (2^16 - 1) ' .
274 'characters, stored with a two-byte prefix indicating the length ' .
275 'of the value in bytes',
278 'A TEXT column with a maximum length of 16,777,215 (2^24 - 1) ' .
279 'characters, stored with a three-byte prefix indicating the ' .
280 'length of the value in bytes',
283 'A TEXT column with a maximum length of 4,294,967,295 or 4GiB ' .
284 '(2^32 - 1) characters, stored with a four-byte prefix indicating ' .
285 'the length of the value in bytes',
288 'Similar to the CHAR type, but stores binary byte strings rather than non-binary character strings',
291 'Similar to the VARCHAR type, but stores binary byte strings ' .
292 'rather than non-binary character strings',
295 'A BLOB column with a maximum length of 255 (2^8 - 1) bytes, ' .
296 'stored with a one-byte prefix indicating the length of the value',
299 'A BLOB column with a maximum length of 16,777,215 (2^24 - 1) ' .
300 'bytes, stored with a three-byte prefix indicating the length of ' .
304 'A BLOB column with a maximum length of 65,535 (2^16 - 1) bytes, ' .
305 'stored with a two-byte prefix indicating the length of the value',
308 'A BLOB column with a maximum length of 4,294,967,295 or 4GiB ' .
309 '(2^32 - 1) bytes, stored with a four-byte prefix indicating the ' .
310 'length of the value',
312 'ENUM' => __('An enumeration, chosen from the list of up to 65,535 values or the special \'\' error value'),
313 'SET' => __('A single value chosen from a set of up to 64 members'),
314 'GEOMETRY' => __('A type that can store a geometry of any type'),
315 'POINT' => __('A point in 2-dimensional space'),
316 'LINESTRING' => __('A curve with linear interpolation between points'),
317 'POLYGON' => __('A polygon'),
318 'MULTIPOINT' => __('A collection of points'),
319 'MULTILINESTRING' => __('A collection of curves with linear interpolation between points'),
320 'MULTIPOLYGON' => __('A collection of polygons'),
321 'GEOMETRYCOLLECTION' => __('A collection of geometry objects of any type'),
322 'JSON' => __('Stores and enables efficient access to data in JSON (JavaScript Object Notation) documents'),
323 'INET6' => __('Intended for storage of IPv6 addresses, as well as IPv4 '
324 . 'addresses assuming conventional mapping of IPv4 addresses '
325 . 'into IPv6 addresses'),
326 'UUID' => __('128-bit UUID (Universally Unique Identifier)'),
332 * Returns class of a type, used for functions available for type
335 * @param string $type The data type to get a class.
337 public function getTypeClass(string $type): string
339 return match (mb_strtoupper($type)) {
391 * Returns array of functions available for a class.
393 * @param string $class The class to get function list.
397 public function getFunctionsClass(string $class): array
399 $isMariaDB = $this->dbi
->isMariaDB();
400 $serverVersion = $this->dbi
->getVersion();
442 if (($isMariaDB && $serverVersion < 100012) ||
$serverVersion < 50603) {
443 $ret = array_diff($ret, ['INET6_NTOA']);
446 return array_values($ret);
514 'UNCOMPRESSED_LENGTH',
523 if (($isMariaDB && $serverVersion < 100012) ||
$serverVersion < 50603) {
524 $ret = array_diff($ret, ['INET6_ATON']);
527 return array_values($ret);
530 if ($serverVersion >= 50600) {
535 'ST_GeomCollFromText',
543 'ST_GeomCollFromWKB',
579 * Returns array of functions available for a type.
581 * @param string $type The data type to get function list.
585 public function getFunctions(string $type): array
587 $class = $this->getTypeClass($type);
589 return $this->getFunctionsClass($class);
593 * Returns array of all functions available.
597 public function getAllFunctions(): array
600 $this->getFunctionsClass('CHAR'),
601 $this->getFunctionsClass('NUMBER'),
602 $this->getFunctionsClass('DATE'),
603 $this->getFunctionsClass('SPATIAL'),
611 * Returns array of all attributes available.
615 public function getAttributes(): array
617 $serverVersion = $this->dbi
->getVersion();
619 $attributes = ['', 'BINARY', 'UNSIGNED', 'UNSIGNED ZEROFILL', 'on update CURRENT_TIMESTAMP'];
621 if (Compatibility
::supportsCompressedColumns($serverVersion)) {
622 $attributes[] = 'COMPRESSED=zlib';
629 * Returns array of all column types available.
631 * VARCHAR, TINYINT, TEXT and DATE are listed first, based on
632 * estimated popularity.
634 * @return string[]|array<string, string[]>
636 public function getColumns(): array
638 $isMariaDB = $this->dbi
->isMariaDB();
639 $serverVersion = $this->dbi
->getVersion();
640 $isUUIDSupported = Compatibility
::isUUIDSupported($this->dbi
);
643 $ret = ['INT', 'VARCHAR', 'TEXT', 'DATE'];
645 if ($isUUIDSupported) {
650 $ret[_pgettext('numeric types', 'Numeric')] = [
668 $ret[_pgettext('date and time types', 'Date and time')] = ['DATE', 'DATETIME', 'TIMESTAMP', 'TIME', 'YEAR'];
691 if ($isMariaDB && $serverVersion >= 100500) {
692 $stringTypes[] = '-';
693 $stringTypes[] = 'INET6';
696 $ret[_pgettext('string types', 'String')] = $stringTypes;
698 $ret[_pgettext('spatial types', 'Spatial')] = [
706 'GEOMETRYCOLLECTION',
709 if (($isMariaDB && $serverVersion > 100207) ||
(! $isMariaDB && $serverVersion >= 50708)) {
710 $ret['JSON'] = ['JSON'];
713 if ($isUUIDSupported) {
714 $ret['UUID'] = ['UUID'];
721 * Returns an array of integer types
723 * @return string[] integer types
725 public function getIntegerTypes(): array
727 return ['tinyint', 'smallint', 'mediumint', 'int', 'bigint'];
730 public function mapAliasToMysqlType(string $alias): string
732 return match ($alias) {
734 'BOOLEAN' => 'TINYINT',
735 'CHARACTER VARYING' => 'VARCHAR',
736 'FIXED' => 'DECIMAL',
738 'FLOAT8' => 'DOUBLE',
740 'INT2' => 'SMALLINT',
741 'INT3' => 'MEDIUMINT',
744 'LONG VARBINARY' => 'MEDIUMBLOB',
745 'LONG VARCHAR' => 'MEDIUMTEXT',
746 'LONG' => 'MEDIUMTEXT',
747 'MIDDLEINT' => 'MEDIUMINT',
748 'NUMERIC' => 'DECIMAL',
754 * Returns an array of float types
756 * @return string[] float types
758 public function getFloatTypes(): array
760 return ['decimal', 'float', 'double', 'real'];
764 * Returns the min and max values of a given integer type
766 * @param string $type integer type
767 * @param bool $signed whether signed
769 * @return string[] min and max values
771 public function getIntegerRange(string $type, bool $signed = true): array
775 'tinyint' => ['0', '255'],
776 'smallint' => ['0', '65535'],
777 'mediumint' => ['0', '16777215'],
778 'int' => ['0', '4294967295'],
779 'bigint' => ['0', '18446744073709551615'],
782 'tinyint' => ['-128', '127'],
783 'smallint' => ['-32768', '32767'],
784 'mediumint' => ['-8388608', '8388607'],
785 'int' => ['-2147483648', '2147483647'],
786 'bigint' => ['-9223372036854775808', '9223372036854775807'],
789 $relevantArray = $signed
790 ?
$minMaxData['signed']
791 : $minMaxData['unsigned'];
793 return $relevantArray[$type] ??
['', ''];