TheDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/invvd/mtg-cheaper-deck/llms.txt
Use this file to discover all available pages before exploring further.
db module is the data layer for MTG Cheaper Deck. It declares the cards table using SQLAlchemy Core, manages the engine singleton that all other modules share, and provides init_db() to create the schema on first run. The default backend is a local SQLite file that requires no external infrastructure. Switching to PostgreSQL requires only a DATABASE_URL change and installing the appropriate driver.
DATABASE_URL
python-dotenv. If the variable is not set, the default is a SQLite database stored at ./data/cards.db relative to the working directory.
To use PostgreSQL, set the environment variable before starting any process:
The
scoring module currently requires SQLite because it uses json_extract for legality filtering. See the warning in the scoring reference before changing DATABASE_URL to a PostgreSQL URL.cards Table
Thecards SQLAlchemy Table object is the schema declaration for the main card store. It maps one-to-one with the Scryfall oracle card data loaded by the sync process.
| Column | Type | Constraints | Description |
|---|---|---|---|
oracle_id | String | Primary Key | Scryfall oracle ID — unique per distinct card regardless of printing |
scryfall_id | String | — | Scryfall ID of the representative printing stored in the database |
name | String | NOT NULL | Card name (English) |
color_identity | JSON | NOT NULL, default [] | List of colour symbols, e.g. ["U", "B"] |
color_identity_mask | Integer | NOT NULL, default 0 | Bitmask: W=1, U=2, B=4, R=8, G=16. Used for fast colour-subset filtering |
type_line | String | — | Full Scryfall type line, e.g. "Legendary Creature — Elf Druid" |
cmc | Float | — | Converted mana cost |
keywords | JSON | NOT NULL, default [] | Scryfall evergreen keyword list, e.g. ["Flying", "Deathtouch"] |
oracle_text | Text | — | Rules text of the oracle card |
power | String | — | Power (creatures only), stored as string to preserve * values |
toughness | String | — | Toughness (creatures only), stored as string to preserve * values |
price_usd | Float | — | Current USD price from Scryfall (may be NULL for unpurchaseable cards) |
legalities | JSON | NOT NULL, default {} | Dict of format → legality status, e.g. {"commander": "legal", "standard": "not_legal"} |
edhrec_rank | Integer | — | EDHREC rank (lower = more popular). NULL for cards without a rank |
updated_at | String | — | ISO-8601 timestamp of the last sync update for this row |
Indexes
Three indexes are created byinit_db():
| Index | Column | Purpose |
|---|---|---|
idx_cards_name_lower | lower(name) | Supports the case-insensitive name lookup in matching.py |
idx_cards_price | price_usd | Speeds up price-range scans in CandidatePool.cheaper_than() |
idx_cards_color_mask | color_identity_mask | Speeds up bitmask colour-subset filtering in suggest_alternatives() |
get_engine
Returns the global SQLAlchemyEngine singleton, creating it on the first call.
Returns Engine — the lazily-initialised engine. Subsequent calls return the same instance.
For SQLite connections the engine is created with check_same_thread=False so that the same connection can be used from multiple threads (relevant when the pipeline runs background tasks).
init_db
Creates thedata/ directory (and any intermediate directories) if it does not exist, then calls metadata.create_all() to create all tables and indexes that are not already present in the database. Safe to call on every startup — it is a no-op when the schema is already up to date.
Returns None.
init_db() is the recommended first step in any script that might run against a fresh environment (e.g. a new clone or a CI job that starts with an empty data/ directory).