Skip to content

Commit 2297d38

Browse files
committed
jdbc成功
1 parent 1eb8260 commit 2297d38

2 files changed

Lines changed: 89 additions & 17 deletions

File tree

app/Proxy/Executor/BackendExecutor.php

Lines changed: 81 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Hyperf\DbConnection\Db;
99
use App\Protocol\MySql\Packet;
1010
use App\Protocol\MySql\Parser;
11+
use App\Protocol\ConnectionContext;
1112
use Hyperf\Logger\LoggerFactory;
1213
use 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
}

app/Proxy/Service/MySQLProxyService.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,12 @@ private function handleAuthentication(ConnectionContext $context, Packet $packet
212212
'client_capabilities' => sprintf('0x%08x', $authData['capabilities'] ?? 0),
213213
]);
214214

215+
// 保存客户端能力标志到上下文
216+
$context->setClientCapabilities([
217+
'capabilities' => $authData['capabilities'] ?? 0,
218+
'deprecate_eof' => (($authData['capabilities'] ?? 0) & 0x01000000) !== 0,
219+
]);
220+
215221
// 当启用 CLIENT_PLUGIN_AUTH 时,第一个包的 auth_response 可能为空
216222
// 实际的认证响应会在第二个包(sequence_id=2)中发送
217223
// 检查是否是第一个包(auth_response_length=0 且已经解析出了用户名)
@@ -384,8 +390,8 @@ private function handleQuery(ConnectionContext $context, \App\Helpers\PHPSQLPars
384390
'sql' => $sql->sql,
385391
]);
386392

387-
// 使用后端执行器执行 SQL
388-
$packets = $this->executor->execute($sql, $context->getDatabase());
393+
// 使用后端执行器执行 SQL,传入客户端上下文
394+
$packets = $this->executor->execute($sql, $context->getDatabase(), $context);
389395

390396
// 调整包的sequence_id,从客户端命令包的sequence_id + 1开始
391397
$adjustedPackets = [];

0 commit comments

Comments
 (0)