Ecto - Multidimensional Array?

Hi Elixir community!

I’m trying to add a column with a two dimensional array type to database.
Here’s my migration.

def change do
    alter table(:decisions) do
      add :sequence, {:array, {:array, :string}}
    end
end

with this, i don’t get error running migration.

Here’s my schema

  schema "decisions" do
    ...
    field :sequence, {:array, {:array, :string}}

    timestamps()
  end

But when i try to save this value [["C83", "N51", "G3"], ["K22", "B17"], ["W46", "N14"]] to field :sequence, I got this error

(ArgumentError) nested lists must have lists with matching lengths
        (postgrex) lib/postgrex/extensions/array.ex:63: anonymous fn/6 in Postgrex.Extensions.Array.encode/4

How do I put matching lists with matching lengths to :sequence column? Any help is appreciated.

Thank You.

2 Likes

All of the inner lists, need to have the same length. Zour first list has three elements, the remaining ones have only 2.

Either make all lists of length 3 or all of them of length 2.

6 Likes

Thank you!
That solved it!
I guess i didn’t really pay attention to the error.
Really appreciate it!

Out of curiosity, what is the reason for that requirement?

1 Like

I am also interested in this. AFAIK, PostgreSQL is fine with arbitrary length lists.

1 Like

I’m not so sure about that:

CREATE TEMPORARY TABLE sal_emp (
    name            text,
    pay_by_quarter  integer[],
    schedule        text[][]
);
# CREATE TABLE

INSERT INTO sal_emp
    VALUES ('Bill',
    '{10000, 10000, 10000, 10000}',
    '{{"meeting", "lunch"}, {"meeting"}}');
# ERROR:  malformed array literal: "{{"meeting", "lunch"}, {"meeting"}}"
# LINE 4:     '{{"meeting", "lunch"}, {"meeting"}}');
#             ^
# DETAIL:  Multidimensional arrays must have sub-arrays with matching dimensions.

INSERT INTO sal_emp
    VALUES ('Bill',
    '{10000, 10000, 10000, 10000}',
    '{{"meeting", "lunch"}, {"lunch", "meeting"}}');
# INSERT 0 1
4 Likes

Indeed. I have re-checked myself; it turns out the lengths of sub-arrays are to be the same. Thanks.

1 Like