Saltar a contenido

1ª Demo

📓 DemoBase: Servidor Quack y conexión remota desde Jupyter

🔍 ¿Qué muestra esta demostración?

Demostración completa y funcional para un cuaderno de Jupyter que muestra el nuevo modo servidor de DuckDB 2.0 mediante el protocolo Quack y la sentencia CONNECT. La demo está pensada para ejecutarse celda a celda y utiliza dos conexiones independientes para simular el servidor y el cliente dentro del mismo cuaderno.

  1. CALL quack_serve(...): Convierte cualquier instancia de DuckDB en un servidor accesible por red.
  2. ATTACH ... (TOKEN ...): Establece la conexión segura al servidor Quack.
  3. CONNECT <alias>: Redirige la sesión SQL completa al servidor remoto, de modo que las consultas posteriores se ejecutan allí y los resultados se transmiten de vuelta.
  4. DISCONNECT: Devuelve la sesión a la base de datos local.

🛠️ Requisitos previos

Instalada la versión 2.0.0 (o superior) de DuckDB y el paquete jupyter:

pip install duckdb>=2.0.0

Celda 1: Importaciones y comprobación de versión

import duckdb
import threading
import time
import uuid

print(f"DuckDB versión: {duckdb.__version__}")
# Debe mostrar 2.0.0 o superior

Celda 2: Configuración del servidor Quack en un hilo separado

Para que el servidor no bloquee el cuaderno, lo lanzamos en un hilo en segundo plano. El servidor escuchará en localhost y usará un token de autenticación.

# Token de autenticación para el servidor
TOKEN = "duckdb_demo_token"
# Puerto por defecto de Quack
PORT = 9494

def run_quack_server():
    """Iniciar servidor Quack en un proceso/hilo independiente."""
    # Crear conexión dedicada para el servidor (en memoria)
    server_con = duckdb.connect()
    # La extensión quack se autoinstala y autocaraga en el primer uso
    server_con.execute(f"CALL quack_serve('quack:localhost:{PORT}', token = '{TOKEN}')")
    # Mantener el servidor vivo hasta que el programa termine
    # (En un cuaderno, el hilo se cerrará al reiniciar el kernel)
    while True:
        time.sleep(1)

# Lanzar servidor en modo demonio para que no bloquee
server_thread = threading.Thread(target=run_quack_server, daemon=True)
server_thread.start()

print(f"Servidor Quack iniciado en quack:localhost:{PORT} con token '{TOKEN}'")
# Un segundo para que el servidor se inicialice
time.sleep(1)

Celda 3: Conexión del cliente al servidor Quack

Ahora, desde una conexión cliente independiente, nos conectamos al servidor usando la sentencia ATTACH (con el token) y luego CONNECT para redirigir la sesión.

# Crear conexión cliente independiente
client_con = duckdb.connect()

# 1. Asociar servidor remoto usando el protocolo quack y el token
client_con.execute(f"""
    ATTACH 'quack:localhost:{PORT}' AS remote_qk (TOKEN '{TOKEN}');
""")

# 2. Redirigir sesión actual al servidor remoto
client_con.execute("CONNECT remote_qk;")

print("Cliente conectado al servidor Quack remoto.")

Celdas 4 y 5: Creación de datos en el servidor y consulta remota

Una vez conectados, cualquier sentencia SQL que ejecutemos se enviará al servidor y los resultados se transmitirán de vuelta.

Crear tabla e insertar datos (la ejecución ocurre en el servidor)

client_con.execute("""
    CREATE TABLE IF NOT EXISTS eventos (
        id INTEGER,
        nombre VARCHAR,
        valor DOUBLE
    );
    INSERT INTO eventos VALUES
        (1, 'clic', 10.5),
        (2, 'vista', 20.0),
        (3, 'clic', 7.2);
""")

Consultar datos remotos

resultado = client_con.execute("""
    SELECT nombre, SUM(valor) AS total
    FROM eventos
    GROUP BY nombre
    ORDER BY total DESC;
""").fetchall()

print("Resultados obtenidos desde el servidor:")
for fila in resultado:
    print(f"  {fila[0]}: {fila[1]}")

Celda 6: Desconexión y limpieza

Finalmente, nos desconectamos del servidor remoto y cerramos las conexiones.

# Desconectar
client_con.execute("DISCONNECT;")
print("Sesión desconectada del servidor remoto.")

# Cerramos las conexiones (el hilo del servidor se detendrá al reiniciar el kernel)
client_con.close()
# Nota: El servidor sigue escuchando en segundo plano hasta que se reinicie el kernel.

Conexión PostgreSQL/MySQL

Este ejemplo se puede modificar fácilmente para mostrar la conexión a PostgreSQL o MySQL usando CONNECT 'postgres://...', gracias al nuevo optimizador de pushdown remoto que envía las consultas al servidor en lugar de descargar las tablas completas.