Translated using Weblate (Portuguese)
[phpmyadmin.git] / src / FieldMetadata.php
blob1df7e57dc562a37ecc892e40e031940de371b1c0
1 <?php
3 declare(strict_types=1);
5 namespace PhpMyAdmin;
7 use function define;
8 use function defined;
10 use const MYSQLI_BLOB_FLAG;
11 use const MYSQLI_ENUM_FLAG;
12 use const MYSQLI_MULTIPLE_KEY_FLAG;
13 use const MYSQLI_NOT_NULL_FLAG;
14 use const MYSQLI_PRI_KEY_FLAG;
15 use const MYSQLI_SET_FLAG;
16 use const MYSQLI_TYPE_BIT;
17 use const MYSQLI_TYPE_BLOB;
18 use const MYSQLI_TYPE_DATE;
19 use const MYSQLI_TYPE_DATETIME;
20 use const MYSQLI_TYPE_DECIMAL;
21 use const MYSQLI_TYPE_DOUBLE;
22 use const MYSQLI_TYPE_ENUM;
23 use const MYSQLI_TYPE_FLOAT;
24 use const MYSQLI_TYPE_GEOMETRY;
25 use const MYSQLI_TYPE_INT24;
26 use const MYSQLI_TYPE_JSON;
27 use const MYSQLI_TYPE_LONG;
28 use const MYSQLI_TYPE_LONG_BLOB;
29 use const MYSQLI_TYPE_LONGLONG;
30 use const MYSQLI_TYPE_MEDIUM_BLOB;
31 use const MYSQLI_TYPE_NEWDATE;
32 use const MYSQLI_TYPE_NEWDECIMAL;
33 use const MYSQLI_TYPE_NULL;
34 use const MYSQLI_TYPE_SET;
35 use const MYSQLI_TYPE_SHORT;
36 use const MYSQLI_TYPE_STRING;
37 use const MYSQLI_TYPE_TIME;
38 use const MYSQLI_TYPE_TIMESTAMP;
39 use const MYSQLI_TYPE_TINY;
40 use const MYSQLI_TYPE_TINY_BLOB;
41 use const MYSQLI_TYPE_VAR_STRING;
42 use const MYSQLI_TYPE_YEAR;
43 use const MYSQLI_UNIQUE_KEY_FLAG;
44 use const MYSQLI_UNSIGNED_FLAG;
45 use const MYSQLI_ZEROFILL_FLAG;
47 // Issue #16043 - client API mysqlnd seem not to have MYSQLI_TYPE_JSON defined
48 if (! defined('MYSQLI_TYPE_JSON')) {
49 define('MYSQLI_TYPE_JSON', 245);
52 /**
53 * Handles fields Metadata
55 * NOTE: Getters are not used in all implementations due to the important cost of getters calls
57 final class FieldMetadata
59 public const TYPE_GEOMETRY = 1;
60 public const TYPE_BIT = 2;
61 public const TYPE_JSON = 3;
62 public const TYPE_REAL = 4;
63 public const TYPE_INT = 5;
64 public const TYPE_BLOB = 6;
65 public const TYPE_UNKNOWN = -1;
66 public const TYPE_NULL = 7;
67 public const TYPE_STRING = 8;
68 public const TYPE_DATE = 9;
69 public const TYPE_TIME = 10;
70 public const TYPE_TIMESTAMP = 11;
71 public const TYPE_DATETIME = 12;
72 public const TYPE_YEAR = 13;
74 /** @readonly */
75 public bool $isMultipleKey;
77 /** @readonly */
78 public bool $isPrimaryKey;
80 /** @readonly */
81 public bool $isUniqueKey;
83 /** @readonly */
84 public bool $isNotNull;
86 /** @readonly */
87 public bool $isUnsigned;
89 /** @readonly */
90 public bool $isZerofill;
92 /** @readonly */
93 public bool $isNumeric;
95 /** @readonly */
96 public bool $isBlob;
98 /** @readonly */
99 public bool $isBinary;
101 /** @readonly */
102 public bool $isEnum;
104 /** @readonly */
105 public bool $isSet;
107 private int|null $mappedType;
109 /** @readonly */
110 public bool $isMappedTypeBit;
112 /** @readonly */
113 public bool $isMappedTypeGeometry;
115 /** @readonly */
116 public bool $isMappedTypeTimestamp;
119 * The column name
121 * @psalm-var non-empty-string
123 public string $name;
126 * The original column name if an alias did exist
128 public string $orgname;
131 * The table name
133 public string $table;
136 * The original table name
138 public string $orgtable;
141 * The charset number
143 * @readonly
145 public int $charsetnr;
148 * The number of decimals used (for integer fields)
150 * @readonly
152 public int $decimals;
155 * The width of the field, as specified in the table definition.
157 * @readonly
159 public int $length;
162 * A field only used by the Results class
164 public string|null $internalMediaType = null;
167 * @psalm-param object{
168 * name: non-empty-string,
169 * orgname: string,
170 * table: string,
171 * orgtable: string,
172 * max_length: int,
173 * length: int,
174 * charsetnr: int,
175 * flags: int,
176 * type: int,
177 * decimals: int,
178 * db: string,
179 * def: string,
180 * catalog: string,
181 * } $field
183 public function __construct(object $field)
185 $type = $field->type;
186 $this->mappedType = $this->getMappedInternalType($type);
188 $flags = $field->flags;
189 $this->isMultipleKey = (bool) ($flags & MYSQLI_MULTIPLE_KEY_FLAG);
190 $this->isPrimaryKey = (bool) ($flags & MYSQLI_PRI_KEY_FLAG);
191 $this->isUniqueKey = (bool) ($flags & MYSQLI_UNIQUE_KEY_FLAG);
192 $this->isNotNull = (bool) ($flags & MYSQLI_NOT_NULL_FLAG);
193 $this->isUnsigned = (bool) ($flags & MYSQLI_UNSIGNED_FLAG);
194 $this->isZerofill = (bool) ($flags & MYSQLI_ZEROFILL_FLAG);
195 $this->isBlob = (bool) ($flags & MYSQLI_BLOB_FLAG);
196 $this->isEnum = (bool) ($flags & MYSQLI_ENUM_FLAG);
197 $this->isSet = (bool) ($flags & MYSQLI_SET_FLAG);
199 // as flags 32768 can be NUM_FLAG or GROUP_FLAG
200 // reference: https://www.php.net/manual/en/mysqli-result.fetch-fields.php
201 // so check field type instead of flags
202 $this->isNumeric = $this->isType(self::TYPE_INT) || $this->isType(self::TYPE_REAL);
204 // MYSQLI_PART_KEY_FLAG => 'part_key',
205 // MYSQLI_TIMESTAMP_FLAG => 'timestamp',
206 // MYSQLI_AUTO_INCREMENT_FLAG => 'auto_increment',
208 $this->isMappedTypeBit = $this->isType(self::TYPE_BIT);
209 $this->isMappedTypeGeometry = $this->isType(self::TYPE_GEOMETRY);
210 $this->isMappedTypeTimestamp = $this->isType(self::TYPE_TIMESTAMP);
212 $this->name = $field->name;
213 $this->orgname = $field->orgname;
214 $this->table = $field->table;
215 $this->orgtable = $field->orgtable;
216 $this->charsetnr = $field->charsetnr;
217 $this->decimals = $field->decimals;
218 $this->length = $field->length;
220 // 63 is the number for the MySQL charset "binary"
221 $this->isBinary = (
222 $type === MYSQLI_TYPE_TINY_BLOB ||
223 $type === MYSQLI_TYPE_BLOB ||
224 $type === MYSQLI_TYPE_MEDIUM_BLOB ||
225 $type === MYSQLI_TYPE_LONG_BLOB ||
226 $type === MYSQLI_TYPE_VAR_STRING ||
227 $type === MYSQLI_TYPE_STRING
228 ) && $this->charsetnr == 63;
232 * @see https://dev.mysql.com/doc/connectors/en/apis-php-mysqli.constants.html
234 * @psalm-return self::TYPE_*|null
236 private function getMappedInternalType(int $type): int|null
238 return match ($type) {
239 MYSQLI_TYPE_DECIMAL => self::TYPE_REAL,
240 MYSQLI_TYPE_NEWDECIMAL => self::TYPE_REAL,
241 MYSQLI_TYPE_TINY => self::TYPE_INT,
242 MYSQLI_TYPE_SHORT => self::TYPE_INT,
243 MYSQLI_TYPE_LONG => self::TYPE_INT,
244 MYSQLI_TYPE_FLOAT => self::TYPE_REAL,
245 MYSQLI_TYPE_DOUBLE => self::TYPE_REAL,
246 MYSQLI_TYPE_NULL => self::TYPE_NULL,
247 MYSQLI_TYPE_TIMESTAMP => self::TYPE_TIMESTAMP,
248 MYSQLI_TYPE_LONGLONG => self::TYPE_INT,
249 MYSQLI_TYPE_INT24 => self::TYPE_INT,
250 MYSQLI_TYPE_DATE => self::TYPE_DATE,
251 MYSQLI_TYPE_TIME => self::TYPE_TIME,
252 MYSQLI_TYPE_DATETIME => self::TYPE_DATETIME,
253 MYSQLI_TYPE_YEAR => self::TYPE_YEAR,
254 MYSQLI_TYPE_NEWDATE => self::TYPE_DATE,
255 MYSQLI_TYPE_ENUM => self::TYPE_UNKNOWN,
256 MYSQLI_TYPE_SET => self::TYPE_UNKNOWN,
257 MYSQLI_TYPE_TINY_BLOB => self::TYPE_BLOB,
258 MYSQLI_TYPE_MEDIUM_BLOB => self::TYPE_BLOB,
259 MYSQLI_TYPE_LONG_BLOB => self::TYPE_BLOB,
260 MYSQLI_TYPE_BLOB => self::TYPE_BLOB,
261 MYSQLI_TYPE_VAR_STRING => self::TYPE_STRING,
262 MYSQLI_TYPE_STRING => self::TYPE_STRING,
263 // MySQL returns MYSQLI_TYPE_STRING for CHAR
264 // and MYSQLI_TYPE_CHAR === MYSQLI_TYPE_TINY
265 // so this would override TINYINT and mark all TINYINT as string
266 // see https://github.com/phpmyadmin/phpmyadmin/issues/8569
267 //$typeAr[MYSQLI_TYPE_CHAR] = self::TYPE_STRING;
268 MYSQLI_TYPE_GEOMETRY => self::TYPE_GEOMETRY,
269 MYSQLI_TYPE_BIT => self::TYPE_BIT,
270 MYSQLI_TYPE_JSON => self::TYPE_JSON,
271 default => null,
275 public function isNotNull(): bool
277 return $this->isNotNull;
280 public function isNumeric(): bool
282 return $this->isNumeric;
285 public function isBinary(): bool
287 return $this->isBinary;
290 public function isBlob(): bool
292 return $this->isBlob;
295 public function isPrimaryKey(): bool
297 return $this->isPrimaryKey;
300 public function isUniqueKey(): bool
302 return $this->isUniqueKey;
305 public function isMultipleKey(): bool
307 return $this->isMultipleKey;
310 public function isUnsigned(): bool
312 return $this->isUnsigned;
315 public function isZerofill(): bool
317 return $this->isZerofill;
320 public function isEnum(): bool
322 return $this->isEnum;
325 public function isSet(): bool
327 return $this->isSet;
331 * Checks that it is type DATE/TIME/DATETIME
333 public function isDateTimeType(): bool
335 return $this->isType(self::TYPE_DATE)
336 || $this->isType(self::TYPE_TIME)
337 || $this->isType(self::TYPE_DATETIME)
338 || $this->isType(self::TYPE_TIMESTAMP);
342 * Checks that it contains time
343 * A "DATE" field returns false for example
345 public function isTimeType(): bool
347 return $this->isType(self::TYPE_TIME)
348 || $this->isType(self::TYPE_TIMESTAMP)
349 || $this->isType(self::TYPE_DATETIME);
353 * Get the mapped type as a string
355 * @return string Empty when nothing could be matched
357 public function getMappedType(): string
359 return match ($this->mappedType) {
360 self::TYPE_GEOMETRY => 'geometry',
361 self::TYPE_BIT => 'bit',
362 self::TYPE_JSON => 'json',
363 self::TYPE_REAL => 'real',
364 self::TYPE_INT => 'int',
365 self::TYPE_BLOB => 'blob',
366 self::TYPE_UNKNOWN => 'unknown',
367 self::TYPE_NULL => 'null',
368 self::TYPE_STRING => 'string',
369 self::TYPE_DATE => 'date',
370 self::TYPE_TIME => 'time',
371 self::TYPE_TIMESTAMP => 'timestamp',
372 self::TYPE_DATETIME => 'datetime',
373 self::TYPE_YEAR => 'year',
374 default => '',
379 * Check if it is the mapped type
381 * @phpstan-param self::TYPE_* $type
383 public function isType(int $type): bool
385 return $this->mappedType === $type;
389 * Check if it is NOT the mapped type
391 * @phpstan-param self::TYPE_* $type
393 public function isNotType(int $type): bool
395 return $this->mappedType !== $type;