Sources son el paso uno de la confiabilidad del contenido
Los models dependen de aliases de source. Si el alias, el filename de credentials o la referencia al dataset están mal, cada model, query y visualization construida arriba falla. Configurá y validá runtime/sources.runtime.yml antes de escribir un solo model.
Si todavía no creaste tu service account de GCP, hacé eso primero. Mirá Acceso al Dataset de BigQuery.
Working example: dataset público de BigQuery
Working example usando el dataset público bigquery-public-data.thelook_ecommerce. Copialo como tu punto de partida; reemplazá project_id con tu propio billing project de GCP y credentials_file con el nombre del archivo JSON de tu service account (el archivo que dropeás en secrets/). El dataset es público, así que cualquiera con un service account de BigQuery funcionando lo puede consultar.
sources:
ecommerce:
name: The Look Ecommerce
type: bigquery
project_id: my-gcp-billing-project
credentials_file: my-workspace-bq.json
datasets:
- bigquery-public-data.thelook_ecommerce
Campo por campo:
ecommerce: el alias que van a usar tus models de Malloy. Elegí algo corto y estable — cambiarlo después rompe cada model que lo referencia.project_id: el proyecto de GCP que paga el costo de las queries. Este es tu billing project, no necesariamente donde viven los datos.credentials_file: filename plano del JSON de service-account dropeado en la carpetasecrets/del workspace. Pattern^[A-Za-z0-9_-][A-Za-z0-9._-]*$— sin separadores de path, sin punto inicial.datasets: las ubicaciones de dataset que el runtime puede consultar. Acá los datos están enbigquery-public-data, un proyecto distinto al billing — eso es normal y esperado.
Working example: tu propio dataset privado
Cuando los datos viven en tu propio proyecto de GCP, project_id y el proyecto del dataset son el mismo:
sources:
sales:
name: Sales Data
type: bigquery
project_id: my-company-gcp-project
credentials_file: my-workspace-bq.json
datasets:
- my-company-gcp-project.sales_warehouse
Podés definir múltiples sources en el mismo archivo:
sources:
sales:
name: Sales Data
type: bigquery
project_id: my-company-gcp-project
credentials_file: my-workspace-bq.json
datasets:
- my-company-gcp-project.sales_warehouse
marketing:
name: Marketing Data
type: bigquery
project_id: my-company-gcp-project
credentials_file: my-workspace-bq.json
datasets:
- my-company-gcp-project.marketing_events
Cada alias se vuelve referenciable de forma independiente en los models.
Working example: Postgres source
Los sources de Postgres separan coordenadas de red y credenciales: el dsn es una URI estándar de libpq (host, port, database, flags TLS o de pool) sin el user:password@; el user y password viven en un JSON dentro de secrets/ referenciado por credentials_file. La plataforma lee los dos, inyecta las credenciales en el DSN en memoria y lo pasa al driver de Postgres. runtime/sources.runtime.yml nunca contiene una password.
sources:
warehouse:
name: Internal Warehouse
type: postgres
dsn: "postgresql://pg.internal.example.com:5432/warehouse?sslmode=require"
credentials_file: warehouse.json
schemas:
- reporting
- public
Dropeá el JSON correspondiente en secrets/warehouse.json:
{
"user": "looky_reader",
"password": "..."
}
Campo por campo:
type: tiene que serpostgres.name: label humano opcional que se muestra en la UI cuando el source aparece en herramientas de operator. Puramente cosmético.dsn: URI libpq sin userinfo. Tiene que empezar conpostgres://opostgresql://; el regex del schema rechaza cualquier URI que contenga@(es decir,user:password@). Cualquier parámetro de query-string libpq —sslmode,application_name,connect_timeout,target_session_attrs,channel_binding,gssencmode, … — pasa intacto.credentials_file: filename plano de un JSON adentro de la carpetasecrets/del workspace. Pattern^[A-Za-z0-9_-][A-Za-z0-9._-]*$— sin separadores de path, sin punto inicial. El JSON tiene que declarar{"user": "…", "password": "…"}.schemas: array opcional que limita la introspección. Default a todos los schemas no-sistema (pg_catalogeinformation_schemaquedan siempre excluidos).
Working example: MySQL source
Los sources de MySQL siguen la misma separación que Postgres: el dsn es una URI mysql://host:port/database sin el user:password@, y el user y password viven en un JSON dentro de secrets/ referenciado por credentials_file. A diferencia de Postgres, un DSN de MySQL no lleva parámetros de query — Looky parsea el host, port y database de la URI y rechaza cualquier ?…. runtime/sources.runtime.yml nunca contiene una password.
sources:
shop:
name: Online Shop
type: mysql
dsn: "mysql://db.internal.example.com:3306/shop"
credentials_file: shop.json
schemas:
- shop
Dropeá el JSON correspondiente en secrets/shop.json:
{
"user": "looky_reader",
"password": "..."
}
Campo por campo:
type: tiene que sermysql.name: label humano opcional que se muestra en la UI cuando el source aparece en herramientas de operator. Puramente cosmético.dsn: URImysql://host:port/databasesin userinfo. El regex del schema rechaza cualquier URI que contenga@(es decir,user:password@) o un query string con?. El port es opcional y default a3306.credentials_file: filename plano de un JSON adentro de la carpetasecrets/del workspace. Pattern^[A-Za-z0-9_-][A-Za-z0-9._-]*$— sin separadores de path, sin punto inicial. El JSON tiene que declarar{"user": "…", "password": "…"}.schemas: array opcional de databases a exponer para introspección. Default a la database nombrada en eldsn.
Dos cosas específicas de MySQL que conviene saber: las conexiones no van encriptadas (todavía no se puede configurar TLS hacia MySQL), así que usalo sobre una red de confianza; y MySQL no tiene un tipo boolean real, así que las columnas que parecen boolean vuelven como números — agregá un cast(… as boolean) explícito en tu model cuando necesites un filtro true/false.
Matriz de campos por adapter
Referencia rápida de qué requiere cada adapter:
- BigQuery — requeridos:
type: bigquery,project_id,credentials_file; opcionales:location,datasets(requeridos en tiempo de introspección, no en tiempo de validation). - Postgres — requeridos:
type: postgres,dsn(URI libpq sin userinfo),credentials_file(filename de un JSON ensecrets/con{"user","password"}); opcionales:schemas. - MySQL — requeridos:
type: mysql,dsn(mysql://host:port/database, sin userinfo, sin query string),credentials_file(filename de un JSON ensecrets/con{"user","password"}); opcionales:schemas(default a la database del DSN).
Para la matriz de divergencias completa por adapter (auth, binding de parámetros, manejo de NULL, dryRun, introspección, caching), mirá la comparación de adapters de source.
Workflow de validación de sources
- Editá
runtime/sources.runtime.ymldesde el root de tu workspace. - Corré:
looky sources list looky sources diff looky validate - Arreglá errores de alias, credentials o dataset antes de tocar models.
sources list muestra los aliases de runtime actualmente registrados. sources diff muestra qué cambiaría en el push. validate chequea consistencia estructural sobre todo el workspace.
Errores comunes en sources
- Alias mismatch: el model referencia
salespero el runtime defineecommerce. Cada query usando ese alias falla. - Filename de credentials equivocado:
credentials_filetiene que ser un filename plano dentro desecrets/— sin slashes, sin path prefix. - Dataset fuera de la lista: si un model consulta una tabla cuyo dataset no está listado en
datasets:, la query se rechaza en runtime. - Billing project equivocado: si
project_idno tiene BigQuery Job User otorgado al service account, las queries fallan incluso si los datos son legibles.
Nunca hagas workaround de problemas de source dentro del model. Arreglá el alias y el runtime config una vez, y mantené los models limpios.