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 ) ]
3
6
pub 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`.
5
38
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