View Source FDBC.Tuple.Extension behaviour (fdbc v0.1.4)

A behaviour module for implementing user type codes.

Using this module makes it possible to extend the FDBC.Tuple layer with user type codes. Only the following type codes are allowed within the implementation 0x40..0x4F as defined in the specification.

Below is an example showing how to create an extension that would enable the tuple layer to handle DateTime:

defmodule TupleExtensions.DateTime do
  use FDBC.Tuple.Extension

  @datetime_typecode 0x40

  def decode(<<@datetime_typecode, length::integer-size(8)>> <> encoded) do
    {value, encoded} =
      case encoded do
        <<value::binary-size(^length), encoded>> -> {value, encoded}
        <<value::binary-size(^length)>> -> {value, <<>>}
      end

    [timestamp] = Tuple.unpack(value)
    {:ok, datetime} = DateTime.from_unix(timestamp)
    {{:datetime, datetime}, encoded}
  end

  def encode({:datetime, data}) do
    timestamp = DateTime.to_unix(data)
    packed = Tuple.pack([timestamp])
    <<@datetime_typecode>> <> <<byte_size(packed)::integer-big-8>> <> packed
  end

  def identify(%DateTime{}) do
    :datetime
  end
end

When using extensions the official documentation recommends that they are used within labelled directories to prevent type code clashes. With that in mind an extended tuple could be utilised like so making use of FDBC.Directory:

FDBC.transact(db, fn tr ->
  dir = FDBC.Directory.new() |> FDBC.Directory.open!(tr, ["example"], label: "datetime")
  key = FDBC.Tuple.pack([DateTime.utc_now()], extension: TupleExtensions.DateTime)
  :ok = FDBC.Transaction.set(tr, key, <<>>)
end)

Summary

Callbacks

Takes the encoded key returning the decoded tuple pair and the tail of the key to still be decoded.

Takes the keyed type to encode in the form of a tuple pair, returning its encoded representation.

Takes the custom type and returns its key.

Types

keyed()

@type keyed() :: {atom(), any()}

Callbacks

decode(binary)

@callback decode(binary()) :: {keyed(), binary()}

Takes the encoded key returning the decoded tuple pair and the tail of the key to still be decoded.

encode(keyed)

@callback encode(keyed()) :: binary()

Takes the keyed type to encode in the form of a tuple pair, returning its encoded representation.

identify(any)

@callback identify(any()) :: atom()

Takes the custom type and returns its key.