1- /// Configuration for the [`sqlx::query!()`] family of macros.
2- #[ derive( Debug , serde:: Deserialize ) ]
1+ use std:: collections:: BTreeMap ;
2+
3+ /// Configuration for the `query!()` family of macros.
4+ #[ derive( Debug , Default , serde:: Deserialize ) ]
5+ #[ serde( default ) ]
36pub struct Config {
4- /// Override the environment variable
7+ /// Override the database URL environment variable used by the macros.
8+ ///
9+ /// Case-sensitive. Defaults to `DATABASE_URL`.
10+ ///
11+ /// Example: Multi-Database Project
12+ /// -------
13+ /// You can use multiple databases in the same project by breaking it up into multiple crates,
14+ /// then using a different environment variable for each.
15+ ///
16+ /// For example, with two crates in the workspace named `foo` and `bar`:
17+ ///
18+ /// #### `foo/sqlx.toml`
19+ /// ```toml
20+ /// [macros]
21+ /// database_url_var = "FOO_DATABASE_URL"
22+ /// ```
23+ ///
24+ /// #### `bar/sqlx.toml`
25+ /// ```toml
26+ /// [macros]
27+ /// database_url_var = "BAR_DATABASE_URL"
28+ /// ```
29+ ///
30+ /// #### `.env`
31+ /// ```text
32+ /// FOO_DATABASE_URL=postgres://postgres@localhost:5432/foo
33+ /// BAR_DATABASE_URL=postgres://postgres@localhost:5432/bar
34+ /// ```
35+ ///
36+ /// The query macros used in `foo` will use `FOO_DATABASE_URL`,
37+ /// and the ones used in `bar` will use `BAR_DATABASE_URL`.
538 pub database_url_var : Option < String > ,
6- }
39+
40+ /// Specify the crate to use for mapping date/time types to Rust.
41+ ///
42+ /// The default behavior is to use whatever crate is enabled,
43+ /// [`chrono`] or [`time`] (the latter takes precedent).
44+ ///
45+ /// [`chrono`]: crate::types::chrono
46+ /// [`time`]: crate::types::time
47+ ///
48+ /// Example: Always Use Chrono
49+ /// -------
50+ /// Thanks to Cargo's [feature unification], a crate in the dependency graph may enable
51+ /// the `time` feature of SQLx which will force it on for all crates using SQLx,
52+ /// which will result in problems if your crate wants to use types from [`chrono`].
53+ ///
54+ /// You can use the type override syntax (see `sqlx::query!` for details),
55+ /// or you can force an override globally by setting this option.
56+ ///
57+ /// #### `sqlx.toml`
58+ /// ```toml
59+ /// [macros]
60+ /// datetime_crate = "chrono"
61+ /// ```
62+ ///
63+ /// [feature unification]: https://doc.rust-lang.org/cargo/reference/features.html#feature-unification
64+ pub datetime_crate : DateTimeCrate ,
65+
66+ /// Specify global overrides for mapping SQL type names to Rust type names.
67+ ///
68+ /// Default type mappings are defined by the database driver.
69+ /// Refer to the `sqlx::types` module for details.
70+ ///
71+ /// ## Note: Orthogonal to Nullability
72+ /// These overrides do not affect whether `query!()` decides to wrap a column in `Option<_>`
73+ /// or not. They only override the inner type used.
74+ ///
75+ /// ## Note: Schema Qualification (Postgres)
76+ /// Type names may be schema-qualified in Postgres. If so, the schema should be part
77+ /// of the type string, e.g. `'foo.bar'` to reference type `bar` in schema `foo`.
78+ ///
79+ /// The schema and/or type name may additionally be quoted in the string
80+ /// for a quoted identifier (see next section).
81+ ///
82+ /// Schema qualification should not be used for types in the search path.
83+ ///
84+ /// ## Note: Quoted Identifiers (Postgres)
85+ /// Type names using [quoted identifiers in Postgres] must also be specified with quotes here.
86+ ///
87+ /// Note, however, that the TOML format parses way the outer pair of quotes,
88+ /// so for quoted names in Postgres, double-quoting is necessary,
89+ /// e.g. `'"Foo"'` for SQL type `"Foo"`.
90+ ///
91+ /// To reference a schema-qualified type with a quoted name, use double-quotes after the
92+ /// dot, e.g. `'foo."Bar"'` to reference type `"Bar"` of schema `foo`, and vice versa for
93+ /// quoted schema names.
94+ ///
95+ /// We recommend wrapping all type names in single quotes, as shown below,
96+ /// to avoid confusion.
97+ ///
98+ /// MySQL/MariaDB and SQLite do not support custom types, so quoting type names should
99+ /// never be necessary.
100+ ///
101+ /// [quoted identifiers in Postgres]: https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
102+ // Note: we wanted to be able to handle this intelligently,
103+ // but the `toml` crate authors weren't interested: https://github.com/toml-rs/toml/issues/761
104+ //
105+ // We decided to just encourage always quoting type names instead.
106+ /// Example: Custom Wrapper Types
107+ /// -------
108+ /// Does SQLx not support a type that you need? Do you want additional semantics not
109+ /// implemented on the built-in types? You can create a custom wrapper,
110+ /// or use an external crate.
111+ ///
112+ /// #### `sqlx.toml`
113+ /// ```toml
114+ /// [macros.type_overrides]
115+ /// # Override a built-in type
116+ /// 'uuid' = "crate::types::MyUuid"
117+ ///
118+ /// # Support an external or custom wrapper type (e.g. from the `isn` Postgres extension)
119+ /// # (NOTE: FOR DOCUMENTATION PURPOSES ONLY; THIS CRATE/TYPE DOES NOT EXIST AS OF WRITING)
120+ /// 'isbn13' = "isn_rs::sqlx::ISBN13"
121+ /// ```
122+ ///
123+ /// Example: Custom Types in Postgres
124+ /// -------
125+ /// If you have a custom type in Postgres that you want to map without needing to use
126+ /// the type override syntax in `sqlx::query!()` every time, you can specify a global
127+ /// override here.
128+ ///
129+ /// For example, a custom enum type `foo`:
130+ ///
131+ /// #### Migration or Setup SQL (e.g. `migrations/0_setup.sql`)
132+ /// ```sql
133+ /// CREATE TYPE foo AS ENUM ('Bar', 'Baz');
134+ /// ```
135+ ///
136+ /// #### `src/types.rs`
137+ /// ```rust,no_run
138+ /// #[derive(sqlx::Type)]
139+ /// pub enum Foo {
140+ /// Bar,
141+ /// Baz
142+ /// }
143+ /// ```
144+ ///
145+ /// If you're not using `PascalCase` in your enum variants then you'll want to use
146+ /// `#[sqlx(rename_all = "<strategy>")]` on your enum.
147+ /// See [`Type`][crate::type::Type] for details.
148+ ///
149+ /// #### `sqlx.toml`
150+ /// ```toml
151+ /// [macros.type_overrides]
152+ /// # Map SQL type `foo` to `crate::types::Foo`
153+ /// 'foo' = "crate::types::Foo"
154+ /// ```
155+ ///
156+ /// Example: Schema-Qualified Types
157+ /// -------
158+ /// (See `Note` section above for details.)
159+ ///
160+ /// ```toml
161+ /// [macros.type_overrides]
162+ /// # Map SQL type `foo.foo` to `crate::types::Foo`
163+ /// 'foo.foo' = "crate::types::Foo"
164+ /// ```
165+ ///
166+ /// Example: Quoted Identifiers
167+ /// -------
168+ /// If a type or schema uses quoted identifiers,
169+ /// it must be wrapped in quotes _twice_ for SQLx to know the difference:
170+ ///
171+ /// ```toml
172+ /// [macros.type_overrides]
173+ /// # `"Foo"` in SQLx
174+ /// '"Foo"' = "crate::types::Foo"
175+ /// # **NOT** `"Foo"` in SQLx (parses as just `Foo`)
176+ /// "Foo" = "crate::types::Foo"
177+ ///
178+ /// # Schema-qualified
179+ /// '"foo".foo' = "crate::types::Foo"
180+ /// 'foo."Foo"' = "crate::types::Foo"
181+ /// '"foo"."Foo"' = "crate::types::Foo"
182+ /// ```
183+ ///
184+ /// (See `Note` section above for details.)
185+ pub type_overrides : BTreeMap < SqlType , RustType > ,
186+
187+ /// Specify per-column overrides for mapping SQL types to Rust types.
188+ ///
189+ /// Default type mappings are defined by the database driver.
190+ /// Refer to the `sqlx::types` module for details.
191+ ///
192+ /// The supported syntax is similar to [`type_overrides`][Self::type_overrides],
193+ /// (with the same caveat for quoted names!) but column names must be qualified
194+ /// by a separately quoted table name, which may optionally be schema-qualified.
195+ ///
196+ /// Multiple columns for the same SQL table may be written in the same table in TOML
197+ /// (see examples below).
198+ ///
199+ /// ## Note: Orthogonal to Nullability
200+ /// These overrides do not affect whether `query!()` decides to wrap a column in `Option<_>`
201+ /// or not. They only override the inner type used.
202+ ///
203+ /// ## Note: Schema Qualification
204+ /// Table names may be schema-qualified. If so, the schema should be part
205+ /// of the table name string, e.g. `'foo.bar'` to reference table `bar` in schema `foo`.
206+ ///
207+ /// The schema and/or type name may additionally be quoted in the string
208+ /// for a quoted identifier (see next section).
209+ ///
210+ /// Postgres users: schema qualification should not be used for tables in the search path.
211+ ///
212+ /// ## Note: Quoted Identifiers
213+ /// Schema, table, or column names using quoted identifiers ([MySQL], [Postgres], [SQLite])
214+ /// in SQL must also be specified with quotes here.
215+ ///
216+ /// Postgres and SQLite use double-quotes (`"Foo"`) while MySQL uses backticks (`\`Foo\`).
217+ ///
218+ /// Note, however, that the TOML format parses way the outer pair of quotes,
219+ /// so for quoted names in Postgres, double-quoting is necessary,
220+ /// e.g. `'"Foo"'` for SQL name `"Foo"`.
221+ ///
222+ /// To reference a schema-qualified table with a quoted name, use the appropriate quotation
223+ /// characters after the dot, e.g. `'foo."Bar"'` to reference table `"Bar"` of schema `foo`,
224+ /// and vice versa for quoted schema names.
225+ ///
226+ /// We recommend wrapping all table and column names in single quotes, as shown below,
227+ /// to avoid confusion.
228+ ///
229+ /// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/identifiers.html
230+ /// [Postgres]: https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
231+ /// [SQLite]: https://sqlite.org/lang_keywords.html
232+ // Note: we wanted to be able to handle this intelligently,
233+ // but the `toml` crate authors weren't interested: https://github.com/toml-rs/toml/issues/761
234+ //
235+ // We decided to just encourage always quoting type names instead.
236+ ///
237+ /// Example
238+ /// -------
239+ ///
240+ /// #### `sqlx.toml`
241+ /// ```toml
242+ /// [macros.column_overrides.'foo']
243+ /// # Map column `bar` of table `foo` to Rust type `crate::types::Foo`:
244+ /// 'bar' = "crate::types::Bar"
245+ ///
246+ /// # Quoted column name
247+ /// # Note: same quoting requirements as `macros.type_overrides`
248+ /// '"Bar"' = "crate::types::Bar"
249+ ///
250+ /// # Note: will NOT work (parses as `Bar`)
251+ /// # "Bar" = "crate::types::Bar"
252+ ///
253+ /// # Table name may be quoted (note the wrapping single-quotes)
254+ /// [macros.column_overrides.'"Foo"']
255+ /// 'bar' = "crate::types::Bar"
256+ /// '"Bar"' = "crate::types::Bar"
257+ ///
258+ /// # Table name may also be schema-qualified.
259+ /// # Note how the dot is inside the quotes.
260+ /// [macros.column_overrides.'my_schema.my_table']
261+ /// 'my_column' = "crate::types::MyType"
262+ ///
263+ /// # Quoted schema, table, and column names
264+ /// [macros.column_overrides.'"My Schema"."My Table"']
265+ /// '"My Column"' = "crate::types::MyType"
266+ /// ```
267+ pub column_overrides : BTreeMap < TableName , BTreeMap < ColumnName , RustType > > ,
268+ }
269+
270+ /// The crate to use for mapping date/time types to Rust.
271+ #[ derive( Debug , Default , PartialEq , Eq , serde:: Deserialize ) ]
272+ #[ serde( rename_all = "snake_case" ) ]
273+ pub enum DateTimeCrate {
274+ /// Use whichever crate is enabled (`time` then `chrono`).
275+ #[ default]
276+ Inferred ,
277+
278+ /// Always use types from [`chrono`][crate::types::chrono].
279+ ///
280+ /// ```toml
281+ /// [macros]
282+ /// datetime_crate = "chrono"
283+ /// ```
284+ Chrono ,
285+
286+ /// Always use types from [`time`][crate::types::time].
287+ ///
288+ /// ```toml
289+ /// [macros]
290+ /// datetime_crate = "time"
291+ /// ```
292+ Time ,
293+ }
294+
295+ /// A SQL type name; may optionally be schema-qualified.
296+ ///
297+ /// See [`macros.type_overrides`][Config::type_overrides] for usages.
298+ pub type SqlType = Box < str > ;
299+
300+ /// A SQL table name; may optionally be schema-qualified.
301+ ///
302+ /// See [`macros.column_overrides`][Config::column_overrides] for usages.
303+ pub type TableName = Box < str > ;
304+
305+ /// A column in a SQL table.
306+ ///
307+ /// See [`macros.column_overrides`][Config::column_overrides] for usages.
308+ pub type ColumnName = Box < str > ;
309+
310+ /// A Rust type name or path.
311+ ///
312+ /// Should be a global path (not relative).
313+ pub type RustType = Box < str > ;
314+
315+ /// Internal getter methods.
316+ impl Config {
317+ /// Get the override for a given type name (optionally schema-qualified).
318+ pub fn type_override ( & self , type_name : & str ) -> Option < & str > {
319+ self . type_overrides . get ( type_name) . map ( |s| & * * s)
320+ }
321+
322+ /// Get the override for a given column and table name (optionally schema-qualified).
323+ pub fn column_override ( & self , table : & str , column : & str ) -> Option < & str > {
324+ self . column_overrides
325+ . get ( table)
326+ . and_then ( |by_column| by_column. get ( column) )
327+ . map ( |s| & * * s)
328+ }
329+ }
0 commit comments