You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/language/learn-ql/beginner/find-thief-1.rst
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,7 @@
1
1
Find the thief: Introduction
2
2
============================
3
3
4
-
There is a small village hidden away in the mountains. The village is divided into four parts - north, south, east, and west - and in the center stands a dark and mysterious castle... Inside the castle, locked away in the highest tower, lies the king's valuable golden crown. One night, a terrible crime is committed. A thief breaks into the tower and steals the crown!
4
+
There is a small village hidden away in the mountains. The village is divided into four parts—north, south, east, and west—and in the center stands a dark and mysterious castle... Inside the castle, locked away in the highest tower, lies the king's valuable golden crown. One night, a terrible crime is committed. A thief breaks into the tower and steals the crown!
5
5
6
6
You know that the thief must live in the village, since nobody else knew about the crown. After some expert detective work, you obtain a list of all the people in the village and some of their personal details.
Copy file name to clipboardExpand all lines: docs/language/learn-ql/beginner/find-thief-2.rst
+3-3Lines changed: 3 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -82,7 +82,7 @@ Notice that we have only temporarily introduced the variable ``c`` and we didn't
82
82
83
83
Note
84
84
85
-
If you are familiar with logic, you may notice that ``exists`` in QL corresponds to the existential `quantifier <https://help.semmle.com/QL/ql-handbook/formulas.html#quantified-formulas>`__ in logic. QL also has a universal quantifier ``forall(vars | formula 1 | formula 2)`` which is logically equivalent to ``not(exists(vars | formula 1 | not formula 2))``.
85
+
If you are familiar with logic, you may notice that ``exists`` in QL corresponds to the existential `quantifier <https://help.semmle.com/QL/ql-handbook/formulas.html#quantified-formulas>`__ in logic. QL also has a universal quantifier ``forall(vars | formula 1 | formula 2)`` which is logically equivalent to ``notexists(vars | formula 1 | not formula 2)``.
86
86
87
87
The real investigation
88
88
----------------------
@@ -124,8 +124,8 @@ Hints
124
124
125
125
from Person t
126
126
where <condition 1> and
127
-
not <condition 2> and
128
-
...
127
+
not <condition 2> and
128
+
...
129
129
select t
130
130
131
131
Once you have finished, you will have a list of possible suspects. One of those people must be the thief!
Copy file name to clipboardExpand all lines: docs/language/learn-ql/beginner/fire-1.rst
+20-21Lines changed: 20 additions & 21 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -12,50 +12,50 @@ Read the examples below to learn how to define predicates and classes in QL. The
12
12
Select the southerners
13
13
----------------------
14
14
15
-
This time you only need to consider a specific group of villagers, namely those living in the south of the village. Instead of writing ``getLocation() = "south"`` in all your queries, you could define a new `predicate <https://help.semmle.com/QL/ql-handbook/predicates.html>`__ ``southern``:
15
+
This time you only need to consider a specific group of villagers, namely those living in the south of the village. Instead of writing ``getLocation() = "south"`` in all your queries, you could define a new `predicate <https://help.semmle.com/QL/ql-handbook/predicates.html>`__ ``isSouthern``:
16
16
17
17
.. code-block:: ql
18
18
19
-
predicate southern(Person p) {
20
-
p.getLocation() = "south"
19
+
predicate isSouthern(Person p) {
20
+
p.getLocation() = "south"
21
21
}
22
22
23
-
The predicate ``southern(p)`` takes a single parameter ``p`` and checks if ``p`` satisfies the property ``p.getLocation() = "south"``.
23
+
The predicate ``isSouthern(p)`` takes a single parameter ``p`` and checks if ``p`` satisfies the property ``p.getLocation() = "south"``.
24
24
25
25
.. pull-quote::
26
26
27
27
Note
28
28
29
29
- The name of a predicate always starts with a lowercase letter.
30
-
- You can also define predicates with a result. In that case, the keyword ``predicate`` is replaced with the type of the result. This is like introducing a new argument, the special variable ``result``. For example, ``int getAge() {result = ...}`` returns an ``int``.
30
+
- You can also define predicates with a result. In that case, the keyword ``predicate`` is replaced with the type of the result. This is like introducing a new argument, the special variable ``result``. For example, ``int getAge() {result = ...}`` returns an ``int``.
31
31
32
32
You can now list all southerners using:
33
33
34
34
.. code-block:: ql
35
35
36
-
/* define predicate `southern` as above */
36
+
/* define predicate `isSouthern` as above */
37
37
38
38
from Person p
39
-
where southern(p)
39
+
where isSouthern(p)
40
40
select p
41
41
42
-
This is already a nice way to simplify the logic, but we could be more efficient. Currently, the query looks at every ``Person p``, and then restricts to those who satisfy ``southern(p)``. Instead, we could define a new `class <https://help.semmle.com/QL/ql-handbook/types.html#classes>`__ ``Southerner`` containing precisely the people we want to consider.
42
+
This is already a nice way to simplify the logic, but we could be more efficient. Currently, the query looks at every ``Person p``, and then restricts to those who satisfy ``isSouthern(p)``. Instead, we could define a new `class <https://help.semmle.com/QL/ql-handbook/types.html#classes>`__ ``Southerner`` containing precisely the people we want to consider.
43
43
44
44
.. code-block:: ql
45
45
46
46
class Southerner extends Person {
47
-
Southerner() { southern(this) }
47
+
Southerner() { isSouthern(this) }
48
48
}
49
49
50
-
A class in QL represents a logical property: when a value satisfies that property, it is a member of the class. This means that a value can be in many classes - being in a particular class doesn't stop it from being in other classes too.
50
+
A class in QL represents a logical property: when a value satisfies that property, it is a member of the class. This means that a value can be in many classes—being in a particular class doesn't stop it from being in other classes too.
51
51
52
-
The expression ``southern(this)`` defines the logical property represented by the class, called its *characteristic predicate*. It uses a special variable ``this`` and indicates that a ``Person`` "``this``" is a ``Southerner`` if the property ``southern(this)`` holds.
52
+
The expression ``isSouthern(this)`` defines the logical property represented by the class, called its *characteristic predicate*. It uses a special variable ``this`` and indicates that a ``Person`` "``this``" is a ``Southerner`` if the property ``isSouthern(this)`` holds.
53
53
54
54
.. pull-quote::
55
55
56
56
Note
57
57
58
-
If you are familiar with object-oriented programming languages, you might be tempted to think of the characteristic predicate as a *constructor*. However, this is **not** the case - it is a logical property which does not create any objects.
58
+
If you are familiar with object-oriented programming languages, you might be tempted to think of the characteristic predicate as a *constructor*. However, this is **not** the case—it is a logical property which does not create any objects.
59
59
60
60
You always need to define a class in QL in terms of an existing (larger) class. In our example, a ``Southerner`` is a special kind of ``Person``, so we say that ``Southerner`` *extends* ("is a subset of") ``Person``.
61
61
@@ -66,7 +66,7 @@ Using this class you can now list all people living in the south simply as:
66
66
from Southerner s
67
67
select s
68
68
69
-
You may have noticed that some predicates are appended, for example ``p.getAge()``, while others are not, for example ``southern(p)``. This is because ``getAge()`` is a member predicate, that is, a predicate that only applies to members of a class. You define such a member predicate inside a class. In this case, ``getAge()`` is defined inside the class ``Person``. In contrast, ``southern`` is defined separately and is not inside any classes. Member predicates are especially useful because you can chain them together easily. For example, ``p.getAge().sqrt()`` first gets the age of ``p`` and then calculates the square root of that number.
69
+
You may have noticed that some predicates are appended, for example ``p.getAge()``, while others are not, for example ``isSouthern(p)``. This is because ``getAge()`` is a member predicate, that is, a predicate that only applies to members of a class. You define such a member predicate inside a class. In this case, ``getAge()`` is defined inside the class ``Person``. In contrast, ``isSouthern`` is defined separately and is not inside any classes. Member predicates are especially useful because you can chain them together easily. For example, ``p.getAge().sqrt()`` first gets the age of ``p`` and then calculates the square root of that number.
70
70
71
71
Travel restrictions
72
72
-------------------
@@ -88,20 +88,19 @@ Start by defining a class ``Child`` containing all villagers under 10 years old.
88
88
.. code-block:: ql
89
89
90
90
class Child extends Person {
91
+
/* the characteristic predicate */
92
+
Child() { this.getAge() < 10 }
91
93
92
-
/* the characteristic predicate */
93
-
Child() { this.getAge() < 10 }
94
-
95
-
/* a member predicate */
96
-
override predicate isAllowedIn(string region) {
97
-
region = this.getLocation()
98
-
}
94
+
/* a member predicate */
95
+
override predicate isAllowedIn(string region) {
96
+
region = this.getLocation()
97
+
}
99
98
}
100
99
101
100
Now try applying ``isAllowedIn(string region)`` to a person ``p``. If ``p`` is not a child, the original definition is used, but if ``p`` is a child, the new predicate definition overrides the original.
102
101
103
102
You know that the fire starters live in the south *and* that they must have been able to travel to the north. Write a query to find the possible suspects. You could also extend the ``select`` clause to list the age of the suspects. That way you can clearly see that all the children have been excluded from the list.
104
103
105
-
➤ `See the answer in the query console <https://lgtm.com/query/2164870087/>`__
104
+
➤ `See the answer in the query console <https://lgtm.com/query/2551838470440192723/>`__
106
105
107
106
Continue to the :doc:`next page <fire-2>` to gather more clues and find out which of your suspects started the fire...
Copy file name to clipboardExpand all lines: docs/language/learn-ql/beginner/fire-2.rst
+7-7Lines changed: 7 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -11,27 +11,27 @@ This is a very helpful clue. Remember that you wrote a QL query to select all ba
11
11
where not exists (string c | p.getHairColor() = c)
12
12
select p
13
13
14
-
To avoid having to type ``not exists (string c | p.getHairColor() = c)`` every time you want to select a bald person, you can instead define another new predicate ``bald``.
14
+
To avoid having to type ``not exists (string c | p.getHairColor() = c)`` every time you want to select a bald person, you can instead define another new predicate ``isBald``.
15
15
16
16
.. code-block:: ql
17
17
18
-
predicate bald(Person p) {
19
-
not exists (string c | p.getHairColor() = c)
18
+
predicate isBald(Person p) {
19
+
not exists (string c | p.getHairColor() = c)
20
20
}
21
21
22
-
The property ``bald(p)`` holds whenever ``p`` is bald, so you can replace the previous query with:
22
+
The property ``isBald(p)`` holds whenever ``p`` is bald, so you can replace the previous query with:
23
23
24
24
.. code-block:: ql
25
25
26
26
from Person p
27
-
where bald(p)
27
+
where isBald(p)
28
28
select p
29
29
30
-
The predicate ``bald`` is defined to take a ``Person``, so it can also take a ``Southerner``, as ``Southerner`` is a subtype of ``Person``. It can't take an ``int`` for example - that would cause an error.
30
+
The predicate ``isBald`` is defined to take a ``Person``, so it can also take a ``Southerner``, as ``Southerner`` is a subtype of ``Person``. It can't take an ``int`` for example—that would cause an error.
31
31
32
32
You can now write a query to select the bald southerners who are allowed into the north.
33
33
34
-
➤ `See the answer in the query console <https://lgtm.com/query/1505746995987/>`__
34
+
➤ `See the answer in the query console <https://lgtm.com/query/2572701606358725253/>`__
35
35
36
36
You have found the two fire starters! They are arrested and the villagers are once again impressed with your work.
Copy file name to clipboardExpand all lines: docs/language/learn-ql/beginner/heir.rst
+14-14Lines changed: 14 additions & 14 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,9 +1,9 @@
1
1
Crown the rightful heir
2
2
=======================
3
3
4
-
Phew! No more crimes in the village - you can finally leave the village and go home.
4
+
Phew! No more crimes in the village—you can finally leave the village and go home.
5
5
6
-
But then... During your last night in the village, the old king - the great King Basil - dies in his sleep and there is chaos everywhere!
6
+
But then... During your last night in the village, the old king—the great King Basil—dies in his sleep and there is chaos everywhere!
7
7
8
8
The king never married and he had no children, so nobody knows who should inherit the king's castle and fortune. Immediately, lots of villagers claim that they are somehow descended from the king's family and that they are the true heir. People argue and fight and the situation seems hopeless.
9
9
@@ -38,8 +38,8 @@ We know that the king has no children himself, but perhaps he has siblings. Writ
38
38
.. code-block:: ql
39
39
40
40
from Person p
41
-
where parentOf(p) = parentOf("King Basil") and
42
-
not p = "King Basil"
41
+
where parentOf(p) = parentOf("King Basil") and
42
+
not p = "King Basil"
43
43
select p
44
44
45
45
He does indeed have siblings! But you need to check if any of them are alive... Here is one more predicate you might need:
@@ -56,16 +56,16 @@ Use this predicate to see if the any of the king's siblings are alive.
56
56
57
57
from Person p
58
58
where parentOf(p) = parentOf("King Basil") and
59
-
not p = "King Basil"
60
-
and not p.isDeceased()
59
+
not p = "King Basil"
60
+
and not p.isDeceased()
61
61
select p
62
62
63
63
Unfortunately, none of King Basil's siblings are alive. Time to investigate further. It might be helpful to define a predicate ``childOf()`` which returns a child of the person. To do this, the ``parentOf()`` predicate can be used inside the definition of ``childOf()``. Remember that someone is a child of ``p`` if and only if ``p`` is their parent:
64
64
65
65
.. code-block:: ql
66
66
67
67
Person childOf(Person p) {
68
-
p = parentOf(result)
68
+
p = parentOf(result)
69
69
}
70
70
71
71
.. pull-quote::
@@ -80,7 +80,7 @@ Try to write a query to find out if any of the king's siblings have children:
80
80
81
81
from Person p
82
82
where parentOf(p) = parentOf("King Basil") and
83
-
not p = "King Basil"
83
+
not p = "King Basil"
84
84
select childOf(p)
85
85
86
86
The query returns no results, so they have no children. But perhaps King Basil has a cousin who is alive or has children, or a second cousin, or...
@@ -100,8 +100,8 @@ You can translate this into QL as follows:
100
100
.. code-block:: ql
101
101
102
102
Person ancestorOf(Person p) {
103
-
result = parentOf(p) or
104
-
result = parentOf(ancestorOf(p))
103
+
result = parentOf(p) or
104
+
result = parentOf(ancestorOf(p))
105
105
}
106
106
107
107
As you can see, you have used the predicate ``ancestorOf()`` inside its own definition. This is an example of `recursion <https://help.semmle.com/QL/ql-handbook/recursion.html>`__.
@@ -120,12 +120,12 @@ Here is one way to define ``relativeOf()``:
120
120
.. code-block:: ql
121
121
122
122
Person relativeOf(Person p) {
123
-
parentOf*(result) = parentOf*(p)
123
+
parentOf*(result) = parentOf*(p)
124
124
}
125
125
126
126
Don't forget to use the predicate ``isDeceased()`` to find relatives that are still alive.
127
127
128
-
➤ `See the answer in the query console <https://lgtm.com/query/2164460071/>`__
128
+
➤ `See the answer in the query console <https://lgtm.com/query/6710025057257064639/>`__
129
129
130
130
Select the true heir
131
131
--------------------
@@ -136,9 +136,9 @@ To decide who should inherit the king's fortune, the villagers carefully read th
136
136
137
137
*"The heir to the throne is the closest living relative of the king. Any person with a criminal record will not be considered. If there are multiple candidates, the oldest person is the heir."*
138
138
139
-
As your final challenge, define a predicate ``criminalRecord`` so that ``criminalRecord(p)`` holds if ``p`` is any of the criminals you unmasked earlier (in the :doc:`Find the thief <find-thief-1>` and :doc:`Catch the fire starter <fire-1>` tutorials).
139
+
As your final challenge, define a predicate ``hasCriminalRecord`` so that ``hasCriminalRecord(p)`` holds if ``p`` is any of the criminals you unmasked earlier (in the :doc:`Find the thief <find-thief-1>` and :doc:`Catch the fire starter <fire-1>` tutorials).
140
140
141
-
➤ `See the answer in the query console <https://lgtm.com/query/1505745996002/>`__
141
+
➤ `See the answer in the query console <https://lgtm.com/query/1820692755164273290/>`__
0 commit comments