| name | bigquery-overture-skill |
|---|---|
| description | Build and optionally execute cost-safe Overture Maps SQL through the BigQuery bq CLI, with mandatory dry-run cost checks and visualization handoff. Use when a user needs map-ready Overture Maps queries in BigQuery, wants SQL-only output or executed numeric results, and needs budget enforcement with clear over-budget fallback options. |
Use this skill for Overture Maps work in BigQuery with strict cost controls.
Never install software automatically. If dependencies are missing, report exact prerequisite commands for the user to run.
Use the bundled script for deterministic behavior:
./scripts/run_cost_checked_query.sh --query-file /path/to/query.sql --mode sql_onlyOr:
./scripts/run_cost_checked_query.sh --query "SELECT ..." --mode executeScript location:
scripts/run_cost_checked_query.sh
The script already handles:
- Optional
.envloading from current working directory BQ_PROJECT_IDfallback togcloud config get-value projectBQ_LOCATIONoptional passthroughBQ_MAX_BYTES_BILLEDsafe default10737418240(10 GiB)- Optional auth env support:
GOOGLE_APPLICATION_CREDENTIALS,BIGQUERY_CREDENTIALS_BASE64 - Mandatory dry run and bytes budget gate before execution
Collect or infer:
mode: infer from user intent (sql_onlyfor query drafting/verification,executewhen user asks for actual numbers/results)- User intent: dataset/theme, filters, output columns, aggregation, map vs numeric output
- Optional bounds: bbox, date/time, row limit
- Optional explicit over-budget override
Apply all guardrails every time:
- Run dry run before execution.
- Enforce
maximum_bytes_billed. - Prefer bounded SQL by default (bbox/date/limit, minimal selected columns).
- If estimated bytes exceed budget and no explicit override: do not execute.
- If over budget: provide lower-cost SQL variants.
- Select only required columns; avoid
SELECT *. - Prefer filtered Overture tables and partition-friendly predicates.
- Add default limits when user omitted bounds:
- Spatial bounding constraints for map requests
- Row cap (
LIMIT) for previews
- Separate heavy geometry retrieval from numeric aggregation when practical.
Use H3 when requested by the user, or when spatial aggregation/binning is needed (heatmaps, density summaries, cell-based rollups).
- Use
jslibs.h3.*(US convenience namespace) for US/default location queries. - Use
jslibs.eu_h3.*for EU location queries. jslibs.us_h3.*is equivalent to US behavior when explicit namespace is preferred.
- Point/cell index:
jslibs.h3.ST_H3(<geography_point>, <resolution>)- Polygon fill to cells:
jslibs.h3.ST_H3_POLYFILLFROMGEOG(<geography_polygon>, <resolution>)- Cell boundary for visualization:
jslibs.h3.ST_H3_BOUNDARY(<h3_index>)- Apply selective
WHERE+ hardcoded bbox first, then compute H3. - For aggregation queries, return
h3+ aggregate metrics before adding boundaries. - Use
COUNT(*)previews before geometry-heavyST_H3_BOUNDARYoutput. - Keep resolution reasonable by default (
7-9city scale) unless user requests otherwise. - If over budget, lower resolution or narrow bbox/date filters before retrying.
List Overture tables:
SELECT table_name
FROM `bigquery-public-data.overture_maps.INFORMATION_SCHEMA.TABLES`
ORDER BY table_name;List columns for one table:
SELECT
column_name,
data_type,
is_nullable,
ordinal_position
FROM `bigquery-public-data.overture_maps.INFORMATION_SCHEMA.COLUMNS`
WHERE table_name = 'division_area'
ORDER BY ordinal_position;Rules:
- Always start with selective
WHEREfilters. - Always include a hard-coded bbox prefilter on
bbox.xmin/xmax/ymin/ymaxfor large feature tables (for example,segment,building,place). This prevents full table scans by enabling partition pruning. - bbox does not replace real boundaries. When the user asks about a named area (city, district, country), always resolve its actual geometry from
division_areaand clip withST_INTERSECTS. bbox is only a fast pre-filter gate — it is rectangular and overshoots real boundaries. - Never omit
ST_INTERSECTSfor named-area queries. Always use bbox +ST_INTERSECTStogether: bbox gates the scan cost,ST_INTERSECTSensures geographic correctness. - Add
LIMITfor exploration. - Prefer aggregate previews (
COUNT(*)) before geometry-heavy pulls. - Avoid full table scans and large result sets.
Example (optimized rail query pattern):
WITH city AS (
SELECT geometry
FROM `bigquery-public-data.overture_maps.division_area`
WHERE country = 'DE'
AND region = 'DE-BE'
AND subtype = 'region'
AND class = 'land'
LIMIT 1
)
SELECT
s.id,
s.geometry
FROM `bigquery-public-data.overture_maps.segment` s
CROSS JOIN city c
WHERE s.subtype = 'rail'
-- hardcoded city bbox (Berlin in this example)
AND s.bbox.xmax >= 13.08834457397461
AND s.bbox.xmin <= 13.761162757873535
AND s.bbox.ymax >= 52.33823776245117
AND s.bbox.ymin <= 52.67551040649414
-- exact clip after bbox gate
AND ST_INTERSECTS(s.geometry, c.geometry)
LIMIT 1000;- Discover table and column metadata via
INFORMATION_SCHEMA. - Resolve the target area's actual geometry from
division_area. Extract its bbox numeric constants and hardcode them into the query as the scan gate. - Draft the query with bbox prefilter first (scan gate), then
ST_INTERSECTSagainst the real boundary geometry second (exact clip). Both are required for named-area queries. - Validate output shape and types with
LIMITorCOUNT(*). - Iterate in small steps; do not run broad/full extraction queries unless explicitly requested.
Decide mode automatically unless user explicitly requests one.
- Build optimized SQL
- Run mandatory dry run
- Return SQL + estimated bytes + budget pass/fail + visualization handoff
- Build optimized SQL
- Run mandatory dry run
- Execute only if user asked for results and estimate is within budget (or explicit user override)
- Return rows/aggregates preview + SQL + visualization handoff
If bq unavailable or auth fails:
- Return exact fix commands only (no auto-install/no auto-auth side effects).
If over budget:
- Keep
status=blocked_over_budget - Do not execute query
- Return at least one cheaper SQL variant
If query invalid:
- Return corrected SQL draft and rerun dry-run logic
Always return:
modestatus(dry_run_only | executed | blocked_over_budget)project_idlocationestimated_bytesmax_bytes_billedquery_sqlresult_preview(if executed)visualization_handoff(dekart,bigquery_studio)next_steps
Always include both handoffs:
dekart: open Dekart, connect to same project, pastequery_sql, map geometry fields.bigquery_studio: openhttps://console.cloud.google.com/bigquery?project=<PROJECT_ID>and pastequery_sqlin SQL workspace.
- Be explicit about budget pass/fail.
- Show the final SQL used for dry run.
- Keep previews concise.
- If blocked, include cheaper alternatives.