Skip to content

Commit b783b3e

Browse files
authored
Add DB_URL support (#240)
* Add DB_URL support * refactor * tests for db_url * fix tsts * docs * fmt
1 parent 9016676 commit b783b3e

File tree

8 files changed

+460
-84
lines changed

8 files changed

+460
-84
lines changed

book/docs/connect/README.md

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,35 @@ based config and specify connection details for those databases. [Please check h
2020

2121
### 2. CLI options
2222

23-
Run the following command for more details
23+
You can provide database connection details via CLI options. This includes individual connection parameters or a complete database URL.
24+
25+
#### Using individual connection parameters
26+
27+
```bash
28+
$ sqlx-ts <path> \
29+
--db-type postgres \
30+
--db-host 127.0.0.1 \
31+
--db-port 5432 \
32+
--db-user postgres \
33+
--db-pass postgres \
34+
--db-name mydb
35+
```
36+
37+
#### Using database URL
38+
39+
Alternatively, you can use `--db-url` to specify the complete connection string:
40+
41+
```bash
42+
# PostgreSQL
43+
$ sqlx-ts <path> --db-type postgres --db-url postgres://user:pass@localhost:5432/mydb
44+
45+
# MySQL
46+
$ sqlx-ts <path> --db-type mysql --db-url mysql://user:pass@localhost:3306/mydb
47+
```
48+
49+
**Note:** When `--db-url` is provided, it takes precedence over individual connection parameters (`--db-host`, `--db-port`, `--db-user`, `--db-pass`, `--db-name`).
50+
51+
Run the following command for more details:
2452

2553
```bash
2654
$ sqlx-ts --help

book/docs/connect/config-file.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,26 @@ Example `.sqlxrc.json`
4646
}
4747
```
4848

49+
Alternatively, you can use `DB_URL` to specify the connection string directly:
50+
51+
```json
52+
{
53+
"generate_types": {
54+
"enabled": true
55+
},
56+
"connections": {
57+
"default": {
58+
"DB_TYPE": "postgres",
59+
"DB_URL": "postgres://postgres:[email protected]:5432/mydb"
60+
},
61+
"mysql_db": {
62+
"DB_TYPE": "mysql",
63+
"DB_URL": "mysql://root:[email protected]:3306/mydatabase"
64+
}
65+
}
66+
}
67+
```
68+
4969
## Configuration options
5070

5171
### connections (required)
@@ -71,6 +91,7 @@ const postgresSQL = sql`
7191
```
7292

7393
Supported fields of each connection include
94+
- `DB_URL`: Database connection URL (e.g. `postgres://user:pass@host:port/dbname` or `mysql://user:pass@host:port/dbname`). If provided, this overrides individual connection parameters (`DB_HOST`, `DB_PORT`, `DB_USER`, `DB_PASS`, `DB_NAME`)
7495
- `DB_TYPE`: type of database connection (mysql | postgres)
7596
- `DB_USER`: database user name
7697
- `DB_PASS`: database password

book/docs/connect/environment-variables.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
| Environment variables | Description |
55
| --------------------- | ------------------------------------------------------------------------------------------ |
6+
| DB_URL | Primary database connection URL (e.g. `postgres://user:pass@host:port/dbname` or `mysql://user:pass@host:port/dbname`). If provided, this overrides individual connection parameters |
67
| DB_HOST | Primary DB host |
78
| DB_PASS | Primary DB password |
89
| DB_PORT | Primary DB port number |
@@ -11,3 +12,38 @@
1112
| DB_NAME | Primary DB name |
1213
| PG_SEARCH_PATH | PostgreSQL schema search path (default is "$user,public") [https://www.postgresql.org/docs/current/ddl-schemas.html#DDL-SCHEMAS-PATH](https://www.postgresql.org/docs/current/ddl-schemas.html#DDL-SCHEMAS-PATH) |
1314

15+
## Examples
16+
17+
### Using individual connection parameters
18+
19+
```bash
20+
export DB_TYPE=postgres
21+
export DB_HOST=127.0.0.1
22+
export DB_PORT=5432
23+
export DB_USER=postgres
24+
export DB_PASS=postgres
25+
export DB_NAME=mydb
26+
27+
sqlx-ts <path>
28+
```
29+
30+
### Using database URL
31+
32+
Alternatively, you can use `DB_URL` to specify the complete connection string:
33+
34+
```bash
35+
# PostgreSQL
36+
export DB_TYPE=postgres
37+
export DB_URL=postgres://postgres:postgres@localhost:5432/mydb
38+
39+
sqlx-ts <path>
40+
41+
# MySQL
42+
export DB_TYPE=mysql
43+
export DB_URL=mysql://root:password@localhost:3306/mydatabase
44+
45+
sqlx-ts <path>
46+
```
47+
48+
**Note:** When `DB_URL` is set, it takes precedence over individual connection parameters (`DB_HOST`, `DB_PORT`, `DB_USER`, `DB_PASS`, `DB_NAME`).
49+

src/common/cli.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ pub struct Cli {
5252
#[clap(long)]
5353
pub db_name: Option<String>,
5454

55+
/// Custom database connection URL (overrides individual connection parameters if provided)
56+
#[clap(long)]
57+
pub db_url: Option<String>,
58+
5559
/// PostgreSQL schema search path (default is "$user,public") https://www.postgresql.org/docs/current/ddl-schemas.html#DDL-SCHEMAS-PATH
5660
#[clap(long)]
5761
pub pg_search_path: Option<String>,

src/common/config.rs

Lines changed: 82 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,18 @@ pub struct GenerateTypesConfig {
4040
pub struct DbConnectionConfig {
4141
#[serde(rename = "DB_TYPE")]
4242
pub db_type: DatabaseType,
43-
#[serde(rename = "DB_HOST")]
43+
#[serde(rename = "DB_HOST", default)]
4444
pub db_host: String,
45-
#[serde(rename = "DB_PORT")]
45+
#[serde(rename = "DB_PORT", default)]
4646
pub db_port: u16,
47-
#[serde(rename = "DB_USER")]
47+
#[serde(rename = "DB_USER", default)]
4848
pub db_user: String,
4949
#[serde(rename = "DB_PASS")]
5050
pub db_pass: Option<String>,
5151
#[serde(rename = "DB_NAME")]
5252
pub db_name: Option<String>,
53+
#[serde(rename = "DB_URL")]
54+
pub db_url: Option<String>,
5355
#[serde(rename = "PG_SEARCH_PATH")]
5456
pub pg_search_path: Option<String>,
5557
#[serde(rename = "POOL_SIZE", default = "default_pool_size")]
@@ -218,43 +220,73 @@ impl Config {
218220
panic!("")
219221
});
220222

221-
let db_host = &CLI_ARGS
222-
.db_host
223+
let db_url = &CLI_ARGS
224+
.db_url
223225
.clone()
224-
.or_else(|| dotenv.db_host.clone())
225-
.or_else(|| default_config.map(|x| x.db_host.clone()))
226-
.expect(
226+
.or_else(|| dotenv.db_url.clone())
227+
.or_else(|| default_config.map(|x| x.db_url.clone()).flatten());
228+
229+
let db_host_chain = || {
230+
CLI_ARGS
231+
.db_host
232+
.clone()
233+
.or_else(|| dotenv.db_host.clone())
234+
.or_else(|| default_config.map(|x| x.db_host.clone()))
235+
};
236+
237+
let db_host = match (db_url.is_some(), db_host_chain()) {
238+
(true, Some(v)) => v,
239+
(true, None) => String::new(),
240+
(false, Some(v)) => v,
241+
(false, None) => panic!(
227242
r"
228-
Failed to fetch DB host.
229-
Please provide it at least through a CLI arg or an environment variable or through
230-
file based configuration
231-
",
232-
);
233-
234-
let db_port = &CLI_ARGS
235-
.db_port
236-
.or(dotenv.db_port)
237-
.or_else(|| default_config.map(|x| x.db_port))
238-
.expect(
243+
Failed to fetch DB host.
244+
Please provide it at least through a CLI arg or an environment variable or through
245+
file based configuration, or provide a custom DB_URL
246+
"
247+
),
248+
};
249+
250+
let db_port_chain = || {
251+
CLI_ARGS
252+
.db_port
253+
.or(dotenv.db_port)
254+
.or_else(|| default_config.map(|x| x.db_port))
255+
};
256+
257+
let db_port = match (db_url.is_some(), db_port_chain()) {
258+
(true, Some(v)) => v,
259+
(true, None) => 0,
260+
(false, Some(v)) => v,
261+
(false, None) => panic!(
239262
r"
240-
Failed to fetch DB port.
241-
Please provide it at least through a CLI arg or an environment variable or through
242-
file based configuration
243-
",
244-
);
245-
246-
let db_user = &CLI_ARGS
247-
.db_user
248-
.clone()
249-
.or_else(|| dotenv.db_user.clone())
250-
.or_else(|| default_config.map(|x| x.db_user.clone()))
251-
.expect(
263+
Failed to fetch DB port.
264+
Please provide it at least through a CLI arg or an environment variable or through
265+
file based configuration, or provide a custom DB_URL
266+
"
267+
),
268+
};
269+
270+
let db_user_chain = || {
271+
CLI_ARGS
272+
.db_user
273+
.clone()
274+
.or_else(|| dotenv.db_user.clone())
275+
.or_else(|| default_config.map(|x| x.db_user.clone()))
276+
};
277+
278+
let db_user = match (db_url.is_some(), db_user_chain()) {
279+
(true, Some(v)) => v,
280+
(true, None) => String::new(),
281+
(false, Some(v)) => v,
282+
(false, None) => panic!(
252283
r"
253-
Failed to fetch DB user.
254-
Please provide it at least through a CLI arg or an environment variable or through
255-
file based configuration
256-
",
257-
);
284+
Failed to fetch DB user.
285+
Please provide it at least through a CLI arg or an environment variable or through
286+
file based configuration, or provide a custom DB_URL
287+
"
288+
),
289+
};
258290

259291
let db_pass = &CLI_ARGS
260292
.db_pass
@@ -286,11 +318,12 @@ impl Config {
286318

287319
DbConnectionConfig {
288320
db_type: db_type.to_owned(),
289-
db_host: db_host.to_owned(),
290-
db_port: db_port.to_owned(),
291-
db_user: db_user.to_owned(),
321+
db_host,
322+
db_port,
323+
db_user,
292324
db_pass: db_pass.to_owned(),
293325
db_name: db_name.to_owned(),
326+
db_url: db_url.to_owned(),
294327
pg_search_path: pg_search_path.to_owned(),
295328
pool_size,
296329
connection_timeout,
@@ -332,6 +365,11 @@ impl Config {
332365
/// This is to follow the spec of connection string for MySQL
333366
/// https://dev.mysql.com/doc/connector-j/8.1/en/connector-j-reference-jdbc-url-format.html
334367
pub fn get_mysql_cred_str(&self, conn: &DbConnectionConfig) -> String {
368+
// If custom DB_URL is provided, use it directly
369+
if let Some(db_url) = &conn.db_url {
370+
return db_url.to_owned();
371+
}
372+
335373
format!(
336374
"mysql://{user}:{pass}@{host}:{port}/{db_name}",
337375
user = &conn.db_user,
@@ -344,6 +382,11 @@ impl Config {
344382
}
345383

346384
pub fn get_postgres_cred(&self, conn: &DbConnectionConfig) -> String {
385+
// If custom DB_URL is provided, use it directly
386+
if let Some(db_url) = &conn.db_url {
387+
return db_url.to_owned();
388+
}
389+
347390
format!(
348391
"postgresql://{user}:{pass}@{host}:{port}/{db_name}",
349392
user = &conn.db_user,

src/common/dotenv.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pub struct Dotenv {
99
pub db_port: Option<u16>,
1010
pub db_pass: Option<String>,
1111
pub db_name: Option<String>,
12+
pub db_url: Option<String>,
1213
pub pg_search_path: Option<String>,
1314
}
1415

@@ -44,6 +45,7 @@ impl Dotenv {
4445
db_port: Self::get_var("DB_PORT").map(|val| val.parse::<u16>().expect("DB_PORT is not a valid integer")),
4546
db_pass: Self::get_var("DB_PASS"),
4647
db_name: Self::get_var("DB_NAME"),
48+
db_url: Self::get_var("DB_URL"),
4749
pg_search_path: Self::get_var("PG_SEARCH_PATH"),
4850
}
4951
}

0 commit comments

Comments
 (0)