sql5 4.0.2

SQLite compatible database with CJK FTS5 full-text search and vector similarity
# sql5 v1.22 版本說明(已完成)

## 版本資訊
- **版本**:1.22
- **日期**:2026-05-04
- **名稱**:PyPI 打包

## 已實作功能

### Python Package (`sql5_pypi/`)

```
sql5_pypi/
├── sql5/                   # Python package
│   ├── __init__.py        # __version__
│   ├── __main__.py        # CLI entry point
│   └── _binary.py         # Binary download manager
├── pyproject.toml         # PEP 517 構建設定
├── setup.cfg              # 安裝設定
├── README.md
├── LICENSE (MIT)
└── .github/workflows/
    ├── release.yml         # 建置 + 發布 PyPI
    └── ci.yml              # 測試 CI
```

## 發布流程

### 1. 設定 GitHub Secrets

在 GitHub Repository Settings → Secrets 新增:
- `PYPI_TOKEN` — PyPI API Token

### 2. 推送 Tag 觸發 Release

```bash
git tag v1.21.0
git push origin v1.21.0
```

### 3. GitHub Actions 自動執行

1. 為 4 個平台建置 binary(macos-arm64, macos-x86_64, linux-x86_64, windows-x86_64)
2. 上傳 binary 到 GitHub Release
3. 發布到 PyPI

### 4. pip install

```bash
pip install sql5
sql5                    # 執行 REPL
sql5 database.db        # 開啟資料庫
```

## Binary 下載時機

- `import sql5` — 不下載任何東西
- 第一次執行 `sql5` CLI — 自動下載對應平台的 binary 到 `~/.cache/sql5/`

## 目標

將 `sql5` 發布到 PyPI(`pip install sql5`),使用 **純 Python 包 + 預編譯 Binary** 方案。

## 套件結構

```
sql5-pypi/
├── sql5/                      # Python package
│   ├── __init__.py            # version, main CLI
│   ├── __main__.py            # python -m sql5
│   └── _binary.py            # 下載並管理 binary
├── pyproject.toml             # PEP 517 構建設定
├── setup.cfg                  # 安裝設定
├── README.md
├── LICENSE
└── .github/
    └── workflows/
        └── release.yml        # CI: 建置 + 發布 PyPI
```

## Binary 管理策略

### 下載時機
- `import sql5` 時不做任何事
- 第一次執行 `sql5` CLI 時,檢查並下載對應平台的 binary

### 版本對應
- PyPI version = Rust package version (e.g., v1.21.0 → 1.21.0)
- Binary 存在於 GitHub Release 的 asset

### 平台偵測

```python
import platform, sys

def get_platform():
    system = platform.system().lower()  # linux / darwin / windows
    machine = platform.machine().lower()  # x86_64 / arm64 / aarch64

    if system == "darwin" and machine == "arm64":
        return "macos-arm64"
    elif system == "darwin":
        return "macos-x86_64"
    elif system == "linux":
        return "linux-x86_64"
    elif system == "windows":
        return "windows-x86_64"
    raise UnsupportedPlatform()
```

### Binary 路徑

```python
BINARY_NAME = {
    "macos-arm64":   "sql5-macos-arm64",
    "macos-x86_64":  "sql5-macos-x86_64",
    "linux-x86_64":  "sql5-linux-x86_64",
    "windows-x86_64": "sql5-windows.exe",
}
VERSION = "1.21.0"
BASE_URL = f"https://github.com/{OWNER}/{REPO}/releases/download/v{VERSION}"
BINARY_URL = f"{BASE_URL}/{BINARY_NAME}"
```

## CI/CD 流程

### 觸發條件
- Push tag `v*.*.*` 到 GitHub
- 或手動 workflow_dispatch

### 步驟

1. **建置 Binary**(矩陣:linux-x86_64, macos-x86_64, macos-arm64, windows-x86_64)
   - `cargo build --release`
   - 輸出到 `target/release/sql5`

2. **命名 Asset**
   - `sql5-{version}-{platform}.{ext}`

3. **上傳到 GitHub Release**
   - 使用 `softprops/action-gh-release`

4. **發布到 PyPI**
   - 使用 `pypa/gh-action-pypi-publish`

### GitHub Actions Workflow

```yaml
name: Release
on:
  push:
    tags: ['v*.*.*']
  workflow_dispatch:

jobs:
  build:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        include:
          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            platform: linux-x86_64
          - os: macos-latest
            target: x86_64-apple-darwin
            platform: macos-x86_64
          - os: macos-latest
            target: aarch64-apple-darwin
            platform: macos-arm64
          - os: windows-latest
            target: x86_64-pc-windows-msvc
            platform: windows-x86_64

  publish:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - uses: pypa/gh-action-pypi-publish@release/v1
```

## Python 包內容

### `sql5/__init__.py`

```python
__version__ = "1.21.0"
```

### `sql5/__main__.py`

```python
import sys, os
from sql5._binary import get_binary_path

def main():
    binary = get_binary_path()
    os.execv(binary, [binary] + sys.argv[1:])

if __name__ == "__main__":
    main()
```

### `sql5/_binary.py`

```python
import os, sys, platform, hashlib, tempfile, subprocess, urllib.request

VERSION = "1.21.0"
OWNER = "你的GitHub用戶名"
REPO = "sql5"

BINARY_URLS = {
    "linux-x86_64":   f"https://github.com/{OWNER}/{REPO}/releases/download/v{VERSION}/sql5-linux-x86_64",
    "macos-x86_64":   f"https://github.com/{OWNER}/{REPO}/releases/download/v{VERSION}/sql5-macos-x86_64",
    "macos-arm64":    f"https://github.com/{OWNER}/{REPO}/releases/download/v{VERSION}/sql5-macos-arm64",
    "windows-x86_64": f"https://github.com/{OWNER}/{REPO}/releases/download/v{VERSION}/sql5-windows.exe",
}

def get_platform():
    system = platform.system().lower()
    machine = platform.machine().lower()
    if system == "darwin" and machine == "arm64":
        return "macos-arm64"
    elif system == "darwin":
        return "macos-x86_64"
    elif system == "linux":
        return "linux-x86_64"
    elif system == "windows":
        return "windows-x86_64"
    raise RuntimeError(f"Unsupported platform: {system}/{machine}")

def get_binary_path():
    cache_dir = os.path.join(os.path.expanduser("~"), ".cache", "sql5")
    os.makedirs(cache_dir, exist_ok=True)

    platform_name = get_platform()
    binary_name = {
        "linux-x86_64": "sql5-linux-x86_64",
        "macos-x86_64": "sql5-macos-x86_64",
        "macos-arm64": "sql5-macos-arm64",
        "windows-x86_64": "sql5-windows.exe",
    }[platform_name]

    binary_path = os.path.join(cache_dir, binary_name)

    if not os.path.exists(binary_path):
        url = BINARY_URLS[platform_name]
        print(f"Downloading sql5 {VERSION} for {platform_name}...", file=sys.stderr)
        urllib.request.urlretrieve(url, binary_path)
        os.chmod(binary_path, 0o755)

    return binary_path
```

## 預備工作

1. **建立 GitHub Repository**(如果還沒有)
2. **設定 PyPI Token**(GitHub Secrets: `PYPI_TOKEN`3. **設定 Cargo.toml 的 `edition`** — 確認 `edition = "2024"` Rust 2024 版需要 nightly

## 版本同步策略

- `Cargo.toml` version → PyPI version
- 在 CI 中從 `Cargo.toml` 讀取 version 並 tag release

## 限制與替代方案

| 挑戰 | 替代方案 |
|-----|---------|
| Cross-compile 到 Windows | 使用 `cargo-xwin` 或 GitHub Windows runner |
| ARM Linux | 可能需要 `cross` 或手動編譯 |
| PyPI 上傳需 API token | 使用 `pypa/gh-action-pypi-publish` |

## 待確認事項

1. GitHub Repository URL?
2. PyPI 帳號是否已申請?
3. 是否要支援 ARM Linux?
4. Binary 授權(MIT)?