Skip to content

Commit 7c2ee80

Browse files
committed
Document builtin InternSets module
1 parent f441c68 commit 7c2ee80

File tree

1 file changed

+80
-3
lines changed

1 file changed

+80
-3
lines changed

docs/codeql/ql-language-reference/modules.rst

+80-3
Original file line numberDiff line numberDiff line change
@@ -285,9 +285,9 @@ Built-in modules
285285
****************
286286

287287
QL defines a ``QlBuiltins`` module that is always in scope.
288-
Currently, it defines a single parameterized sub-module
289-
``EquivalenceRelation``, that provides an efficient abstraction for working with
290-
(partial) equivalence relations in QL.
288+
``QlBuiltins`` defines parameterized sub-modules for working with
289+
(partial) equivalence relations (``EquivalenceRelation``) and sets
290+
(``InternSets``) in QL.
291291

292292
Equivalence relations
293293
=====================
@@ -347,3 +347,80 @@ The above select clause returns the following partial equivalence relation:
347347
+---+---+
348348
| 4 | 4 |
349349
+---+---+
350+
351+
Sets
352+
====
353+
354+
The built-in ``InternSets`` module is parameterized by ``Key`` and ``Value`` types
355+
and a ``Value getAValue(Key key)`` relation. The module groups the ``Value``
356+
column by ``Key`` and creates a set for each group of values related by a key.
357+
358+
The ``InternSets`` module exports a functional ``Set getSet(Key key)`` relation
359+
that relates keys with the set of value related to the given key by
360+
``getAValue``. Sets are represented by the exported ``Set`` type which exposes
361+
a ``contains(Value v)`` member predicate that holds for values contained in the
362+
given set. `getSet(k).contains(v)` is thus equivalent to `v = getAValue(k)` as
363+
illustrated by the following ``InternSets`` example:
364+
365+
.. code-block:: ql
366+
367+
int getAValue(int key) {
368+
key = 1 and result = 1
369+
or
370+
key = 2 and
371+
(result = 1 or result = 2)
372+
or
373+
key = 3 and result = 1
374+
or
375+
key = 4 and result = 2
376+
}
377+
378+
module Sets = QlBuiltins::InternSets<int, int, getAValue/1>;
379+
380+
from int k, int v
381+
where Sets::getSet(k).contains(v)
382+
select k, v
383+
384+
This evalutes to the `getAValue` relation:
385+
386+
+---+---+
387+
| k | v |
388+
+===+===+
389+
| 1 | 1 |
390+
+---+---+
391+
| 2 | 1 |
392+
+---+---+
393+
| 2 | 2 |
394+
+---+---+
395+
| 3 | 1 |
396+
+---+---+
397+
| 4 | 2 |
398+
+---+---+
399+
400+
If two keys `k1` and `k2` relate to the same set of values, then `getSet(k1) = getSet(k2)`.
401+
For the above example, keys 1 and 3 relate to the same set of values (namely the singleton
402+
set containing 1) and are therefore related to the same set by ``getSet``:
403+
404+
.. code-block:: ql
405+
406+
from int k1, int k2
407+
where Sets::getSet(k1) = Sets::getSet(k2)
408+
select k1, k2
409+
410+
The above query therefore evalutes to:
411+
412+
+----+----+
413+
| k1 | k2 |
414+
+====+====+
415+
| 1 | 1 |
416+
+----+----+
417+
| 1 | 3 |
418+
+----+----+
419+
| 2 | 2 |
420+
+----+----+
421+
| 3 | 1 |
422+
+----+----+
423+
| 3 | 3 |
424+
+----+----+
425+
| 4 | 4 |
426+
+----+----+

0 commit comments

Comments
 (0)