| name | coding-with-query-engine | ||||
|---|---|---|---|---|---|
| description | Build and troubleshoot Mu2e Query Engine (QE) URL reads for PostgreSQL-backed conditions and operations data. Use when composing QE URLs, doing Python HTTP reads, or implementing C++ database fetches with Offline DbService DbReader/DbId helpers. | ||||
| compatibility | Requires Mu2e Offline environment, network access to FNAL QE endpoints, and familiarity with Offline/DbService and conditions table naming | ||||
| metadata |
|
Use this skill for Mu2e code that reads PostgreSQL table data through Fermilab Query Engine (QE) over HTTP.
Primary usage modes:
- Build QE query URLs and validate query semantics
- Read data in Python via HTTP GET
- Read data in C++ using Mu2e DbService wrappers
For Mu2e C++ applications, do not use the official QE C API directly. Use Mu2e wrappers centered on:
Offline/DbService/inc/DbReader.hhOffline/DbService/inc/DbIdList.hhOffline/DbTables/inc/DbId.hhOffline/DbService/inc/DbCurl.hh
Reference docs:
- https://github.com/fermisda/qengine/wiki/Query-Engine
- https://mu2ewiki.fnal.gov/wiki/ConditionsDbCode#URL_format
Base endpoint pattern:
<prefix>/query?dbname=<db>&t=<table>[&c=<cols>][&w=<cond>...][&o=<sort>][&l=<limit>][&f=<fmt>][&x=<cacheCtl>]
Core parameters:
dbname(required): logical database namet(required): table name (schema.tablewhen needed)c(optional): comma-separated column list, default all columnsw(optional, repeatable): where terms, typicallycolumn:op:valueo(optional): sort columns, prefix-for descendingl(optional): row limitf(optional): output format (csvdefault,textsupported)x(optional): cache control (yes,no,clear)
Comparison operators for w: lt, le, eq, ne, ge, gt.
Example semantics:
w=cid:eq:2&w=channel:le:1
means SQL-like AND conditions.
Mu2e relies on two QE URL heads per database connection:
- cache URL (
...:8444/.../query?): uses web cache for scale - nocache URL (
...:9443/.../query?): bypasses cache and reads DB directly
In Mu2e connection config (Offline/DbService/data/connections.txt), each database has both endpoints.
Important behavior:
- Use cache for high-rate stable table reads
- Use no-cache when latest DB entries must be discovered immediately
- Non-cache reads bypass cache and do not refresh cached entries
C++ DbReader behavior details:
- Non-
val*tables use cache by default (setUseCache(true)) val*IoV metadata tables default to no-cache for freshnesssetCacheLifetime(n)can provide bounded caching forval*queries via a rolling URL token
Known logical database names in current config include:
mu2e_conditions_prdmu2e_conditions_devmu2e_dqm_prddcs_archivemu2e_tracker_prdrun_info
Always pass the logical name via dbname=<name>.
Define precisely:
- target logical database (
dbname) - target table (
t) - required columns (
c) - filter predicates (
w) - sort/limit (
o,l) - freshness requirement (cache vs no-cache)
curl -s "https://dbdata0vm.fnal.gov:8444/QE/mu2e/prod/app/SQ/query?dbname=mu2e_conditions_prd&t=val.tables&c=tid,name&o=tid" | headForce direct DB read:
curl -s "https://dbdata0vm.fnal.gov:9443/QE/mu2e/prod/app/SQ/query?dbname=mu2e_conditions_prd&t=val.tables&c=tid,name&o=tid" | head- Python: compose URL with proper query encoding and repeat
w - C++: use
DbIdList+DbReaderand pass select/table/where/order pieces
- Verify header/content format (
csvdefault) - Check row count and ordering
- Re-run against cache and no-cache endpoints when freshness matters
Use this when you need enough detail to identify the run table definition.
- Confirm tables in schema
test_sc:
curl -s "https://dbdata0vm.fnal.gov:8444/QE/mu2e/prod/app/SQ/I/tables?dbname=run_info&ns=test_sc&f=json"- Get
runtable column definition (names/types):
curl -s "https://dbdata0vm.fnal.gov:8444/QE/mu2e/prod/app/SQ/I/columns?dbname=run_info&t=test_sc.run&f=json"- Optional: probe a few rows from the table using cache endpoint:
curl -s "https://dbdata0vm.fnal.gov:8444/QE/mu2e/prod/app/SQ/query?dbname=run_info&t=test_sc.run&c=*&l=5"- If the definition appears stale, compare against no-cache endpoint:
curl -s "https://dbdata0vm.fnal.gov:9443/QE/mu2e/prod/app/SQ/I/columns?dbname=run_info&t=test_sc.run&f=json"Notes:
- For table definition, prefer
/I/columnsover/query. - Use fully qualified table name
test_sc.run. f=jsonis easiest for parsing column metadata programmatically.- In current QE deployment,
/I/tables?...&f=csvmay return a server error; usef=jsonfor schema introspection.
Use URL parameter encoding rather than manual string concatenation.
from urllib.parse import urlencode
from urllib.request import urlopen
base = "https://dbdata0vm.fnal.gov:9443/QE/mu2e/prod/app/SQ/query?"
params = [
("dbname", "mu2e_conditions_prd"),
("t", "tst.calib1"),
("c", "flag,dtoe"),
("w", "cid:eq:2"),
("w", "channel:le:1"),
("o", "-flag"),
("f", "csv"),
]
url = base + urlencode(params)
with urlopen(url, timeout=30) as response:
payload = response.read().decode("utf-8")
print(payload)Guidelines:
- Keep
paramsas ordered tuples so repeatedwkeys are preserved - Use timeout and explicit error handling for production code
- Prefer no-cache endpoint when checking for just-inserted rows
Use DbIdList to resolve logical DB name to endpoint URLs, then query through DbReader.
#include "Offline/DbService/inc/DbIdList.hh"
#include "Offline/DbService/inc/DbReader.hh"
mu2e::DbIdList idList;
mu2e::DbId id = idList.getDbId("mu2e_conditions_prd");
mu2e::DbReader reader;
reader.setDbId(id);
reader.setUseCache(true);
reader.setAbortOnFail(false);
std::string csv;
mu2e::DbReader::StringVec where;
where.emplace_back("cid:eq:2");
where.emplace_back("channel:le:1");
int rc = reader.query(csv, "flag,dtoe", "tst.calib1", where, "-flag");
if (rc != 0) {
auto err = reader.lastError();
}Key API notes:
query(csv, select, table, where, order)maps directly to URL piecesmultiQuery(...)reuses socket/handle for multiple related readssetAbortOnFail(false)lets caller handle failures instead of throwing- Returned CSV from
DbReaderhas header line removed by default
Do not switch to QE official C API for Mu2e Offline code paths unless specifically required by external integration.
- Keep table and column names exact and lower-case where required by schema.
- Build each
wclause asfield:op:valueunless using impliciteqform. - Repeat
wfor AND logic; avoid embedding SQL text. - Use deterministic ordering for reproducible comparisons.
- Prefer explicit columns over
*in production code. - Separate freshness checks (no-cache) from steady-state reads (cache).
- Verify
dbname, schema/table name, and column names - Test same URL with no-cache endpoint
- Remove filters incrementally, then re-add one by one
- Retry with bounded backoff
- For C++, inspect
reader.lastError()and return code - Increase
DbReadertimeout only when justified
- Confirm you are using no-cache endpoint (or
x=noif supported) - For Mu2e C++, disable cache with
setUseCache(false)where appropriate - Re-check
val*table behavior and any cache lifetime settings
- Keep queries narrow (
c,w,l) to reduce payload and latency - Avoid repeated broad scans from grid jobs
- Default to cached reads for stable data at scale
- Use direct DB reads sparingly and intentionally
- Log canonical URL components (without secrets) when debugging
When asked to produce QE access code, return:
Goal:
- <what data is needed and why>
Chosen endpoint mode:
- cache|nocache
- reason: <freshness vs scale>
Query components:
- dbname: <...>
- table: <...>
- columns: <...>
- where:
- <w1>
- <w2>
- order: <...>
- limit: <...>
Implementation:
- Language: Python|C++
- Code: <minimal runnable snippet>
Validation:
- curl URL used:
- row-count or sample rows:
- cache-vs-nocache comparison result:
- Query Engine
- Mu2e ConditionsDbCode URL format
Offline/DbService/inc/DbReader.hhOffline/DbService/src/DbReader.ccOffline/DbService/inc/DbIdList.hhOffline/DbService/src/DbIdList.ccOffline/DbService/data/connections.txt