Skip to content

Commit

Permalink
Support Elixir v1.3 calendar types
Browse files Browse the repository at this point in the history
  • Loading branch information
José Valim committed Oct 1, 2017
1 parent 0c8a507 commit d9c546d
Show file tree
Hide file tree
Showing 8 changed files with 335 additions and 151 deletions.
2 changes: 2 additions & 0 deletions lib/mariaex.ex
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ defmodule Mariaex do
if not `DBConnection.Connection` (default: `DBConnection.Connection`);
* `:name` - A name to register the started process (see the `:name` option
in `GenServer.start_link/3`).
* `:datetime` - How datetimes should be returned. `:structs` for Elixir v1.3
calendar types or `:tuples` for the backwards compatible tuples
## Function signatures
Expand Down
18 changes: 9 additions & 9 deletions lib/mariaex/messages.ex
Original file line number Diff line number Diff line change
Expand Up @@ -229,32 +229,32 @@ defmodule Mariaex.Messages do
do: {nil, rest}

def decode_bin_rows(<< len :: size(24)-little-integer, seqnum :: size(8)-integer, body :: size(len)-binary, rest :: binary>>,
fields, nullbin_size, rows) do
fields, nullbin_size, rows, datetime) do
case body do
<<0 :: 8, nullbin::size(nullbin_size)-little-unit(8), values :: binary>> ->
row = Mariaex.RowParser.decode_bin_rows(values, fields, nullbin)
decode_bin_rows(rest, fields, nullbin_size, [row | rows])
row = Mariaex.RowParser.decode_bin_rows(values, fields, nullbin, datetime)
decode_bin_rows(rest, fields, nullbin_size, [row | rows], datetime)
body ->
msg = decode_msg(body, :bin_rows)
{:ok, packet(size: len, seqnum: seqnum, msg: msg, body: body), rows, rest}
end
end
def decode_bin_rows(<<rest :: binary>>, _fields, _nullbin_size, rows) do
def decode_bin_rows(<<rest :: binary>>, _fields, _nullbin_size, rows, _datetime) do
{:more, rows, rest}
end

def decode_text_rows(<< len :: size(24)-little-integer, seqnum :: size(8)-integer, body :: size(len)-binary, rest :: binary>>,
fields, rows) do
fields, rows, datetime) do
case body do
<< 254 :: 8, _ :: binary >> = body when byte_size(body) < 9 ->
msg = decode_msg(body, :text_rows)
{:ok, packet(size: len, seqnum: seqnum, msg: msg, body: body), rows, rest}
body ->
row = Mariaex.RowParser.decode_text_rows(body, fields)
decode_text_rows(rest, fields, [row | rows])
row = Mariaex.RowParser.decode_text_rows(body, fields, datetime)
decode_text_rows(rest, fields, [row | rows], datetime)
end
end
def decode_text_rows(<<rest :: binary>>, _fields, rows) do
def decode_text_rows(<<rest :: binary>>, _fields, rows, _datetime) do
{:more, rows, rest}
end

Expand All @@ -280,6 +280,6 @@ defmodule Mariaex.Messages do
<< contents :: size(length_nul_terminated)-binary, 0 :: 8 >> -> contents
contents -> contents
end
{String.strip(auth_plugin_data2, 0), next}
{String.trim(auth_plugin_data2, "\0"), next}
end
end
19 changes: 11 additions & 8 deletions lib/mariaex/protocol.ex
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ defmodule Mariaex.Protocol do
cache: nil,
cursors: %{},
seqnum: 0,
datetime: :structs,
ssl_conn_state: :undefined # :undefined | :not_used | :ssl_handshake | :connected

@doc """
Expand All @@ -74,6 +75,7 @@ defmodule Mariaex.Protocol do
host = opts[:hostname] |> parse_host
connect_opts = [host, opts[:port], opts[:socket_options], opts[:timeout]]
binary_as = opts[:binary_as] || :field_type_var_string
datetime = opts[:datetime] || :structs

case apply(sock_mod, :connect, connect_opts) do
{:ok, sock} ->
Expand All @@ -85,6 +87,7 @@ defmodule Mariaex.Protocol do
cache: reset_cache(),
lru_cache: reset_lru_cache(opts[:cache_size]),
timeout: opts[:timeout],
datetime: datetime,
opts: opts}
handshake_recv(s, %{opts: opts})
{:error, reason} ->
Expand Down Expand Up @@ -126,7 +129,7 @@ defmodule Mariaex.Protocol do
end

defp parse_host(host) do
host = if is_binary(host), do: String.to_char_list(host), else: host
host = if is_binary(host), do: String.to_charlist(host), else: host

case :inet.parse_strict_address(host) do
{:ok, address} ->
Expand Down Expand Up @@ -323,8 +326,8 @@ defmodule Mariaex.Protocol do
other
end
end
def handle_prepare(%Query{type: :binary} = query, _, s) do
case prepare_lookup(%Query{query | binary_as: s.binary_as}, s) do
def handle_prepare(%Query{type: :binary} = query, _, %{binary_as: binary_as} = s) do
case prepare_lookup(%Query{query | binary_as: binary_as}, s) do
{:prepared, query} ->
{:ok, query, s}
{:prepare, query} ->
Expand Down Expand Up @@ -528,8 +531,8 @@ defmodule Mariaex.Protocol do
end
end

defp text_row_decode(s, fields, rows, buffer) do
case decode_text_rows(buffer, fields, rows) do
defp text_row_decode(%{datetime: datetime} = s, fields, rows, buffer) do
case decode_text_rows(buffer, fields, rows, datetime) do
{:ok, packet, rows, rest} ->
{:ok, packet, rows, %{s | buffer: rest}}
{:more, rows, rest} ->
Expand Down Expand Up @@ -635,8 +638,8 @@ defmodule Mariaex.Protocol do
end
end

defp binary_row_decode(s, fields, nullbin_size, rows, buffer) do
case decode_bin_rows(buffer, fields, nullbin_size, rows) do
defp binary_row_decode(%{datetime: datetime} = s, fields, nullbin_size, rows, buffer) do
case decode_bin_rows(buffer, fields, nullbin_size, rows, datetime) do
{:ok, packet, rows, rest} ->
{:ok, packet, rows, %{s | buffer: rest}}
{:more, rows, rest} ->
Expand Down Expand Up @@ -1022,7 +1025,7 @@ defmodule Mariaex.Protocol do
l |> Enum.map(&bxor(&1, extra - 64)) |> to_string
end

defp hash(bin) when is_binary(bin), do: bin |> to_char_list |> hash
defp hash(bin) when is_binary(bin), do: bin |> to_charlist |> hash
defp hash(s), do: hash(s, 1345345333, 305419889, 7)
defp hash([c | s], n1, n2, add) do
n1 = bxor(n1, (((band(n1, 63) + add) * c + n1 * 256)))
Expand Down
15 changes: 15 additions & 0 deletions lib/mariaex/query.ex
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,20 @@ defimpl DBConnection.Query, for: Mariaex.Query do
bin = Decimal.to_string(value, :normal)
{0, :field_type_newdecimal, << to_length_encoded_integer(byte_size(bin)) :: binary, bin :: binary >>}
end

defp encode_param(%Date{year: year, month: month, day: day}, _binary_as),
do: {0, :field_type_date, << 4::8-little, year::16-little, month::8-little, day::8-little>>}
defp encode_param(%Time{hour: hour, minute: min, second: sec, microsecond: {0, 0}}, _binary_as),
do: {0, :field_type_time, << 8 :: 8-little, 0 :: 8-little, 0 :: 32-little, hour :: 8-little, min :: 8-little, sec :: 8-little >>}
defp encode_param(%Time{hour: hour, minute: min, second: sec, microsecond: {msec, _}}, _binary_as),
do: {0, :field_type_time, << 12 :: 8-little, 0 :: 8-little, 0 :: 32-little, hour :: 8-little, min :: 8-little, sec :: 8-little, msec :: 32-little>>}
defp encode_param(%NaiveDateTime{year: year, month: month, day: day,
hour: hour, minute: min, second: sec, microsecond: {0, 0}}, _binary_as),
do: {0, :field_type_datetime, << 7::8-little, year::16-little, month::8-little, day::8-little, hour::8-little, min::8-little, sec::8-little>>}
defp encode_param(%NaiveDateTime{year: year, month: month, day: day,
hour: hour, minute: min, second: sec, microsecond: {msec, _}}, _binary_as),
do: {0, :field_type_datetime, <<11::8-little, year::16-little, month::8-little, day::8-little, hour::8-little, min::8-little, sec::8-little, msec::32-little>>}

defp encode_param({year, month, day}, _binary_as),
do: {0, :field_type_date, << 4::8-little, year::16-little, month::8-little, day::8-little>>}
defp encode_param({hour, min, sec, 0}, _binary_as),
Expand All @@ -123,6 +137,7 @@ defimpl DBConnection.Query, for: Mariaex.Query do
do: {0, :field_type_datetime, << 7::8-little, year::16-little, month::8-little, day::8-little, hour::8-little, min::8-little, sec::8-little>>}
defp encode_param({{year, month, day}, {hour, min, sec, msec}}, _binary_as),
do: {0, :field_type_datetime, <<11::8-little, year::16-little, month::8-little, day::8-little, hour::8-little, min::8-little, sec::8-little, msec::32-little>>}

defp encode_param(other, _binary_as),
do: raise ArgumentError, "query has invalid parameter #{inspect other}"

Expand Down
Loading

0 comments on commit d9c546d

Please sign in to comment.