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