Metadata-Version: 2.4
Name: loaddata
Version: 1.2.0
Summary: Incremental load to database
Author: gis4tech
Project-URL: Repository, https://github.com/gis4tech/loaddata
Description-Content-Type: text/markdown
Requires-Dist: pandas
Requires-Dist: SQLAlchemy
Requires-Dist: psycopg2-binary
Requires-Dist: python-dateutil
Requires-Dist: polars
Requires-Dist: PyYAML
Requires-Dist: pyarrow

# LoadData

Utilidad Python para cargar `pandas.DataFrame` en PostgreSQL con soporte para **cargas incrementales**, **TRUNCATE**, **PRIMARY KEY simples y compuestas**, generación de IDs reproducibles y reporting.

## Características

- PostgreSQL mediante SQLAlchemy + psycopg2.
- Configuración por argumentos o variables de entorno.
- Carga incremental.
- Soporte de **PRIMARY KEY real de PostgreSQL**.
- Soporte de **PRIMARY KEY compuesta**.
- Compatibilidad con `uid_cols` / `uid_need`.
- Carga completa mediante `TRUNCATE`.
- Creación automática de tablas inexistentes.
- Procesamiento opcional mediante Polars.
- Generación de rangos de fechas.
- Reporting estructurado por consola.

## Instalación

```bash
pip install pandas numpy polars sqlalchemy psycopg2-binary python-dateutil pyyaml
```

## Configuración

Puedes pasar las credenciales directamente:

```python
from tu_modulo import LoadData

loader = LoadData(
    usuario="usuario",
    password="password",
    database="database",
    port="5432",
    hostname="localhost",
)
```

O utilizar variables de entorno:

```bash
export USUARIO="usuario"
export PASSWORD="password"
export DATABASE="database"
export PORT="5432"
export HOSTNAME="localhost"
```

## Uso

### PRIMARY KEY simple

```python
loader.load_all_data(
    input_table=df,
    output_table="public.clientes",
    primary_key_cols=["cliente_id"],
)
```

### PRIMARY KEY compuesta

```python
loader.load_all_data(
    input_table=df,
    output_table="public.ventas",
    primary_key_cols=[
        "cliente_id",
        "producto_id",
        "fecha",
    ],
)
```

Esto permite utilizar una clave real de PostgreSQL equivalente a:

```sql
PRIMARY KEY (cliente_id, producto_id, fecha)
```

La carga incremental considera la combinación completa de esas columnas para determinar si un registro ya existe.

### Carga por TRUNCATE

```python
loader.load_all_data(
    input_table=df,
    output_table="public.ventas",
    primary_key_cols=["cliente_id", "fecha"],
    truncate=True,
)
```

### Compatibilidad con `unique_id`

Para generar una columna única en base a una lista de columnas del dataframe:

```python
loader.load_all_data(
    input_table=df,
    output_table="public.clientes",
    uid_cols=["cliente_id"],
)
```

También puedes utilizar una columna de ID ya existente:

```python
loader.load_all_data(
    input_table=df,
    output_table="public.clientes",
    uid_need="unique_id",
)
```

## `primary_key_cols` vs `uid_cols`

| Opción              | Uso                                                                           |
| -------------------- | ----------------------------------------------------------------------------- |
| `primary_key_cols` | **Recomendado** cuando existe una PK natural o compuesta en PostgreSQL. |
| `uid_cols`         | Compatibilidad con el sistema basado en`unique_id`.                         |
| `uid_need`         | Cuando el DataFrame ya contiene el identificador que se quiere utilizar.      |

Para una tabla cuya identidad sea `(cliente_id, fecha)`, se recomienda:

```python
primary_key_cols=["cliente_id", "fecha"]
```

en lugar de generar un `unique_id` adicional.

## Rangos de fechas

```python
start_date, end_date = loader.generar_rango_fechas(
    "2026-08-31",
    años_atras=2,
)
```

## Notas

- `output_table` debe tener formato `schema.table`.
- Para cargas incrementales debe existir una estrategia de identificación: `primary_key_cols`, `uid_cols` o `uid_need`.
