Saltar a contenido

Servidor Quack y conexi贸n remota en dos cuadernos Jupyter independientes

Demostraci贸n en dos cuadernos Jupyter independientes: uno dedicado exclusivamente al servidor y otro al cliente. Ambos se ejecutan en la misma m谩quina (todo local) y se comunican a trav茅s de localhost.

馃摀 Cuaderno 1: servidor_quack.ipynb

Inicia un servidor Quack en segundo plano. Debe permanecer ejecut谩ndose mientras se usa el cuaderno cliente.

Celda 1: Importaciones y configuraci贸n

import duckdb
import threading
import time

# --- Par谩metros del servidor (aj煤star si es necesario) ---
HOST = "localhost"
PORT = 9494
TOKEN = "demo_token_local_2026"  # M铆nimo 4 caracteres, seg煤n la documentaci贸n

print(f"DuckDB versi贸n: {duckdb.__version__}")

Celda 2: Funci贸n que inicializa el servidor

def iniciar_servidor_quack():
    """
    Crea una conexi贸n dedicada, instala/carga la extensi贸n quack
    y deja el servidor escuchando en localhost:PORT.
    """
    con = duckdb.connect()
    con.install_extension("quack")
    con.load_extension("quack")
    con.execute(f"""
        CALL quack_serve(
            'quack:{HOST}:{PORT}',
            token = '{TOKEN}',
            allow_other_hostname => false   -- solo localhost, como pediste
        );
    """)
    print(f"Servidor Quack escuchando en quack:{HOST}:{PORT}")
    # Mantenemos la conexi贸n viva (y con ella el servidor)
    while True:
        time.sleep(1)

Celda 3: Lanzar el servidor en un hilo background (daemon=True)

hilo_servidor = threading.Thread(target=iniciar_servidor_quack, daemon=True)
hilo_servidor.start()

# Damos un margen para que el servidor se inicialice
time.sleep(1)
print("Hilo del servidor iniciado. Pasar al cuaderno cliente.")

Celda 4 (opcional): Verificaci贸n r谩pida del servidor

Comprobar desde el propio cuaderno del servidor que quack_serve ha devuelto la informaci贸n esperada ejecutando esta consulta antes de lanzar el hilo (o en una conexi贸n aparte). Lo m谩s sencillo es confiar en el mensaje de la Celda 3 y pasar directamente al cliente.

Nota importante

El hilo es un proceso daemon por lo que el servidor se detendr谩 autom谩ticamente si se reinicia el kernel python. Por tanto, si se cierra el cuaderno sin reiniciar, el hilo podr铆a seguir vivo hasta que el proceso de Python termine.


馃摀 Cuaderno 2: cliente_quack.ipynb

Este cuaderno contiene dos apartados independientes:

  • Conexi贸n v铆a Quack
  • Conexi贸n a MariaDB/MySQL local

Ambas usan CONNECT, la nueva sentencia de DuckDB 2.0 que redirige la sesi贸n al motor remoto y aplica pushdown de consultas.

Celda 1: Importaciones y verificaci贸n

import duckdb
import pandas as pd

print(f"DuckDB versi贸n: {duckdb.__version__}")

馃敼 Caso A: Conexi贸n al servidor Quack local

Celda 2: Adjuntar y conectar al servidor Quack

con = duckdb.connect()

# 1) Instalar y cargar la extensi贸n quack en el cliente (si no est谩 ya)
con.install_extension("quack")
con.load_extension("quack")

# 2) Adjuntar el servidor remoto con el token acordado
con.execute(f"""
    ATTACH 'quack:localhost:9494' AS qk (TOKEN 'demo_token_local_2026');
""")

# 3) Redirigir la sesi贸n al servidor Quack
con.execute("CONNECT qk;")
print("Sesi贸n redirigida al servidor Quack")

Celda 3: Crear datos y consultar de forma remota

# Estas sentencias se ejecutan en el servidor
con.execute("""
    CREATE OR REPLACE TABLE ventas_quack (
        producto VARCHAR,
        unidades INTEGER,
        precio DOUBLE
    );
    INSERT INTO ventas_quack VALUES
        ('teclado', 10, 25.5),
        ('rat贸n', 15, 12.0),
        ('monitor', 5, 180.0);
""")

df_quack = con.execute("""
    SELECT producto, unidades * precio AS ingreso
    FROM ventas_quack
    ORDER BY ingreso DESC;
""").df()

print("Resultados obtenidos desde el servidor Quack:")
display(df_quack)

Celda 4: Desconectar y cerrar

con.execute("DISCONNECT;")
con.close()
print("Cliente Quack desconectado.")

馃敼 Caso B: Conexi贸n a servidor MariaDB/MySQL (local)

Celda 5: Instalar extensi贸n y conectar a MySQL/MariaDB

con_mysql = duckdb.connect()

# Instalar y cargar la extensi贸n mysql (soporta MySQL y MariaDB)
con_mysql.install_extension("mysql")
con_mysql.load_extension("mysql")

# Usar CONNECT directamente con una cadena de conexi贸n.
# La cadena debe empezar por "mysql:" y usar formato key=value (estilo PostgreSQL),
# NO aplica el formato DSN "mysql://usuario:clave@host/db".
con_mysql.execute("""
    CONNECT 'mysql:host=localhost user=eurostar password=eurostar database=eurostar';
""")

print("Sesi贸n redirigida al servidor MySQL/MariaDB")

Consulta SQL

con_mysql.execute("""
    select StopCode, StopName, StopLat, StopLng from eurostar.Stations where Country like 'F';
""")

Mostrar resultados

output = con_mysql.fetchall() 

for i in output: 
    print(i) 

Alternativa con ATTACH + CONNECT

Es posible separar los pasos:

con_mysql.execute("""
    ATTACH 'host=localhost user=eurostar password=eurostar database=eurostar'
    AS mysql_local (TYPE mysql_scanner);
""")
con_mysql.execute("CONNECT mysql_local;")

Celda 6: Resultado en un dataframe Pandas

# Esta consulta se ejecuta directamente en el servidor MySQL/MariaDB
# gracias al optimizador de pushdown remoto de DuckDB 2.0
df_mysql = con_mysql.execute("""
    SELECT table_name, table_rows
    FROM information_schema.tables
    WHERE table_schema = 'eurostar'
    ORDER BY table_name;
""").df()

print("Tablas en la base de datos MySQL/MariaDB local:")
display(df_mysql)

Celda 7: Desconectar

con_mysql.execute("DISCONNECT;")
con_mysql.close()
print("Cliente MySQL/MariaDB desconectado.")

馃Л Resumen de cada cuaderno

Cuaderno Funcionalidad Sentencias clave
Servidor Arrancar un endpoint Quack local CALL quack_serve(...)
Cliente A) Conectarse a un DuckDB remoto ATTACH ... (TOKEN ...); CONNECT qk;
Cliente B) Conectarse a MariaDB/MySQL CONNECT 'mysql:host=... user=... database=...' o ATTACH ... (TYPE mysql_scanner); CONNECT ...
Ambas demos usan exclusivamente localhost y no exponen ning煤n servicio a la red externa. Para ajustar el puerto, el token o las credenciales de MySQL, basta con modificar las variables al inicio de cada cuaderno.