zf

zenflows testing
git clone https://s.sonu.ch/~srfsh/zf.git
Log | Files | Refs | Submodules | README | LICENSE

type_module.ex (24603B)


      1 defmodule Postgrex.TypeModule do
      2   @moduledoc false
      3 
      4   alias Postgrex.TypeInfo
      5 
      6   def define(module, extensions, opts) do
      7     opts =
      8       opts
      9       |> Keyword.put_new(:decode_binary, :copy)
     10 
     11     config = configure(extensions, opts)
     12     define_inline(module, config, opts)
     13   end
     14 
     15   ## Helpers
     16 
     17   defp directives(config, opts) do
     18     requires =
     19       for {extension, _} <- config do
     20         quote do: require(unquote(extension))
     21       end
     22 
     23     preludes =
     24       for {extension, {state, _, _}} <- config,
     25           function_exported?(extension, :prelude, 1),
     26           do: extension.prelude(state)
     27 
     28     null = Keyword.get(opts, :null)
     29 
     30     moduledoc = Keyword.get(opts, :moduledoc, false)
     31 
     32     quote do
     33       @moduledoc unquote(moduledoc)
     34       import Postgrex.BinaryUtils
     35       require unquote(__MODULE__)
     36       unquote(requires)
     37       unquote(preludes)
     38       unquote(bin_opt_info(opts))
     39       @compile {:inline, [encode_value: 2]}
     40       @dialyzer {:no_opaque, [decode_tuple: 5]}
     41       @null unquote(Macro.escape(null))
     42     end
     43   end
     44 
     45   defp bin_opt_info(opts) do
     46     if Keyword.get(opts, :bin_opt_info) do
     47       quote do: @compile(:bin_opt_info)
     48     else
     49       []
     50     end
     51   end
     52 
     53   @anno [generated: true]
     54 
     55   defp find(config) do
     56     clauses = Enum.flat_map(config, &find_clauses/1)
     57     clauses = clauses ++ quote do: (_ -> nil)
     58 
     59     quote @anno do
     60       @doc false
     61       def find(type_info, formats) do
     62         case {type_info, formats} do
     63           unquote(clauses)
     64         end
     65       end
     66     end
     67   end
     68 
     69   defp find_clauses({extension, {opts, matching, format}}) do
     70     for {key, value} <- matching do
     71       [clause] = find_clause(extension, opts, key, value, format)
     72       clause
     73     end
     74   end
     75 
     76   defp find_clause(extension, opts, key, value, :super_binary) do
     77     quote do
     78       {%{unquote(key) => unquote(value)} = type_info, formats}
     79       when formats in [:any, :binary] ->
     80         oids = unquote(extension).oids(type_info, unquote(opts))
     81         {:super_binary, unquote(extension), oids}
     82     end
     83   end
     84 
     85   defp find_clause(extension, _opts, key, value, format) do
     86     quote do
     87       {%{unquote(key) => unquote(value)}, formats}
     88       when formats in [:any, unquote(format)] ->
     89         {unquote(format), unquote(extension)}
     90     end
     91   end
     92 
     93   defp maybe_rewrite(ast, extension, cases, opts) do
     94     if Postgrex.Utils.default_extension?(extension) and
     95          not Keyword.get(opts, :debug_defaults, false) do
     96       ast
     97     else
     98       rewrite(ast, cases)
     99     end
    100   end
    101 
    102   defp rewrite(ast, [{:->, clause_meta, _} | _original]) do
    103     Macro.prewalk(ast, fn
    104       {kind, meta, [{fun, _, args}, block]} when kind in [:def, :defp] and is_list(args) ->
    105         {kind, meta, [{fun, clause_meta, args}, block]}
    106 
    107       other ->
    108         other
    109     end)
    110   end
    111 
    112   defp encode(config, define_opts) do
    113     encodes =
    114       for {extension, {opts, [_ | _], format}} <- config do
    115         encode = extension.encode(opts)
    116 
    117         clauses =
    118           for clause <- encode do
    119             encode_type(extension, format, clause)
    120           end
    121 
    122         clauses = [encode_null(extension, format) | clauses]
    123 
    124         quote do
    125           unquote(encode_value(extension, format))
    126 
    127           unquote(encode_inline(extension, format))
    128 
    129           unquote(clauses |> maybe_rewrite(extension, encode, define_opts))
    130         end
    131       end
    132 
    133     quote location: :keep do
    134       unquote(encodes)
    135 
    136       @doc false
    137       def encode_params(params, types) do
    138         encode_params(params, types, [])
    139       end
    140 
    141       defp encode_params([param | params], [type | types], encoded) do
    142         encode_params(params, types, [encode_value(param, type) | encoded])
    143       end
    144 
    145       defp encode_params([], [], encoded), do: Enum.reverse(encoded)
    146       defp encode_params(params, _, _) when is_list(params), do: :error
    147 
    148       @doc false
    149       def encode_tuple(tuple, nil, _types) do
    150         raise DBConnection.EncodeError, """
    151         cannot encode anonymous tuple #{inspect(tuple)}. \
    152         Please define a custom Postgrex extension that matches on its underlying type:
    153 
    154             use Postgrex.BinaryExtension, type: "typeinthedb"
    155         """
    156       end
    157 
    158       def encode_tuple(tuple, oids, types) do
    159         encode_tuple(tuple, 1, oids, types, [])
    160       end
    161 
    162       defp encode_tuple(tuple, n, [oid | oids], [type | types], acc) do
    163         param = :erlang.element(n, tuple)
    164         acc = [acc, <<oid::uint32()>> | encode_value(param, type)]
    165         encode_tuple(tuple, n + 1, oids, types, acc)
    166       end
    167 
    168       defp encode_tuple(tuple, n, [], [], acc) when tuple_size(tuple) < n do
    169         acc
    170       end
    171 
    172       defp encode_tuple(tuple, n, [], [], _) when is_tuple(tuple) do
    173         raise DBConnection.EncodeError,
    174               "expected a tuple of size #{n - 1}, got: #{inspect(tuple)}"
    175       end
    176 
    177       @doc false
    178       def encode_list(list, type) do
    179         encode_list(list, type, [])
    180       end
    181 
    182       defp encode_list([value | rest], type, acc) do
    183         encode_list(rest, type, [acc | encode_value(value, type)])
    184       end
    185 
    186       defp encode_list([], _, acc) do
    187         acc
    188       end
    189     end
    190   end
    191 
    192   defp encode_type(extension, :super_binary, clause) do
    193     encode_super(extension, clause)
    194   end
    195 
    196   defp encode_type(extension, _, clause) do
    197     encode_extension(extension, clause)
    198   end
    199 
    200   defp encode_extension(extension, clause) do
    201     case split_extension(clause) do
    202       {pattern, guard, body} ->
    203         encode_extension(extension, pattern, guard, body)
    204 
    205       {pattern, body} ->
    206         encode_extension(extension, pattern, body)
    207     end
    208   end
    209 
    210   defp encode_extension(extension, pattern, guard, body) do
    211     quote do
    212       defp unquote(extension)(unquote(pattern)) when unquote(guard) do
    213         unquote(body)
    214       end
    215     end
    216   end
    217 
    218   defp encode_extension(extension, pattern, body) do
    219     quote do
    220       defp unquote(extension)(unquote(pattern)) do
    221         unquote(body)
    222       end
    223     end
    224   end
    225 
    226   defp encode_super(extension, clause) do
    227     case split_super(clause) do
    228       {pattern, sub_oids, sub_types, guard, body} ->
    229         encode_super(extension, pattern, sub_oids, sub_types, guard, body)
    230 
    231       {pattern, sub_oids, sub_types, body} ->
    232         encode_super(extension, pattern, sub_oids, sub_types, body)
    233     end
    234   end
    235 
    236   defp encode_super(extension, pattern, sub_oids, sub_types, guard, body) do
    237     quote do
    238       defp unquote(extension)(unquote(pattern), unquote(sub_oids), unquote(sub_types))
    239            when unquote(guard) do
    240         unquote(body)
    241       end
    242     end
    243   end
    244 
    245   defp encode_super(extension, pattern, sub_oids, sub_types, body) do
    246     quote do
    247       defp unquote(extension)(unquote(pattern), unquote(sub_oids), unquote(sub_types)) do
    248         unquote(body)
    249       end
    250     end
    251   end
    252 
    253   defp encode_inline(extension, :super_binary) do
    254     quote do
    255       @compile {:inline, [{unquote(extension), 3}]}
    256     end
    257   end
    258 
    259   defp encode_inline(extension, _) do
    260     quote do
    261       @compile {:inline, [{unquote(extension), 1}]}
    262     end
    263   end
    264 
    265   defp encode_null(extension, :super_binary) do
    266     quote do
    267       defp unquote(extension)(@null, _sub_oids, _sub_types), do: <<-1::int32()>>
    268     end
    269   end
    270 
    271   defp encode_null(extension, _) do
    272     quote do
    273       defp unquote(extension)(@null), do: <<-1::int32()>>
    274     end
    275   end
    276 
    277   defp encode_value(extension, :super_binary) do
    278     quote do
    279       @doc false
    280       def encode_value(value, {unquote(extension), sub_oids, sub_types}) do
    281         unquote(extension)(value, sub_oids, sub_types)
    282       end
    283     end
    284   end
    285 
    286   defp encode_value(extension, _) do
    287     quote do
    288       @doc false
    289       def encode_value(value, unquote(extension)) do
    290         unquote(extension)(value)
    291       end
    292     end
    293   end
    294 
    295   defp decode(config, define_opts) do
    296     rest = quote do: rest
    297     acc = quote do: acc
    298     rem = quote do: rem
    299     full = quote do: full
    300     rows = quote do: rows
    301 
    302     row_dispatch =
    303       for {extension, {_, [_ | _], format}} <- config do
    304         decode_row_dispatch(extension, format, rest, acc, rem, full, rows)
    305       end
    306 
    307     next_dispatch = decode_rows_dispatch(rest, acc, rem, full, rows)
    308     row_dispatch = row_dispatch ++ next_dispatch
    309 
    310     decodes =
    311       for {extension, {opts, [_ | _], format}} <- config do
    312         decode = extension.decode(opts)
    313 
    314         clauses =
    315           for clause <- decode do
    316             decode_type(extension, format, clause, row_dispatch, rest, acc, rem, full, rows)
    317           end
    318 
    319         null_clauses = decode_null(extension, format, row_dispatch, rest, acc, rem, full, rows)
    320 
    321         quote location: :keep do
    322           unquote(clauses |> maybe_rewrite(extension, decode, define_opts))
    323 
    324           unquote(null_clauses)
    325         end
    326       end
    327 
    328     quote location: :keep do
    329       unquote(decode_rows(row_dispatch, rest, acc, rem, full, rows))
    330 
    331       unquote(decode_simple())
    332 
    333       unquote(decode_list(config))
    334 
    335       unquote(decode_tuple(config))
    336 
    337       unquote(decodes)
    338     end
    339   end
    340 
    341   defp decode_rows(dispatch, rest, acc, rem, full, rows) do
    342     quote location: :keep, generated: true do
    343       @doc false
    344       def decode_rows(binary, types, rows) do
    345         decode_rows(binary, byte_size(binary), types, rows)
    346       end
    347 
    348       defp decode_rows(
    349              <<?D, size::int32(), _::int16(), unquote(rest)::binary>>,
    350              rem,
    351              unquote(full),
    352              unquote(rows)
    353            )
    354            when rem > size do
    355         unquote(rem) = rem - (1 + size)
    356         unquote(acc) = []
    357 
    358         case unquote(full) do
    359           unquote(dispatch)
    360         end
    361       end
    362 
    363       defp decode_rows(<<?D, size::int32(), rest::binary>>, rem, _, rows) do
    364         more = size + 1 - rem
    365         {:more, [?D, <<size::int32()>> | rest], rows, more}
    366       end
    367 
    368       defp decode_rows(<<?D, rest::binary>>, _, _, rows) do
    369         {:more, [?D | rest], rows, 0}
    370       end
    371 
    372       defp decode_rows(<<rest::binary-size(0)>>, _, _, rows) do
    373         {:more, [], rows, 0}
    374       end
    375 
    376       defp decode_rows(<<rest::binary>>, _, _, rows) do
    377         {:ok, rows, rest}
    378       end
    379     end
    380   end
    381 
    382   defp decode_row_dispatch(extension, :super_binary, rest, acc, rem, full, rows) do
    383     [clause] =
    384       quote do
    385         [{unquote(extension), sub_oids, sub_types} | types] ->
    386           unquote(extension)(
    387             unquote(rest),
    388             sub_oids,
    389             sub_types,
    390             types,
    391             unquote(acc),
    392             unquote(rem),
    393             unquote(full),
    394             unquote(rows)
    395           )
    396       end
    397 
    398     clause
    399   end
    400 
    401   defp decode_row_dispatch(extension, _, rest, acc, rem, full, rows) do
    402     [clause] =
    403       quote do
    404         [unquote(extension) | types2] ->
    405           unquote(extension)(
    406             unquote(rest),
    407             types2,
    408             unquote(acc),
    409             unquote(rem),
    410             unquote(full),
    411             unquote(rows)
    412           )
    413       end
    414 
    415     clause
    416   end
    417 
    418   defp decode_rows_dispatch(rest, acc, rem, full, rows) do
    419     quote do
    420       [] ->
    421         rows = [Enum.reverse(unquote(acc)) | unquote(rows)]
    422         decode_rows(unquote(rest), unquote(rem), unquote(full), rows)
    423     end
    424   end
    425 
    426   defp decode_simple() do
    427     rest = quote do: rest
    428     acc = quote do: acc
    429 
    430     dispatch = decode_simple_dispatch(Postgrex.Extensions.Raw, rest, acc)
    431 
    432     quote do
    433       @doc false
    434       def decode_simple(binary) do
    435         decode_simple(binary, [])
    436       end
    437 
    438       defp decode_simple(<<>>, unquote(acc)), do: Enum.reverse(acc)
    439       defp decode_simple(<<unquote(rest)::binary>>, unquote(acc)), do: unquote(dispatch)
    440     end
    441   end
    442 
    443   defp decode_simple_dispatch(extension, rest, acc) do
    444     quote do
    445       unquote(extension)(unquote(rest), unquote(acc), &decode_simple/2)
    446     end
    447   end
    448 
    449   defp decode_list(config) do
    450     rest = quote do: rest
    451 
    452     dispatch =
    453       for {extension, {_, [_ | _], format}} <- config do
    454         decode_list_dispatch(extension, format, rest)
    455       end
    456 
    457     quote do
    458       @doc false
    459       def decode_list(<<unquote(rest)::binary>>, type) do
    460         case type do
    461           unquote(dispatch)
    462         end
    463       end
    464     end
    465   end
    466 
    467   defp decode_list_dispatch(extension, :super_binary, rest) do
    468     [clause] =
    469       quote do
    470         {unquote(extension), sub_oids, sub_types} ->
    471           unquote(extension)(unquote(rest), sub_oids, sub_types, [])
    472       end
    473 
    474     clause
    475   end
    476 
    477   defp decode_list_dispatch(extension, _, rest) do
    478     [clause] =
    479       quote do
    480         unquote(extension) ->
    481           unquote(extension)(unquote(rest), [])
    482       end
    483 
    484     clause
    485   end
    486 
    487   defp decode_tuple(config) do
    488     rest = quote do: rest
    489     oids = quote do: oids
    490     n = quote do: n
    491     acc = quote do: acc
    492 
    493     dispatch =
    494       for {extension, {_, [_ | _], format}} <- config do
    495         decode_tuple_dispatch(extension, format, rest, oids, n, acc)
    496       end
    497 
    498     quote generated: true do
    499       @doc false
    500       def decode_tuple(<<rest::binary>>, count, types) when is_integer(count) do
    501         decode_tuple(rest, count, types, 0, [])
    502       end
    503 
    504       def decode_tuple(<<rest::binary>>, oids, types) do
    505         decode_tuple(rest, oids, types, 0, [])
    506       end
    507 
    508       defp decode_tuple(
    509              <<oid::int32(), unquote(rest)::binary>>,
    510              [oid | unquote(oids)],
    511              types,
    512              unquote(n),
    513              unquote(acc)
    514            ) do
    515         case types do
    516           unquote(dispatch)
    517         end
    518       end
    519 
    520       defp decode_tuple(<<>>, [], [], n, acc) do
    521         :erlang.make_tuple(n, @null, acc)
    522       end
    523 
    524       defp decode_tuple(
    525              <<oid::int32(), unquote(rest)::binary>>,
    526              rem,
    527              types,
    528              unquote(n),
    529              unquote(acc)
    530            )
    531            when rem > 0 do
    532         case Postgrex.Types.fetch(oid, types) do
    533           {:ok, {:binary, type}} ->
    534             unquote(oids) = rem - 1
    535 
    536             case [type | types] do
    537               unquote(dispatch)
    538             end
    539 
    540           {:ok, {:text, _}} ->
    541             msg =
    542               "oid `#{oid}` was bootstrapped in text format and can not " <>
    543                 "be decoded inside an anonymous record"
    544 
    545             raise RuntimeError, msg
    546 
    547           {:error, %TypeInfo{type: pg_type}, _mod} ->
    548             msg = "type `#{pg_type}` can not be handled by the configured extensions"
    549             raise RuntimeError, msg
    550 
    551           {:error, nil, _mod} ->
    552             msg = "oid `#{oid}` was not bootstrapped and lacks type information"
    553             raise RuntimeError, msg
    554         end
    555       end
    556 
    557       defp decode_tuple(<<>>, 0, _types, n, acc) do
    558         :erlang.make_tuple(n, @null, acc)
    559       end
    560     end
    561   end
    562 
    563   defp decode_tuple_dispatch(extension, :super_binary, rest, oids, n, acc) do
    564     [clause] =
    565       quote do
    566         [{unquote(extension), sub_oids, sub_types} | types] ->
    567           unquote(extension)(
    568             unquote(rest),
    569             sub_oids,
    570             sub_types,
    571             unquote(oids),
    572             types,
    573             unquote(n) + 1,
    574             unquote(acc)
    575           )
    576       end
    577 
    578     clause
    579   end
    580 
    581   defp decode_tuple_dispatch(extension, _, rest, oids, n, acc) do
    582     [clause] =
    583       quote do
    584         [unquote(extension) | types] ->
    585           unquote(extension)(unquote(rest), unquote(oids), types, unquote(n) + 1, unquote(acc))
    586       end
    587 
    588     clause
    589   end
    590 
    591   defp decode_type(extension, :super_binary, clause, dispatch, rest, acc, rem, full, rows) do
    592     decode_super(extension, clause, dispatch, rest, acc, rem, full, rows)
    593   end
    594 
    595   defp decode_type(extension, _, clause, dispatch, rest, acc, rem, full, rows) do
    596     decode_extension(extension, clause, dispatch, rest, acc, rem, full, rows)
    597   end
    598 
    599   defp decode_null(extension, :super_binary, dispatch, rest, acc, rem, full, rows) do
    600     decode_super_null(extension, dispatch, rest, acc, rem, full, rows)
    601   end
    602 
    603   defp decode_null(extension, _, dispatch, rest, acc, rem, full, rows) do
    604     decode_extension_null(extension, dispatch, rest, acc, rem, full, rows)
    605   end
    606 
    607   defp decode_extension(extension, clause, dispatch, rest, acc, rem, full, rows) do
    608     case split_extension(clause) do
    609       {pattern, guard, body} ->
    610         decode_extension(extension, pattern, guard, body, dispatch, rest, acc, rem, full, rows)
    611 
    612       {pattern, body} ->
    613         decode_extension(extension, pattern, body, dispatch, rest, acc, rem, full, rows)
    614     end
    615   end
    616 
    617   defp decode_extension(extension, pattern, guard, body, dispatch, rest, acc, rem, full, rows) do
    618     quote do
    619       defp unquote(extension)(
    620              <<unquote(pattern), unquote(rest)::binary>>,
    621              types,
    622              acc,
    623              unquote(rem),
    624              unquote(full),
    625              unquote(rows)
    626            )
    627            when unquote(guard) do
    628         unquote(acc) = [unquote(body) | acc]
    629 
    630         case types do
    631           unquote(dispatch)
    632         end
    633       end
    634 
    635       defp unquote(extension)(<<unquote(pattern), rest::binary>>, acc)
    636            when unquote(guard) do
    637         unquote(extension)(rest, [unquote(body) | acc])
    638       end
    639 
    640       defp unquote(extension)(<<unquote(pattern), rest::binary>>, acc, callback)
    641            when unquote(guard) do
    642         unquote(extension)(rest, [unquote(body) | acc], callback)
    643       end
    644 
    645       defp unquote(extension)(<<unquote(pattern), rest::binary>>, oids, types, n, acc)
    646            when unquote(guard) do
    647         decode_tuple(rest, oids, types, n, [{n, unquote(body)} | acc])
    648       end
    649     end
    650   end
    651 
    652   defp decode_extension(extension, pattern, body, dispatch, rest, acc, rem, full, rows) do
    653     quote do
    654       defp unquote(extension)(
    655              <<unquote(pattern), unquote(rest)::binary>>,
    656              types,
    657              acc,
    658              unquote(rem),
    659              unquote(full),
    660              unquote(rows)
    661            ) do
    662         unquote(acc) = [unquote(body) | acc]
    663 
    664         case types do
    665           unquote(dispatch)
    666         end
    667       end
    668 
    669       defp unquote(extension)(<<unquote(pattern), rest::binary>>, acc) do
    670         decoded = unquote(body)
    671         unquote(extension)(rest, [decoded | acc])
    672       end
    673 
    674       defp unquote(extension)(<<unquote(pattern), rest::binary>>, acc, callback) do
    675         decoded = unquote(body)
    676         unquote(extension)(rest, [decoded | acc], callback)
    677       end
    678 
    679       defp unquote(extension)(<<unquote(pattern), rest::binary>>, oids, types, n, acc) do
    680         decode_tuple(rest, oids, types, n, [{n, unquote(body)} | acc])
    681       end
    682     end
    683   end
    684 
    685   defp decode_extension_null(extension, dispatch, rest, acc, rem, full, rows) do
    686     quote do
    687       defp unquote(extension)(
    688              <<-1::int32(), unquote(rest)::binary>>,
    689              types,
    690              acc,
    691              unquote(rem),
    692              unquote(full),
    693              unquote(rows)
    694            ) do
    695         unquote(acc) = [@null | acc]
    696 
    697         case types do
    698           unquote(dispatch)
    699         end
    700       end
    701 
    702       defp unquote(extension)(<<-1::int32(), rest::binary>>, acc) do
    703         unquote(extension)(rest, [@null | acc])
    704       end
    705 
    706       defp unquote(extension)(<<>>, acc) do
    707         acc
    708       end
    709 
    710       defp unquote(extension)(<<-1::int32(), rest::binary>>, acc, callback) do
    711         unquote(extension)(rest, [@null | acc], callback)
    712       end
    713 
    714       defp unquote(extension)(<<rest::binary-size(0)>>, acc, callback) do
    715         callback.(rest, acc)
    716       end
    717 
    718       defp unquote(extension)(<<-1::int32(), rest::binary>>, oids, types, n, acc) do
    719         decode_tuple(rest, oids, types, n, acc)
    720       end
    721     end
    722   end
    723 
    724   defp split_extension({:->, _, [head, body]}) do
    725     case head do
    726       [{:when, _, [pattern, guard]}] ->
    727         {pattern, guard, body}
    728 
    729       [pattern] ->
    730         {pattern, body}
    731     end
    732   end
    733 
    734   defp decode_super(extension, clause, dispatch, rest, acc, rem, full, rows) do
    735     case split_super(clause) do
    736       {pattern, oids, types, guard, body} ->
    737         decode_super(
    738           extension,
    739           pattern,
    740           oids,
    741           types,
    742           guard,
    743           body,
    744           dispatch,
    745           rest,
    746           acc,
    747           rem,
    748           full,
    749           rows
    750         )
    751 
    752       {pattern, oids, types, body} ->
    753         decode_super(extension, pattern, oids, types, body, dispatch, rest, acc, rem, full, rows)
    754     end
    755   end
    756 
    757   defp decode_super(
    758          extension,
    759          pattern,
    760          sub_oids,
    761          sub_types,
    762          guard,
    763          body,
    764          dispatch,
    765          rest,
    766          acc,
    767          rem,
    768          full,
    769          rows
    770        ) do
    771     quote do
    772       defp unquote(extension)(
    773              <<unquote(pattern), unquote(rest)::binary>>,
    774              unquote(sub_oids),
    775              unquote(sub_types),
    776              types,
    777              acc,
    778              unquote(rem),
    779              unquote(full),
    780              unquote(rows)
    781            )
    782            when unquote(guard) do
    783         unquote(acc) = [unquote(body) | acc]
    784 
    785         case types do
    786           unquote(dispatch)
    787         end
    788       end
    789 
    790       defp unquote(extension)(
    791              <<unquote(pattern), rest::binary>>,
    792              unquote(sub_oids),
    793              unquote(sub_types),
    794              acc
    795            )
    796            when unquote(guard) do
    797         acc = [unquote(body) | acc]
    798         unquote(extension)(rest, unquote(sub_oids), unquote(sub_types), acc)
    799       end
    800 
    801       defp unquote(extension)(
    802              <<unquote(pattern), rest::binary>>,
    803              unquote(sub_oids),
    804              unquote(sub_types),
    805              oids,
    806              types,
    807              n,
    808              acc
    809            )
    810            when unquote(guard) do
    811         decode_tuple(rest, oids, types, n, [{n, unquote(body)} | acc])
    812       end
    813     end
    814   end
    815 
    816   defp decode_super(
    817          extension,
    818          pattern,
    819          sub_oids,
    820          sub_types,
    821          body,
    822          dispatch,
    823          rest,
    824          acc,
    825          rem,
    826          full,
    827          rows
    828        ) do
    829     quote do
    830       defp unquote(extension)(
    831              <<unquote(pattern), unquote(rest)::binary>>,
    832              unquote(sub_oids),
    833              unquote(sub_types),
    834              types,
    835              acc,
    836              unquote(rem),
    837              unquote(full),
    838              unquote(rows)
    839            ) do
    840         unquote(acc) = [unquote(body) | acc]
    841 
    842         case types do
    843           unquote(dispatch)
    844         end
    845       end
    846 
    847       defp unquote(extension)(
    848              <<unquote(pattern), rest::binary>>,
    849              unquote(sub_oids),
    850              unquote(sub_types),
    851              acc
    852            ) do
    853         acc = [unquote(body) | acc]
    854         unquote(extension)(rest, unquote(sub_oids), unquote(sub_types), acc)
    855       end
    856 
    857       defp unquote(extension)(
    858              <<unquote(pattern), rest::binary>>,
    859              unquote(sub_oids),
    860              unquote(sub_types),
    861              oids,
    862              types,
    863              n,
    864              acc
    865            ) do
    866         acc = [{n, unquote(body)} | acc]
    867         decode_tuple(rest, oids, types, n, acc)
    868       end
    869     end
    870   end
    871 
    872   defp decode_super_null(extension, dispatch, rest, acc, rem, full, rows) do
    873     quote do
    874       defp unquote(extension)(
    875              <<-1::int32(), unquote(rest)::binary>>,
    876              _sub_oids,
    877              _sub_types,
    878              types,
    879              acc,
    880              unquote(rem),
    881              unquote(full),
    882              unquote(rows)
    883            ) do
    884         unquote(acc) = [@null | acc]
    885 
    886         case types do
    887           unquote(dispatch)
    888         end
    889       end
    890 
    891       defp unquote(extension)(<<-1::int32(), rest::binary>>, sub_oids, sub_types, acc) do
    892         unquote(extension)(rest, sub_oids, sub_types, [@null | acc])
    893       end
    894 
    895       defp unquote(extension)(<<>>, _sub_oid, _sub_types, acc) do
    896         acc
    897       end
    898 
    899       defp unquote(extension)(
    900              <<-1::int32(), rest::binary>>,
    901              _sub_oids,
    902              _sub_types,
    903              oids,
    904              types,
    905              n,
    906              acc
    907            ) do
    908         decode_tuple(rest, oids, types, n, acc)
    909       end
    910     end
    911   end
    912 
    913   defp split_super({:->, _, [head, body]}) do
    914     case head do
    915       [{:when, _, [pattern, sub_oids, sub_types, guard]}] ->
    916         {pattern, sub_oids, sub_types, guard, body}
    917 
    918       [pattern, sub_oids, sub_types] ->
    919         {pattern, sub_oids, sub_types, body}
    920     end
    921   end
    922 
    923   defp configure(extensions, opts) do
    924     defaults = Postgrex.Utils.default_extensions(opts)
    925     Enum.map(extensions ++ defaults, &configure/1)
    926   end
    927 
    928   defp configure({extension, opts}) do
    929     state = extension.init(opts)
    930     matching = extension.matching(state)
    931     format = extension.format(state)
    932     {extension, {state, matching, format}}
    933   end
    934 
    935   defp configure(extension) do
    936     configure({extension, []})
    937   end
    938 
    939   defp define_inline(module, config, opts) do
    940     quoted = [
    941       directives(config, opts),
    942       find(config),
    943       encode(config, opts),
    944       decode(config, opts)
    945     ]
    946 
    947     Module.create(module, quoted, Macro.Env.location(__ENV__))
    948   end
    949 end