jackc / pgx

PostgreSQL driver and toolkit for Go

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

pgx.NamedArgs method skips argument except for integer types

stanlyzoolo opened this issue · comments

Description

I use pgm.NamedArgs for preparing a query that should return a list, for example, of users from a table. So, the preparation of the map looks like this:

        var users []*model.User

        args := make(pgx.NamedArgs)

	q := `select * from users`

	if order != "" {
		args["order"] = order
		q += ` order by @order `
	}

	args["limit"] = limit
	args["offset"] = offset
	q += ` limit @limit offset @offset `

	return users, pgxscan.Select(ctx, repo.qb.Querier(), &users, q, args)

In the end query wil be:

select * from users order by @order limit @limit offset @offset

which is equal to:

select * from users order by id limit 15 offset 0

As a result, returned rows have no order, but according to limit and offset.

The same problem I faced with

if order != "" {
q += ` order by $1 `
}

q += ` limit $2 offset $3 `

rows, err := repo.qb.Querier().Query(ctx, q, order, limit, offset)
if err != nil {
    return nil, err
}

To scan the rows I used

pgx.CollectRows(rows, func(row pgx.CollectableRow) (*model.User, error) {
   // logic
}

As a result, returned rows have no order, but according to limit and offset, too.

Can you, please, explain to me what I'm doing wrong?

Bound parameters can only be used for values not column names or other expressions.

I assume you are trying to do something like the following:

select * from users order by name;

But what is actually happening in effect is the following:

select * from users order by 'name';

Ordering by a constant is meaningless. In fact, if you run the above SQL directly PostgreSQL will return an error. But by using placeholders PostgreSQL doesn't detect an error and instead the order by is essentially a no-op. e.g.

prepare s as select * from users order by $1;
execute s('name');

The above is syntactically allowed and executable, but the order by has no effect.

@jackc thanks for the explanation. This is really helpful!