$value) { $tmp = $value; oci_bind_by_name($stmt, ':' . ($key + 1), $tmp); } } $resultado = oci_execute($stmt); if (!$resultado) { $e = oci_error($stmt); oci_free_statement($stmt); throw new Exception("Error Oracle: " . $e['message'] . " | SQL: " . $sql); } return $stmt; } /** * Obtiene la siguiente fila como array asociativo y cierra el statement si no hay más * @param resource $stmt Statement de Oracle * @return array|false Array asociativo o false si no hay más filas */ function db_fetch_assoc($stmt) { $row = oci_fetch_assoc($stmt); if ($row === false) { oci_free_statement($stmt); // ✅ Cierre automático al terminar } return $row; } /** * Obtiene la siguiente fila como array numérico y cierra el statement si no hay más * @param resource $stmt Statement de Oracle * @return array|false Array numérico o false si no hay más filas */ function db_fetch_row($stmt) { $row = oci_fetch_array($stmt, OCI_NUM); if ($row === false) { oci_free_statement($stmt); // ✅ Cierre automático al terminar } return $row; } /** * Obtiene todas las filas como array de arrays asociativos y cierra el statement * @param resource $stmt Statement de Oracle * @return array Array con todas las filas */ function db_fetch_all($stmt) { $rows = []; oci_fetch_all($stmt, $rows, 0, -1, OCI_FETCHSTATEMENT_BY_ROW); oci_free_statement($stmt); // ✅ Cierre inmediato return $rows; } /** * Cuenta el número de filas (útil después de un SELECT COUNT(*)) * @param resource $stmt Statement de Oracle * @return int Número de filas */ function db_num_rows($stmt) { return oci_num_rows($stmt); } /** * Escapa un string (compatibilidad con MySQLi, no necesario en Oracle) * @param string $str String a escapar * @return string El mismo string sin cambios */ function db_escape($str) { return $str; } /** * Ejecuta una consulta simple sin parámetros y retorna el statement * @param string $sql Consulta SQL * @return resource Statement de Oracle * @throws Exception */ function db_query_simple($sql) { global $conn; $stmt = oci_parse($conn, $sql); if (!$stmt) { $e = oci_error($conn); throw new Exception("Error oci_parse: " . ($e['message'] ?? 'Error desconocido')); } $resultado = oci_execute($stmt); if (!$resultado) { $e = oci_error($stmt); oci_free_statement($stmt); throw new Exception("Error en consulta SQL: " . $e['message'] . " | SQL: " . $sql); } return $stmt; } /** * Ejecuta una consulta con parámetros y retorna el statement (alias de db_query) * @param string $sql Consulta SQL con placeholders :1, :2, etc. * @param array $params Parámetros para la consulta * @return resource Statement de Oracle */ function db_query_prepared($sql, $params = []) { return db_query($sql, $params); } /** * Inicia una transacción */ function db_begin_transaction() { global $conn; // Oracle inicia transacción automáticamente con la primera operación // Esta función es solo por compatibilidad } /** * Confirma una transacción */ function db_commit() { global $conn; oci_commit($conn); } /** * Revierte una transacción */ function db_rollback() { global $conn; oci_rollback($conn); } /** * Obtiene el último ID insertado usando una secuencia * @param string $sequence_name Nombre de la secuencia (ej: 'mi_tabla_seq') * @return int|null Último ID o null si no existe */ function db_last_insert_id($sequence_name) { global $conn; $sequence_name = preg_replace('/[^A-Z0-9_]/i', '', $sequence_name); $stmt = oci_parse($conn, "SELECT {$sequence_name}.CURRVAL FROM DUAL"); $resultado = oci_execute($stmt); if (!$resultado) { return null; } $row = oci_fetch_array($stmt, OCI_NUM); oci_free_statement($stmt); return $row[0] ?? null; } /** * Ejecuta un SELECT en Oracle y retorna resultados como array (con cierre automático) * * @param resource $con Conexión OCI (oci_connect / oci_pconnect) * @param string $sql Query SQL (con binds :nombre) * @param array $binds Binds asociativos: [':p1' => $val] o ['p1' => $val] * @param bool $close true = cierra conexión al final * @param int $execMode OCI_NO_AUTO_COMMIT o OCI_COMMIT_ON_SUCCESS * @return array * @throws Exception */ function oracleSelectToArray($con, string $sql, array $binds = [], bool $close = true, int $execMode = OCI_NO_AUTO_COMMIT): array { if (!$con) { throw new Exception("Conexión Oracle inválida."); } $stmt = oci_parse($con, $sql); if (!$stmt) { $e = oci_error($con); throw new Exception("oci_parse error: " . ($e['message'] ?? 'Error desconocido')); } // Binds automáticos $bindVars = []; foreach ($binds as $key => $value) { $param = (strpos((string)$key, ':') === 0) ? (string)$key : ':' . (string)$key; $bindVars[$param] = $value; oci_bind_by_name($stmt, $param, $bindVars[$param], -1); } $ok = oci_execute($stmt, $execMode); if (!$ok) { $e = oci_error($stmt); oci_free_statement($stmt); if ($close) @oci_close($con); throw new Exception("oci_execute error: " . ($e['message'] ?? 'Error desconocido') . " | SQL: " . $sql); } $rows = []; while (($row = oci_fetch_assoc($stmt)) !== false) { $rows[] = $row; } oci_free_statement($stmt); // ✅ Cierre automático del statement if ($close) { @oci_close($con); } return $rows; } /** * Versión simplificada de oracleSelectToArray que usa la conexión global * @param string $sql Consulta SQL con binds :nombre * @param array $binds Parámetros * @return array Resultados */ function db_select_to_array($sql, $binds = []) { global $conn; return oracleSelectToArray($conn, $sql, $binds, false); } ?>