88use Hyperf \DbConnection \Db ;
99use App \Protocol \MySql \Packet ;
1010use App \Protocol \MySql \Parser ;
11+ use App \Protocol \ConnectionContext ;
1112use Hyperf \Logger \LoggerFactory ;
1213use Psr \Log \LoggerInterface ;
1314
@@ -34,9 +35,10 @@ public function __construct(LoggerFactory $loggerFactory)
3435 *
3536 * @param PHPSQLParserHelper $sql 要执行的 SQL 语句
3637 * @param string|null $database 要使用的数据库名
38+ * @param ConnectionContext|null $context 客户端连接上下文
3739 * @return array 执行结果,包含 MySQL 协议包
3840 */
39- public function execute (PHPSQLParserHelper $ sql , ?string $ database = null ): array
41+ public function execute (PHPSQLParserHelper $ sql , ?string $ database = null , ? ConnectionContext $ context = null ): array
4042 {
4143 $ startTime = microtime (true );
4244 $ retryCount = 0 ;
@@ -115,7 +117,7 @@ public function execute(PHPSQLParserHelper $sql, ?string $database = null): arra
115117 'result_summary ' => $ resultSummary ,
116118 ]);
117119
118- return $ this ->createResultSetPackets ($ result );
120+ return $ this ->createResultSetPackets ($ result, $ context );
119121 } else {
120122 // 对于其他查询(如 INSERT, UPDATE, DELETE),使用 statement 方法
121123 $ affectedRows = $ connection ->statement ($ sql ->sql );
@@ -253,14 +255,25 @@ private function createOkPacket(int $affectedRows = 0, int $insertId = 0): array
253255
254256 /**
255257 * 创建结果集包
258+ *
259+ * @param array $result 查询结果
260+ * @param ConnectionContext|null $context 客户端连接上下文
261+ * @return array MySQL协议包数组
256262 */
257- private function createResultSetPackets (array $ result ): array
263+ private function createResultSetPackets (array $ result, ? ConnectionContext $ context = null ): array
258264 {
259265 $ packets = [];
260266
261267 if (empty ($ result )) {
262268 // 空结果集
263- return $ this ->createEmptyResultSet ();
269+ return $ this ->createEmptyResultSet ($ context );
270+ }
271+
272+ // 检查客户端是否支持 CLIENT_DEPRECATE_EOF
273+ $ deprecateEof = false ;
274+ if ($ context !== null ) {
275+ $ clientCapabilities = $ context ->getClientCapabilities ();
276+ $ deprecateEof = $ clientCapabilities ['deprecate_eof ' ] ?? false ;
264277 }
265278
266279 // 获取列信息
@@ -277,8 +290,14 @@ private function createResultSetPackets(array $result): array
277290 $ packets [] = Packet::create ($ sequenceId ++, $ this ->createColumnDefinition ($ columnName ));
278291 }
279292
280- // EOF Packet after columns
281- $ packets [] = Packet::create ($ sequenceId ++, $ this ->createEofPacket ()); // EOF
293+ // EOF/OK Packet after columns
294+ if ($ deprecateEof ) {
295+ // 客户端支持 CLIENT_DEPRECATE_EOF,发送 OK 包
296+ $ packets [] = Packet::create ($ sequenceId ++, $ this ->createOkPayload (0 , 0 , 0x0002 , 0 ));
297+ } else {
298+ // 客户端不支持,发送 EOF 包
299+ $ packets [] = Packet::create ($ sequenceId ++, $ this ->createEofPacket ());
300+ }
282301
283302 // Row Data Packets
284303 foreach ($ result as $ row ) {
@@ -290,32 +309,79 @@ private function createResultSetPackets(array $result): array
290309 $ packets [] = Packet::create ($ sequenceId ++, $ rowData );
291310 }
292311
293- // EOF Packet after rows
294- $ packets [] = Packet::create ($ sequenceId ++, $ this ->createEofPacket ()); // EOF
312+ // EOF/OK Packet after rows
313+ if ($ deprecateEof ) {
314+ // 客户端支持 CLIENT_DEPRECATE_EOF,发送 OK 包
315+ $ packets [] = Packet::create ($ sequenceId ++, $ this ->createOkPayload (0 , 0 , 0x0002 , 0 ));
316+ } else {
317+ // 客户端不支持,发送 EOF 包
318+ $ packets [] = Packet::create ($ sequenceId ++, $ this ->createEofPacket ());
319+ }
295320
296321 return $ packets ;
297322 }
298323
299324 /**
300325 * 创建EOF包
326+ *
327+ * MySQL EOF包格式:
328+ * - 0xfe (1字节) - EOF标记
329+ * - warnings (2字节) - 警告计数
330+ * - status_flags (2字节) - 状态标志
301331 */
302332 private function createEofPacket (): string
303333 {
304- // MySQL 5.7 EOF包格式:只包含EOF标记
305- // 在某些客户端实现中,EOF包只需要0xfe一个字节
306- return chr (0xfe );
334+ $ payload = chr (0xfe ); // EOF marker
335+ $ payload .= pack ('v ' , 0 ); // warning count (2字节)
336+ $ payload .= pack ('v ' , 0 ); // status flags (2字节)
337+ return $ payload ;
338+ }
339+
340+ /**
341+ * 创建OK包payload
342+ *
343+ * @param int $affectedRows 受影响的行数
344+ * @param int $lastInsertId 最后插入ID
345+ * @param int $statusFlags 状态标志,0x0002表示无结果集
346+ * @param int $warnings 警告数
347+ * @return string OK包payload
348+ */
349+ private function createOkPayload (int $ affectedRows = 0 , int $ lastInsertId = 0 , int $ statusFlags = 0 , int $ warnings = 0 ): string
350+ {
351+ $ payload = chr (0x00 ); // OK packet header
352+ $ payload .= $ this ->encodeLength ($ affectedRows ); // affected_rows
353+ $ payload .= $ this ->encodeLength ($ lastInsertId ); // last_insert_id
354+ $ payload .= pack ('v ' , $ statusFlags ); // status_flags
355+ $ payload .= pack ('v ' , $ warnings ); // warnings
356+ return $ payload ;
307357 }
308358
309359 /**
310360 * 创建空结果集
361+ *
362+ * @param ConnectionContext|null $context 客户端连接上下文
363+ * @return array MySQL协议包数组
311364 */
312- private function createEmptyResultSet (): array
365+ private function createEmptyResultSet (? ConnectionContext $ context = null ): array
313366 {
367+ // 检查客户端是否支持 CLIENT_DEPRECATE_EOF
368+ $ deprecateEof = false ;
369+ if ($ context !== null ) {
370+ $ clientCapabilities = $ context ->getClientCapabilities ();
371+ $ deprecateEof = $ clientCapabilities ['deprecate_eof ' ] ?? false ;
372+ }
373+
314374 // Column count: 0
315375 $ packets = [Packet::create (0 , $ this ->encodeLength (0 ))];
316376
317- // EOF
318- $ packets [] = Packet::create (1 , $ this ->createEofPacket ());
377+ // EOF/OK packet
378+ if ($ deprecateEof ) {
379+ // 客户端支持 CLIENT_DEPRECATE_EOF,发送 OK 包
380+ $ packets [] = Packet::create (1 , $ this ->createOkPayload (0 , 0 , 0x0002 , 0 ));
381+ } else {
382+ // 客户端不支持,发送 EOF 包
383+ $ packets [] = Packet::create (1 , $ this ->createEofPacket ());
384+ }
319385
320386 return $ packets ;
321387 }
@@ -627,7 +693,7 @@ public function executeExecute(array $data, ?string $database = null): array
627693 'result_count ' => count ($ result ),
628694 ]);
629695
630- return $ this ->createResultSetPackets ($ result );
696+ return $ this ->createResultSetPackets ($ result, $ context );
631697 }
632698 }
633699 }
0 commit comments