georgysavva / scany

Library for scanning data from a database into Go structs and more
MIT License
1.31k stars 68 forks source link

cannot use db (variable of type *pgxpool.Pool) as pgxscan.Querier value in argument to pgxscan.Select: *pgxpool.Pool does not implement pgxscan.Querier (wrong type for method Query) #122

Closed edewindt closed 10 months ago

edewindt commented 10 months ago
package data

import (
    "context"
    "log"
    "os"

    "github.com/georgysavva/scany/pgxscan"
    "github.com/jackc/pgx/v5/pgxpool"
)

var dburl = os.Getenv("PG_URI")

var ctx = context.Background()

var db, _ = pgxpool.New(ctx, dburl)

type HTTPError struct {
    Status  string
    Message string
}

type Hello struct {
    ID    int    `json:"id"`
    Hello string `json:"hello"`
}

func HelloFunc(id string) []*Hello {
    var hellos []*Hello
    defer func() {
        if err := recover(); err != nil {
            log.Println("panic occurred:", err)
        }
    }()
    pgxscan.Select(ctx, db, &hellos, `SELECT * from hello WHERE id = $1`, id)

    return hellos

}

db is erroring with:cannot use db (variable of type pgxpool.Pool) as pgxscan.Querier value in argument to pgxscan.Select: pgxpool.Pool does not implement pgxscan.Querier (wrong type for method Query)

Xamss commented 10 months ago

The same issue here but it should be fine as long as you use module jackc/pgx version 4 instead of version 5

edewindt commented 10 months ago
func QueryAndScan(ctx context.Context, query string, dest interface{}, args ...interface{}) error {
    rows, err := db.Query(ctx, query, args...)
    if err != nil {
        return err
    }
    defer rows.Close()

    sliceVal := reflect.ValueOf(dest)
    if sliceVal.Kind() != reflect.Ptr || sliceVal.Elem().Kind() != reflect.Slice {
        return errors.New("dest must be a pointer to a slice")
    }

    sliceElemType := sliceVal.Elem().Type().Elem()
    isPointer := sliceElemType.Kind() == reflect.Ptr
    if isPointer {
        sliceElemType = sliceElemType.Elem() // Get the type that the pointer points to
    }
    if sliceElemType.Kind() != reflect.Struct {
        return errors.New("slice elements must be structs or pointers to structs")
    }

    for rows.Next() {
        var elem reflect.Value
        if isPointer {
            elem = reflect.New(sliceElemType)
        } else {
            elem = reflect.New(sliceElemType).Elem()
        }

        fields := make([]interface{}, elem.Elem().NumField())
        for i := range fields {
            fields[i] = elem.Elem().Field(i).Addr().Interface()
        }

        err := rows.Scan(fields...)
        if err != nil {
            log.Println("Error scanning row:", err)
            continue
        }

        if isPointer {
            sliceVal.Elem().Set(reflect.Append(sliceVal.Elem(), elem))
        } else {
            sliceVal.Elem().Set(reflect.Append(sliceVal.Elem(), elem.Elem()))
        }
    }

    if err := rows.Err(); err != nil {
        return err
    }

    return nil
}

I've been using this as a replacement until it gets patched

edewindt commented 10 months ago

Also assume that db is a *pgxpool.Pool type

georgysavva commented 10 months ago

@edewindt @Xamss to use "github.com/jackc/pgx/v5" you need to use "scany/v2".

This is also true:

The same issue here but it should be fine as long as you use module jackc/pgx version 4 instead of version 5

georgysavva commented 10 months ago

Feel free to reopen if it doesn't solve your problem