# PQL Language Features

PQL adds several language features over GQL. This is a summary of them.

# Operators

Standard operations, such as not, or, and, if, equals, isNull, sprintf and many others, are supported as fields:

1. ?query=not(true)
2. ?query=or([1,0])
3. ?query=and([1,0])
4. ?query=if(true, Show this text, Hide this text)
5. ?query=equals(first text, second text)
6. ?query=isNull(),isNull(something)
7. ?query=sprintf(%s API is %s, [PoP, cool])

[View query results: query #1, query #2, query #3, query #4, query #5, query #6, query #7]

# Composable fields

Arguments passed to a field can receive other fields or operators as input.

?query=
  posts.
    if (
      hasComments(),
      sprintf(
        "Post with ID %s has %s comment(s) and title '%s'",
        [
          id(),
          commentCount(),
          title()
        ]
      ),
      sprintf(
        "Post with ID %s, created on %s, has no comments",
        [
          id(),
          date(d/m/Y)
        ]
      )
    )@postDesc

[View query results]

# Composable fields in directive arguments

Through composable fields, the directive can be evaluated against the object, granting it a dynamic behavior.

The example below implements the standard GraphQL skip directive, however it is able to decide if to skip the field or not based on a condition from the object itself:

/?query=
  posts.
    title|
    featuredimage<
      skip(if:isNull(featuredimage()))
    >.
      src

[View query results]

# Composable directives

A directive can modify the behaviour of another directive. Values can be passed from one to another through "expressions": special variables set by each directive, wrapped with %...%.

For instance, in the example below, directive <forEach> iterates through all the items in an array, passing each of them to its composed directive <applyFunction> through expression %value%.

?query=
  echo([
    [banana, apple],
    [strawberry, grape, melon]
  ])@fruitJoin<
    forEach<
      applyFunction(
        function: arrayJoin,
        addArguments: [
          array: %value%,
          separator: "---"
        ]
      )
    >
  >

[View query results]

# Directive expressions

An expression, defined through symbols %...%, is a variable used by directives to pass values to each other. An expression can be pre-defined by the directive or created on-the-fly in the query itself.

In the example below, an array contains strings to translate and the language to translate the string to. The array element is passed from directive <forEach> to directive <advancePointerInArray> through pre-defined expression %value%, and the language code is passed from directive <advancePointerInArray> to directive <translate> through variable %toLang%, which is defined only in the query:

/?query=
  echo([
    [
      text: Hello my friends,
      translateTo: fr
    ],
    [
      text: How do you like this software so far?,
      translateTo: es
    ],
  ])@translated<
    forEach<
      advancePointerInArray(
        path: text,
        appendExpressions: [
          toLang:extract(%value%,translateTo)
        ]
      )<
        translate(
          from: en,
          to: %toLang%,
          oneLanguagePerField: true,
          override: true
        )
      >
    >
  >

[View query results]

# Skip output if null

Exactly the same result above (<skip(if(isNull(...)))>) can be accomplished using the ? operator: Adding it after a field, it skips the output of its value if it is null.

/?query=
  posts.
    title|
    featuredimage?.
      src

[View query results]

# Skip argument names

Field and directive argument names can be deduced from the schema.

This query...

/?
postId=1&
query=
  post($postId).
    date(d/m/Y)|
    title<
      skip(false)
    >

...is equivalent to this query:

/?
postId=1&
query=
  post(id: $postId).
    date(format: d/m/Y)|
    title<
      skip(if: false)
    >

[View query results: query #1, query #2]

Last Updated: 8/3/2020, 7:17:37 PM