Golang PGX:扫描行时带有返回语句的更新返回错误

发布于 2025-02-04 14:01:29 字数 4321 浏览 2 评论 0原文

我将Postgres与PostGis扩展名一起使用, pgx & sqlf 插入/删除和读取行的工作正常,我只是在努力争夺一行的更新,因为当我尝试将返回的行扫描到GO结构中时,我总是会从pgx中返回此错误。

no rows in result set

以下是我创建的用于进行部分更新的方法。我首先创建SQL查询并设置列以更新,还添加返回语句以返回整个行。由于我的位置列是一个后点,我需要用st_asbinary函数包装列,以便我可以将其扫描到 orb.point

type UpdatePartyParams struct {
    ID            string
    Title         string
    Lat           float32
    Long          float32
    StreetAddress string
    PostalCode    string
    State         string
    Country       string
    StartDate     time.Time
    EndDate       time.Time
}

func (d Directory) UpdateParty(ctx context.Context, arg UpdatePartyParams) (Party, error) {
    sqlf.SetDialect(sqlf.PostgreSQL)
    b := sqlf.Update(TABLE_NAME)

    if arg.Title != "" {
        b = b.Set("title", arg.Title)
    }
    if arg.Lat != 0 && arg.Long != 0 {
        b = b.SetExpr("location", "ST_SetSRID(ST_MakePoint(?, ?), 4326)", arg.Long, arg.Lat)
    }
    if arg.StreetAddress != "" {
        b = b.Set("street_address", arg.StreetAddress)
    }
    if arg.PostalCode != "" {
        b = b.Set("postal_code", arg.PostalCode)
    }
    if arg.State != "" {
        b = b.Set("state", arg.State)
    }
    if arg.Country != "" {
        b = b.Set("country", arg.Country)
    }
    startYear := arg.StartDate.Year()
    if !(startYear == 1970) {
        b = b.Set("start_date", arg.StartDate)
    }
    endYear := arg.StartDate.Year()
    if !(endYear == 1970) {
        b = b.Set("end_date", arg.EndDate)
    }

    b.
        Where("id = ?", arg.ID).
        Returning("id, user_id, title, is_public, ST_AsBinary(location) AS location, street_address, postal_code, state, country, start_date, end_date")

    log.Println(b.String()) // UPDATE parties SET title=$1 WHERE id = $2 RETURNING id, user_id, title, is_public, ST_AsBinary(location) AS location, street_address, postal_code, state, country, start_date, end_date

    row := d.pool.QueryRow(ctx, b.String(), b.Args()...)
    var i Party
    err := row.Scan(
        &i.ID,
        &i.UserID,
        &i.Title,
        &i.IsPublic,
        wkb.Scanner(&i.Location),
        &i.StreetAddress,
        &i.PostalCode,
        &i.State,
        &i.Country,
        &i.StartDate,
        &i.EndDate,
    )

    return i, err
}

我的数据库架构

CREATE TABLE parties (
    id varchar(27) PRIMARY KEY,
    user_id TEXT NOT NULL,
    title TEXT NOT NULL,
    is_public BOOLEAN NOT NULL DEFAULT false,
    location geometry(POINT, 4326) NOT NULL,
    street_address TEXT,
    postal_code TEXT,
    state TEXT,
    country TEXT,
    start_date TIMESTAMP,
    end_date TIMESTAMP
);

上述错误是由 row.scan 方法并抛出“如果找不到行” 。但是,当我使用差异SQL UI客户端执行SQL语句时,它可以正常运行,并且返回了行。知道什么可能导致row.scan()方法失败,而行不返回?

编辑

怪异的部分是,一行的简单读取效果很好,并将返回的记录扫描到GO结构中。以下是一种工作方法,它仅通过select语句使用相同的row.scan方法。

func (d PartyRepository) GetParty(ctx context.Context, id string) (Party, error) {
    sqlf.SetDialect(sqlf.PostgreSQL)
    b := sqlf.
        Select("id, user_id, title, is_public, ST_AsBinary(location) AS location, street_address, postal_code, state, country, start_date, end_date").
        From(TABLE_NAME).
        Where("id = ?", id)

    log.Println(b.String())

    row := d.pool.QueryRow(ctx, b.String(), b.Args()...)
    var i Party
    err := row.Scan(
        &i.ID,
        &i.UserID,
        &i.Title,
        &i.IsPublic,
        wkb.Scanner(&i.Location),
        &i.StreetAddress,
        &i.PostalCode,
        &i.State,
        &i.Country,
        &i.StartDate,
        &i.EndDate,
    )
    return i, err
}

I use Postgres with the Postgis extension and pgx & sqlf on the Go side.
Inserting/deleting and reading Rows works fine I'm just struggeling with Updates of a row since I always get this error returned from pgx when I try to scan the returned row into a Go struct.

no rows in result set

Below is the method I created to do partial updates. I first creates the SQL query and set columns to update and also add a RETURNING statement to return the whole row. Since my location column is a Postgis Point I need to wrap the column with the ST_AsBinary function so that I can scan it into an Orb.Point.

type UpdatePartyParams struct {
    ID            string
    Title         string
    Lat           float32
    Long          float32
    StreetAddress string
    PostalCode    string
    State         string
    Country       string
    StartDate     time.Time
    EndDate       time.Time
}

func (d Directory) UpdateParty(ctx context.Context, arg UpdatePartyParams) (Party, error) {
    sqlf.SetDialect(sqlf.PostgreSQL)
    b := sqlf.Update(TABLE_NAME)

    if arg.Title != "" {
        b = b.Set("title", arg.Title)
    }
    if arg.Lat != 0 && arg.Long != 0 {
        b = b.SetExpr("location", "ST_SetSRID(ST_MakePoint(?, ?), 4326)", arg.Long, arg.Lat)
    }
    if arg.StreetAddress != "" {
        b = b.Set("street_address", arg.StreetAddress)
    }
    if arg.PostalCode != "" {
        b = b.Set("postal_code", arg.PostalCode)
    }
    if arg.State != "" {
        b = b.Set("state", arg.State)
    }
    if arg.Country != "" {
        b = b.Set("country", arg.Country)
    }
    startYear := arg.StartDate.Year()
    if !(startYear == 1970) {
        b = b.Set("start_date", arg.StartDate)
    }
    endYear := arg.StartDate.Year()
    if !(endYear == 1970) {
        b = b.Set("end_date", arg.EndDate)
    }

    b.
        Where("id = ?", arg.ID).
        Returning("id, user_id, title, is_public, ST_AsBinary(location) AS location, street_address, postal_code, state, country, start_date, end_date")

    log.Println(b.String()) // UPDATE parties SET title=$1 WHERE id = $2 RETURNING id, user_id, title, is_public, ST_AsBinary(location) AS location, street_address, postal_code, state, country, start_date, end_date

    row := d.pool.QueryRow(ctx, b.String(), b.Args()...)
    var i Party
    err := row.Scan(
        &i.ID,
        &i.UserID,
        &i.Title,
        &i.IsPublic,
        wkb.Scanner(&i.Location),
        &i.StreetAddress,
        &i.PostalCode,
        &i.State,
        &i.Country,
        &i.StartDate,
        &i.EndDate,
    )

    return i, err
}

My Database Schema

CREATE TABLE parties (
    id varchar(27) PRIMARY KEY,
    user_id TEXT NOT NULL,
    title TEXT NOT NULL,
    is_public BOOLEAN NOT NULL DEFAULT false,
    location geometry(POINT, 4326) NOT NULL,
    street_address TEXT,
    postal_code TEXT,
    state TEXT,
    country TEXT,
    start_date TIMESTAMP,
    end_date TIMESTAMP
);

The mentioned error is caused by the row.Scan method and thrown "If no rows were found". But when I execute the sql statement with a difference SQL UI client it works fine and the row is returned. Any Idea what could cause the row.Scan() method to fail and the row not to be returned?

Edit

The weird part is that a simple read for one row works fine and scans the returned record into the Go struct. Below is a working method which uses the same row.Scan method just through a select statement.

func (d PartyRepository) GetParty(ctx context.Context, id string) (Party, error) {
    sqlf.SetDialect(sqlf.PostgreSQL)
    b := sqlf.
        Select("id, user_id, title, is_public, ST_AsBinary(location) AS location, street_address, postal_code, state, country, start_date, end_date").
        From(TABLE_NAME).
        Where("id = ?", id)

    log.Println(b.String())

    row := d.pool.QueryRow(ctx, b.String(), b.Args()...)
    var i Party
    err := row.Scan(
        &i.ID,
        &i.UserID,
        &i.Title,
        &i.IsPublic,
        wkb.Scanner(&i.Location),
        &i.StreetAddress,
        &i.PostalCode,
        &i.State,
        &i.Country,
        &i.StartDate,
        &i.EndDate,
    )
    return i, err
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文