From f2483801c5a3bb9851c041cd1c9f644727ac5033 Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Thu, 21 Apr 2016 16:44:59 +0200 Subject: [PATCH] Optimize column definition parsing by 25% --- lib/Connection.php | 52 +++++++++++++--------------------------------- lib/DataTypes.php | 26 +++++++++++++++++++++++ 2 files changed, 41 insertions(+), 37 deletions(-) diff --git a/lib/Connection.php b/lib/Connection.php index 57c6d4e..e2ccd7f 100644 --- a/lib/Connection.php +++ b/lib/Connection.php @@ -661,8 +661,7 @@ private function parseOk($packet) { } if ($this->capabilities & self::CLIENT_SESSION_TRACK) { - $this->connInfo->statusInfo = DataTypes::decodeString(substr($packet, $off), $intlen, $strlen); - $off += $intlen + $strlen; + $this->connInfo->statusInfo = DataTypes::decodeStringOff($packet, $off); if ($this->connInfo->statusFlags & StatusFlags::SERVER_SESSION_STATE_CHANGED) { $sessionState = DataTypes::decodeString(substr($packet, $off), $intlen, $sessionStateLen); @@ -870,26 +869,13 @@ private function parseColumnDefinition($packet) { $column = []; if ($this->capabilities & self::CLIENT_PROTOCOL_41) { - $column["catalog"] = DataTypes::decodeString(substr($packet, $off), $intlen, $len); - $off += $intlen + $len; - - $column["schema"] = DataTypes::decodeString(substr($packet, $off), $intlen, $len); - $off += $intlen + $len; - - $column["table"] = DataTypes::decodeString(substr($packet, $off), $intlen, $len); - $off += $intlen + $len; - - $column["original_table"] = DataTypes::decodeString(substr($packet, $off), $intlen, $len); - $off += $intlen + $len; - - $column["name"] = DataTypes::decodeString(substr($packet, $off), $intlen, $len); - $off += $intlen + $len; - - $column["original_name"] = DataTypes::decodeString(substr($packet, $off), $intlen, $len); - $off += $intlen + $len; - - $fixlen = DataTypes::decodeInt(substr($packet, $off), $len); - $off += $len; + $column["catalog"] = DataTypes::decodeStringOff($packet, $off); + $column["schema"] = DataTypes::decodeStringOff($packet, $off); + $column["table"] = DataTypes::decodeStringOff($packet, $off); + $column["original_table"] = DataTypes::decodeStringOff($packet, $off); + $column["name"] = DataTypes::decodeStringOff($packet, $off); + $column["original_name"] = DataTypes::decodeStringOff($packet, $off); + $fixlen = DataTypes::decodeIntOff($packet, $off); $len = 0; $column["charset"] = DataTypes::decode_int16(substr($packet, $off + $len)); @@ -905,31 +891,24 @@ private function parseColumnDefinition($packet) { $off += $fixlen; } else { - $column["table"] = DataTypes::decodeString(substr($packet, $off), $intlen, $len); - $off += $intlen + $len; - - $column["name"] = DataTypes::decodeString(substr($packet, $off), $intlen, $len); - $off += $intlen + $len; - - $collen = DataTypes::decodeInt(substr($packet, $off), $len); - $off += $len; + $column["table"] = DataTypes::decodeStringOff($packet, $off); + $column["name"] = DataTypes::decodeStringOff($packet, $off); + $collen = DataTypes::decodeIntOff($packet, $off); $column["columnlen"] = DataTypes::decode_intByLen(substr($packet, $off), $collen); $off += $collen; - $typelen = DataTypes::decodeInt(substr($packet, $off), $len); - $off += $len; - + $typelen = DataTypes::decodeIntOff($packet, $off); $column["type"] = DataTypes::decode_intByLen(substr($packet, $off), $typelen); $off += $typelen; $len = 1; - $flaglen = $this->capabilities & self::CLIENT_LONG_FLAG ? DataTypes::decodeInt(substr($packet, $off), $len) : ord($packet[$off]); + $flaglen = $this->capabilities & self::CLIENT_LONG_FLAG ? DataTypes::decodeInt(substr($packet, $off, 9), $len) : ord($packet[$off]); $off += $len; if ($flaglen > 2) { $len = 2; - $column["flags"] = DataTypes::decode_int16(substr($packet, $off)); + $column["flags"] = DataTypes::decode_int16(substr($packet, $off, 4)); } else { $len = 1; $column["flags"] = ord($packet[$off]); @@ -984,8 +963,7 @@ private function handleTextResultsetRow($packet) { $fields[] = null; $off += 1; } else { - $fields[] = DataTypes::decodeString(substr($packet, $off), $intlen, $len); - $off += $intlen + $len; + $fields[] = DataTypes::decodeStringOff($packet, $off); } } $this->result->rowFetched($fields); diff --git a/lib/DataTypes.php b/lib/DataTypes.php index 320671f..fd9916a 100644 --- a/lib/DataTypes.php +++ b/lib/DataTypes.php @@ -190,6 +190,32 @@ public static function decodeNullString($str, &$len = 0) { return substr($str, 0, $len = strpos($str, "\0")); } + public static function decodeStringOff($str, &$off) { + $len = self::decodeIntOff($str, $off); + $off += $len; + return substr($str, $off - $len, $len); + } + + public static function decodeIntOff($str, &$off) { + $int = ord($str[$off]); + if ($int < 0xfb) { + $off += 1; + return $int; + } elseif ($int == 0xfc) { + $off += 3; + return self::decode_int16(substr($str, $off - 2, 2)); + } elseif ($int == 0xfd) { + $off += 4; + return self::decode_int24(substr($str, $off - 3, 3)); + } elseif ($int == 0xfe) { + $off += 9; + return self::decode_int64(substr($str, $off - 8, 8)); + } else { + // If that happens connection is borked... + throw new \RangeException("$int is not in ranges [0x00, 0xfa] or [0xfc, 0xfe]"); + } + } + public static function decodeString($str, &$intlen = 0, &$len = 0) { $len = self::decodeInt($str, $intlen); return substr($str, $intlen, $len);