Parameterized Queries
QQL supports parameterized queries: instead of hardcoding values in the query text, you define named placeholders and supply their values at call time via the params argument of executeQuery.
Benefits:
- The query is compiled once and cached - subsequent calls with different parameter values reuse the compiled plan, which reduces overhead when the same query runs repeatedly.
- Separating the query structure from its data values improves readability and prevents injection issues.
As placeholder, use any valid QQL identifier anywhere a scalar value is expected. The identifier must follow standard QQL naming rules.
Example
Parameterized query example
select trade.price as 'price', trade.size as 'size' from "mystream"
array join entries[this is TradeEntry] as trade
where timestamp >= START_TS and timestamp <= END_TS
and symbol in ($S1, $S2)
and trade.size > MIN_SIZE
The placeholders (START_TS, END_TS, $S1, $S2, MIN_SIZE) are bound to concrete values when executeQuery is called.
Supported Parameter Types
| Type group | Types |
|---|---|
| Integer | INT8, INT16, INT32, INT64 |
| Float | FLOAT32, FLOAT64 |
| String | VARCHAR |
Code Examples
- Java
- Python
try (DXTickDB db = TickDBFactory.openFromUrl("dxtick://localhost:8011", false)) {
String query =
"select trade.price as 'price', trade.size as 'size' from kraken " +
"array join entries[this is TradeEntry] as trade " +
"where timestamp >= START_TS and timestamp <= END_TS " +
"and symbol in ($S1, $S2) " +
"and trade.size > MIN_SIZE";
Parameter[] parameters = {
Parameter.INTEGER("START_TS", Instant.parse("2026-03-04T16:25:30.000Z").toEpochMilli()),
Parameter.INTEGER("END_TS", Instant.parse("2026-03-04T16:30:00.000Z").toEpochMilli()),
Parameter.VARCHAR("$S1", "BTC/EUR"),
Parameter.VARCHAR("$S2", "DOGE/USDT"),
Parameter.FLOAT("MIN_SIZE", 5.1),
};
try (InstrumentMessageSource cursor =
db.executeQuery(query, new SelectionOptions(true, false), parameters)) {
while (cursor.next()) {
System.out.println(cursor.getMessage());
}
}
}
import dxapi
def parse_datetime_as_epoch_ms(time_string):
return int(datetime.strptime(time_string, '%Y-%m-%d %H:%M:%S.%f').replace(tzinfo=pytz.UTC).timestamp() * 1000)
timebase = "dxtick://localhost:8011"
query = f"""
select trade.price as 'price', trade.size as 'size' from kraken
array join entries[this is TradeEntry] as trade
where timestamp >= START_TS and timestamp <= END_TS
and symbol in ($S1, $S2)
and trade.size > MIN_SIZE
"""
start_dt_ms = parse_datetime_as_epoch_ms('2024-07-23 07:35:00.000')
end_dt_ms = parse_datetime_as_epoch_ms('2024-07-29 13:10:00.000')
with dxapi.TickDb.openFromUrl(timebase, True) as db:
with db.tryExecuteQuery(
query=query,
options=dxapi.SelectionOptions(),
params=[
dxapi.QueryParameter('START_TS', 'INT64', str(start_dt_ms)),
dxapi.QueryParameter('END_TS', 'INT64', str(end_dt_ms)),
dxapi.QueryParameter('SYMBOL1', 'VARCHAR', 'BTC/EUR'),
dxapi.QueryParameter('SYMBOL2', 'VARCHAR', 'DOGE/USDT'),
dxapi.QueryParameter('MIN_SIZE', 'FLOAT64', '5.1'),
]
) as cursor:
while cursor.next():
msg = cursor.getMessage()
print(f"Trade: '{msg.symbol}' ({msg.getDateTime()}) {msg.size}@{msg.price}")