launchbadge/sqlx

[Ideas Wanted] Generically accepting a &Pool or &mut Connection and allowing the argument to be used more than once

Open

#419 ouverte le 18 juin 2020

Voir sur GitHub
 (20 commentaires) (13 réactions) (0 assignés)Rust (1 307 forks)batch import
enhancementhelp wantedneeds rust feature

Métriques du dépôt

Stars
 (13 916 stars)
Métriques de merge PR
 (Aucune PR mergée en 30 j)

Description

Sometimes I find it easier to start with how this should look to the user:

// async fn foo(executor: impl Executor<'_, Database = Postgres>) -> anyhow::Result<()> { 
async fn foo(executor: impl PgExecutor<'_>) -> anyhow::Result<()> { 
  assert!(executor.fetch_one("SELECT 2").await?.get(0) == 2_i32);
  assert!(executor.fetch_one("SELECT 5").await?.get(0) == 5_i32);

  Ok(())
}

Anything goes, no matter ugly it makes the SQLx side look as long as it doesn't cause the compiler to ICE if you look at it funny (so try to avoid too many HRTBs).

I can think of a few different ways to do this given full access to the nightly compiler (GATs, arbitrary self types) but we do need this to work on stable.

The key issue is fetch_one is defined as fetch_one(self, query: impl Execute). Executor is then implemented for &Pool and &mut PgConnection, &mut MssqlConnection, etc.

Note that this example works if instead of the generic argument it is &mut PgConnection or &Pool. This works because of the implicit re-borrowing that happens outside of a generic context. I'm reasonably sure we can't mimic re-borrowing in the trait system due to lack of GATs.

Guide contributeur