BQL Examples

Back to BQL Overview

This document is a collection of example queries that illustrate how to identify some common sets of data with BQL. While each example in this document only presents a single solution, keep in mind that in most cases there are several different ways get the same result.

All points

select slotPath, out from control:ControlPoint
The result is the slot path and output value of all control points. Since we specified "out" the result is the combination of value and status. If we wanted just the value, we would have used out.value. Or if we wanted value and status in separate columns we would have specified out.value and out.status.

All points in alarm
select slotPath, out from control:ControlPoint where status.alarm
The result is the slot path and output value of all control points currently in the alarm state. In the where clause, the path "status.alarm" evaluates to true if the alarm status bit is set and false otherwise. This mechanism can be used to check the state of any of the status bits. See BStatus for more information on status flags.

All points with "Meter" in their name
select slotPath, out from control:ControlPoint where name like '%Meter%'
The result is the slot path and output value of all points whose name includes the substring "Meter". BQL supports simple pattern matching. A '%' or '*' matches zero or more characters. A '_' matches exactly one character. The normal character matching is case sensitive.

All points with a totalizer extension
select parent.slotPath, total from control:NumericTotalizerExt
The result is the slot path of every point that has a totalizer extension and the total for each totalizer. Note that the extent is the set of all totalizers. To get the point path, we look at the parent of each object in the extent.

All current schedule output values
select slotPath, out from schedule:AbstractSchedule stop
The result is the slot path and output value of all schedules. Note the keyword "stop". The schedule component model makes the "stop" keyword necessary. All of the common schedule (BooleanSchedule, NumericSchedule, etc.) are actually composed of many more precise schedules. Without the "stop", the result would include all of the inner schedules in addition to the top level schedules that this query is actually looking for. The "stop" tells the query processor to stop the recursion when it reaches a component whose type matches the extent type.

All points overridden at priority level 8
select slotPath, out from control:IWritablePoint
  where activeLevel = control:PriorityLevel.level_8
The result is the slot path and output value of all writable points that are currently overridden at priority level 8. I know that every writable point is an instance of BIWritablePoint. All writable points provide access to their active level with a method called getActiveLevel(). Following the pattern for translating method names to BQL fields, I can access the active level on writable points using "activeLevel". In this case I know that active level is represented by a PriorityLevel enum. The level 8 value of the enum is specified by "control:PriorityLevel.level_8".

All points with units of degrees fahrenheit
select slotPath from control:NumericPoint
  where facets.units.unitName = 'fahrenheit'
The key to this query is understanding how units are associated with a point. All control points have facets. For numeric points, the units are defined as a facet. So facets.units gets the units for the point. BUnit has a method called getUnitName() so "unitName" gets the result of that method.

All points linked to a specific schedule
select targetComponent.slotPath from baja:Link
  where sourceSlotName = 'out' and
        sourceComponent.slotPath = 'slot:/app/MainSchedule'
        
This one is tricky. Because links are dynamic, they do not have a fixed name that we can search for. There is also no way to access just the links to a schedule output from BQL. Instead we have to look at all of the links and check the endpoints. So the extent is all links. Then we check for a source slot of "out". Finally we check the source slot path.

All points that generate alarms of a specific class
select parent.slotPath from alarm:AlarmSourceExt where alarmClass = 'hvac'
The result is the slot path of all control points that generate alarms for the "hvac" alarm class. The extent is all alarm source extensions. We find the extensions that specify "hvac" for the alarm class and get the parent slot path from those. The parent of an alarm source extension is always a control point.

All points with a history extension
select parent.slotPath from history:HistoryExt
This one is simple. We find all of the history extensions by using history:HistoryExt as the extent. Then we just get the slot path of the parent. The parent of a history extension is always a control point.

All points that collect a history with a capacity greater than 1000 records.
select parent.slotPath, historyConfig.capacity from history:HistoryExt
  where historyConfig.capacity.isUnlimited or
        historyConfig.capacity.maxRecords > 1000
For this query you have to understand how history extensions are configured. The capacity is a property of HistoryConfig. However, Capacity is not a simple numeric value. To exceed 1000 records of capacity, the configured capacity may either be unlimited or limited to a value greater than 1000. So first we check for unlimited and then we check for a limit of more than 1000 records.

The number of unacked alarms in all alarm classes
select name, unackedAlarmCount from alarm:AlarmClass
This query just looks at all of the alarm classes and for each one returns the name and the unackedAlarmCount. In this case, it will be much more efficient to narrow the search by making the alarm service be the query base. All alarm classes must be children of the AlarmService. So it is much better to only search the AlarmService container.
slot:/Services/Alarm|bql:select name, numberOfUnackedAlarms from alarm:AlarmClass