Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

doc: Split TQL documentation #1527

Merged
merged 7 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
nterray marked this conversation as resolved.
Show resolved Hide resolved
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ Project management:

* This module is part of :ref:`Tuleap Entreprise <tuleap-enterprise>`.

* :ref:`crosstracker <portfolio>`: Aggregate data across trackers, even in across projects (beta)
* :ref:`crosstracker <xts>`: Aggregate data across trackers, even in across projects (beta)
nterray marked this conversation as resolved.
Show resolved Hide resolved

* This module is part of :ref:`Tuleap Entreprise <tuleap-enterprise>`.

Expand Down
2 changes: 1 addition & 1 deletion languages/en/user-guide/project-admin.rst
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ A widget "Cross tracker search" enables you to do that.

If you don't fill a query, the request will retrieve "Open" artifacts.
If you use the query, the retrieved artifacts will match the query and not only the "Open" ones.
The query uses the TQL language. You can find more information about the query format :ref:`here <tql>`.
The query uses the TQL language. You can find more information about the query format :ref:`here <xts>`.
nterray marked this conversation as resolved.
Show resolved Hide resolved
nterray marked this conversation as resolved.
Show resolved Hide resolved

The search respects Tuleap permissions model: you can choose only projects you are member of and trackers you can read.
If you can't read all trackers or all columns needed by the query, an error message will be displayed.
Expand Down
385 changes: 26 additions & 359 deletions languages/en/user-guide/tql.rst

Large diffs are not rendered by default.

300 changes: 300 additions & 0 deletions languages/en/user-guide/tql/cross-tracker-search.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,300 @@
.. _xts:

TQL in Cross-Tracker Search
===========================

.. attention::

This module is part of :ref:`Tuleap Enterprise <tuleap-enterprise>`. It might
not be available on your installation of Tuleap.

The widget
----------

TQL can be used in the Cross-Tracker Search widget, in the search area.
nterray marked this conversation as resolved.
Show resolved Hide resolved

.. figure:: ../../images/screenshots/tql/expert_query_xtracker_widget.png
:align: center
:alt: TQL on cross-tracker search
:name: TQL on cross-tracker search

The widget is part of the :ref:`Cross-Tracker Search plugin <install-plugins>` and can be added on any dashboard that you have permission to modify.

.. _xts_default_mode:

Default mode
------------

The widget has two modes, allowing you to choose the level of fine-tuning you want. There is Default mode and :ref:`Expert mode <xts_expert_mode>`.
Let's first see the default mode.

This is the mode in which the widget is created. It allows you to choose a list of trackers coming from different projects and
to filter artifacts from those trackers according to some criteria.

Examples:

.. code-block:: tql

@title = 'documentation' AND @status = OPEN() AND @last_update_date > NOW() - 1w
// Returns all open artifacts with 'documentation' in the title that have been
// updated during the last week.

@title = 'documentation' AND @submitted_by = 'alice' AND @assigned_to IN (MYSELF(), 'charles')
// Returns all artifacts with 'documentation' in the title that have been submitted
// by user 'alice' and are assigned to the viewing user (for example 'bob')
// or user 'charles'.

To filter artifacts, you have access to several criteria detailed below.

.. _tql_duck_typing:

Similar fields
''''''''''''''

You can search on any custom field with its name as long as there is at least one Tracker with a compatible definition. We consider that 2 fields from 2 Trackers are compatible if:
* You can see both fields
* They have the same name
* Their types are compatible

Compatible field types:
* Numerics: integer and float
* Lists with same bind (user, user group, static)
* String and text
* Date
* Date time

Semantics and dynamic fields
''''''''''''''''''''''''''''

The following keywords are supported:

String/Text semantics:
* ``@title``: the "Title" semantic. It behaves like a string field.
* ``@description``: the "Description" semantic. It behaves like a text field.

Integer:
* ``@id``: the "Artifact id" dynamic field. It contains the unique id of the artifact, a strictly positive integer.

Dates:
* ``@submitted_on``: the "Submitted On" dynamic field. It behaves like a date field, but the empty string ``''`` is not allowed (this field cannot be empty).
* ``@last_update_date``: the "Last Update Date" dynamic field. It behaves like a date field, but the empty string ``''`` is not allowed (this field cannot be empty).

Lists:
* ``@status``: the "Status" semantic. It can only be compared to ``OPEN()``

Lists bound to users:
* ``@submitted_by``: the "Submitted By" dynamic field. It behaves like a list and can have only a single value at a time.
* ``@last_update_by``: the "Last Updated by" dynamic field. It behaves like a list and can have only a single value at a time.
* ``@assigned_to``: the "Contributor/assignee" semantic. It behaves like a list and can have multiple values at a time (multiple users assigned to an artifact).

Comparison
''''''''''

* For string and text fields: ``=``, ``!=``
* For date, integer and float fields: ``=``, ``!=``, ``<``, ``<=``, ``>``, ``>=``, ``BETWEEN()``
* For list fields: ``=``, ``!=``, ``IN()``, ``NOT IN()``

Comparison values
~~~~~~~~~~~~~~~~~

* For string and text fields: simple quote or double quote string like ``'simple quote'`` or ``"double quote"``.
* For integer fields: integer (``3``) or string convertible to integer (``"3"``)
* For float fields: integer (``3``), float (``4.2``) or string convertible to float (``"5.6"``)
* For date fields: ``NOW()`` or string convertible to date (``"2024-10-07"``)
* For list fields: matching list values (for example: ``"In Review"``, ``"Ongoing"``)
* For list fields bound to users: ``MYSELF()`` or ``string`` user names (for example: ``"jdoe"``, ``"John Doe"``)
* For list fields bound to user groups: ``string`` matching either the name of a user-defined ("Static") user group (for example: ``"Customers"``)
or matching the translated system-defined ("Dynamic") user group name (for example: ``"Project members"``).

Empty string ``''`` can be used for any field to specify no value.

``@submitted_by``, ``@last_update_by``, ``@submitted_on``, ``@last_update_date`` and ``@id`` cannot be compared to empty string ``''`` as these fields always have a value.

Dynamic value for date fields
+++++++++++++++++++++++++++++

* ``start_date > NOW()`` matches all artifacts where the field ``start_date`` is greater (more recent) than the current time (time when the query
is displayed).
* You can use interval periods with ``NOW()``, for example ``submitted_on > NOW() - 1m`` will matches
all artifacts that have been created during the last month. The supported specificators are:

* years (``y``)
* months (``m``)
* weeks (``w``)
* days (``d``)

Dynamic value for list fields bound to users: ``MYSELF()``
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

``owner = MYSELF()`` matches all artifacts where the field ``owner`` is equal to the current user.

.. include:: tql-artlink.rst

Queries
'''''''

You can assemble your different comparisons with logical operators ``AND`` and ``OR`` and use parenthesis ``()`` to force precedence.

Preconditions for multi-tracker search
''''''''''''''''''''''''''''''''''''''

When you use a semantic, at least one of the selected trackers must have it configured and the field linked to the semantic must be readable by the current user.

For example, if you run an expert query containing ``@status``, at least one of the selected trackers **must** have defined a "Status" semantic and the "Status" field **must** be readable by the user viewing the widget.
If **none** of the trackers defines the "Status" semantic, it will cause an error to be shown. The same is true for permissions: if **none** of the "Status" fields are readable by the current user, it will raise an error.

If only part of the selected trackers match these preconditions, the query will be performed only on those trackers.

Errors you can receive
~~~~~~~~~~~~~~~~~~~~~~

.. note:: Be careful, you must use the name of fields and not the label to construct queries.

Sending the query to the server can produce the following errors:

- The query syntax is incorrect (for example: if you forget a closing quote ``"``)
- The name used in a comparison doesn't match any existing field name in any of the trackers selected (or there is a mistake in the name)
- The value is not defined for the list field (for example: ``assigned_to = "non_existent_user"``)
- The dynamic value is not supported for this field (for example: ``text_field = NOW()``)
- The comparison operator is not supported for this field (for example: ``list_field >= 3``)
- The empty value is not allowed for this comparison (for example: ``date_field BETWEEN("", "2017-01-18")``)
- The query uses ``MYSELF()`` and the current user is not logged in (for example: when browsing a Tuleap platform as an anonymous user)
- The field type is unsupported
- The query is too complex

.. important:: The query is too complex when it exceeds a limit. This limit is defined by Site Administrators on Site Administration > Tracker > Report.
nterray marked this conversation as resolved.
Show resolved Hide resolved

.. _xts_expert_mode:

Expert mode
-----------

.. attention::

This part is still work in progress, future releases may break your report.
You can follow advancement in `epic #37567 SuperTableau - Full TQL mode <https://tuleap.net/plugins/tracker/?aid=37567>`_

The Cross-Tracker Search widget has a second mode called "Expert mode" allowing you to search even more specifically on your whole platform.
You can switch between modes by using the button ``Expert mode`` on the widget

.. figure:: ../../images/screenshots/tql/expert_query_xts_change_mode.png
:align: center
:alt: Change mode of widget
:name: Change mode of widget

In expert mode, the widget uses an extended TQL syntax:

In this extended syntax of TQL you can choose which fields you want to display on the widget through ``SELECT`` syntax, and also on which tracker to perform the query with ``FROM``:

.. code-block:: tql

SELECT @pretty_title, @status, open_date
FROM @project = 'self' AND @tracker.name IN('activity', 'task')
WHERE @assigned_to = MYSELF()
ORDER BY @last_update_date DESCENDING
// Returns all artifacts from current project activity and task trackers assigned to me.
// Display their title, status and opening date ordered according to their last modification date.

When using Cross-tracker search expert mode, you must use ``SELECT`` syntax with at least one field, ``FROM`` with at least one condition, and a condition after the ``WHERE``. The ``ORDER BY`` part is optional.

The condition after the ``WHERE`` corresponds to what you write in :ref:`default mode <xts_default_mode>`.

``SELECT``
''''''''''

TQL ``SELECT`` syntax allows you to select on the same fields allowed for the condition plus some special fields:
nterray marked this conversation as resolved.
Show resolved Hide resolved

Semantics and always there fields:
* ``@id`` Artifact id.
* ``@submitted_on`` The creation date and time of the artifact.
* ``@last_update_date`` The date and time of the last change to the artifact.
* ``@submitted_by`` The user who first created the artifact.
* ``@last_update_by`` The user who made the last change to the artifact.
* ``@title`` Artifact title semantic.
* ``@description`` Artifact description semantic.
* ``@status`` Artifact status semantic.
* ``@assigned_to`` Artifact assignee/contributor semantic.

Fields short name:
* Same as for condition (see :ref:`Similar fields rules <tql_duck_typing>`)
* Note that in ``SELECT`` date and datetime fields are considered compatible

Special fields:
* ``@project.name`` The name and icon of the project that the artifact belongs to.
* ``@tracker.name`` The name and color of the tracker the artifact belongs to.
* ``@pretty_title`` It's equivalent to the Artifact column of classic Cross-tracker search widget (or the title of the artifact view).
robinsoc marked this conversation as resolved.
Show resolved Hide resolved

``FROM``
''''''''

TQL ``FROM`` syntax allows you to select on which tracker to perform the query by filtering projects and trackers. You can use only one condition of each type joined by ``AND``:
Hyzual marked this conversation as resolved.
Show resolved Hide resolved

Project condition:
* ``@project = 'self'`` get current project. Works only in a project dashboard.
* ``@project = 'aggregated'`` get project aggregated to the current one. Works only in a :ref:`program <program-management>` project dashboard.
* ``@project.name`` either with ``= 'project_name'`` or ``IN('project_name', 'another_project')``, get all projects with the corresponding short name.
* ``@project.category = 'Topic::Hardware'`` get all projects with corresponding category or sub category. A category is specified by its full path (root category to current one) with ``::`` as delimiter.
* ``@project.category IN('Topic::Hardware', 'License::Open Source')`` get all projects with corresponding category.

Tracker condition:
* ``@tracker.name`` either with ``= 'release'`` or ``IN('release', 'sprint')``, get all trackers with corresponding short name.

You must provide 1 or 2 condition of different kind. If only the project condition is provided then it gets all trackers from corresponding projects.
nterray marked this conversation as resolved.
Show resolved Hide resolved
If only the tracker condition is provided, then match the trackers from current project. It means that in a personal dashboard you must provide the project condition.

To provide both condition, you can use ``AND`` between them. There is no restriction for the order of the conditions.
Hyzual marked this conversation as resolved.
Show resolved Hide resolved

``ORDER BY``
''''''''''''

TQL ``ORDER BY`` syntax allows you to sort artifacts on a single field. Ordering on more than one criteria is not possible.

There are some restrictions on the fields you can use. As for the condition (``WHERE``) their types must be compatible. Date and date with time fields are not compatible together.
For list fields, only selectbox and radio buttons are allowed. All the ``@`` fields and semantics valid in conditions (``WHERE``) are allowed.

You must provide the direction of the ordering:
* ``ASC`` or ``ASCENDING`` from smallest to largest
* ``DESC`` or ``DESCENDING`` from largest to smallest

User list and user group list fields are compared on displayed value. For user lists, it means that the ordering depends on your preference on user display (login, real name or both).
For user groups like Project members or Project administrators, the sort is done on their translated name and so the ordering depends on your language.

If you do not provide an ``ORDER BY`` to your query, it will default to ``ORDER BY @id DESCENDING``.

Some examples you can take inspiration from:
nterray marked this conversation as resolved.
Show resolved Hide resolved

.. code-block:: tql

SELECT @pretty_title, @status, @submitted_by, @last_update_date
FROM @project.name = 'support' AND @tracker.name = 'ticket'
WHERE @status = OPEN() AND @assigned_to = MYSELF()
ORDER BY @last_update_date DESC
// Get tickets assigned to me from support project. Display their title, status, who opened the ticket and the last modification date

SELECT @title, @status, @project.name
FROM @project.category = 'Topic::Team' AND @tracker.name IN('epic', 'story')
WHERE @status = OPEN()
// Get open epics and stories from project with category Topic::Team (or sub category)
// display their title, status and from which project it comes

SELECT @pretty_title
FROM @project = 'self'
WHERE @id >= 1
// Display title of all artifacts of current project

SELECT @pretty_title, @status, @assigned_to, @project.name
FROM @project IN('self', 'aggregated')
WHERE @status = OPEN()
// Display artifacts from current project and teams projects in the context of a program project

Errors you can receive
~~~~~~~~~~~~~~~~~~~~~~
nterray marked this conversation as resolved.
Show resolved Hide resolved

Sending the query to the server can produce the following errors:

- Missing part of the query (missing ``SELECT`` or ``FROM`` or ``WHERE``).
- The ``FROM`` part found no trackers (for example: ``FROM @tracker.name = 'sprint'`` but there is no tracker ``sprint`` in the current project).
- Using ``FROM @project = 'self'`` in a personal dashboard.
- Using ``FROM @project = 'aggregated'`` in a personal dashboard or a project without :ref:`Program management service <program-management>` enabled.
- Fields with the same name are not compatible between them (for example: date and int field). This can happen for fields used in ``SELECT``, ``WHERE`` and ``ORDER BY``.
- Using a list field with multiple values in ``ORDER BY`` (open list, multi-selectbox, checkbox fields are not allowed).
Loading