Skip to content
This repository was archived by the owner on Jul 12, 2025. It is now read-only.
This repository was archived by the owner on Jul 12, 2025. It is now read-only.

Unable to create and use [][]String types in postgres #219

@jacksoncalvert

Description

@jacksoncalvert

Im using Gorm for the mapping gorm structs to database tables, and im trying to configure an easy way to do [][]string (text[][]) in postgres.

What im finding is the script created to insert data is correct, but the data that is passing through is being flattened into a []string array.

the code that ive found thats doing this is

func (plan *encodePlanDriverValuer) Encode(value any, buf []byte) (newBuf []byte, err error) {
	dv := value.(driver.Valuer)
	if dv == nil {
		return nil, nil
	}
	v, err := dv.Value()
	if err != nil {
		return nil, err
	}
	if v == nil {
		return nil, nil
	}

	newBuf, err = plan.m.Encode(plan.oid, plan.formatCode, v, buf)
	if err == nil {
		return newBuf, nil
	}

	s, ok := v.(string)
	if !ok {
		return nil, err
	}

	var scannedValue any
	scanErr := plan.m.Scan(plan.oid, TextFormatCode, []byte(s), &scannedValue)
	if scanErr != nil {
		return nil, err
	}

	// Prevent infinite loop. We can't encode this. See https://github.com/jackc/pgx/issues/1331.
	if reflect.TypeOf(value) == reflect.TypeOf(scannedValue) {
		return nil, fmt.Errorf("tried to encode %v via encoding to text and scanning but failed due to receiving same type back", value)
	}

	var err2 error
	newBuf, err2 = plan.m.Encode(plan.oid, BinaryFormatCode, scannedValue, buf)
	if err2 != nil {
		return nil, err
	}

	return newBuf, nil
}

and im working through a struct thats similar to this

import "github.com/lib/pq"

type Task struct {
	ID             string      `json:"id" gorm:"primaryKey;column:id;"`
	TaskName       *string     `json:"taskName" gorm:"column:taskName"`
	Liststringtask pq.GenericArray `json:"liststringtask" gorm:"column:liststringtask;type:text[][]"`
}

Ive found so far that this line is pushing a correctly formatted 2d string array into a 1d string array, and if i change it from

var scannedValue any
	scanErr := plan.m.Scan(plan.oid, TextFormatCode, []byte(s), &scannedValue)
	if scanErr != nil {
		return nil, err
	}

to

var scannedValue [][]string
	scanErr := plan.m.Scan(plan.oid, TextFormatCode, []byte(s), &scannedValue)
	if scanErr != nil {
		return nil, err
	}

then the insertion into the db is correct and then scannedValue is of the correct type. Is there another way to create 2d (or multi-d) arrays for postgres?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions