Saltar a contenido

07 · Quack cliente-servidor

Cuadernos asociados

cuadernos/06_quack_servidor.ipynb (déjalo ejecutándose) y cuadernos/07_quack_cliente.ipynb. Volver al 00 - Índice de la demo.

La idea

Imaginar una máquina con 400 GB de Parquet junto al lago de datos (Data Lake) y nuestro portátil con 16 GB 😳😳. En tales circunstacias, mover los datos es absurdo: mejor mover el cómputo.

sequenceDiagram
    autonumber
    participant CLI as Cuaderno cliente
    participant SRV as Servidor Quack
    participant FS as Parquet / S3

    Note over SRV: CALL quack_serve('quack:localhost:9494', token='...')
    CLI->>SRV: ATTACH 'quack:localhost:9494' AS qk (TOKEN '...')
    CLI->>SRV: CONNECT qk
    CLI->>SRV: SELECT producto, sum(importe) GROUP BY ALL
    SRV->>FS: Lee y agrega EN LOCAL
    FS-->>SRV: Páginas Parquet
    SRV-->>CLI: Solo el resultado agregado
    CLI->>SRV: DISCONNECT

Quack es HTTP puro (puerto por defecto 9494), serialización binaria nativa de DuckDB y una petición-respuesta por consulta. No hay protocolo exótico que abrir en el firewall.

Lado servidor

INSTALL quack;
LOAD quack;

CALL quack_serve('quack:localhost:9494', token = 'demo_token_local_2026');

Devuelve tres valores útiles:

('quack:localhost:9494', 'http://localhost:9494', 'demo_token_local_2026')
  • 1º URI lógica
  • 2º URL HTTP real
  • 3º token efectivo (si no lo pasas, lo genera).

Detalles que importan:

Parámetro Efecto
Sin URI Escucha en quack:localhost (9494)
allow_other_hostname = true Permite bind a una IP no local (quack:0.0.0.0:9494)
ssl_cert_file / ssl_key_file TLS propio; si no, certificado autofirmado
CALL quack_stop('quack:localhost:9494') Detiene el servidor

Desde la CLI, sin escribir SQL

duckdb -serve quack:localhost:9494 levanta el servidor y duckdb -connect quack:localhost:9494 se conecta.

Lado cliente

INSTALL quack;
LOAD quack;

ATTACH 'quack:localhost:9494' AS qk (TOKEN 'demo_token_local_2026');
CONNECT qk;

SELECT producto, unidades * precio AS ingreso
FROM ventas
ORDER BY ingreso DESC;

Sin CONNECT también funciona, pero cualificando el catálogo:

SELECT count(*) FROM qk.ventas;

Las tres formas de hablar con un servidor

Forma Sintaxis Cuándo
Sesión redirigida ATTACH + CONNECT qk Lo recomendado: escribes SQL sin prefijos
Catálogo remoto SELECT * FROM qk.tabla Cuando necesitas mezclar local y remoto
Consulta sin estado FROM quack_query('quack:host', 'SELECT 42', token='...') Scripts sueltos, sin ATTACH

⚠️ Tres trampas que el cuaderno demuestra en vivo

1 · Dentro de CONNECT, con.sql() no funciona

InvalidInputException: materialize() is not available while CONNECT-ed; DISCONNECT first. Mientras la sesión está redirigida, usa con.execute(q).fetchall() / .fetchdf() / .df(). Las relaciones (.sql()) se materializan en el cliente y no están permitidas.

2 · Lo que creas dentro de CONNECT es efímero

Una CREATE TABLE ejecutada dentro de la sesión redirigida no persiste en el servidor: desaparece al hacer DISCONNECT y no aparece en el catálogo qk.. Verificado en el taller. Para escrituras que duren, cualifica el catálogo: CREATE TABLE qk.resumen AS ....

3 · CONNECT sin ATTACH previo no adivina el destino

CONNECT acepta un alias ya adjuntado o una cadena de conexión con esquema (mysql:, postgres:). Para Quack, el camino es siempre ATTACH ... AS alias y luego CONNECT alias.

Comprobar que el trabajo ocurre en remoto

EXPLAIN SELECT producto FROM qk.ventas WHERE unidades > 6;

Aparece un operador propio (Projection):

╭─ Quack Query By Name ────────╮
│ Server: quack:localhost:9494 │
│ Projections: producto        │
│ ~1 row                       │
╰──────────────────────────────╯

Si el plan muestra Quack Query By Name, el filtro y la proyección viajaron al servidor. Si muestra un SCAN de tabla completa, el pushdown no ocurrió.

Identidad del nodo

FROM whoami();

Devuelve name, provider, hostname, region, uptime, ts_now y un meta JSON con versión y plataforma. Útil cuando hay varios servidores detrás de un proxy. Se rellena con CALL quack_identify(...).

Estado del protocolo

Quack es beta

DuckDB 2.0 es LTS, pero el protocolo Quack sigue marcado como beta: nombres de función, parámetros y valores por defecto pueden cambiar. Y no convierte DuckDB en un motor distribuido: varios clientes no forman un clúster que reparta una consulta entre máquinas.

Ejercicios

  1. Levanta el servidor en 9494, conéctate desde otro cuaderno y cuenta las filas de una tabla remota.
  2. Demuestra que con.sql() falla con CONNECT activo y escribe la alternativa.
  3. Crea qk.auditoria (cualificada) y comprueba que sobrevive al DISCONNECT; crea otra sin cualificar y comprueba que no.
  4. Cambia el puerto a 9600 y el token, y repite la conexión.
  5. Interpreta el EXPLAIN de una consulta remota: ¿qué operador indica pushdown?

Soluciones en cuadernos/99_soluciones.ipynb.