Schema Parsing
Relevant source files
The following files were used as context for generating this wiki page:
Schema Parsing is a core module in the SeaSchema library responsible for transforming raw database query results from INFORMATION_SCHEMA into structured, type-safe Rust definitions. It acts as the bridge between the discovery layer, which executes SQL queries against a live database, and the definition layer, which provides a unified representation of database objects like tables, columns, indexes, and constraints.
The parsing logic is specialized for each supported database backend (MySQL and PostgreSQL), ensuring that database-specific features—such as MySQL's engine types or PostgreSQL's custom enums—are accurately captured. This module is essential for the "Schema Discovery" workflow, enabling tools to programmatically understand and manipulate existing database structures.
Sources: README.md:21-27, src/mysql/discovery/mod.rs:1-8, src/postgres/discovery/mod.rs:1-12
Architecture and Data Flow
The parsing process follows a structured pipeline where raw rows returned by database executors are first mapped into intermediate QueryResult structures before being parsed into final Def objects.
The diagram above illustrates how the parser consumes data retrieved by the discovery module and converts it into the final domain models.
Sources: src/mysql/discovery/mod.rs:56-68, src/postgres/discovery/mod.rs:60-70
Backend Implementations
MySQL Parsing logic
MySQL parsing focuses on extracting table metadata, column attributes (including character sets and numeric attributes), and relational structures like indexes and foreign keys. The discovery module utilizes specialized parser functions to group multi-row query results into single entity definitions.
Key parsing components for MySQL include:
- Index Parsing:
parse_index_query_resultshandles the transformation of multiple rows representing index parts into a cohesiveIndexInfovector. - Foreign Key Parsing:
parse_foreign_key_query_resultsaggregates column mappings between tables.
| Component | Description |
|---|---|
TableQueryResult | Intermediate representation of MySQL table metadata (engine, collation). |
ColumnQueryResult | Raw column data including type strings and default values. |
IndexQueryResult | Individual rows from index metadata queries. |
Sources: src/mysql/discovery/mod.rs:11-18, src/mysql/discovery/mod.rs:141-160, src/mysql/parser/mod.rs
PostgreSQL Parsing Logic
PostgreSQL parsing is more complex due to its support for User-Defined Types (UDTs) and a wide array of constraints. The parser must handle enums, check constraints, and exclusion constraints specifically.
The flowchart shows the categorization logic used in PostgreSQL to separate general constraints from unique indexes.
Sources: src/postgres/discovery/mod.rs:115-135, src/postgres/parser/mod.rs
Discovery and Parsing Orchestration
The SchemaDiscovery struct orchestrates the parsing by calling specific discovery methods that internally invoke the parser logic.
Parsing Steps in Discovery
- System Discovery: Parses version information to adjust parsing logic for different DB versions.
- Table Discovery: Iterates through tables in the target schema.
- Column Discovery: Processes column types and maps them to Rust enums (e.g.,
NumericAttr). - Relationship Discovery: Parses indexes and foreign keys using multi-row aggregation.
// Example of orchestration in MySQL discovery
fn discover_table_with<C: Connection>(
&self,
conn: &C,
info: TableInfo,
) -> Result<TableDef, RusqliteError> {
let table = SeaRc::new(Alias::new(info.name.as_str()));
let columns = self.discover_columns_with(conn, self.schema.clone(), table.clone(), &self.query.system)?;
let indexes = self.discover_indexes_with(conn, self.schema.clone(), table.clone())?;
let foreign_keys = self.discover_foreign_keys_with(conn, self.schema.clone(), table.clone())?;
Ok(TableDef { info, columns, indexes, foreign_keys })
}
Sources: src/mysql/discovery/mod.rs:98-118, src/postgres/discovery/mod.rs:92-113
Shared Parser Utilities
The project maintains shared parsing utilities in src/parser.rs that provide common logic used across different database implementations to maintain consistency in how identifiers and standard SQL types are handled.
Sources: src/parser.rs
Conclusion
Schema Parsing in SeaSchema provides a robust mechanism for converting database-specific metadata into a unified Rust representation. By separating the discovery of data from the parsing logic, the library allows for highly accurate schema mapping that supports complex database features like PostgreSQL enums and MySQL's varied storage engines. This structured approach ensures that the resulting Schema and TableDef objects are ready for use in code generation or synchronization tasks.
Sources: README.md:21-25, src/mysql/discovery/mod.rs:50-55