sqlseed 0.1.14__tar.gz → 0.1.16__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. {sqlseed-0.1.14 → sqlseed-0.1.16}/.gitignore +17 -21
  2. {sqlseed-0.1.14 → sqlseed-0.1.16}/CHANGELOG.md +37 -1
  3. {sqlseed-0.1.14 → sqlseed-0.1.16}/CHANGELOG.zh-CN.md +36 -0
  4. {sqlseed-0.1.14 → sqlseed-0.1.16}/PKG-INFO +48 -27
  5. {sqlseed-0.1.14 → sqlseed-0.1.16}/README.md +43 -26
  6. {sqlseed-0.1.14 → sqlseed-0.1.16}/README.zh-CN.md +40 -23
  7. sqlseed-0.1.16/examples/build_demo_db.py +233 -0
  8. sqlseed-0.1.16/examples/notebooks/01-quickstart.ipynb +1314 -0
  9. sqlseed-0.1.16/examples/notebooks/02-column-mapping.ipynb +1437 -0
  10. sqlseed-0.1.16/examples/notebooks/03-generators.ipynb +1025 -0
  11. sqlseed-0.1.16/examples/notebooks/04-database-advanced.ipynb +1019 -0
  12. sqlseed-0.1.16/examples/notebooks/05-dag-and-constraints.ipynb +833 -0
  13. sqlseed-0.1.16/examples/notebooks/06-config-deep-dive.ipynb +1247 -0
  14. sqlseed-0.1.16/examples/notebooks/07-ai-plugin.ipynb +630 -0
  15. sqlseed-0.1.16/examples/notebooks/08-mcp-server.ipynb +595 -0
  16. sqlseed-0.1.16/examples/notebooks/09-plugin-hooks.ipynb +634 -0
  17. sqlseed-0.1.16/examples/notebooks/10-cli-reference.ipynb +785 -0
  18. sqlseed-0.1.16/examples/notebooks/11-utilities.ipynb +542 -0
  19. sqlseed-0.1.16/examples/notebooks/12-testing-patterns.ipynb +729 -0
  20. {sqlseed-0.1.14 → sqlseed-0.1.16}/pyproject.toml +5 -3
  21. sqlseed-0.1.16/sqlseed-/344/273/243/347/240/201/350/264/250/351/207/217/351/227/256/351/242/230/346/261/207/346/200/273.md +204 -0
  22. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/__init__.py +11 -12
  23. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/_utils/__init__.py +2 -0
  24. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/_utils/logger.py +5 -0
  25. sqlseed-0.1.16/src/sqlseed/_utils/paths.py +41 -0
  26. sqlseed-0.1.16/src/sqlseed/_utils/progress.py +280 -0
  27. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/cli/main.py +24 -12
  28. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/config/models.py +40 -0
  29. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/config/snapshot.py +2 -1
  30. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/core/enrichment.py +6 -0
  31. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/core/expression.py +1 -4
  32. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/core/mapper.py +1 -0
  33. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/core/orchestrator.py +21 -15
  34. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/core/plugin_mediator.py +13 -2
  35. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/core/relation.py +46 -4
  36. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/core/result.py +1 -1
  37. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/core/unique_adjuster.py +5 -2
  38. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/database/_helpers.py +0 -2
  39. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/generators/__init__.py +3 -1
  40. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/generators/_protocol.py +8 -0
  41. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/generators/base_provider.py +3 -2
  42. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/generators/stream.py +57 -6
  43. sqlseed-0.1.16/uv.lock +1587 -0
  44. sqlseed-0.1.14/examples/ai_generation_demo.py +0 -177
  45. sqlseed-0.1.14/src/sqlseed/_utils/progress.py +0 -23
  46. {sqlseed-0.1.14 → sqlseed-0.1.16}/LICENSE +0 -0
  47. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/_utils/metrics.py +0 -0
  48. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/_utils/schema_helpers.py +0 -0
  49. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/_utils/sql_safe.py +0 -0
  50. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/_version.py +0 -0
  51. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/cli/__init__.py +0 -0
  52. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/config/__init__.py +0 -0
  53. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/config/loader.py +0 -0
  54. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/core/__init__.py +0 -0
  55. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/core/column_dag.py +0 -0
  56. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/core/constraints.py +0 -0
  57. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/core/schema.py +0 -0
  58. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/core/transform.py +0 -0
  59. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/database/__init__.py +0 -0
  60. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/database/_base_adapter.py +0 -0
  61. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/database/_compat.py +0 -0
  62. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/database/_protocol.py +0 -0
  63. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/database/optimizer.py +0 -0
  64. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/database/raw_sqlite_adapter.py +0 -0
  65. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/database/sqlite_utils_adapter.py +0 -0
  66. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/generators/_dispatch.py +0 -0
  67. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/generators/_json_helpers.py +0 -0
  68. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/generators/_string_helpers.py +0 -0
  69. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/generators/faker_provider.py +0 -0
  70. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/generators/mimesis_provider.py +0 -0
  71. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/generators/registry.py +0 -0
  72. {sqlseed-0.1.14 → sqlseed-0.1.16}/src/sqlseed/py.typed +0 -0
@@ -19,6 +19,8 @@ wheels/
19
19
  *.egg-info/
20
20
  .installed.cfg
21
21
  *.egg
22
+ *.whl
23
+ *.tar.gz
22
24
 
23
25
  # Virtual Environment
24
26
  .venv/
@@ -29,46 +31,40 @@ ENV/
29
31
  # IDE
30
32
  .vscode/
31
33
  .idea/
34
+ .trae/
35
+ .claude/
36
+ .sonarlint/
32
37
  *.swp
33
38
  *.swo
34
39
  *~
35
40
 
36
- # Testing
41
+ # Testing & Quality
37
42
  .pytest_cache/
38
43
  .benchmarks/
39
44
  .coverage
40
45
  coverage.xml
41
46
  htmlcov/
42
-
43
- # Type checking
44
47
  .mypy_cache/
45
48
  .dmypy.json
46
49
  dmypy.json
47
-
48
- # Linting
49
50
  .ruff_cache/
50
51
 
51
- # Project specific
52
+ # sqlseed
52
53
  *.db
53
54
  *.sqlite
54
55
  *.sqlite3
55
- snapshots/
56
-
57
- # AI cache
58
56
  .sqlseed_cache/
57
+ snapshots/
58
+ .env
59
+ examples/notebooks/_*.yaml
60
+ examples/notebooks/_*.json
61
+ examples/notebooks/batch_config.yaml
62
+ *.nbconvert.ipynb
63
+ .ipynb_checkpoints/
59
64
 
60
- # macOS
65
+ # OS
61
66
  .DS_Store
62
67
 
63
- # Trae IDE
64
- .trae/
65
-
66
- # Build artifacts
67
- *.whl
68
- *.tar.gz
69
-
70
- # Local git worktrees
68
+ # Other
71
69
  .worktrees/
72
-
73
- # IDE - SonarLint
74
- .sonarlint/
70
+ .sisyphus/
@@ -7,6 +7,42 @@ All notable changes to this project will be documented in this file.
7
7
  Format based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
8
8
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
9
9
 
10
+ ## [v0.1.16]
11
+
12
+ ### Added
13
+
14
+ - `_utils/paths.py` — `get_cache_dir(subdir)` platform-specific cache directory utility (macOS `~/Library/Caches/sqlseed/`, Linux `~/.cache/sqlseed/`, Windows `%LOCALAPPDATA%/sqlseed/`), respects `SQLSEED_CACHE_DIR` env var
15
+ - `_utils/progress.py` refactored to Strategy Pattern with multi-backend architecture: `RichProgressBackend` (terminal), `TqdmNotebookBackend` (Jupyter), `NullProgressBackend` (disabled), with automatic environment detection
16
+ - `generators/_protocol.py` adds `GenerationError` (retriable runtime error) and `ConfigurationError` (non-retriable config error) exception classes
17
+ - `ColumnConfig` adds `normalize_dict_input` model_validator: supports `type` as `generator` alias, auto-routes unknown keys to `params`, flattens nested `params`
18
+ - `DataStream` now logs UNIQUE constraint exhaustion warnings with column and generator details
19
+ - `DataStream` RuntimeError message includes non-skip column names for faster debugging
20
+ - Jupyter notebook tutorial series (`examples/notebooks/`): quickstart, column mapping, generators, DB association, expression/DAGs, AI configuration, MCP server, testing patterns, utilities, CLI reference
21
+
22
+ ### Changed
23
+
24
+ - `SnapshotManager` default directory changed from `./snapshots` to platform cache dir (`get_cache_dir("snapshots")`)
25
+ - `AiConfigRefiner` default cache directory changed from `.sqlseed_cache/ai_configs/` to platform cache dir (`get_cache_dir("ai_configs")`)
26
+ - `cli/main.py` `inspect --show-mapping` now uses `orch._resolve_specs()` for accurate column mapping display (previously used `orch.map_column(col)` which skipped FK resolution)
27
+ - `cli/main.py` `fill` now outputs warnings for `result.errors` to stderr
28
+ - `orchestrator._resolve_user_configs` supports `derive_from`/`expression` in dict-style column configs
29
+ - Demo database (`examples/build_demo_db.py`) rewritten as idempotent schema initializer (`ensure_db()`), no longer embeds seed data
30
+ - **⚠️ Breaking**: `register_shared_pool` now only registers PK and FK columns to SharedPool (previously registered all non-PK-skip columns). Implicit cross-table association for same-name non-PK/FK columns now requires explicit `ColumnAssociation` config
31
+ - UNIQUE columns are no longer overridden by SharedPool implicit association or template pool, preventing duplicate values that caused `IntegrityError`
32
+
33
+ ### Fixed
34
+
35
+ - `orchestrator.fill_table` now catches `sqlite3.IntegrityError` alongside `OperationalError`, preventing unhandled crashes on UNIQUE/FK violations
36
+ - `UniqueAdjuster` uses `params.get("max_length", max_length)` to prevent `KeyError` when `max_length` is absent from params
37
+ - `DataStream._attempt_node_generation` catches generator exceptions gracefully instead of propagating to caller
38
+ - Backtrack/no-values log level reduced from `warning` to `debug` to reduce noise
39
+
40
+ ## [v0.1.15]
41
+
42
+ ### Fixed
43
+ - CI: remove unnecessary try/except in `ExpressionEngine.evaluate` to resolve SonarCloud S2737 and CodeFlow try-except-raise warnings
44
+ - CI: add comment documenting intentional `list()` usage in `PluginMediator.apply_template_pool` (SonarCloud S7504)
45
+
10
46
  ## [v0.1.14]
11
47
 
12
48
  ### Fixed
@@ -36,7 +72,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
36
72
  #### AI Plugin (sqlseed-ai)
37
73
  - Auto model selection: `_model_selector` picks the best free model from OpenRouter by priority
38
74
  - Structured output: `response_format: json_object` forces LLM to return JSON
39
- - Few-shot example library: 4 typical scenarios (users, bank cards, orders, employees)
75
+ - Few-shot example library: 4 typical scenarios (users, projects, orders, employees)
40
76
  - `AiConfigRefiner` self-correction loop: auto-detects and fixes invalid configs, up to 3 retries
41
77
  - File caching: `.sqlseed_cache/ai_configs/` with schema hash validation, `--no-cache` to skip
42
78
  - Pre-computed template pool: `sqlseed_pre_generate_templates` hook pre-generates candidate values for complex columns
@@ -7,6 +7,42 @@
7
7
  格式基于 [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
8
8
  本项目遵循[语义化版本](https://semver.org/spec/v2.0.0.html)。
9
9
 
10
+ ## [v0.1.16]
11
+
12
+ ### 新增
13
+
14
+ - `_utils/paths.py` — `get_cache_dir(subdir)` 平台标准缓存目录工具(macOS `~/Library/Caches/sqlseed/`,Linux `~/.cache/sqlseed/`,Windows `%LOCALAPPDATA%/sqlseed/`),支持 `SQLSEED_CACHE_DIR` 环境变量覆盖
15
+ - `_utils/progress.py` 重构为 Strategy Pattern 多后端架构:`RichProgressBackend`(终端)、`TqdmNotebookBackend`(Jupyter)、`NullProgressBackend`(禁用),含自动环境检测
16
+ - `generators/_protocol.py` 新增 `GenerationError`(可重试运行时错误)和 `ConfigurationError`(不可重试配置错误)异常类
17
+ - `ColumnConfig` 新增 `normalize_dict_input` model_validator:支持 `type` 作为 `generator` 别名、未知键自动归入 `params`、嵌套 `params` 展平
18
+ - `DataStream` 新增 UNIQUE 约束耗尽警告日志,包含列名和生成器详情
19
+ - `DataStream` RuntimeError 消息现在包含非 skip 列名,便于快速定位问题
20
+ - Jupyter Notebook 教程系列(`examples/notebooks/`):快速上手、列映射、生成器、数据库关联、表达式/DAG、AI 配置、MCP 服务器、测试模式、工具类、CLI 参考
21
+
22
+ ### 变更
23
+
24
+ - `SnapshotManager` 默认目录从 `./snapshots` 改为平台缓存目录(`get_cache_dir("snapshots")`)
25
+ - `AiConfigRefiner` 默认缓存目录从 `.sqlseed_cache/ai_configs/` 改为平台缓存目录(`get_cache_dir("ai_configs")`)
26
+ - `cli/main.py` `inspect --show-mapping` 现在使用 `orch._resolve_specs()` 显示准确的列映射(此前使用 `orch.map_column(col)` 会跳过 FK 解析)
27
+ - `cli/main.py` `fill` 命令现在会将 `result.errors` 的警告输出到 stderr
28
+ - `orchestrator._resolve_user_configs` 支持 dict 风格的 `derive_from`/`expression` 列配置
29
+ - 示例数据库(`examples/build_demo_db.py`)重写为幂等 schema 初始化(`ensure_db()`),不再内置种子数据
30
+ - **⚠️ Breaking**: `register_shared_pool` 现在只注册 PK 和 FK 列到 SharedPool(此前会注册所有非 PK-skip 列)。同名非 PK/FK 列的隐式跨表关联需通过 `ColumnAssociation` 显式声明
31
+ - UNIQUE 列不再被 SharedPool 隐式关联或 template pool 覆盖,避免生成重复值导致 `IntegrityError`
32
+
33
+ ### 修复
34
+
35
+ - `orchestrator.fill_table` 现在捕获 `sqlite3.IntegrityError`,避免 UNIQUE/FK 冲突导致未处理崩溃
36
+ - `UniqueAdjuster` 使用 `params.get("max_length", max_length)` 防止 `max_length` 缺失时的 `KeyError`
37
+ - `DataStream._attempt_node_generation` 优雅捕获生成器异常,不再向上传播
38
+ - 回溯/无值日志级别从 `warning` 降为 `debug`,减少日志噪音
39
+
40
+ ## [v0.1.15]
41
+
42
+ ### 修复
43
+ - CI: 移除 `ExpressionEngine.evaluate` 中不必要的 try/except,解决 SonarCloud S2737 和 CodeFlow try-except-raise 警告
44
+ - CI: 为 `PluginMediator.apply_template_pool` 中的 `list()` 调用添加注释说明其必要性(SonarCloud S7504)
45
+
10
46
  ## [v0.1.14]
11
47
 
12
48
  ### 修复
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlseed
3
- Version: 0.1.14
3
+ Version: 0.1.16
4
4
  Summary: Declarative SQLite test data generation toolkit
5
5
  Project-URL: Homepage, https://github.com/sunbos/sqlseed
6
6
  Project-URL: Documentation, https://github.com/sunbos/sqlseed#readme
@@ -34,6 +34,7 @@ Requires-Dist: typing-extensions>=4.4
34
34
  Provides-Extra: all
35
35
  Requires-Dist: faker>=30.0; extra == 'all'
36
36
  Requires-Dist: mimesis>=18.0; extra == 'all'
37
+ Requires-Dist: tqdm>=4.66; extra == 'all'
37
38
  Provides-Extra: dev
38
39
  Requires-Dist: mypy>=1.10; extra == 'dev'
39
40
  Requires-Dist: pre-commit>=3.0; extra == 'dev'
@@ -42,6 +43,7 @@ Requires-Dist: pytest-benchmark>=4.0; extra == 'dev'
42
43
  Requires-Dist: pytest-cov>=5.0; extra == 'dev'
43
44
  Requires-Dist: pytest>=8.0; extra == 'dev'
44
45
  Requires-Dist: ruff>=0.5; extra == 'dev'
46
+ Requires-Dist: tqdm>=4.66; extra == 'dev'
45
47
  Provides-Extra: docs
46
48
  Requires-Dist: mkdocs-material>=9.0; extra == 'docs'
47
49
  Requires-Dist: mkdocstrings[python]>=0.25; extra == 'docs'
@@ -49,6 +51,8 @@ Provides-Extra: faker
49
51
  Requires-Dist: faker>=30.0; extra == 'faker'
50
52
  Provides-Extra: mimesis
51
53
  Requires-Dist: mimesis>=18.0; extra == 'mimesis'
54
+ Provides-Extra: notebook
55
+ Requires-Dist: tqdm>=4.66; extra == 'notebook'
52
56
  Description-Content-Type: text/markdown
53
57
 
54
58
  <div align="center">
@@ -136,7 +140,7 @@ Topological sort auto-detects table dependencies. SharedPool cross-table value s
136
140
 
137
141
  **🧮 Expression Engine & Constraint Solving**
138
142
 
139
- Supports derived column computation (`last_eight = card_number[-8:]`), unique constraint backtracking, and timeout protection against infinite loops.
143
+ Supports derived column computation (`short_code = project_no[-8:]`), unique constraint backtracking, and timeout protection against infinite loops.
140
144
 
141
145
  </td>
142
146
  <td>
@@ -233,6 +237,22 @@ mypy src/sqlseed/
233
237
 
234
238
  ## 🚀 Quick Start
235
239
 
240
+ ### Try with Demo Database
241
+
242
+ Want to try sqlseed right away? Build the demo database:
243
+
244
+ ```bash
245
+ python examples/build_demo_db.py
246
+ ```
247
+
248
+ Then explore:
249
+
250
+ ```bash
251
+ sqlseed preview examples/sqlseed_demo.db --table members --count 5
252
+ sqlseed inspect examples/sqlseed_demo.db --show-mapping
253
+ sqlseed fill examples/sqlseed_demo.db --table members --count 100
254
+ ```
255
+
236
256
  ### Get Started in 30 Seconds
237
257
 
238
258
  Suppose you have a SQLite database `app.db` with a `users` table:
@@ -378,7 +398,7 @@ with sqlseed.connect("app.db", provider="mimesis", locale="en_US") as db:
378
398
  # → orders: 50000 rows
379
399
  ```
380
400
 
381
- > **💡 Tip**: If two tables share a column name (e.g., `account_id`), even without a declared FK constraint, sqlseed automatically maintains cross-table consistency via the **SharedPool implicit association mechanism**.
401
+ > **💡 Tip**: If two tables share a column name (e.g., `member_no`), even without a declared FK constraint, sqlseed automatically maintains cross-table consistency via the **SharedPool implicit association mechanism**.
382
402
 
383
403
  #### Explicit Cross-Table Associations (ColumnAssociation)
384
404
 
@@ -494,42 +514,42 @@ for r in results:
494
514
  sqlseed v2.0 introduces column dependency DAG and expression engine for computing derived columns:
495
515
 
496
516
  ```yaml
497
- # Bank card info table scenario
517
+ # Project info table scenario
498
518
  tables:
499
- - name: bank_cards
519
+ - name: projects
500
520
  count: 10000
501
521
  columns:
502
- - name: card_number
522
+ - name: project_no
503
523
  generator: pattern
504
524
  params:
505
- regex: "62[0-9]{17}" # 19-digit UnionPay card number
525
+ regex: "PRJ-\\d{6}" # Project number pattern
506
526
  constraints:
507
527
  unique: true
508
528
 
509
- - name: last_eight
510
- derive_from: card_number # Depends on card_number
511
- expression: "value[-8:]" # Last 8 digits
529
+ - name: short_code
530
+ derive_from: project_no # Depends on project_no
531
+ expression: "value[-6:]" # Last 6 chars
512
532
  constraints:
513
533
  unique: true
514
534
 
515
- - name: last_six
516
- derive_from: card_number
517
- expression: "value[-6:]" # Last 6 digits
535
+ - name: region_code
536
+ derive_from: project_no
537
+ expression: "value[-4:]" # Last 4 chars
518
538
 
519
- - name: account_id
539
+ - name: member_no
520
540
  generator: pattern
521
541
  params:
522
- regex: "U[0-9]{10}"
542
+ regex: "M-\\d{4}" # Member number pattern
523
543
  constraints:
524
544
  unique: true
525
545
  ```
526
546
 
527
547
  **How it works**:
528
548
 
529
- 1. sqlseed builds a column dependency DAG: `card_numberlast_eight, last_six`
549
+ 1. sqlseed builds a column dependency DAG: `project_noshort_code, region_code`
530
550
  2. Topological sort determines generation order
531
- 3. Generates `card_number` first, then computes `last_eight` via `value[-8:]`
532
- 4. If `last_eight` unique constraint fails, backtracks to regenerate `card_number`
551
+ 3. Generates `project_no` first, then computes `short_code` via `value[-6:]`
552
+ 4. If `short_code` unique constraint fails, backtracks to regenerate `project_no`
533
553
 
534
554
  #### Expression Engine Functions (21 total)
535
555
 
@@ -664,10 +684,10 @@ Save a successful generation config for exact replay later:
664
684
  ```bash
665
685
  # Generate and save snapshot
666
686
  sqlseed fill app.db --table users --count 10000 --seed 42 --snapshot
667
- # → Snapshot saved: snapshots/2026-04-15_033000_users.yaml
687
+ # → Snapshot saved: <cache_dir>/snapshots/YYYY-MM-DD_HHMMSS_users.yaml
668
688
 
669
689
  # Replay anytime
670
- sqlseed replay snapshots/2026-04-15_033000_users.yaml
690
+ sqlseed replay <cache_dir>/snapshots/YYYY-MM-DD_HHMMSS_users.yaml
671
691
  # → GenerationResult(table=users, count=10000, elapsed=0.52s, speed=19230 rows/s)
672
692
  ```
673
693
 
@@ -692,16 +712,16 @@ export SQLSEED_AI_API_KEY="your-api-key"
692
712
  export SQLSEED_AI_BASE_URL="https://your-llm-api-endpoint"
693
713
 
694
714
  # AI analysis and config generation
695
- sqlseed ai-suggest app.db --table bank_cards --output bank_cards.yaml
715
+ sqlseed ai-suggest app.db --table projects --output projects.yaml
696
716
 
697
717
  # AI suggestions with self-correction (3 rounds by default)
698
- sqlseed ai-suggest app.db --table bank_cards --output bank_cards.yaml --verify
718
+ sqlseed ai-suggest app.db --table projects --output projects.yaml --verify
699
719
 
700
720
  # Specify model (defaults to most popular free model)
701
- sqlseed ai-suggest app.db --table bank_cards --output bank_cards.yaml --model nvidia/nemotron-3-super-120b-a12b:free
721
+ sqlseed ai-suggest app.db --table projects --output projects.yaml --model nvidia/nemotron-3-super-120b-a12b:free
702
722
 
703
723
  # Skip cache
704
- sqlseed ai-suggest app.db --table bank_cards --output bank_cards.yaml --no-cache
724
+ sqlseed ai-suggest app.db --table projects --output projects.yaml --no-cache
705
725
  ```
706
726
 
707
727
  **AI Workflow**:
@@ -757,7 +777,7 @@ python -m mcp_server_sqlseed
757
777
 
758
778
  This means you can tell your AI assistant:
759
779
 
760
- > "Analyze the structure of the `bank_cards` table in `app.db`, generate a YAML config, then fill 5000 rows."
780
+ > "Analyze the structure of the `projects` table in `app.db`, generate a YAML config, then fill 5000 rows."
761
781
 
762
782
  The AI assistant will call `sqlseed_inspect_schema` → `sqlseed_generate_yaml` → `sqlseed_execute_fill` in sequence, without you writing any code.
763
783
 
@@ -874,7 +894,7 @@ sqlseed inspect app.db --table users --show-mapping
874
894
  sqlseed init generate.yaml --db app.db
875
895
 
876
896
  # Replay snapshot
877
- sqlseed replay snapshots/2026-04-15_users.yaml
897
+ sqlseed replay <cache_dir>/snapshots/YYYY-MM-DD_users.yaml
878
898
 
879
899
  # ═══════════════════════════════════════
880
900
  # 🤖 AI Features
@@ -914,7 +934,7 @@ Level 5 │ DEFAULT check Has default → skip / __enrich__ (when enrich=T
914
934
 
915
935
  Level 6 │ Custom pattern Regex rules registered via plugin hooks
916
936
 
917
- Level 7 │ Built-in pattern 25 regexes: *_at→datetime, *_id→foreign_key, is_*→boolean...
937
+ Level 7 │ Built-in pattern 26 regexes: *_at→datetime, *_id→foreign_key, is_*→boolean...
918
938
 
919
939
  Level 8 │ NULLABLE fallback Nullable → skip / __enrich__
920
940
 
@@ -991,6 +1011,7 @@ src/sqlseed/
991
1011
  ├── sql_safe.py # quote_identifier — SQL injection protection
992
1012
  ├── schema_helpers.py # AUTOINCREMENT detection
993
1013
  ├── metrics.py # MetricsCollector performance metrics
1014
+ ├── paths.py # get_cache_dir — platform cache directory
994
1015
  ├── progress.py # Rich progress bar
995
1016
  └── logger.py # structlog logging
996
1017
 
@@ -83,7 +83,7 @@ Topological sort auto-detects table dependencies. SharedPool cross-table value s
83
83
 
84
84
  **🧮 Expression Engine & Constraint Solving**
85
85
 
86
- Supports derived column computation (`last_eight = card_number[-8:]`), unique constraint backtracking, and timeout protection against infinite loops.
86
+ Supports derived column computation (`short_code = project_no[-8:]`), unique constraint backtracking, and timeout protection against infinite loops.
87
87
 
88
88
  </td>
89
89
  <td>
@@ -180,6 +180,22 @@ mypy src/sqlseed/
180
180
 
181
181
  ## 🚀 Quick Start
182
182
 
183
+ ### Try with Demo Database
184
+
185
+ Want to try sqlseed right away? Build the demo database:
186
+
187
+ ```bash
188
+ python examples/build_demo_db.py
189
+ ```
190
+
191
+ Then explore:
192
+
193
+ ```bash
194
+ sqlseed preview examples/sqlseed_demo.db --table members --count 5
195
+ sqlseed inspect examples/sqlseed_demo.db --show-mapping
196
+ sqlseed fill examples/sqlseed_demo.db --table members --count 100
197
+ ```
198
+
183
199
  ### Get Started in 30 Seconds
184
200
 
185
201
  Suppose you have a SQLite database `app.db` with a `users` table:
@@ -325,7 +341,7 @@ with sqlseed.connect("app.db", provider="mimesis", locale="en_US") as db:
325
341
  # → orders: 50000 rows
326
342
  ```
327
343
 
328
- > **💡 Tip**: If two tables share a column name (e.g., `account_id`), even without a declared FK constraint, sqlseed automatically maintains cross-table consistency via the **SharedPool implicit association mechanism**.
344
+ > **💡 Tip**: If two tables share a column name (e.g., `member_no`), even without a declared FK constraint, sqlseed automatically maintains cross-table consistency via the **SharedPool implicit association mechanism**.
329
345
 
330
346
  #### Explicit Cross-Table Associations (ColumnAssociation)
331
347
 
@@ -441,42 +457,42 @@ for r in results:
441
457
  sqlseed v2.0 introduces column dependency DAG and expression engine for computing derived columns:
442
458
 
443
459
  ```yaml
444
- # Bank card info table scenario
460
+ # Project info table scenario
445
461
  tables:
446
- - name: bank_cards
462
+ - name: projects
447
463
  count: 10000
448
464
  columns:
449
- - name: card_number
465
+ - name: project_no
450
466
  generator: pattern
451
467
  params:
452
- regex: "62[0-9]{17}" # 19-digit UnionPay card number
468
+ regex: "PRJ-\\d{6}" # Project number pattern
453
469
  constraints:
454
470
  unique: true
455
471
 
456
- - name: last_eight
457
- derive_from: card_number # Depends on card_number
458
- expression: "value[-8:]" # Last 8 digits
472
+ - name: short_code
473
+ derive_from: project_no # Depends on project_no
474
+ expression: "value[-6:]" # Last 6 chars
459
475
  constraints:
460
476
  unique: true
461
477
 
462
- - name: last_six
463
- derive_from: card_number
464
- expression: "value[-6:]" # Last 6 digits
478
+ - name: region_code
479
+ derive_from: project_no
480
+ expression: "value[-4:]" # Last 4 chars
465
481
 
466
- - name: account_id
482
+ - name: member_no
467
483
  generator: pattern
468
484
  params:
469
- regex: "U[0-9]{10}"
485
+ regex: "M-\\d{4}" # Member number pattern
470
486
  constraints:
471
487
  unique: true
472
488
  ```
473
489
 
474
490
  **How it works**:
475
491
 
476
- 1. sqlseed builds a column dependency DAG: `card_numberlast_eight, last_six`
492
+ 1. sqlseed builds a column dependency DAG: `project_noshort_code, region_code`
477
493
  2. Topological sort determines generation order
478
- 3. Generates `card_number` first, then computes `last_eight` via `value[-8:]`
479
- 4. If `last_eight` unique constraint fails, backtracks to regenerate `card_number`
494
+ 3. Generates `project_no` first, then computes `short_code` via `value[-6:]`
495
+ 4. If `short_code` unique constraint fails, backtracks to regenerate `project_no`
480
496
 
481
497
  #### Expression Engine Functions (21 total)
482
498
 
@@ -611,10 +627,10 @@ Save a successful generation config for exact replay later:
611
627
  ```bash
612
628
  # Generate and save snapshot
613
629
  sqlseed fill app.db --table users --count 10000 --seed 42 --snapshot
614
- # → Snapshot saved: snapshots/2026-04-15_033000_users.yaml
630
+ # → Snapshot saved: <cache_dir>/snapshots/YYYY-MM-DD_HHMMSS_users.yaml
615
631
 
616
632
  # Replay anytime
617
- sqlseed replay snapshots/2026-04-15_033000_users.yaml
633
+ sqlseed replay <cache_dir>/snapshots/YYYY-MM-DD_HHMMSS_users.yaml
618
634
  # → GenerationResult(table=users, count=10000, elapsed=0.52s, speed=19230 rows/s)
619
635
  ```
620
636
 
@@ -639,16 +655,16 @@ export SQLSEED_AI_API_KEY="your-api-key"
639
655
  export SQLSEED_AI_BASE_URL="https://your-llm-api-endpoint"
640
656
 
641
657
  # AI analysis and config generation
642
- sqlseed ai-suggest app.db --table bank_cards --output bank_cards.yaml
658
+ sqlseed ai-suggest app.db --table projects --output projects.yaml
643
659
 
644
660
  # AI suggestions with self-correction (3 rounds by default)
645
- sqlseed ai-suggest app.db --table bank_cards --output bank_cards.yaml --verify
661
+ sqlseed ai-suggest app.db --table projects --output projects.yaml --verify
646
662
 
647
663
  # Specify model (defaults to most popular free model)
648
- sqlseed ai-suggest app.db --table bank_cards --output bank_cards.yaml --model nvidia/nemotron-3-super-120b-a12b:free
664
+ sqlseed ai-suggest app.db --table projects --output projects.yaml --model nvidia/nemotron-3-super-120b-a12b:free
649
665
 
650
666
  # Skip cache
651
- sqlseed ai-suggest app.db --table bank_cards --output bank_cards.yaml --no-cache
667
+ sqlseed ai-suggest app.db --table projects --output projects.yaml --no-cache
652
668
  ```
653
669
 
654
670
  **AI Workflow**:
@@ -704,7 +720,7 @@ python -m mcp_server_sqlseed
704
720
 
705
721
  This means you can tell your AI assistant:
706
722
 
707
- > "Analyze the structure of the `bank_cards` table in `app.db`, generate a YAML config, then fill 5000 rows."
723
+ > "Analyze the structure of the `projects` table in `app.db`, generate a YAML config, then fill 5000 rows."
708
724
 
709
725
  The AI assistant will call `sqlseed_inspect_schema` → `sqlseed_generate_yaml` → `sqlseed_execute_fill` in sequence, without you writing any code.
710
726
 
@@ -821,7 +837,7 @@ sqlseed inspect app.db --table users --show-mapping
821
837
  sqlseed init generate.yaml --db app.db
822
838
 
823
839
  # Replay snapshot
824
- sqlseed replay snapshots/2026-04-15_users.yaml
840
+ sqlseed replay <cache_dir>/snapshots/YYYY-MM-DD_users.yaml
825
841
 
826
842
  # ═══════════════════════════════════════
827
843
  # 🤖 AI Features
@@ -861,7 +877,7 @@ Level 5 │ DEFAULT check Has default → skip / __enrich__ (when enrich=T
861
877
 
862
878
  Level 6 │ Custom pattern Regex rules registered via plugin hooks
863
879
 
864
- Level 7 │ Built-in pattern 25 regexes: *_at→datetime, *_id→foreign_key, is_*→boolean...
880
+ Level 7 │ Built-in pattern 26 regexes: *_at→datetime, *_id→foreign_key, is_*→boolean...
865
881
 
866
882
  Level 8 │ NULLABLE fallback Nullable → skip / __enrich__
867
883
 
@@ -938,6 +954,7 @@ src/sqlseed/
938
954
  ├── sql_safe.py # quote_identifier — SQL injection protection
939
955
  ├── schema_helpers.py # AUTOINCREMENT detection
940
956
  ├── metrics.py # MetricsCollector performance metrics
957
+ ├── paths.py # get_cache_dir — platform cache directory
941
958
  ├── progress.py # Rich progress bar
942
959
  └── logger.py # structlog logging
943
960