Other Commands
The star of the FSQL show is the QUERY command. But FSQL has a supporting cast of other commands. The EXPLAIN commands allow users to interrogate the schema, inspect what's actually mapped across their connected data, list their connections, or review FSQL documentation, and the VALIDATE QUERY command checks the validity of an FSQL query.
Note: if you're using FSQL through Query's search UI, you only have access to the QUERY command today. API and console users have access to the full set of commands shown here.
EXPLAIN VERSION
FSQL is new technology and advancing quickly. The EXPLAIN VERSION command can retrieve the FSQL and Query Data Model versions of the FSQL server you're working with.
EXPLAIN VERSIONResponse:
{
"fsql": "fsql-0.5.0",
"qdm": "qdm-1.4.1+ocsf-1.4.0"
}EXPLAIN ATTRIBUTES
FSQL owes a lot of its power to its attribute selectors. If you'd like to test an attribute selector, you can see what one evaluates to with the EXPLAIN ATTRIBUTES command.
For example, if you want to see all fields of network_activity that are IP observables, try the following:
EXPLAIN ATTRIBUTES network_activity.%ipResponse:
[
"network_activity.device.ip",
"network_activity.device.network_interfaces.ip",
"network_activity.dst_endpoint.intermediate_ips",
"network_activity.dst_endpoint.ip",
"network_activity.dst_endpoint.ip_intelligence.ip",
"network_activity.dst_endpoint.proxy_endpoint.intermediate_ips",
"network_activity.dst_endpoint.proxy_endpoint.ip",
"network_activity.load_balancer.dst_endpoint.intermediate_ips",
"network_activity.load_balancer.dst_endpoint.ip",
"network_activity.load_balancer.ip",
"network_activity.osint.email.x_originating_ip",
"network_activity.proxy.intermediate_ips",
"network_activity.proxy.ip",
"network_activity.proxy.ip_intelligence.ip",
"network_activity.proxy_endpoint.intermediate_ips",
"network_activity.proxy_endpoint.ip",
"network_activity.proxy_endpoint.ip_intelligence.ip",
"network_activity.proxy_http_request.x_forwarded_for",
"network_activity.src_endpoint.intermediate_ips",
"network_activity.src_endpoint.ip",
"network_activity.src_endpoint.ip_intelligence.ip",
"network_activity.src_endpoint.proxy_endpoint.intermediate_ips",
"network_activity.src_endpoint.proxy_endpoint.ip"
]EXPLAIN SCHEMA
The EXPLAIN SCHEMA command describes the schema for a given attribute selection. It expands the attribute selector expression and responds with the schema definition for each path that's been selected. If you're familiar with OCSF schema definitions, you should feel right at home with the output.
EXPLAIN SCHEMA network_activity.proxy.%ipResponse:
{
"network_activity.proxy.intermediate_ips": {
"caption": "Intermediate IP Addresses",
"type": "ip_t",
"requirement": "optional",
"description": "The intermediate IP Addresses. For example, the IP addresses in the HTTP X-Forwarded-For header.",
"is_array": true,
"observable": 2
},
"network_activity.proxy.ip": {
"caption": "IP Address",
"type": "ip_t",
"requirement": "recommended",
"description": "The IP address of the endpoint, in either IPv4 or IPv6 format.",
"is_array": false,
"observable": 2
},
"network_activity.proxy.ip_intelligence.ip": {
"caption": "IP Address",
"type": "ip_t",
"requirement": "optional",
"description": "The IP address, in either IPv4 or IPv6 format.",
"is_array": false,
"observable": 2
}
}By default, FSQL removes keys from the response with null values. You can enable them by adding WITH NULLS after the attribute selector (WITHOUT NULLS has the opposite effect). For example:
EXPLAIN SCHEMA network_activity.proxy.ip WITH NULLSResponse:
{
"network_activity.proxy.ip": {
"caption": "IP Address",
"type": "ip_t",
"requirement": "recommended",
"description": "The IP address of the endpoint, in either IPv4 or IPv6 format.",
"is_array": false,
"@deprecated": null,
"enum": null,
"group": null,
"observable": 2,
"profile": null,
"sibling": null,
"object_type": null,
"object_name": null,
"type_name": null
}
}EXPLAIN CONNECTORS
The EXPLAIN CONNECTORS command lists all connectors available in your Query tenant relevant to your FSQL session.
The output includes the connector ID, connector name, the connector's alias, any tags applied to it, whether or not the connector is enabled, the name of the source platform, as well as OCSF events and objects supported by the Connector.
The alias and tags fields give you the stable references you can use in a FROM clause: the alias for a single connector, or a #-prefixed tag to query every connector that carries it. See Data Sources (FROM).
EXPLAIN CONNECTORS [<conns>]The connector selection is optional:
- With no selection,
EXPLAIN CONNECTORSlists every connector available in your session. - Add
<conns>to limit the response to a subset of your connectors. It accepts any connector list you could use in aFROMclause — refer to connectors by numeric ID,#-prefixed tag, alias, or quoted display name, and separate multiple selections with commas to combine them. See Data Sources (FROM).
EXPLAIN CONNECTORS #siem, alienvaultResponse:
{
"command":"EXPLAIN CONNECTORS",
"connectors":[
{
"id":523,
"name":"AlienVault",
"alias":"alienvault",
"tags":[
"threat-intel"
],
"is_enabled":true,
"platform_name":"AlienVault",
"events":[
"osint_inventory_info"
],
"objects":[
"autonomous_system",
"digital_signature",
"dns_answer",
"location",
"metadata",
"observable",
"osint",
"product",
"reputation",
"threat_intelligence",
"unmapped"
]
},
{
"id":1011,
"name":"ATB - AzureActivity",
"alias":"atb-azureactivity",
"tags":[
"cloud",
"env/prod"
],
"is_enabled":true,
"platform_name":"AzureLogAnalytics",
"events":[
"api_activity"
],
"objects":[
"actor",
"api",
"group",
"network_endpoint",
"observable",
"resource_details",
"user"
]
}
]
}EXPLAIN CATALOG
Where EXPLAIN SCHEMA describes what the data model says an attribute could be, EXPLAIN CATALOG describes what your actual connected data does. It returns a computed view of your catalog: for each attribute that's mapped across your connections, it reports the attribute's scalar type and the invariants — the constraints that are known to hold on the values you can search. It's a machine-readable answer to the question "what can I usefully filter on across these connections?"
EXPLAIN CATALOG [<attribute-selector>] [FROM <connectors>]Both parts are optional:
- With no attribute selector,
EXPLAIN CATALOGreturns the whole catalog. Add an attribute selector (or a comma-separated list of them) to filter the response to just the attributes you care about. - Add a
FROMclause to compute the catalog over a subset of your connections. It accepts the same references as aQUERY'sFROMclause — a connector alias, a#-prefixed tag, a numeric connector ID, or a quoted display name. See Data Sources (FROM). With noFROMclause, the catalog spans all connections in your session.
Each entry reports a path, its type (for example ip, int, str, enum, or datetime), and its invariants. Common invariants include:
| Invariant | Meaning |
|---|---|
IsMapped | The attribute is populated, but no tighter constraint is known. |
EQ | Every record carries the same single value. |
OneOf | Values are drawn from a known, finite set. |
StartsWith / Matches | Values share a known prefix or match a known pattern. |
IfNotEmpty | When present, the value satisfies the nested invariant (it may also be absent). |
EXPLAIN CATALOG api_activity.* FROM #siemResponse:
{
"command": "EXPLAIN CATALOG",
"entries": [
{
"path": "api_activity.class_uid",
"type": "int",
"invariants": { "EQ": 6003 }
},
{
"path": "api_activity.count",
"type": "int",
"invariants": { "IfNotEmpty": { "OneOf": [0, 1, 2] } }
},
{
"path": "api_activity.message",
"type": "str",
"invariants": { "EQ": "m" }
},
{
"path": "api_activity.observables.type_id",
"type": "enum",
"invariants": { "OneOf": ["URL_STRING", "USER_NAME"] }
},
{
"path": "api_activity.observables.value",
"type": "str",
"invariants": { "IsMapped": null }
}
]
}Note: because the catalog is a union across the selected connections, invariants weaken as you widen the FROM clause. An attribute that always holds a single value in one connection (EQ) may relax to a set of values (OneOf) once a second connection is included, and an attribute mapped in only some connections may relax to a bare IsMapped. Narrowing the FROM clause to fewer connections tends to produce tighter invariants.
EXPLAIN MANUAL
The EXPLAIN MANUAL command responds with this documentation in Markdown format.
EXPLAIN QUERY
The EXPLAIN QUERY command shows how your FSQL query is converted into Query's internal search syntax. Invoke it with any search QUERY input to see how it will be interpreted by Query's engine.
The response has two key elements.
expanded_query shows your FSQL query with all attribute selectors in the SHOW and WITH clauses expanded and any additional attributes or filters that were added by Query.
ast_query shows how your query will be translated into Query's internal hierarchical search syntax. The SHOW and WITH clauses are separate for each event type and list operations are explicitly assigned.
The values of these fields are meant to be human readable, and their formatting may change slightly.
EXPLAIN QUERY http_activity.* WITH %ip='136.103.57.67'Response:
{
"command": "explain ast query http_activity.* with %ip='136.103.57.67'",
"expanded_query": "QUERY\nSHOW\n http_activity.action_id,\n http_activity.activity_id,\n http_activity.app_name,\n http_activity.category_uid,\n http_activity.class_uid,\n http_activity.confidence_id,\n http_activity.confidence_score,\n http_activity.count,\n http_activity.disposition_id,\n http_activity.duration,\n http_activity.end_time,\n http_activity.http_status,\n http_activity.is_alert,\n http_activity.message,\n http_activity.record_id,\n http_activity.risk_details,\n http_activity.risk_level_id,\n http_activity.risk_score,\n http_activity.severity_id,\n http_activity.start_time,\n http_activity.status_code,\n http_activity.status_detail,\n http_activity.status_id,\n http_activity.time,\n http_activity.timezone_offset,\n http_activity.type_uid\nWITH ANY http_activity.observables.type_id EQ 'IP_ADDRESS'\n AND ANY http_activity.observables.value EQ '136.103.57.67'\n AND ANY http_activity.time GT '2025-06-27T04:07:44'\n AND ANY http_activity.time LE '2025-06-28T04:07:44'\nSINCE 2025-06-27T04:07:44\nUNTIL 2025-06-28T04:07:44\n",
"ast_query": "EVENT: http_activity\n WITH\n ANY observables { (type_id EQ 'IP_ADDRESS' AND value EQ '136.103.57.67') }\n AND time GT '2025-06-27T04:07:44'\n AND time LE '2025-06-28T04:07:44'\n SHOW\n action_id\n activity_id\n app_name\n category_uid\n class_uid\n confidence_id\n confidence_score\n count\n disposition_id\n duration\n end_time\n http_status\n is_alert\n message\n record_id\n risk_details\n risk_level_id\n risk_score\n severity_id\n start_time\n status_code\n status_detail\n status_id\n time\n timezone_offset\n type_uid\n"
}Below is an example from a terminal† with newlines rendered:
>>> EXPLAIN AST QUERY authentication.#primary WITH %ip='1.2.3.4'
EVENT: authentication
SHOW
auth_protocol_id
is_mfa
is_remote
logon_type_id
message
record_id
status_code
status_detail
status_id
WITH
ANY observables { (type_id EQ 'IP_ADDRESS' AND value EQ '1.2.3.4') }
AND time GT '2025-06-27T09:55:23'
AND time LE '2025-06-28T09:55:23'
† Terminal users may wish to useEXPLAIN AST QUERY or EXPLAIN EXPANDED QUERY to specify which format they prefer in the output.
EXPLAIN GRAPHQL QUERY
If you're familiar with Query's GraphQL search API, you can use the EXPLAIN GRAPHQL QUERY command to translate an FSQL query into a GraphQL request. The example below shows a translated search query, but the EXPLAIN GRAPHQL command also provides a subscription query that can be used to retrieve results for a submitted search query.
EXPLAIN GRAPHQL QUERY network_activity.* WITH network_activity.count < 50 SINCE 720h UNTIL 1hResponse:
query {
search {
id
status
data {
network_activity(
filter: {
op: AND
conditions: [
{
fields: {
time: {
greater_than_equals: "2025-03-29T14:49:02.884049"
less_than_equals: "2025-04-28T13:49:02.883945"
}
}
}
{ op: OR, conditions: [{ fields: { count: { less_than: 50 } } }] }
]
}
) {
connection_id
action_id
activity_id
app_name
category_uid
class_uid
confidence_id
confidence_score
count
disposition_id
duration
end_time
is_alert
message
record_id
risk_details
risk_level_id
risk_score
severity_id
start_time
status_code
status_detail
status_id
time
timezone_offset
type_uid
}
}
}
}
VALIDATE QUERY
The VALIDATE QUERY command validates a FSQL query for debugging. VALIDATE SUMMARIZE works the same way, but validates a SUMMARIZE command with analytics functions.
VALIDATE QUERY #network.* WITH %ip = '10.0.0.1'Response:
{
"is_valid": true,
"input": "validate query #network.* with %ip = '10.0.0.1'"
}Updated 18 days ago