Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I want to be able to use PostgreSQL's parametric placeholders. #967

Open
iwashi623 opened this issue Mar 26, 2024 · 0 comments
Open

I want to be able to use PostgreSQL's parametric placeholders. #967

iwashi623 opened this issue Mar 26, 2024 · 0 comments

Comments

@iwashi623
Copy link

iwashi623 commented Mar 26, 2024

Hello everyone, I'd like to ask if you have ever wanted to execute the following query in bun

Have you ever wanted to execute the following query in bun?

INSERT INTO table_name (value1) VALUES ($1);

The $1 and $2 parts of the above query are PostgreSQL placeholders.
You can execute the query by calling the Exec method with the standard package sql.DB.

query := "INSERT INTO table_name (value1) VALUES ($1);"
url := os.LookupEnv("DB_URL")
db, _ := sql.Open("postgres", url)
db.Exec(query, "test_value1")

However, when I call the Exec method using bun.DB, I get the following error.

There is no parameter $1

On the other hand, using ? as a placeholder can be used to execute successfully.

query := "INSERT INTO table_name (value1) VALUES (?) ;"
url := os.LookupEnv("DB_URL")
db, _ := sql.Open("postgres", url)
db.Exec(query, "test_value1")

DB.Exec() and sql.DB.Exec() are methods of different structures, so it does not matter that they behave differently.
Each RDBMS (MySQL, PostgreSQL, Oracle...) Exec() is probably used to abstract the notation of each RDBMS (MySQL, PostgreSQL, Oracle...).
However, it would be nice to have compatibility with each DB engine's own notation.

From my research, it works with PostgreSQL placeholders by simply modifying the following sentence in db.go.

func (c Conn) ExecContext(
	ctx context.Context, query string, args . .interface{}, .
) (sql.Result, error) {
	formattedQuery := c.db.format(query, args)
	ctx, event := c.db.beforeQuery(ctx, nil, query, args, formattedQuery, nil)
	res, err := c.Conn.ExecContext(ctx, formattedQuery, args...)  // modified here
	c.db.afterQuery(ctx, event, res, err)
	return res, err
}

I don't know how many people will be happy with this change, but at least I'm happy to make the best ORM while keeping compatibility, as I was initially confused by the PostgreSQL placeholders not working.

By the way, the following works because sql.DB embedded in bun.DB is public.
db.DB.Exec()
When used this way, Exec in *sql.DB is executed and works with placeholders like $1 without problems. (db=bun.DB, db.DB: sql.DB)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant