# `PgInterop.Array`
[🔗](https://github.com/electric-sql/electric/tree/%40core/sync-service%401.6.2/packages/sync-service/lib/pg_interop/array.ex#L1)

# `array_append`

# `array_append_concat`

# `array_prepend`

# `array_prepend_concat`

# `concat_arrays`

# `get_array_dim`

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

# `index_access`

```elixir
@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

# `parse`

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

# `serialize`

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

# `slice_access`

```elixir
@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}])
    []

---

*Consult [api-reference.md](api-reference.md) for complete listing*
