Skip to main content

sqlc_gen_sqlx/codegen/
mod.rs

1use crate::{
2    catalog, config::Config, emit::FileEmitter, error::Error, plugin::GenerateRequestView,
3    types::TypeMap,
4};
5
6mod batch;
7mod composites;
8mod copyfrom;
9mod enums;
10mod query;
11
12pub fn generate(request: &GenerateRequestView<'_>, config: &Config) -> Result<String, Error> {
13    let mut type_map = TypeMap::new(&config.overrides, &config.copy_cheap_types);
14    let catalog_info = catalog::walk(request, &mut type_map)?;
15    let col_overrides = crate::types::build_column_overrides(&config.overrides);
16    let mut emitter = FileEmitter::new(request.sqlc_version, env!("CARGO_PKG_VERSION"));
17
18    // Emit the AsExecutor trait + impls up front so query functions can reference it.
19    emitter.push(quote::quote! {
20        pub trait AsExecutor {
21            fn as_executor(&mut self) -> impl sqlx::Executor<'_, Database = sqlx::Postgres>;
22        }
23
24        impl AsExecutor for sqlx::PgPool {
25            fn as_executor(&mut self) -> impl sqlx::Executor<'_, Database = sqlx::Postgres> {
26                &*self
27            }
28        }
29
30        impl AsExecutor for &sqlx::PgPool {
31            fn as_executor(&mut self) -> impl sqlx::Executor<'_, Database = sqlx::Postgres> {
32                *self
33            }
34        }
35
36        impl AsExecutor for sqlx::PgConnection {
37            fn as_executor(&mut self) -> impl sqlx::Executor<'_, Database = sqlx::Postgres> {
38                &mut *self
39            }
40        }
41
42        impl AsExecutor for sqlx::Transaction<'_, sqlx::Postgres> {
43            fn as_executor(&mut self) -> impl sqlx::Executor<'_, Database = sqlx::Postgres> {
44                &mut **self
45            }
46        }
47
48        impl AsExecutor for sqlx::pool::PoolConnection<sqlx::Postgres> {
49            fn as_executor(&mut self) -> impl sqlx::Executor<'_, Database = sqlx::Postgres> {
50                &mut **self
51            }
52        }
53
54        impl<T: AsExecutor + ?Sized> AsExecutor for &mut T {
55            fn as_executor(&mut self) -> impl sqlx::Executor<'_, Database = sqlx::Postgres> {
56                (**self).as_executor()
57            }
58        }
59    });
60
61    // Emit type definitions before query code.
62    for info in &catalog_info.enums {
63        emitter.push(enums::gen_enum(info, &config.enum_derives)?);
64    }
65    for info in &catalog_info.composites {
66        emitter.push(composites::gen_composite(info, &config.composite_derives)?);
67    }
68
69    for q in request.queries.iter() {
70        let tokens = match q.cmd {
71            ":exec" => query::gen_exec(q, &type_map, config, &col_overrides)?,
72            ":execrows" => query::gen_execrows(q, &type_map, config, &col_overrides)?,
73            ":execresult" => query::gen_execresult(q, &type_map, config, &col_overrides)?,
74            ":execlastid" => query::gen_execlastid(q, &type_map, config, &col_overrides)?,
75            ":batchexec" => batch::gen_batchexec(q, &type_map, config, &col_overrides)?,
76            ":batchone" => batch::gen_batchone(q, &type_map, config, &col_overrides)?,
77            ":batchmany" => batch::gen_batchmany(q, &type_map, config, &col_overrides)?,
78            ":copyfrom" => copyfrom::gen_copyfrom(q, &type_map, config, &col_overrides)?,
79            ":one" => query::gen_one(q, &type_map, config, &col_overrides)?,
80            ":many" => query::gen_many(q, &type_map, config, &col_overrides)?,
81            cmd => {
82                eprintln!("sqlc-gen-sqlx: skipping unsupported annotation {cmd}");
83                continue;
84            }
85        };
86        emitter.push(tokens);
87    }
88
89    emitter.finish()
90}