In gorm, how do you escape the `?` operator in postgres?
Asked Answered
E

1

6

Say I have a table 'testing' with a column 'agents' of type jsonb that stores an array of agent names

> SELECT * FROM testing;
+--------------------------------------+---------------------+
| id                                   | agents              |
|--------------------------------------+---------------------|
| 018d17a4-5418-1f87-f702-3ed8325f4d11 | ["mikel", "arsene"] |
+--------------------------------------+---------------------+

I can use the ? operator to find records that have a string as one of the agents.

> SELECT * FROM testing WHERE agents ? 'mikel'
+--------------------------------------+---------------------+
| id                                   | agents              |
|--------------------------------------+---------------------|
| 018d17a4-5418-1f87-f702-3ed8325f4d11 | ["mikel", "arsene"] |
+--------------------------------------+---------------------+

However, in gorm the ? also acts as a placeholder. So I can't form the query as

query := `SELECT * FROM testing WHERE agents ? ?
gorm.Raw(query, 'mikel')

will produce the raw query

SELECT * FROM testing WHERE agents 'mikel' ? 

I know I could use the @> operator to achieve this but I would like to know how I can specifically use the ? operator

Epicene answered 17/1, 2024 at 13:43 Comment(12)
That's not an operator in SQL, it's a positional parameter placeholder. This isn't a gorm feature. Most ODBC drivers work that way. What database are you using? PostgreSQL ?Guilder
Did you try using a named argument instead?Goosefoot
Does this answer your question? jsonb existential operators with parameterised queriesGuilder
As the duplicate shows, you can use jsonb_exists instead of ?Guilder
@PanagiotisKanavos Yes that's an operator in Postgres (postgresql.org/docs/9.5/functions-json.html).Epicene
In PostgreSQL only, which you didn't tag. It's also the positional parameter placeholder in the ODBC drivers for most databases, no matter the programming language. I only suspected you use PostgreSQL because you mentioned @>. Did you check the duplicate?Guilder
@PanagiotisKanavos that's interesting and will solve my issue. However, I am specifically looking to see if I can use the ? operator itself just out of curiosity. I have solved using @> operator in my case.Epicene
@PanagiotisKanavos I immediately edited my question & mentioned Postgres in the title. Maybe you read it before the edit :)Epicene
@Goosefoot just tried named arg and the ? operator is simply erased by gorm.Epicene
Use the correct tags instead of editing the title. Only tags are used to notify people interested in PostgreSQL. That's why the people that typically answer PostgreSQL questions haven't showed up yetGuilder
If you switch from ? to any equivalent function, you'll lose index support - those are tied to operator classes. I think postgres was in the title from the start. Did you try duplicating the ? to ?? or even ????Rescue
@Rescue ya I tried duplicating, but both ?? were erased by gorm.Epicene
U
1

GORM have package for it: https://github.com/go-gorm/datatypes#json

As the documentation says, your code should look like this:

import "gorm.io/datatypes"

err := db.Raw(
    `SELECT * FROM testing WHERE ? AND foo = 'bar'`, 
    datatypes.JSONQuery("agents").HasKey("mikel"),
  ).
    Scan(...).
    Error

This gives the query:

SELECT * FROM testing WHERE "agents"::jsonb ? 'mikel' AND foo = 'bar'

Alternative solution:

    err := db.Raw(
        `SELECT * FROM testing WHERE ? ? AND foo = 'bar'`, 
        gorm.Expr(`?`),
        `mikel`,
      ).
        Scan(...).
        Error
    // SELECT * FROM testing WHERE agents ? 'mikel' AND foo = 'bar'
Ultramicroscopic answered 23/4, 2024 at 7:39 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.