1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace MySQLReplication\Event\RowEvent; |
4
|
|
|
|
5
|
|
|
use MySQLReplication\BinaryDataReader\BinaryDataReader; |
6
|
|
|
use MySQLReplication\Definitions\ConstFieldType; |
7
|
|
|
|
8
|
|
|
/** |
9
|
|
|
* Class Columns |
10
|
|
|
* @package MySQLReplication\Event\RowEvent |
11
|
|
|
*/ |
12
|
|
|
class Columns |
13
|
|
|
{ |
14
|
|
|
/** |
15
|
|
|
* @var array |
16
|
|
|
*/ |
17
|
|
|
private static $field; |
18
|
|
|
|
19
|
|
|
/** |
20
|
|
|
* @param string $columnType |
21
|
|
|
* @param array $columnSchema |
22
|
|
|
* @param BinaryDataReader $binaryDataReader |
23
|
|
|
* @return array |
24
|
|
|
* @throws \MySQLReplication\BinaryDataReader\BinaryDataReaderException |
25
|
|
|
*/ |
26
|
51 |
|
public static function parse($columnType, array $columnSchema, BinaryDataReader $binaryDataReader) |
27
|
|
|
{ |
28
|
51 |
|
self::$field = []; |
29
|
51 |
|
self::$field['type'] = $columnType; |
30
|
51 |
|
self::$field['name'] = $columnSchema['COLUMN_NAME']; |
31
|
51 |
|
self::$field['collation_name'] = $columnSchema['COLLATION_NAME']; |
32
|
51 |
|
self::$field['character_set_name'] = $columnSchema['CHARACTER_SET_NAME']; |
33
|
51 |
|
self::$field['comment'] = $columnSchema['COLUMN_COMMENT']; |
34
|
51 |
|
self::$field['unsigned'] = !(stripos($columnSchema['COLUMN_TYPE'], 'unsigned') === false); |
35
|
51 |
|
self::$field['type_is_bool'] = false; |
36
|
51 |
|
self::$field['is_primary'] = $columnSchema['COLUMN_KEY'] === 'PRI'; |
37
|
|
|
|
38
|
51 |
|
if (self::$field['type'] === ConstFieldType::VARCHAR) { |
39
|
5 |
|
self::$field['max_length'] = $binaryDataReader->readInt16(); |
40
|
51 |
|
} elseif (self::$field['type'] === ConstFieldType::DOUBLE) { |
41
|
1 |
|
self::$field['size'] = $binaryDataReader->readUInt8(); |
42
|
49 |
|
} elseif (self::$field['type'] === ConstFieldType::FLOAT) { |
43
|
1 |
|
self::$field['size'] = $binaryDataReader->readUInt8(); |
44
|
48 |
|
} elseif (self::$field['type'] === ConstFieldType::TIMESTAMP2) { |
45
|
2 |
|
self::$field['fsp'] = $binaryDataReader->readUInt8(); |
46
|
47 |
|
} elseif (self::$field['type'] === ConstFieldType::DATETIME2) { |
47
|
4 |
|
self::$field['fsp'] = $binaryDataReader->readUInt8(); |
48
|
45 |
|
} elseif (self::$field['type'] === ConstFieldType::TIME2) { |
49
|
2 |
|
self::$field['fsp'] = $binaryDataReader->readUInt8(); |
50
|
42 |
|
} elseif (self::$field['type'] === ConstFieldType::TINY && $columnSchema['COLUMN_TYPE'] === 'tinyint(1)') { |
51
|
3 |
|
self::$field['type_is_bool'] = true; |
52
|
41 |
|
} elseif (self::$field['type'] === ConstFieldType::VAR_STRING || self::$field['type'] === ConstFieldType::STRING) { |
53
|
5 |
|
self::getFieldSpecial($binaryDataReader, $columnSchema); |
54
|
41 |
|
} elseif (self::$field['type'] === ConstFieldType::BLOB || self::$field['type'] === ConstFieldType::IGNORE) { |
55
|
5 |
|
self::$field['length_size'] = $binaryDataReader->readUInt8(); |
56
|
36 |
|
} elseif (self::$field['type'] === ConstFieldType::GEOMETRY) { |
57
|
1 |
|
self::$field['length_size'] = $binaryDataReader->readUInt8(); |
58
|
32 |
|
} elseif (self::$field['type'] === ConstFieldType::JSON) { |
59
|
|
|
self::$field['length_size'] = $binaryDataReader->readUInt8(); |
60
|
31 |
|
} elseif (self::$field['type'] === ConstFieldType::NEWDECIMAL) { |
61
|
10 |
|
self::$field['precision'] = $binaryDataReader->readUInt8(); |
62
|
10 |
|
self::$field['decimals'] = $binaryDataReader->readUInt8(); |
63
|
31 |
|
} elseif (self::$field['type'] === ConstFieldType::BIT) { |
64
|
1 |
|
$bits = $binaryDataReader->readUInt8(); |
65
|
1 |
|
$bytes = $binaryDataReader->readUInt8(); |
66
|
1 |
|
self::$field['bits'] = ($bytes * 8) + $bits; |
67
|
1 |
|
self::$field['bytes'] = (int)((self::$field['bits'] + 7) / 8); |
68
|
1 |
|
} |
69
|
|
|
|
70
|
51 |
|
return self::$field; |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
/** |
74
|
|
|
* @param BinaryDataReader $packet |
75
|
|
|
* @param array $columnSchema |
76
|
|
|
* @throws \MySQLReplication\BinaryDataReader\BinaryDataReaderException |
77
|
|
|
*/ |
78
|
5 |
|
protected static function getFieldSpecial(BinaryDataReader $packet, array $columnSchema) |
79
|
|
|
{ |
80
|
5 |
|
$metadata = ($packet->readUInt8() << 8) + $packet->readUInt8(); |
81
|
5 |
|
$real_type = $metadata >> 8; |
82
|
5 |
|
if ($real_type === ConstFieldType::SET || $real_type === ConstFieldType::ENUM) { |
83
|
2 |
|
self::$field['type'] = $real_type; |
84
|
2 |
|
self::$field['size'] = $metadata & 0x00ff; |
85
|
2 |
|
self::getFieldSpecialValues($columnSchema); |
86
|
2 |
|
} else { |
87
|
3 |
|
self::$field['max_length'] = ((($metadata >> 4) & 0x300) ^ 0x300) + ($metadata & 0x00ff); |
88
|
|
|
} |
89
|
5 |
|
} |
90
|
|
|
|
91
|
|
|
/** |
92
|
|
|
* @param array $columnSchema |
93
|
|
|
*/ |
94
|
2 |
|
protected static function getFieldSpecialValues(array $columnSchema) |
95
|
|
|
{ |
96
|
2 |
|
if (self::$field['type'] === ConstFieldType::ENUM) { |
97
|
1 |
|
self::$field['enum_values'] = explode( |
98
|
1 |
|
',', str_replace(['enum(', ')', '\''], '', $columnSchema['COLUMN_TYPE']) |
99
|
1 |
|
); |
100
|
2 |
|
} else if (self::$field['type'] === ConstFieldType::SET) { |
101
|
1 |
|
self::$field['set_values'] = explode( |
102
|
1 |
|
',', str_replace(['set(', ')', '\''], '', $columnSchema['COLUMN_TYPE']) |
103
|
1 |
|
); |
104
|
1 |
|
} |
105
|
|
|
} |
106
|
|
|
} |