1

I am writing a service wherein I students from a UUID with PostgreSQL. I chose pgx (https://github.com/jackc/pgx) as a driver. I've debugged my program entirely and it seems that nothing is called after I call row.Scan. My connection is working and I am able to interact with the database (tested with inserts). The connection URI has a user with all permissions granted so that is not an issue. Here is my function definition:

func (r *StudentPgRepo) GetStudentById(uuid *uuid.UUID) (*aggregate.Student, error) {
    row := r.pool.QueryRow(context.Background(), "SELECT * FROM students WHERE student_id = $1", uuid.String())

    student := new(aggregate.Student)
    if err := row.Scan(
        &student.Id, &student.FName, &student.LName, &student.PwHash, &student.Created,
        &student.Updated, &student.P1.FName, &student.P1.LName, &student.P1.Email,
        &student.P2.FName, &student.P2.LName, &student.P2.Email, &student.ParentDetails,
        &student.Timezone, &student.Country, &student.State, &student.City, &student.Age,
        &student.Gender, &student.Race, &student.NewStudent, &student.MealAssistance,
    ); err != nil {
        if err == pgx.ErrNoRows {
            return nil, ErrStudentNotFound
        }
        return nil, err
    }

    return student, nil
}

Please let me know if there are any other details I should provide. Thank you.

Here is my function call:

    if err != nil {
        panic(err)
    }
    defer dbpool.Close()

    r, err := student.NewStudentPgRepo(dbpool)
    if err != nil {
        panic(err)
    }

    uid := uuid.New()
    _, err = r.GetStudentById(&uid)
    if err != nil {
        panic(err)
    }
Robert Nubel
  • 7,104
  • 1
  • 18
  • 30
reb0und
  • 23
  • 2
  • 1
    So you're seeing that execution is pausing inside the row.Scan? Does passing `context.WithTimeout(context.Background(), time.Second*5)` cause it to time out after 5 seconds? – Robert Nubel Jun 13 '23 at 01:47
  • I replaced the context with your suggestion and unfortunately encountered the same error in which the program goes idle. i implemented it as such: `ctx, cancel := context.WithTimeout(context.Background(), time.Second*1); defer cancel()` Everything is on a single line here for simplicity. I passed `ctx` into `QueryRow` instead of `context.Background`. – reb0und Jun 15 '23 at 23:36

1 Answers1

0

Probably, this won't solve your issue cause we need to deep dive into it with more information. However, my code works and can be used as the starting point for you too. Right below, you can find it:

package main

import (
    "context"
    "fmt"

    "github.com/jackc/pgx/v5"
)

type Todo struct {
    Id   int
    Name string
}

func main() {
    conn, err := pgx.Connect(context.Background(), "postgres://postgres:postgres@localhost:54322/postgres")
    if err != nil {
        panic(err)
    }
    defer conn.Close(context.Background())

    var todo Todo
    row := conn.QueryRow(context.Background(), "select id, name from todos where id = $1", 2)
    // row := conn.QueryRow(context.Background(), "select id, name from todos where id = $1", 3) // "3" not found
    if err := row.Scan(&todo.Id, &todo.Name); err != nil {
        if err == pgx.ErrNoRows {
            fmt.Println("record not found")
            return
        }
        panic(err)
    }
    fmt.Println(todo)
}

I run the PostgreSQL instance with this command:

docker run -d -p 54322:5432 -e POSTGRES_PASSWORD=postgres postgres

Within the DB, I manually created a table with the following script:

CREATE TABLE public.todos (
id INTEGER CONSTRAINT todos_pk PRIMARY KEY,
name TEXT
);

Then, I added two records just for the sake of the demo.
If this solves your issue that's fine, otherwise edit the question by adding the missing details and I'll try to dig into it. Let me know, thanks!

Edit - Connection Pool

I've just updated the code by using the connection pool feature provided by the github.com/jackc/pgx/v5/pgxpool package.

package main

import (
    "context"
    "fmt"

    "github.com/jackc/pgx"
    "github.com/jackc/pgx/v5/pgxpool"
)

type Todo struct {
    Id   int
    Name string
}

func main() {
    pool, err := pgxpool.New(context.Background(), "postgres://postgres:postgres@localhost:54322/postgres")
    if err != nil {
        panic(err)
    }
    defer pool.Close()

    var todo Todo
    row := pool.QueryRow(context.Background(), "select id, name from todos where id = $1", 2)
    // row := conn.QueryRow(context.Background(), "select id, name from todos where id = $1", 3) // "3" not found
    if err := row.Scan(&todo.Id, &todo.Name); err != nil {
        if err == pgx.ErrNoRows {
            fmt.Println("record not found")
            return
        }
        panic(err)
    }
    fmt.Println(todo)
}

The code is pretty similar, and it works as before. Let me know in case you have any other question, thanks!

ossan
  • 1,665
  • 4
  • 10
  • 1
    Thank you, I am very much able to insert records. The difficulty is reading. The key difference here is that you used a single connection instead of a connection pool; I will try that. – reb0und Jun 15 '23 at 23:40
  • Answer just edited! – ossan Jun 16 '23 at 07:09