You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CONTRIBUTING.md
+208Lines changed: 208 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -37,6 +37,214 @@ To start with, check out:
37
37
38
38
Additionally, it's always good to work on improving/adding examples and documentation.
39
39
40
+
## Adding Support for New Databases
41
+
42
+
Adding support for a new database to SQLx is a significant undertaking that requires implementing multiple traits and components. This guide provides a step-by-step approach to building a database driver progressively, with testing at each stage.
43
+
44
+
### Overview of SQLx Architecture
45
+
46
+
SQLx uses a trait-based architecture where each database implements a set of core traits:
47
+
48
+
-**[`Database`](sqlx-core/src/database.rs)**: The main trait that defines all associated types for a database. This is the central trait that ties everything together and must be implemented for your database struct.
49
+
50
+
-**[`Connection`](sqlx-core/src/connection.rs)**: Handles database connections and basic operations like connecting, closing, pinging, and transaction management. See examples: [PostgreSQL](sqlx-core/src/postgres/connection/mod.rs), [MySQL](sqlx-core/src/mysql/connection/mod.rs), [SQLite](sqlx-core/src/sqlite/connection/mod.rs).
51
+
52
+
-**[`Row`](sqlx-core/src/row.rs)**: Represents a single row from a query result, providing access to column data by index or name. Examples: [PgRow](sqlx-core/src/postgres/row.rs), [MySqlRow](sqlx-core/src/mysql/row.rs).
-**[`Value`](sqlx-core/src/value.rs) and [`ValueRef`](sqlx-core/src/value.rs)**: Handle owned and borrowed values from the database. Examples: [PgValue](sqlx-core/src/postgres/value.rs), [MySqlValue](sqlx-core/src/mysql/value.rs).
57
+
58
+
-**[`TypeInfo`](sqlx-core/src/type_info.rs)**: Provides information about database types for the type system. Examples: [PgTypeInfo](sqlx-core/src/postgres/type_info.rs), [MySqlTypeInfo](sqlx-core/src/mysql/type_info.rs).
59
+
60
+
-**[`Arguments`](sqlx-core/src/arguments.rs)**: Handles query parameter binding and encoding. Examples: [PgArguments](sqlx-core/src/postgres/arguments.rs), [MySqlArguments](sqlx-core/src/mysql/arguments.rs).
61
+
62
+
-**[`Statement`](sqlx-core/src/statement.rs)**: Handles prepared statements and their metadata. Examples: [PgStatement](sqlx-core/src/postgres/statement.rs), [MySqlStatement](sqlx-core/src/mysql/statement.rs).
63
+
64
+
-**Query execution**: Implement [`Executor`](sqlx-core/src/executor.rs) for your connection type to handle query execution and result streaming.
65
+
66
+
### Prerequisites
67
+
68
+
Before starting, ensure you have:
69
+
1. A working database server/client library to connect to your database
70
+
2. Understanding of your database's wire protocol or client API
71
+
3. Knowledge of your database's type system and SQL dialect
72
+
73
+
### Step 1: Initial Setup and Feature Configuration
74
+
75
+
**1.1 Add feature flags to Cargo.toml files:**
76
+
77
+
Add your database feature to the main `Cargo.toml`, `sqlx-core/Cargo.toml`, and `sqlx-macros/Cargo.toml`. Follow the pattern used by existing databases like `postgres` or `mysql`. Include any native client library dependencies as optional dependencies.
78
+
79
+
**1.2 Create the basic module structure:**
80
+
```bash
81
+
mkdir -p sqlx-core/src/yourdb
82
+
```
83
+
84
+
**1.3 Add the module to `sqlx-core/src/lib.rs` and main `src/lib.rs`** with appropriate feature gates.
85
+
86
+
**Test:**`cargo check --features yourdb`
87
+
88
+
### Step 2: Database Struct and Core Types
89
+
90
+
**2.1 Create your database struct** that will implement the [`Database`](sqlx-core/src/database.rs) trait. Look at [Postgres](sqlx-core/src/postgres/database.rs), [MySQL](sqlx-core/src/mysql/database.rs), or [SQLite](sqlx-core/src/sqlite/database.rs) for examples.
91
+
92
+
**2.2 Implement core types:**
93
+
-**TypeInfo**: Represents your database's type system. Study existing implementations to understand how to map database types to Rust types.
94
+
-**Value and ValueRef**: Handle data storage and retrieval. These work with your database's binary or text protocol.
95
+
-**DatabaseError**: Convert your database's native errors to SQLx's error system.
96
+
97
+
**Test:**`cargo check --features yourdb`
98
+
99
+
### Step 3: Connection Implementation
100
+
101
+
**3.1 Implement [`Connection`](sqlx-core/src/connection.rs)** for your database. This handles:
102
+
- Connection establishment and URL parsing ([`ConnectOptions`](sqlx-core/src/connection.rs))
103
+
- Connection lifecycle (open, close, ping)
104
+
- Basic connection management
105
+
106
+
Study the connection implementations in existing drivers, particularly how they handle:
107
+
- Network protocols (see [PostgreSQL stream handling](sqlx-core/src/postgres/connection/stream.rs))
108
+
- Authentication (see [MySQL auth](sqlx-core/src/mysql/connection/auth.rs))
109
+
- Connection options parsing (see [PostgreSQL options](sqlx-core/src/postgres/options/mod.rs))
110
+
111
+
**Test:** Basic connection establishment
112
+
113
+
### Step 4: Type System Integration
114
+
115
+
**4.1 Implement [`Type`](sqlx-core/src/types/mod.rs), [`Encode`](sqlx-core/src/encode.rs), and [`Decode`](sqlx-core/src/decode.rs)** traits for basic Rust types.
116
+
117
+
Start with simple types like strings and integers. Look at existing type implementations:
**6.1 Implement [`Executor`](sqlx-core/src/executor.rs)** for your connection type. This is where queries are actually sent to the database and results are processed.
**9.1 Add your database to the [`Any`](sqlx-core/src/any/) driver** to support runtime database selection.
177
+
178
+
This involves:
179
+
- Adding your database to [`AnyKind`](sqlx-core/src/any/kind.rs)
180
+
- Adding connection type to [`AnyConnectionKind`](sqlx-core/src/any/connection/mod.rs)
181
+
- Updating delegation macros in Any implementations
182
+
- Adding to other Any components (arguments, values, etc.)
183
+
184
+
Study how existing databases are integrated into the Any driver.
185
+
186
+
**Test:** Runtime database selection with Any driver
187
+
188
+
### Step 10: CI and Testing Infrastructure
189
+
190
+
**10.1 Add CI support** by updating `.github/workflows/ci.yml` with:
191
+
- Your database service in GitHub Actions
192
+
- Test job for your database
193
+
- Appropriate environment variables and health checks
194
+
195
+
**10.2 Create integration tests** in `tests/yourdb/` following the pattern of existing database tests.
196
+
197
+
**10.3 Add testing utilities** by implementing [`TestSupport`](sqlx-core/src/testing/mod.rs) for your database.
198
+
199
+
### Step 11: Advanced Features (Optional)
200
+
201
+
**11.1 Migration support**: Implement [`MigrateDatabase`](sqlx-core/src/migrate/migrate.rs) if your database supports schema migrations.
202
+
203
+
**11.2 Listen/Notify**: If your database supports real-time notifications, implement listener functionality (see [PostgreSQL listener](sqlx-core/src/postgres/listener.rs)).
204
+
205
+
**11.3 Additional type support**: Add support for database-specific types, arrays, JSON, etc.
206
+
207
+
### Step 12: Documentation and Examples
208
+
209
+
**12.1 Add comprehensive documentation** to all public APIs with examples.
210
+
211
+
**12.2 Create examples** in `examples/yourdb/` showing common usage patterns.
212
+
213
+
**12.3 Update the main README** to include your database in the supported databases list.
2.**Unit tests**: Test individual components in isolation
221
+
3.**Integration tests**: Test database connectivity and operations
222
+
4.**Type safety**: Ensure compile-time type checking works
223
+
5.**Runtime behavior**: Test actual database operations
224
+
225
+
### Implementation Tips
226
+
227
+
-**Study existing implementations**: The PostgreSQL, MySQL, and SQLite drivers provide excellent examples of different approaches (network protocols vs embedded databases, binary vs text protocols, etc.).
228
+
229
+
-**Start simple**: Begin with basic string queries before adding prepared statements, transactions, and complex types.
230
+
231
+
-**Incremental development**: Test each component thoroughly before moving to the next.
232
+
233
+
-**Protocol efficiency**: Use binary protocols when available for better performance.
234
+
235
+
-**Error handling**: Provide clear error messages and proper error type conversions.
236
+
237
+
-**Memory safety**: Pay careful attention to lifetimes, especially in async contexts.
238
+
239
+
### Common Patterns
240
+
241
+
-**Module organization**: Follow the established pattern of separate modules for connection, types, arguments, etc.
242
+
-**Feature gating**: Ensure all database-specific code is behind feature flags.
243
+
-**Async patterns**: Use `BoxFuture` for async trait methods and `BoxStream` for result streaming.
244
+
-**Protocol handling**: Implement proper buffering and message framing for network protocols.
245
+
246
+
This progressive approach ensures you can test and validate each component before moving to the next, making the development process manageable and reducing the likelihood of errors.
247
+
40
248
## Communication
41
249
42
250
If you're unsure about your contribution or simply want to ask a question about anything, you can:
0 commit comments