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

project/1, query/1 and unify/1 added to builtin.jq, with tests and documentation #1062

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

pkoppstein
Copy link
Contributor

make check ran successfully.

Summary:

   query(q)   provides a kind of "query by example" functionality based on
              unification, where q is normally a query object that may contain 
              nested objects and arrays.

   project(e) emits the projection of the input object, as defined by
              e, which is normally an object or an array of strings;

    unify(e)  emits the unification of the input entity with e if
              possible or null otherwise, where e may be any JSON entity.

Description:

query(q)
      is defined as: unify(q) | select(.) | project(q);

project(e)
      Assuming the input is an object and that e is an object or an array of strings,
      project(e) returns an object with the same keys as in e, in
      the same order, but with values determined by the
      corresponding keys in the input object;

unify(e)
      This filter attempts to unify the input and e using a
      recursive process for both arrays and objects; on success, the
      filter emits the unified entity; on failure, the filter emits
      null.  Both the input and e may be arbitrary JSON entities.
      Unification is based on replacing nulls with corresponding values at
      structurally equivalent locations.
      Note that x|unify(y) yields null either if x and y are both null, or
      if unification fails.

unify/1 is defined so as to achieve the following basic principles, where
it is to be understood that x, y and z are valid JSON values:

  1. Non-failure: x|unify(y) always yields a value.
  2. Zero: null|unify(x) is x
  3. Reflexivity: x|unify(x) is x
  4. Symmetry: x|unify(y) == y|unify(x)
  5. Idempotence: unify(y)|unify(y) is unify(y)
  6. Commutativity: unify(x)|unify(y) is unify(y)|unify(x)
  7. Associativity: (unify(x)|unify(y))|unify(y) is unify(x)|(unify(y))|unify(y))
  8. If x and y cannot be unified, x|unify(y) yields null.

Semantics of (x|unify(y))

Terminology:
If x and y are not both null but x|unify(y) is null, then the unification of x and y is said to fail.

If x and y are two scalars, then x|unify(y) is:
if x == y then x elif x == null then y elif y == null then x else null end;

if x and y are two objects, and if $keys is (x + y) | keys | unique,
then (x|unify(y)) is the sum of {($k): (x[$k] | unify(y[$k]) )} as $k ranges through $keys,
provided that none of these values reflects unification failure;

if x and y are two arrays of the same length,
and if z is the array formed from (x[i]|unify(y[i]))
and if z[i] is only null when x[i] and y[i] are both null,
then (x|unify(y)) is z;

otherwise x|unify(y) is null.

Notice that:

  • e|unify(null) yields e by symmetry
  • x|unify(y) is null if and only if x==y==null or x and y fail to unify.
  • if $a is {"a": null} then {} | unify($a) is $a.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants