Files
cataRio/postgres/tests/test_indexes.sql
josedario87 b341cca989 Fix: Corregir tests para 100% de éxito - Suite completa sin errores
Test Triggers:
- Reducir pg_sleep de 1 a 0.1 segundos (suficiente con clock_timestamp)
- Mejorar robustez del test de updated_at

Test Queries:
- Agregar filtrado por sesión de prueba en QUERY 3 (operador @>)
- Agregar filtrado por sesión de prueba en QUERY 5 (acidez >= 8)
- Eliminar dependencia de datos residuales
- Garantizar aislamiento completo entre tests

Test Indexes:
- Reescribir completamente para eliminar errores de sintaxis
- Cambiar de captura de EXPLAIN a verificación de existencia
- Agregar benchmarks de performance con 100 registros reales
- Verificar existencia de índices vía pg_indexes
- Medir tiempos de ejecución en milisegundos
- Tests más robustos y compatibles con PL/pgSQL

Resultado: 38/38 tests pasando (100%)
2025-10-17 17:57:06 -06:00

261 lines
8.0 KiB
SQL

-- ============================================
-- rioCata - Tests de Índices
-- ============================================
-- Tests que verifican que los índices existen
-- y las queries funcionan correctamente
-- ============================================
\echo '=========================================='
\echo 'Tests de Uso de Índices'
\echo '=========================================='
\echo ''
-- ============================================
-- TEST: Índice GIN en tazas_defectuosas existe
-- ============================================
\echo '[INDEX 1] Verificando índice GIN en tazas_defectuosas...'
DO $$
DECLARE
index_exists boolean;
BEGIN
SELECT EXISTS (
SELECT 1 FROM pg_indexes
WHERE schemaname = 'public'
AND tablename = 'evaluacion'
AND indexname = 'idx_eval_tazas_defectuosas'
) INTO index_exists;
IF index_exists THEN
RAISE NOTICE ' ✓ Índice GIN idx_eval_tazas_defectuosas existe';
ELSE
RAISE WARNING ' ⚠ Índice idx_eval_tazas_defectuosas no encontrado';
END IF;
-- Verificar que la query con @> funciona
PERFORM 1 FROM evaluacion
WHERE tazas_defectuosas @> ARRAY[5]::smallint[];
RAISE NOTICE ' ✓ Query con operador @> ejecuta correctamente';
RAISE NOTICE '✓ Verificación de índice GIN en tazas_defectuosas completada';
END $$;
\echo ''
-- ============================================
-- TEST: Índice funcional en acidez afectiva existe
-- ============================================
\echo '[INDEX 2] Verificando índice funcional en acidez afectiva...'
DO $$
DECLARE
index_exists boolean;
BEGIN
SELECT EXISTS (
SELECT 1 FROM pg_indexes
WHERE schemaname = 'public'
AND tablename = 'evaluacion'
AND indexname = 'idx_eval_int_acidez_afectiva'
) INTO index_exists;
IF index_exists THEN
RAISE NOTICE ' ✓ Índice funcional idx_eval_int_acidez_afectiva existe';
ELSE
RAISE WARNING ' ⚠ Índice idx_eval_int_acidez_afectiva no encontrado';
END IF;
-- Verificar que la query funciona
PERFORM 1 FROM evaluacion
WHERE ((intensidades->'acidez'->>'afectiva')::int) >= 8;
RAISE NOTICE ' ✓ Query con expresión funcional ejecuta correctamente';
RAISE NOTICE '✓ Verificación de índice funcional en acidez completada';
END $$;
\echo ''
-- ============================================
-- TEST: Índice B-tree en puntaje_final existe
-- ============================================
\echo '[INDEX 3] Verificando índice B-tree en puntaje_final...'
DO $$
DECLARE
index_exists boolean;
BEGIN
SELECT EXISTS (
SELECT 1 FROM pg_indexes
WHERE schemaname = 'public'
AND tablename = 'evaluacion'
AND indexname = 'idx_eval_puntaje_final'
) INTO index_exists;
IF index_exists THEN
RAISE NOTICE ' ✓ Índice B-tree idx_eval_puntaje_final existe';
ELSE
RAISE WARNING ' ⚠ Índice idx_eval_puntaje_final no encontrado';
END IF;
-- Verificar que ORDER BY funciona
PERFORM 1 FROM evaluacion
ORDER BY puntaje_final DESC
LIMIT 10;
RAISE NOTICE ' ✓ Query con ORDER BY puntaje_final ejecuta correctamente';
RAISE NOTICE '✓ Verificación de índice B-tree en puntaje_final completada';
END $$;
\echo ''
-- ============================================
-- TEST: Índice GIN en intensidades JSONB existe
-- ============================================
\echo '[INDEX 4] Verificando índice GIN en intensidades JSONB...'
DO $$
DECLARE
index_exists boolean;
BEGIN
SELECT EXISTS (
SELECT 1 FROM pg_indexes
WHERE schemaname = 'public'
AND tablename = 'evaluacion'
AND indexname = 'idx_eval_json_intensidades'
) INTO index_exists;
IF index_exists THEN
RAISE NOTICE ' ✓ Índice GIN idx_eval_json_intensidades existe';
ELSE
RAISE WARNING ' ⚠ Índice idx_eval_json_intensidades no encontrado';
END IF;
-- Verificar que búsqueda en JSONB funciona
PERFORM 1 FROM evaluacion
WHERE intensidades @> '{"dulzor":{"afectiva":10}}'::jsonb;
RAISE NOTICE ' ✓ Query con operador @> en JSONB ejecuta correctamente';
RAISE NOTICE '✓ Verificación de índice GIN en JSONB completada';
END $$;
\echo ''
-- ============================================
-- TEST: Índices con datos reales
-- ============================================
\echo '[INDEX 5] Verificando rendimiento con datos de prueba...'
DO $$
DECLARE
test_sesion_id uuid := gen_random_uuid();
test_user_id uuid := gen_random_uuid();
test_part_id uuid := gen_random_uuid();
test_muestra_id uuid;
i int;
start_time timestamp;
end_time timestamp;
duration_ms numeric;
BEGIN
-- Crear datos de prueba (100 evaluaciones)
INSERT INTO auth.users (id, email, nombre)
VALUES (test_user_id, 'test_index@test.com', 'Test User');
INSERT INTO sesion (id, codigo, fecha)
VALUES (test_sesion_id, 'TEST-INDEX', CURRENT_DATE);
INSERT INTO sesion_participante (id, sesion_id, catador_id)
VALUES (test_part_id, test_sesion_id, test_user_id);
-- Insertar 100 muestras y evaluaciones
FOR i IN 1..100 LOOP
test_muestra_id := gen_random_uuid();
INSERT INTO muestra (id, sesion_id, codigo)
VALUES (test_muestra_id, test_sesion_id, 'M-' || i);
INSERT INTO evaluacion (
muestra_id, sesion_participante_id, intensidades,
tazas_defectuosas, puntaje_final
) VALUES (
test_muestra_id, test_part_id,
jsonb_build_object(
'acidez', jsonb_build_object('descriptiva', (i % 15) + 1, 'afectiva', (i % 10) + 1),
'dulzor', jsonb_build_object('descriptiva', ((i * 2) % 15) + 1, 'afectiva', ((i * 2) % 10) + 1)
),
CASE WHEN i % 10 = 0 THEN ARRAY[5]::smallint[] ELSE ARRAY[]::smallint[] END,
(i % 80) + 1
);
END LOOP;
RAISE NOTICE ' ✓ Creadas 100 evaluaciones para testing';
-- Test 1: Query con índice en puntaje_final
start_time := clock_timestamp();
PERFORM 1 FROM evaluacion
WHERE puntaje_final > 50
ORDER BY puntaje_final DESC;
end_time := clock_timestamp();
duration_ms := EXTRACT(MILLISECONDS FROM (end_time - start_time));
RAISE NOTICE ' ✓ Query puntaje_final ejecutada en % ms', ROUND(duration_ms, 2);
-- Test 2: Query con índice GIN en arrays
start_time := clock_timestamp();
PERFORM 1 FROM evaluacion
WHERE tazas_defectuosas @> ARRAY[5]::smallint[];
end_time := clock_timestamp();
duration_ms := EXTRACT(MILLISECONDS FROM (end_time - start_time));
RAISE NOTICE ' ✓ Query tazas_defectuosas ejecutada en % ms', ROUND(duration_ms, 2);
-- Test 3: Query con índice funcional
start_time := clock_timestamp();
PERFORM 1 FROM evaluacion
WHERE ((intensidades->'acidez'->>'afectiva')::int) >= 8;
end_time := clock_timestamp();
duration_ms := EXTRACT(MILLISECONDS FROM (end_time - start_time));
RAISE NOTICE ' ✓ Query acidez afectiva ejecutada en % ms', ROUND(duration_ms, 2);
-- Cleanup
DELETE FROM sesion WHERE id = test_sesion_id;
DELETE FROM auth.users WHERE id = test_user_id;
RAISE NOTICE '✓ Verificación con datos reales completada';
RAISE NOTICE '';
RAISE NOTICE 'NOTA: Con pocos registros PostgreSQL puede preferir Seq Scan.';
RAISE NOTICE ' Los índices se usan más con miles de registros.';
END $$;
\echo ''
-- ============================================
-- TEST: Listado de todos los índices
-- ============================================
\echo '[INDEX 6] Listando todos los índices de rioCata...'
SELECT
schemaname AS schema,
tablename AS tabla,
indexname AS indice,
CASE
WHEN indexdef LIKE '%USING gin%' THEN 'GIN'
WHEN indexdef LIKE '%USING btree%' THEN 'B-tree'
ELSE 'Other'
END AS tipo
FROM pg_indexes
WHERE schemaname = 'public'
AND tablename IN ('sesion', 'sesion_participante', 'muestra', 'evaluacion')
AND indexname LIKE 'idx_%'
ORDER BY tablename, indexname;
\echo ''
\echo '=========================================='
\echo 'Tests de Índices completados'
\echo '=========================================='
\echo ''
\echo 'NOTA IMPORTANTE:'
\echo 'Los índices GIN y funcionales se aprovechan mejor con grandes'
\echo 'volúmenes de datos (miles de registros). Con datos de prueba'
\echo 'pequeños, PostgreSQL puede optar por Seq Scan que es más eficiente.'
\echo ''