
## Llamar procedimientos almacenados

Debido a que la clase DB es agnóstica (conecta con diferentes motores de DB) el mecanismo de llamado de los SP es el mismo indistintamente del motor de base de datos, pero para eso se necesita hacer unas concesiones.

PostgreSQL usa cursores para devolver resultsets, pudiendo devolver varios sets de datos en una misma llamada

la forma de llamar a un SP es la siguiente:

### Automatic transaction:

Las siguientes llamadas generan un contexto transaccional para cada llamada individual que hace commit o rollback de forma automática:

```php
$exec = app()->dbLink->callProcedure([
    'name' => 'sp_obt_periodo_empresa',
    'params' => [
        $id_empresa
    ],
    'cursors' => [
        'cursor_periodo'
    ]
]);
```
El SP anterior devuelve datos en un cursor llamado 'cursor_periodo'

```php
app()->dbLink->callProcedure([
    'name' => 'sp_bor_periodo_empresa',
    'params' => [
        $id,
        $id_empresa
    ],
    'cursors' => [],
]);
```
El SP anterior no devuelve datos, por lo que el item cursor va vacío (se puede omitir)

```php
$exec = app()->dbLink->callProcedure([
    'name' => 'sp_some_name',
    'params' => [
        $args['some_param_1'],
        $args['some_param_2'],
        $args['some_param_3'],
    ],
    'cursors' => [
        'cursor_1', 'cursor_2', 'cursor_3'
    ]
]);
```
El SP retorna 3 sets de datos en un array, bajo los indices de los nombres de cada cursor

### Transaction aware:

Es posible hacer múltiples llamadas a procedimientos, como por ejemplo dentro de una iteración, y mantenerlas en el contexto de una transacción:

```php
app()->dbLink->tryTransaction();

$exec = app()->dbLink->callProcedure([
    'name' => 'sp_that_selects_some_data',
    'params' => [
        $args['some_param_1'],
        $args['some_param_2'],
        $args['some_param_3'],
    ],
    'cursors' => [
        'cursor_1', 'cursor_2', 'cursor_3'
    ]
]);

app()->dbLink->callProcedure([
    'name' => 'sp_that_updates_some_data',
    'params' => [
        $args['some_param_1'],
        $args['some_param_2'],
        $args['some_param_3'],
    ],
    'cursors' => [],
]);

app()->dbLink->callProcedure([
    'name' => 'sp_that_deletes_some_data',
    'params' => [
        $args['some_param_1'],
        $args['some_param_2'],
        $args['some_param_3'],
    ],
    'cursors' => [],
]);

app()->dbLink->endTransaction();

```


## Eliminar procedimientos con mismo nombre pero diferente firma:
```sql
SELECT 
    p.proname AS sp,
    pg_get_function_identity_arguments(p.oid) AS firma
FROM pg_proc p
JOIN pg_namespace n ON n.oid = p.pronamespace
WHERE n.nspname = 'public'
AND p.proname = 'sp_act_periodo_empresa';
```

El resultado de la consulta obtiene las firmas TAL CUAL deben ser usadas para eliminar el procedimiento deseado

obtenido los datos, usar la columna firma como la firma a buscar para eliminar:
```sql
drop procedure sp_act_periodo_empresa(  IN p_id integer, IN p_activo character varying);

drop procedure sp_act_periodo_empresa(  IN p_id integer, IN p_id_empresa integer, IN p_periodo integer, IN p_activo character varying);
```

