MCPcopy Index your code
hub / github.com/SeaQL/sea-schema

github.com/SeaQL/sea-schema @0.18.1

Chat with this repo
repository ↗ · DeepWiki ↗ · release 0.18.1 ↗ · + Follow
1,031 symbols 1,743 edges 218 files 94 documented · 9%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

SeaSchema

<strong>🌿 SQL schema definition and discovery</strong>

crate docs build status

About

SeaSchema is a library to help you manage database schema for MySQL, Postgres and SQLite. It provides 1) type definitions for representing database schema mapping each database closely and 2) utilities to discover them.

GitHub stars If you like what we do, consider starring, commenting, sharing and contributing!

Discord Join our Discord server to chat with others in the SeaQL community!

Architecture

The crate is divided into different modules:

  • def: type definitions
  • query, parser: for querying and parsing information_schema
  • discovery: connect to a live database and discover a Schema
  • writer: for exporting Schema into SeaQuery and SQL statements

JSON de/serialize on type definitions can be enabled with with-serde.

Schema Discovery

Take the MySQL Sakila Sample Database as example, given the following table:

CREATE TABLE film_actor (
  actor_id SMALLINT UNSIGNED NOT NULL,
  film_id SMALLINT UNSIGNED NOT NULL,
  last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY  (actor_id,film_id),
  KEY idx_fk_film_id (`film_id`),
  CONSTRAINT fk_film_actor_actor FOREIGN KEY (actor_id) REFERENCES actor (actor_id) ON DELETE RESTRICT ON UPDATE CASCADE,
  CONSTRAINT fk_film_actor_film FOREIGN KEY (film_id) REFERENCES film (film_id) ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

The discovered schema result:

TableDef {
    info: TableInfo {
        name: "film_actor",
        engine: InnoDb,
        auto_increment: None,
        char_set: Utf8Mb4,
        collation: Utf8Mb40900AiCi,
        comment: "",
    },
    columns: [
        ColumnInfo {
            name: "actor_id",
            col_type: SmallInt(
                NumericAttr {
                    maximum: None,
                    decimal: None,
                    unsigned: Some(true),
                    zero_fill: None,
                },
            ),
            null: false,
            key: Primary,
            default: None,
            extra: ColumnExtra {
                auto_increment: false,
                on_update_current_timestamp: false,
                generated: false,
                default_generated: false,
            },
            expression: None,
            comment: "",
        },
        ColumnInfo {
            name: "film_id",
            col_type: SmallInt(
                NumericAttr {
                    maximum: None,
                    decimal: None,
                    unsigned: Some(true),
                    zero_fill: None,
                },
            ),
            null: false,
            key: Primary,
            default: None,
            extra: ColumnExtra {
                auto_increment: false,
                on_update_current_timestamp: false,
                generated: false,
                default_generated: false,
            },
            expression: None,
            comment: "",
        },
        ColumnInfo {
            name: "last_update",
            col_type: Timestamp(TimeAttr { fractional: None }),
            null: false,
            key: NotKey,
            default: Some(ColumnDefault::CurrentTimestamp),
            extra: ColumnExtra {
                auto_increment: false,
                on_update_current_timestamp: true,
                generated: false,
                default_generated: true,
            },
            expression: None,
            comment: "",
        },
    ],
    indexes: [
        IndexInfo {
            unique: false,
            name: "idx_fk_film_id",
            parts: [
                IndexPart {
                    column: "film_id",
                    order: Ascending,
                    sub_part: None,
                },
            ],
            nullable: false,
            idx_type: BTree,
            comment: "",
            functional: false,
        },
        IndexInfo {
            unique: true,
            name: "PRIMARY",
            parts: [
                IndexPart {
                    column: "actor_id",
                    order: Ascending,
                    sub_part: None,
                },
                IndexPart {
                    column: "film_id",
                    order: Ascending,
                    sub_part: None,
                },
            ],
            nullable: false,
            idx_type: BTree,
            comment: "",
            functional: false,
        },
    ],
    foreign_keys: [
        ForeignKeyInfo {
            name: "fk_film_actor_actor",
            columns: [ "actor_id" ],
            referenced_table: "actor",
            referenced_columns: [ "actor_id" ],
            on_update: Cascade,
            on_delete: Restrict,
        },
        ForeignKeyInfo {
            name: "fk_film_actor_film",
            columns: [ "film_id" ],
            referenced_table: "film",
            referenced_columns: [ "film_id" ],
            on_update: Cascade,
            on_delete: Restrict,
        },
    ],
}

License

Licensed under either of

  • Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
  • MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

SeaSchema is a community driven project. We welcome you to participate, contribute and together build for Rust's future.

A big shout out to our contributors:

Contributors

Extension points exported contracts — how you extend this code

Connection (Interface)
(no doc) [7 implementers]
src/connection.rs
Connection (Interface)
(no doc) [7 implementers]
sea-schema-sync/src/connection.rs
SchemaProbe (Interface)
(no doc) [3 implementers]
src/probe.rs
IntoExecutor (Interface)
(no doc) [1 implementers]
src/postgres/discovery/executor/mock.rs
IntoExecutor (Interface)
(no doc) [1 implementers]
src/mysql/discovery/executor/mock.rs
IntoExecutor (Interface)
(no doc) [1 implementers]
src/sqlite/executor/rusqlite.rs
Name (Interface)
(no doc)
src/name.rs
Row (Interface)
(no doc)
src/sqlx_types/mock.rs

Core symbols most depended-on inside this repo

get
called by 78
src/rusqlite_types/real.rs
get
called by 76
sea-schema-sync/src/rusqlite_types/real.rs
take
called by 31
src/mysql/def/types.rs
take
called by 31
sea-schema-sync/src/mysql/def/types.rs
from
called by 30
src/sqlite/error.rs
get_string
called by 21
src/mysql/discovery/executor/real.rs
get_string
called by 21
sea-schema-sync/src/mysql/discovery/executor/real.rs
next_if_punctuation
called by 16
src/parser.rs

Shape

Method 398
Function 323
Class 182
Enum 104
Interface 24

Languages

Rust99%
PHP1%

Modules by API surface

src/mysql/parser/column.rs48 symbols
sea-schema-sync/src/mysql/parser/column.rs48 symbols
src/mysql/def/types.rs34 symbols
sea-schema-sync/src/mysql/def/types.rs34 symbols
src/mysql/writer/types.rs31 symbols
sea-schema-sync/src/mysql/writer/types.rs31 symbols
tests/live/postgres/src/main.rs20 symbols
src/postgres/def/types.rs19 symbols
sea-schema-sync/src/postgres/def/types.rs19 symbols
src/postgres/parser/column.rs14 symbols
sea-schema-sync/src/postgres/parser/column.rs14 symbols
tests/live/sqlite/src/main.rs13 symbols

Datastores touched

(mysql)Database · 1 repos
sakilaDatabase · 1 repos
sakilaDatabase · 1 repos

For agents

$ claude mcp add sea-schema \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact