View Source PgInterop.Array (electric v0.9.5)

Summary

Functions

Get the dimension of a postgres array.

Access an index of a postgres array. If the index is out of bounds or array has more dimensions than the indices provided, returns nil.

Parse a Postgres string-serialized array into a list of strings, unwrapping the escapes. Parses nested arrays. If a casting function is provided, it will be applied to each element.

Serialize a list of strings into a postgres string-serialized array into a list of strings, wrapping the contents

Access a slice or index of a postgres array.

Functions

Link to this function

array_append(list, elem)

View Source
Link to this function

array_prepend(elem, list)

View Source
Link to this function

concat_arrays(arr1, arr2)

View Source
Link to this function

get_array_dim(arr, dim \\ 0)

View Source

Get the dimension of a postgres array.

Examples

iex> ~S|{}| |> parse() |> get_array_dim()
nil

iex> ~S|{1,2,3,4,5}| |> parse() |> get_array_dim()
1

iex> ~S|{{1,2},{3,4}}| |> parse() |> get_array_dim()
2
Link to this function

index_access(array, list_of_indices)

View Source
@spec index_access(list(), [{:index, integer()}]) :: list()

Access an index of a postgres array. If the index is out of bounds or array has more dimensions than the indices provided, returns nil.

Examples

iex> ~S|{1,2,3,4,5}| |> parse(&String.to_integer/1) |> index_access([{:index, 3}])
3

iex> ~S|{{1,2},{3,4}}| |> parse(&String.to_integer/1) |> index_access([{:index, 2}, {:index, 1}])
3

iex> ~S|{{1,2},{3,4}}| |> parse(&String.to_integer/1) |> index_access([{:index, 3}])
nil
Link to this function

parse(str, casting_fun \\ & &1)

View Source

Parse a Postgres string-serialized array into a list of strings, unwrapping the escapes. Parses nested arrays. If a casting function is provided, it will be applied to each element.

Parsing follows SOME of the same rules as the postgres parser, in particular:

  1. at most 6 nesting levels are allowed,
  2. arrays must be of uniform dimension, i.e. all sub-arrays must have the same number of elements if at the same depth.

This implementation also breaks away from the postgres parser in that some bugs are NOT reimplemented:

  • select '{{1},{{2}}}'::text[]; yields {{{1}},{{2}}} in PG, we raise an error
  • select '{{{1}},{2}}'::text[]; yields {} in PG, we raise an error
  • select '{{{1}},{2},{{3}}}::text[]; yields {{{1}},{{NULL}},{{3}}} in PG, we raise an error

Examples

iex> ~S|{"(\"2023-06-15 11:18:05.372698+00\",)"}| |> parse()
[~s|("2023-06-15 11:18:05.372698+00",)|]

iex> ~S|{"(\"2023-06-15 11:18:05.372698+00\",)","(\"2023-06-15 11:18:05.372698+00\",)"}| |> parse()
[~s|("2023-06-15 11:18:05.372698+00",)|, ~s|("2023-06-15 11:18:05.372698+00",)|]

iex> ~S|{hello, world, null, "null"}| |> parse()
["hello", "world", nil, "null"]

iex> ~S|{"2023-06-15 11:18:05.372698+00",2023-06-15 11:18:05.372698+00}| |> parse(fn x -> {:ok, n, _} = DateTime.from_iso8601(x); n end)
[~U[2023-06-15 11:18:05.372698Z], ~U[2023-06-15 11:18:05.372698Z]]

iex> ~s|{ "1" , 3  ,   "2" ,    3 3  }| |> parse()
["1", "3", "2", "3 3"]

iex> ~s|{ {{1, 1}, { "2"   , 2 }} ,{{"3", 3}, {4, 4} }, {  {5, 5},{6, 6}  }}| |> parse(&String.to_integer/1)
[[[1, 1], [2, 2]], [[3, 3], [4, 4]], [[5, 5], [6, 6]]]

iex> ~s|{ "1" ,   "2" ,    3 3   , , 4}| |> parse()
** (RuntimeError) Unexpected ',' character

iex> ~s|{ "1" , 3,  "2" ,    3 3   , }| |> parse()
** (RuntimeError) Unexpected '}' character

iex> ~s|{ {1} ,{   2 }, {3  }}  }| |> parse()
** (RuntimeError) Invalid array syntax

iex> ~s|{{{1} ,{   2 }, {3  }} | |> parse()
** (RuntimeError) Unexpected end of input

iex> ~s|{"}| |> parse()
** (RuntimeError) Unexpected end of input

iex> ~s|{{1},2,{3}}| |> parse(&String.to_integer/1)
** (RuntimeError) Unexpected array element

iex> ~s|{{{{{{{1}}}}}}}| |> parse()
** (RuntimeError) number of dimensions (7) exceeds maximum of 6

iex> ~s|{ {1} ,{   {2} }, {3  }}| |> parse()
** (RuntimeError) Inconsistent array dimensions

iex> ~s|{ {{1}} ,{2}, {3  }}| |> parse()
** (RuntimeError) Inconsistent array dimensions
Link to this function

serialize(array, quote_char \\ 34)

View Source

Serialize a list of strings into a postgres string-serialized array into a list of strings, wrapping the contents

Examples

iex> [~s|("2023-06-15 11:18:05.372698+00",)|] |> serialize()
~S|{"(\"2023-06-15 11:18:05.372698+00\",)"}|

iex> [~s|("2023-06-15 11:18:05.372698+00",)|, ~s|("2023-06-15 11:18:05.372698+00",)|] |> serialize()
~S|{"(\"2023-06-15 11:18:05.372698+00\",)","(\"2023-06-15 11:18:05.372698+00\",)"}|

iex> str = ~S|{"(\"2023-06-15 11:18:05.372698+00\",)","(\"2023-06-15 11:18:05.372698+00\",)"}|
iex> str |> parse() |> serialize()
str
Link to this function

slice_access(array, instructions)

View Source
@spec slice_access(
  list(),
  [{:slice, nil | integer(), nil | integer()} | {:index, integer()}]
) :: list()

Access a slice or index of a postgres array.

Examples

iex> ~S|{1,2,3,4,5}| |> parse(&String.to_integer/1) |> slice_access([{:slice, nil, 3}])
[1, 2, 3]

iex> ~S|{1,2,3,4,5}| |> parse(&String.to_integer/1) |> slice_access([{:slice, 3, nil}])
[3, 4, 5]

iex> ~S|{1,2,3,4,5}| |> parse(&String.to_integer/1) |> slice_access([{:slice, 3, 4}])
[3, 4]

iex> ~S|{{1,2},{3,4}}| |> parse(&String.to_integer/1) |> slice_access([{:slice, nil, nil}, {:index, 2}])
[[1, 2], [3, 4]]

iex> ~S|{{1,2},{3,4}}| |> parse(&String.to_integer/1) |> slice_access([{:slice, nil, nil}, {:slice, 2, 2}])
[[2], [4]]

iex> ~S|{{1,2},{3,4}}| |> parse(&String.to_integer/1) |> slice_access([{:slice, nil, nil}, {:slice, -1, 1}])
[[1], [3]]

iex> ~S|{{1,2},{3,4}}| |> parse(&String.to_integer/1) |> slice_access([{:slice, nil, nil}, {:slice, 1, -1}])
[]