View Source FDBC.Tuple (fdbc v0.1.4)
An implementation of upstreams builtin tuple layer. This layer is used for encoding keys that are useable by FoundationDB. The encoded key maintains the same sort order as the original tuple: sorted first by the first element, then by the second element, etc. This makes the tuple layer ideal for building a variety of higher-level data models.
Below is an example showing the usage of the tuple layer for handling population figures for the United States are stored using keys formed from the tuple of state and county:
defmodule Example do
def get_county_populations_in_state(db, state) do
FDBC.transact(db, fn tr ->
{start, stop} = FDBC.Tuple.range([state])
Transaction.get_range(tr, start, stop) |> Enum.map(fn {_, v} -> String.to_integer(v) end)
end)
end
def set_county_population(db, state, county, population) do
FDBC.transact(db, fn tr ->
key = FDBC.Tuple.pack([state, county])
Transaction.set(tr, key, Integer.to_string(population))
end)
end
end
Upstream Compatibility
At the time of writing all type codes are implemented.
Although fully complaint, the tuple layer implementation is lossy by default
due to Elixir's type system. While not an issue when the key space is
exclusively managed by this library, this is not the case if the key space is
shared. This is because types like String.t/0
map directly down to
binary/0
which is a lossy process at the time of packing.
# A string will encode to the type code of a binary and not of a unicode string.
assert "\x01foobar\x00" == Tuple.pack(["foobar"])
# This can be countered via a keyword list.
assert "\x02foobar\x00" == Tuple.pack([{string: "foobar"}])
To allow interoperability on shared key spaces the FDBC.Tuple
module
supports the :keyed
option. When used this option changes the tuple from a
list into a keyword list, where the keys are used to type the tuple.
# In this case `keyed` will ensure the tuple is a keyword list and raise an exception if not.
assert "\x02foobar\x00" == Tuple.pack([{string: "foobar"}], keyed: true)
# In this case `keyed` will ensure the tuple is returned as a keyword list.
assert [{string: "foobar"}] == Tuple.unpack("\x02foobar\x00", keyed: true)
The following atoms are used for keying tuple type codes:
:null
-0x00
:binary
-0x01
:string
-0x02
:integer
-0x0B..0x1D
:float
-0x20
:double
-0x21
:boolean
-0x26..0x27
:uuid
-0x30
:versionstamp
-0x33
User Type Codes
It is possible to extend the tuple layer with user type codes which can be
achieved by implementing the FDBC.Tuple.Extension
behaviour and supplying
it to the tuple functions via the :extension
option. For more information
and example refer to the documentation in FDBC.Tuple.Extension
.
Summary
Functions
Returns a key encoding the specified tuple.
Returns the start and stop keys for a given tuple.
Returns the tuple that encoded into the given key.
Functions
Returns a key encoding the specified tuple.
Raises an ArgumentError
if more than one incomplete
FDBC.Tuple.Versionstamp
is provided.
Options
:extension
- a module that implements the behaviourFDBC.Tuple.Extension
allowing the Tuple layer to be extended with user type codes.:keyed
- if present, then the tuple is returned as a keyword list, such as[{string: "flip"}, {string: "flop"}]
.:versionstamp
- if present, then the tuple must contain one incomplete versionstamp whose postition will be encoded on the end of the key to enable compatability with versionstamp operations; AnArgumentError
will be raised if no incomplete versionstamp is found or if more than one is found. By default packing a tuple with an incomplete versionstamp will raise anArgumentError
.
Returns the start and stop keys for a given tuple.
The start and stop keys allow the retrieval of all tuples of greater length
than the provided prefix
.
Options
:extension
- a module that implements the behaviourFDBC.Tuple.Extension
allowing the Tuple layer to be extended with user type codes.:keyed
- if present, then the tuple must be keyedly typed as a keyword list, such as[{string: "flip"}, {string: "flop"}]
.
Examples
# Returns start & stop keys which when used in a range query would return # tuples like ["A", 2, x], ["A", 2, x, y], etc. FDBC.Tuple.range(["A", 2])
Returns the tuple that encoded into the given key.
Options
:extension
- a module that implements the behaviourFDBC.Tuple.Extension
allowing the Tuple layer to be extended with user type codes.:keyed
- if present, then the tuple is returned as a keyword list, such as[{string: "flip"}, {string: "flop"}]
.