rocketlaunchr / dbq

Zero boilerplate database operations for Go

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Add support for PostgreSQL arrays

Rirush opened this issue · comments

Problem

PostgreSQL has support for arrays. For example, we have this table:

CREATE TABLE example (
    bytes BYTEA -- byte array
);

In order to insert data into it, we need this query:

INSERT INTO example (bytes) VALUES ({0, 1, 2, 3, 4});

or

INSERT INTO example (bytes) VALUES (ARRAY[0, 1, 2, 3, 4]);

Using dbq that code should've looked like:

stmt := dbq.INSERT("example", []string{"bytes"}, 1, dbq.PostgreSQL)
_, _ = dbq.E(context.Background(), db, stmt, nil, []byte{0, 1, 2, 3, 4})

Expected behavior of this code

It will create statement

INSERT INTO example (bytes) VALUES ({0, 1, 2, 3, 4});

which will correctly insert array into the table.

Actual behavior

It creates statement

INSERT INTO example (bytes) VALUES (0, 1, 2, 3, 4);

which is invalid and doesn't work because each array element is treated like separate field.

I've tried wrapping byte array into []interface{} and even [][]interface{} - it doesn't resolve the issue, dbq still treats arrays as lists of fields.

commented

A new insert function will need to be created in a postgresql sub package to create "exotic" queries.

commented

Can you do a PR?

Thanks for a quick response! I will see what I can do. From what I can see right now, dbq.Insert forms a perfectly valid statement (as it relies on field names provided manually by the user), the problems arise when the query is actually executed. dbq.E/dbq.Q treat all arrays like arrays of fields and unpack them. Seems like there's a need for separate function, that will treat all arrays like actual arrays.

commented

E and Q are nothing more than the Exec and Query func in database/sql

commented
stmt := dbq.INSERT("example", []string{"bytes"}, 1, dbq.PostgreSQL)
_, _ = dbq.E(context.Background(), db, stmt, nil, []byte{0, 1, 2, 3, 4})

Have you tried json encoding instead:

stmt := dbq.INSERT("example", []string{"bytes"}, 1, dbq.PostgreSQL)
_, _ = dbq.E(context.Background(), db, stmt, nil, string(json.Marshal([]byte{0, 1, 2, 3, 4})))

commented

Going to close this since I think you know what needs to be done

Yes, okay. I'll make a PR if I'll figure out a good solution for this issue

commented

What's wrong with the solution I have above with JSON?