Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(pgdialect): postgres syntax errors for pointers and slices #877 #1111

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

rfarrjr
Copy link

@rfarrjr rfarrjr commented Jan 22, 2025

Addresses issue identified in #877.

New tests added for pointers to slice and slice of pointer elements including arrays of JSONB columns.

ID int64 `bun:",pk,autoincrement"`
Item Item `bun:",type:jsonb"`
ItemPtr *Item `bun:",type:jsonb"`
Items []Item `bun:",type:jsonb,array"`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does it mean to use both jsonb and array together?
I think PostgreSQL will handle the JSONB type, and we only need to consider JSONB when inserting and reading data?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. PostgreSQL doesn't actually support a JSONB array directly, but rather includes several functions (jsonb_array_elements) for working with a JSONB arrays on a JSONB column. Can read more here.

@j2gg0s
Copy link
Collaborator

j2gg0s commented Jan 23, 2025

Thanks your PR, it seems like it could help us a lot.

I have a strange example, not sure if it’s appropriate.
The model:

type Location struct {
	ID string `bun:"type:uuid,pk"`

	// Users []User `bun:"type:jsonb,array"`
	UserIDs []UserID `bun:"type:text[]"`
}

type UserID struct {
	ID string
}

func (u UserID) AppendQuery(fmter schema.Formatter, b []byte) ([]byte, error) {
        v := []byte(`"` + u.ID + `"`)
        return append(b, v...), nil
}

var _ schema.QueryAppender = (*UserID)(nil)

Run with output:

[bun]  12:21:27.085   DROP TABLE           49.112ms  DROP TABLE IF EXISTS "locations" CASCADE
[bun]  12:21:27.102   CREATE TABLE         16.262ms  CREATE TABLE "locations" ("id" uuid NOT NULL, "user_i_ds" text[], PRIMARY KEY ("id"))
[bun]  12:21:27.109   INSERT                7.047ms  INSERT INTO "locations" ("id", "user_i_ds") VALUES ('a2cd66d9-c5c6-4b06-a0a9-da2b4ed85960', '["foo","bar"]')       pgdriver.Error: ERROR: malformed array literal: "["foo","bar"]" (SQLSTATE=22P02)
panic: ERROR: malformed array literal: "["foo","bar"]" (SQLSTATE=22P02)

}

if elemType.Kind() == reflect.Struct {
brackets = "[]"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this meant to handle JSONB? But why would the JSONB type end up being processed here?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are needed to format a JSON array since the underlying column is just JSONB.

I think I need to add a check here to ignore this if the type is no JSONB or if the elemType implement query appender to handle your example above correctly. Will add that test and fix.

@Aoang
Copy link
Contributor

Aoang commented Jan 23, 2025

I believe this is intended to enhance structural support for "text[]", but the underlying logic appears to be somewhat perplexing. Perhaps I am not fully grasping it yet.

It may be beneficial for you to review the following link: https://github.com/FlowerLab/sorbifolia/blob/main/bunpgd/datatype/typ_array.go to determine if it aligns with your objectives.

@rfarrjr
Copy link
Author

rfarrjr commented Jan 23, 2025

This PR addresses a couple of things:

  1. Handle array of structs mapping to a JSONB column, which does enhance the option of serializing/deserializing structs into a text[] type.

  2. ,array sql type detection doesn't handle arrays of pointers with specifying the type. i.e.

type Person {
   Names []*string `bun:",array"`  
}
  1. Property quoting strings in an array when using []*string

@j2gg0s
Copy link
Collaborator

j2gg0s commented Jan 26, 2025

In my understanding, this PR aims to accomplish two things:

  1. Fix bug when Go type is []*string and the PostgreSQL's type is text[]
  2. Support append&scan, when Go type is []struct and type PostgreSQL's type is array

For 1, this should be fixed, and we can also handle other basic types along the way.

For 2, I don’t see the necessity to support this feature for now.
Most of the time, we use text or JSONB in PostgreSQL for storage.

@rfarrjr
Copy link
Author

rfarrjr commented Jan 27, 2025

This actually got me thinking, so I tried the following and it is functional. Could be worth updating the documentation to show how to handle arrays when using jsonb.

type Model struct {
  ID        int64    `bun:",pk,autoincrement"`
  Items     []Item   `bun:",type:jsonb"`
  ItemsP    []*Item  `bun:",type:jsonb"`
}

I will back out the enhancement changes and just leave the fixes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants