Metadata-Version: 2.4
Name: tai-sql
Version: 0.7.2
Summary: SQL database management and code generation tool
License-Expression: MIT
License-File: LICENSE
Keywords: sql,database,code-generation,orm,sqlalchemy
Author: MateoSaezMata
Author-email: msaez@triplealpha.in
Requires-Python: >=3.10,<4.0
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Database
Classifier: Topic :: Software Development :: Code Generators
Provides-Extra: all
Provides-Extra: backup
Provides-Extra: bigquery
Provides-Extra: deploy
Provides-Extra: diagrams
Provides-Extra: encryption
Provides-Extra: mysql
Provides-Extra: sqlserver
Provides-Extra: vectors
Requires-Dist: click (>=8.2.1,<9.0)
Requires-Dist: cryptography (>=45.0.4,<46.0) ; extra == "all"
Requires-Dist: cryptography (>=45.0.4,<46.0) ; extra == "encryption"
Requires-Dist: graphviz (>=0.20.3,<1.0) ; extra == "all"
Requires-Dist: graphviz (>=0.20.3,<1.0) ; extra == "diagrams"
Requires-Dist: inquirerpy (>=0.3.4,<0.4.0)
Requires-Dist: jinja2 (>=3.1.6,<4.0)
Requires-Dist: pgvector (>=0.3.0,<1.0) ; extra == "all"
Requires-Dist: pgvector (>=0.3.0,<1.0) ; extra == "vectors"
Requires-Dist: psycopg2-binary (>=2.9.10,<3.0)
Requires-Dist: pydantic (>=2.11.7,<3.0)
Requires-Dist: pymysql (>=1.1.1,<2.0) ; extra == "all"
Requires-Dist: pymysql (>=1.1.1,<2.0) ; extra == "mysql"
Requires-Dist: pynacl (>=1.5.0,<2.0) ; extra == "all"
Requires-Dist: pynacl (>=1.5.0,<2.0) ; extra == "deploy"
Requires-Dist: pyodbc (>=5.2.0,<6.0) ; extra == "all"
Requires-Dist: pyodbc (>=5.2.0,<6.0) ; extra == "sqlserver"
Requires-Dist: requests (>=2.32.4,<3.0) ; extra == "all"
Requires-Dist: requests (>=2.32.4,<3.0) ; extra == "deploy"
Requires-Dist: rich (>=15.0.0,<16.0.0)
Requires-Dist: sqlalchemy (>=2.0.42,<3.0)
Requires-Dist: sqlalchemy-bigquery (>=1.11.0,<2.0) ; extra == "all"
Requires-Dist: sqlalchemy-bigquery (>=1.11.0,<2.0) ; extra == "bigquery"
Requires-Dist: tai-alphi (>=2.0.1,<3.0) ; extra == "all"
Requires-Dist: tai-alphi (>=2.0.1,<3.0) ; extra == "backup"
Requires-Dist: tai-storage (>=0.1.0) ; extra == "all"
Requires-Dist: tai-storage (>=0.1.0) ; extra == "backup"
Project-URL: Documentation, https://triplealpha-innovation.github.io/tai-sql/
Project-URL: Homepage, https://www.triplealpha.in/es/
Project-URL: Issues, https://github.com/triplealpha-innovation/tai-sql/issues
Project-URL: Repository, https://github.com/triplealpha-innovation/tai-sql
Description-Content-Type: text/markdown

# tai-sql

[![PyPI](https://img.shields.io/pypi/v/tai-sql.svg)](https://pypi.org/project/tai-sql/)
[![Python](https://img.shields.io/pypi/pyversions/tai-sql.svg)](https://pypi.org/project/tai-sql/)
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
[![Manual](https://img.shields.io/badge/manual-github.io-blue.svg)](https://triplealpha-innovation.github.io/tai-sql/)

**Framework declarativo de Python, sobre SQLAlchemy, que gestiona el ciclo de vida completo de
una base de datos.** Declaras el modelo una vez, en un fichero Python, y a partir de ahí tai-sql
sincroniza la estructura de la base de datos, genera un cliente Python completo —modelos, DTOs y
DAOs síncronos y asíncronos— y dibuja el diagrama entidad-relación.

```
schemas/public.py  ──▶  tai-sql push      ──▶  la base de datos se parece al schema
                   ──▶  tai-sql generate  ──▶  cliente Python + diagrama ER
                   ──▶  tai-sql feed      ──▶  datos iniciales
                   ◀──  tai-sql pull      ◀──  una base de datos que ya existe
```

Motores soportados: **PostgreSQL**, **MySQL**, **SQL Server** y **BigQuery**.

📖 **[El manual completo está en triplealpha-innovation.github.io/tai-sql](https://triplealpha-innovation.github.io/tai-sql/)**

---

## Quickstart

```bash
pip install tai-sql                       # PostgreSQL funciona sin extras
tai-sql init -n mi_proyecto -s public     # crea el proyecto
cd mi_proyecto
export MAIN_DATABASE_URL="postgresql://user:pass@localhost:5432/mydb"
tai-sql install                           # instala lo que el cliente generado necesitará
```

Edita `schemas/public.py`:

```python
# -*- coding: utf-8 -*-
from __future__ import annotations
from tai_sql import *
from tai_sql.generators import *

datasource(provider=env('MAIN_DATABASE_URL'), schema='public', syntax='v2')

generate(
    PythonClientGenerator(output_dir='database'),
    ERDiagramGenerator(output_dir='diagrams', format='html'),
)


class Usuario(Table):
    """Usuarios del sistema."""
    __tablename__ = 'usuario'

    id: col[int] = column(primary_key=True, autoincrement=True)
    nombre: col[str]
    email: col[str] = column(unique=True)
    creado_en: col[datetime] = column(server_now=True)

    posts: onetomany[Post]


class Post(Table):
    """Posts publicados."""
    __tablename__ = 'post'

    id: col[bigint] = column(primary_key=True, autoincrement=True)
    titulo: col[str]
    contenido: col[text]
    autor_id: col[int]

    autor: manytoone[Usuario] = relation(fields=['autor_id'], references=['id'], backref='posts')
```

```bash
tai-sql push --dry-run --verbose   # enseña el DDL sin ejecutar nada
tai-sql push                       # lo aplica y regenera el cliente
```

Y a usarlo:

```python
from database.public import public_sync_api, UsuarioCreate

usuario = public_sync_api.usuario.create(UsuarioCreate(nombre='Ana', email='ana@example.com'))
usuarios = public_sync_api.usuario.find_many(limit=10, includes=['posts'])
```

---

## Los cinco principios que explican el resto

1. **El schema es la única fuente de verdad.** Todo lo demás —DDL, cliente, diagramas— es
   derivado y desechable. Si el cliente generado no hace lo que necesitas, no se edita el
   cliente: se arregla el schema y se regenera.
2. **Mapear y después actuar.** Todo comando importa el schema, lo analiza y actúa sobre ese
   mapeo. Ningún comando parsea el fichero por su cuenta.
3. **El código generado nunca importa `tai_sql`.** tai-sql es una herramienta de desarrollo, no
   una dependencia de producción: el cliente se despliega donde tai-sql no está instalado.
4. **Modelo declarativo, sin migraciones versionadas.** No hay ficheros de migración: `push`
   compara el estado declarado con el real y genera el DDL que hace falta.
5. **Definición ≠ runtime.** El ORM de tai-sql *describe*; el comportamiento en producción vive
   en el código generado.

---

## Qué trae

| | |
|---|---|
| **Schema declarativo** | Tablas, relaciones, vistas, enumerados, constraints e índices de varias columnas, columnas calculadas y jerarquías. Dos sintaxis, v1 y v2, y las dos se soportan |
| **Sincronización sin migraciones** | `push` compara y genera el DDL, clasificando cada operación en SAFE / WARNING / BLOCKED antes de tocar nada |
| **Cliente Python generado** | CRUD completo, filtros por tipo de columna, relaciones anidadas, agregaciones con GROUP BY, DataFrames, RLS, auditoría y transacciones, en síncrono y asíncrono |
| **Triggers transpilados** | Lógica de negocio declarada en el schema que se *inlinea* en los DAOs: sin coste en runtime |
| **Cifrado y vectores** | Columnas cifradas con Fernet, transparentes al leer, y columnas vectoriales con pgvector y búsqueda por similitud |
| **Diagrama ER** | Una página HTML interactiva, o una imagen con Graphviz |
| **Introspección** | `pull` escribe el schema de una base de datos que ya existe |
| **Reglas para asistentes de IA** | `rules install` deja en tu proyecto la documentación que un asistente necesita, incluida la derivada de tu schema |

---

## El manual

| Sección | Qué responde |
|---|---|
| [Instalación](https://triplealpha-innovation.github.io/tai-sql/empezar/instalacion/) | Qué instalar, y por qué son dos instalaciones y no una |
| [Tu primer proyecto](https://triplealpha-innovation.github.io/tai-sql/empezar/primer-proyecto/) | De cero a un cliente generado funcionando |
| [El schema](https://triplealpha-innovation.github.io/tai-sql/schema/) | Todo lo que se puede declarar, y cómo |
| [El CLI](https://triplealpha-innovation.github.io/tai-sql/cli/) | Qué hace cada comando, y qué puede destruir `push` |
| [El cliente generado](https://triplealpha-innovation.github.io/tai-sql/cliente/) | La API que vas a usar desde tu aplicación |
| [Referencia](https://triplealpha-innovation.github.io/tai-sql/referencia/dsl/) | Firmas del DSL, motores, extensión y catálogo de errores |

---

## Desarrollo

```bash
git clone https://github.com/triplealpha-innovation/tai-sql
cd tai-sql
poetry install --all-extras        # los extras no son opcionales para la suite

poetry run pytest                            # todo lo que el entorno permita
poetry run pytest -m "not db and not mysql"  # lo que corre sin ninguna base de datos
poetry run pytest -m mysql                   # el ciclo completo contra MySQL
```

Los tests marcados `db` necesitan un PostgreSQL alcanzable y se **saltan** si no lo hay; los
marcados `mysql`, un MySQL en `TAI_SQL_MYSQL_URL`. Sus schemas salen de `tests/fixtures/project/`.

El CI tiene tres workflows: `tests.yaml` ejecuta la suite en cada push y PR a `main` y `dev` —un
trabajo con PostgreSQL y otro con MySQL—, `docs.yaml` publica el manual y `publish.yaml` publica
a PyPI en push a `main`. La rama de trabajo habitual es `dev`, y la versión se bumpea a mano en
`pyproject.toml`.

### El manual, en local

```bash
pip install -r docs/requirements.txt
mkdocs serve            # http://127.0.0.1:8000, con recarga en caliente
mkdocs build --strict   # lo mismo que valida el CI
```

El manual vive en `docs/` y es para quien **usa** tai-sql. Las reglas de diseño internas
(`.claude/rules/`) y el `README.md` de cada paquete son para quien trabaja **en** tai-sql, y no
se publican: son dos audiencias con preguntas distintas.

### El mapa del código

| Ruta | Qué es |
|---|---|
| `tai_sql/orm/` | El mapeo, en cuatro capas: `declarative/` → `analysis/` → `model/` → `mapping/` |
| `tai_sql/sync/` | Sincronización schema ↔ BD: `state/` → `diff/` → `report.py` → `plan/` → `safety.py` → `executor.py` |
| `tai_sql/feed/` | Poblar la base de datos: recoger → planificar → aplicar en una transacción |
| `tai_sql/introspect/` | La dirección contraria: BD existente → fichero de schema |
| `tai_sql/drivers/` | Todo el SQL dialectal, más las capacidades de cada motor |
| `tai_sql/generators/` | Cliente Python, diagrama ER y reglas |
| `tai_sql/connection/` | Con qué se conecta tai-sql y cómo se conectará el cliente generado |
| `tai_sql/cli/` | El CLI de Click |
| `tai_sql/errors/` | `TaiSqlError` (mensaje + **solución** obligatoria) y su presentador |

Cada uno de esos paquetes tiene su propio `README.md` con el detalle.

---

## Licencia

MIT. Ver [LICENSE](LICENSE).

---

<sub>Desarrollado por [Triple Alpha Innovation](https://www.triplealpha.in/es/) ·
[Issues](https://github.com/triplealpha-innovation/tai-sql/issues)</sub>

