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.