---
name: crud_generate_table_sql
kind: function
lang: go
domain: infra
version: "1.0.0"
purity: pure
signature: "func CRUDGenerateTableSQL(res CRUDResource) string"
description: "Genera el DDL CREATE TABLE IF NOT EXISTS de un CRUDResource. Incluye id como PRIMARY KEY, timestamps created_at/updated_at y deleted_at si soft_delete. Cada campo aplica su tipo SQLite y constraints NOT NULL/UNIQUE/DEFAULT."
tags: [crud, sql, ddl, generate, sqlite, infra]
uses_functions: []
uses_types: [CRUDResource_go_infra]
returns: []
returns_optional: false
error_type: ""
imports: [fmt, strings]
params:
  - name: res
    desc: "CRUDResource con la definicion completa del recurso"
output: "string con el statement CREATE TABLE listo para ejecutar"
tested: true
tests: ["genera tabla basica con timestamps", "aplica NOT NULL y UNIQUE", "aplica DEFAULT", "anade deleted_at si soft_delete"]
test_file_path: "functions/infra/crud_test.go"
file_path: "functions/infra/crud_generate_table_sql.go"
---

## Ejemplo

```go
res, _ := CRUDDefineResource("project", "projects", []CRUDField{
    {Name: "name", Type: "TEXT", Required: true, Unique: true},
    {Name: "priority", Type: "INTEGER", Default: "0"},
}, false)
ddl := CRUDGenerateTableSQL(res)
// CREATE TABLE IF NOT EXISTS projects (
//     id TEXT PRIMARY KEY,
//     name TEXT NOT NULL UNIQUE,
//     priority INTEGER DEFAULT 0,
//     created_at TEXT NOT NULL,
//     updated_at TEXT NOT NULL
// );
db.Exec(ddl)
```

## Notas

Funcion pura — solo manipula strings. Usa CREATE TABLE IF NOT EXISTS para ser idempotente. Las columnas id, created_at y updated_at siempre se generan. Si el CRUDResource es SoftDelete, se anade deleted_at TEXT nullable. El resultado se puede ejecutar directamente con db.Exec o envolver como migracion.
