From 4f97928eafe3568d883d73af67b1dee8b4518940 Mon Sep 17 00:00:00 2001 From: Nate Date: Mon, 29 Sep 2025 14:20:07 +0300 Subject: [PATCH 1/5] fix for doris --- lib/myxql/protocol.ex | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/lib/myxql/protocol.ex b/lib/myxql/protocol.ex index 74dd083..3e7351b 100644 --- a/lib/myxql/protocol.ex +++ b/lib/myxql/protocol.ex @@ -339,6 +339,38 @@ defmodule MyXQL.Protocol do decode_resultset(payload, next_data, state, &Values.decode_text_row/2) end + # Handle 10-byte packet (DorisDB/Apache Doris - without num_warnings field) + # DorisDB sends: [0x00 status (1 byte) | statement_id (4 bytes) | num_columns (2 bytes) | num_params (2 bytes) | 0x00 reserved (1 byte)] + # Total: 10 bytes (missing the 2-byte num_warnings field that MySQL includes after the reserved byte) + def decode_com_stmt_prepare_response( + <<0x00, statement_id::uint4(), num_columns::uint2(), num_params::uint2(), 0x00>>, + next_data, + :initial + ) do + # DorisDB sends 10-byte packets without num_warnings field + # Default num_warnings to 0 for compatibility + result = + com_stmt_prepare_ok( + statement_id: statement_id, + num_columns: num_columns, + num_params: num_params, + num_warnings: 0 + ) + + cond do + num_params > 0 -> + {:cont, {result, :params, num_params, num_columns}} + + num_columns > 0 -> + {:cont, {result, :columns, num_columns}} + + true -> + "" = next_data + {:halt, result} + end + end + + # Handle 12-byte packet (Standard MySQL - with num_warnings field) def decode_com_stmt_prepare_response( <<0x00, statement_id::uint4(), num_columns::uint2(), num_params::uint2(), 0, num_warnings::uint2()>>, From 72afa9954356618f6813172fb52f2766fbe65cd1 Mon Sep 17 00:00:00 2001 From: Nate Date: Fri, 21 Nov 2025 17:31:31 +0200 Subject: [PATCH 2/5] Support Doris 3.1 --- lib/myxql/protocol.ex | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/lib/myxql/protocol.ex b/lib/myxql/protocol.ex index 3e7351b..22fab23 100644 --- a/lib/myxql/protocol.ex +++ b/lib/myxql/protocol.ex @@ -398,6 +398,24 @@ defmodule MyXQL.Protocol do end end + # Handle 13-byte packet (Newer DorisDB/Apache Doris - with num_warnings and metadata_follows) + def decode_com_stmt_prepare_response( + <<0x00, statement_id::uint4(), num_columns::uint2(), num_params::uint2(), 0, + num_warnings::uint2(), _metadata_follows::uint1()>>, + next_data, + :initial + ) do + result = com_stmt_prepare_ok(statement_id: statement_id, num_columns: num_columns, num_params: num_params, warning_count: num_warnings) + + case next_data do + "" -> + {:halt, result} + + _ -> + {:cont, {result, :params, num_params, num_columns}, next_data} + end + end + def decode_com_stmt_prepare_response(<>, "", :initial) do {:halt, decode_generic_response(rest)} end From 45c79a9b4280338f3a91c0c9022fc42b91a415bf Mon Sep 17 00:00:00 2001 From: Nate Date: Fri, 21 Nov 2025 17:36:17 +0200 Subject: [PATCH 3/5] fix --- lib/myxql/protocol.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/myxql/protocol.ex b/lib/myxql/protocol.ex index 22fab23..8d4182b 100644 --- a/lib/myxql/protocol.ex +++ b/lib/myxql/protocol.ex @@ -405,7 +405,7 @@ defmodule MyXQL.Protocol do next_data, :initial ) do - result = com_stmt_prepare_ok(statement_id: statement_id, num_columns: num_columns, num_params: num_params, warning_count: num_warnings) + result = com_stmt_prepare_ok(statement_id: statement_id, num_columns: num_columns, num_params: num_params, num_warnings: num_warnings) case next_data do "" -> From 1a1158543f74905d4775d1cf70e962289cc95e3f Mon Sep 17 00:00:00 2001 From: Nate Date: Fri, 21 Nov 2025 17:37:55 +0200 Subject: [PATCH 4/5] no case clause matching --- lib/myxql/protocol.ex | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/myxql/protocol.ex b/lib/myxql/protocol.ex index 8d4182b..20a5147 100644 --- a/lib/myxql/protocol.ex +++ b/lib/myxql/protocol.ex @@ -407,12 +407,11 @@ defmodule MyXQL.Protocol do ) do result = com_stmt_prepare_ok(statement_id: statement_id, num_columns: num_columns, num_params: num_params, num_warnings: num_warnings) - case next_data do - "" -> - {:halt, result} - - _ -> - {:cont, {result, :params, num_params, num_columns}, next_data} + if num_params > 0 or num_columns > 0 do + {:cont, {result, :params, num_params, num_columns}} + else + "" = next_data + {:halt, result} end end From f7c376b573a6b0142e7cb8187f5d26b4ead7e309 Mon Sep 17 00:00:00 2001 From: Nate Date: Fri, 21 Nov 2025 17:39:51 +0200 Subject: [PATCH 5/5] fix eof --- lib/myxql/protocol.ex | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/lib/myxql/protocol.ex b/lib/myxql/protocol.ex index 20a5147..d55ef02 100644 --- a/lib/myxql/protocol.ex +++ b/lib/myxql/protocol.ex @@ -431,12 +431,26 @@ defmodule MyXQL.Protocol do column_def() = decode_column_def(payload) {:cont, {com_stmt_prepare_ok, :params, num_params - 1, num_columns}} else - eof_packet() = decode_eof_packet(payload) + # Apache Doris 3.1+ may skip EOF packet when num_params = 0 and directly send column defs + # Check if this is an EOF packet (0xFE) or a column definition (0x03, "def") + case payload do + <<0xFE, _::binary>> -> + eof_packet() = decode_eof_packet(payload) + + if num_columns > 0 do + {:cont, {com_stmt_prepare_ok, :columns, num_columns}} + else + {:halt, com_stmt_prepare_ok} + end - if num_columns > 0 do - {:cont, {com_stmt_prepare_ok, :columns, num_columns}} - else - {:halt, com_stmt_prepare_ok} + <<3, "def", _::binary>> -> + # No EOF packet, directly process column definition + if num_columns > 0 do + column_def() = decode_column_def(payload) + {:cont, {com_stmt_prepare_ok, :columns, num_columns - 1}} + else + {:halt, com_stmt_prepare_ok} + end end end end