-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path3_migrar_postgres.py
More file actions
129 lines (109 loc) · 6.35 KB
/
Copy path3_migrar_postgres.py
File metadata and controls
129 lines (109 loc) · 6.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import subprocess
import json
import os
os.chdir(os.path.dirname(os.path.abspath(__file__)))
CONTAINER = "escuela_postgres"
USER = "user"
DB = "escuela_db"
def psql(sql):
"""Ejecuta SQL dentro del contenedor PostgreSQL y retorna el valor de la primera celda."""
result = subprocess.run(
["docker", "exec", "-i", CONTAINER, "psql", "-U", USER, "-d", DB, "-t", "-A", "-c", sql],
capture_output=True, text=True, encoding="utf-8"
)
return result.stdout.strip(), result.stderr.strip()
def psql_file(filepath):
"""Ejecuta un archivo SQL dentro del contenedor."""
with open(filepath, "r", encoding="utf-8") as f:
sql_content = f.read()
result = subprocess.run(
["docker", "exec", "-i", CONTAINER, "psql", "-U", USER, "-d", DB],
input=sql_content,
capture_output=True, text=True, encoding="utf-8"
)
return result.stdout, result.stderr
# ─── Paso 1: Verificar conexion ───────────────────────────────────────────────
print("[1/5] Verificando conexion con PostgreSQL en Docker...")
out, err = psql("SELECT version();")
if err and "error" in err.lower():
print(f" ERROR: {err}")
print(" Verifica que Docker esta corriendo: docker compose up -d")
exit(1)
print(f" OK - PostgreSQL responde correctamente")
# ─── Paso 2: Ejecutar DDL ─────────────────────────────────────────────────────
print("[2/5] Ejecutando script_bd.sql (tablas, vistas, funciones, triggers)...")
if not os.path.exists("script_bd.sql"):
print(" ERROR: No se encuentra script_bd.sql")
exit(1)
out, err = psql_file("script_bd.sql")
warns = [l for l in err.splitlines() if l.strip() and "already exists" not in l.lower() and "notice" not in l.lower()]
if warns:
for w in warns[:3]:
print(f" WARN: {w}")
print(" OK - script_bd.sql ejecutado")
# ─── Paso 3: Insertar datos ───────────────────────────────────────────────────
print("[3/5] Insertando datos desde datos_limpios.json...")
if not os.path.exists("datos_limpios.json"):
print(" ERROR: No se encuentra datos_limpios.json")
print(" Ejecuta primero: python 1_limpiar_datos.py")
exit(1)
with open("datos_limpios.json", "r", encoding="utf-8") as f:
datos = json.load(f)
# Construir SQL de insercion
inserts = []
for n in datos["niveles"]:
inserts.append(f"INSERT INTO niveles (id_nivel,nombre_nivel) VALUES ({n['id_nivel']},'{n['nombre_nivel']}') ON CONFLICT DO NOTHING;")
for d in datos["docentes"]:
nombres = d['nombres'].replace("'","''")
p_ap = d['primer_apellido'].replace("'","''")
s_ap = d['segundo_apellido'].replace("'","''")
prof = d['profesion'].replace("'","''")
edad = d.get('edad', None)
edad_val = str(int(edad)) if edad is not None else 'NULL'
inserts.append(f"INSERT INTO docentes (id_docente,nombres,primer_apellido,segundo_apellido,profesion,edad) VALUES ({d['id_docente']},'{nombres}','{p_ap}','{s_ap}','{prof}',{edad_val}) ON CONFLICT DO NOTHING;")
for m in datos["materias"]:
nombre_m = m['nombre_materia'].replace("'","''")
inserts.append(f"INSERT INTO materias VALUES ('{m['id_materia']}','{nombre_m}') ON CONFLICT DO NOTHING;")
for mn in datos["materia_nivel"]:
inserts.append(f"INSERT INTO materia_nivel VALUES ('{mn['id_materia']}',{int(mn['id_nivel'])}) ON CONFLICT DO NOTHING;")
for e in datos["estudiantes"]:
p_nom = e['primer_nombre'].replace("'","''")
p_ap = e['primer_apellido'].replace("'","''")
s_ap = e['segundo_apellido'].replace("'","''")
fecha = e['fecha_nacimiento'] if e['fecha_nacimiento'] else 'NULL'
fecha_val = f"'{fecha}'" if fecha != 'NULL' else 'NULL'
inserts.append(f"INSERT INTO estudiantes VALUES ({e['id_estudiante']},'{p_nom}','{p_ap}','{s_ap}','{e['genero']}',{fecha_val},{int(e['id_nivel'])}) ON CONFLICT DO NOTHING;")
for a in datos["asignaciones"]:
inserts.append(f"INSERT INTO asignaciones (id_asignacion,id_materia,id_docente,id_nivel) VALUES ({a['id_asignacion']},'{a['id_materia']}',{int(a['id_docente'])},{int(a['id_nivel'])}) ON CONFLICT DO NOTHING;")
sql_inserts = "\n".join(inserts)
result = subprocess.run(
["docker", "exec", "-i", CONTAINER, "psql", "-U", USER, "-d", DB],
input=sql_inserts,
capture_output=True, text=True, encoding="utf-8"
)
if result.returncode != 0:
print(f" ERROR insertando: {result.stderr[:200]}")
exit(1)
print(" OK - Datos insertados correctamente")
# ─── Paso 4: Verificar vistas y funciones ─────────────────────────────────────
print("[4/5] Verificando vistas y funciones...")
out, _ = psql("SELECT COUNT(*) FROM vista_carga_docentes;")
print(f" vista_carga_docentes: {out} registros")
out, _ = psql("SELECT COUNT(*) FROM vista_estudiantes_por_nivel;")
print(f" vista_estudiantes_por_nivel: {out} registros")
out, _ = psql("SELECT fn_edad_promedio_docentes();")
print(f" fn_edad_promedio_docentes(): {out} anios promedio")
out, _ = psql("SELECT fn_materias_por_estudiante(1001);")
print(f" fn_materias_por_estudiante(1001): {out} materias")
# ─── Paso 5: Probar trigger ───────────────────────────────────────────────────
print("[5/5] Probando trigger de auditoria...")
psql("UPDATE estudiantes SET id_nivel = 2 WHERE id_estudiante = 1001;")
out, _ = psql("SELECT COUNT(*) FROM auditoria_nivel WHERE id_estudiante = 1001;")
print(f" Registros de auditoria generados: {out} OK")
psql("UPDATE estudiantes SET id_nivel = 1 WHERE id_estudiante = 1001;")
# ─── Conteos finales ──────────────────────────────────────────────────────────
print("\n--- CONTEOS FINALES EN POSTGRESQL ---")
for t in ["niveles","docentes","materias","materia_nivel","estudiantes","asignaciones","auditoria_nivel"]:
out, _ = psql(f"SELECT COUNT(*) FROM {t};")
print(f" {t:<22} {out} registros")
print("\n[OK] Migracion a PostgreSQL completada exitosamente!")