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

Update docs to cover modifying functions. #8106

Merged
merged 5 commits into from
Jan 9, 2025
Merged
Show file tree
Hide file tree
Changes from 4 commits
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
7 changes: 4 additions & 3 deletions docs/datamodel/computeds.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,10 @@ field is referenced in a query.

.. warning::

Volatile functions are not allowed in computed properties defined in schema.
This means that, for example, your schema-defined computed property cannot
call :eql:func:`datetime_current`, but it *can* call
:ref:`Volatile and modifying <_ref_reference_volatility>` expressions are not
allowed in computed properties defined in schema. This means that, for
example, your schema-defined computed property cannot call
:eql:func:`datetime_current`, but it *can* call
:eql:func:`datetime_of_transaction` or :eql:func:`datetime_of_statement`.
This does *not* apply to computed properties outside of schema.

Expand Down
115 changes: 115 additions & 0 deletions docs/datamodel/functions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,121 @@ This function accepts a :eql:type:`str` as an argument and produces a
test> select exclamation({'Hello', 'World'});
{'Hello!', 'World!'}

.. _ref_datamodel_functions_modifying:

Sets as arguments
^^^^^^^^^^^^^^^^^

Calling a user-defined function on a set will always apply it as
:ref:`*element-wise* <_ref_reference_cardinality_functions_operators>`.

.. code-block:: sdl

function magnitude(x: float64) -> float64
using (
math::sqrt(sum(x * x))
);

.. code-block:: edgeql-repl

db> select magnitude({3, 4});
{3, 4}

In order to pass in multiple arguments at once, arguments should be packed into
arrays:

.. code-block:: sdl

function magnitude(xs: array<float64>) -> float64
using (
with x := array_unpack(xs)
select math::sqrt(sum(x * x))
);

.. code-block:: edgeql-repl

db> select magnitude([3, 4]);
{5}

Multiple packed arrays can be passed into such a function, which will then be
applied element-wise.

.. code-block:: edgeql-repl

db> select magnitude({[3, 4], [5, 12]});
{5, 13}

Modifying Functions
^^^^^^^^^^^^^^^^^^^

.. versionadded:: 6.0

User-defined functions can contain DML (i.e.,
:ref:`insert <ref_eql_insert>`, :ref:`update <ref_eql_update>`,
:ref:`delete <ref_eql_delete>`) to make changes to existing data. These
functions have a :ref:`modifying <_ref_reference_volatility>` volatility.

.. code-block:: sdl

function add_user(name: str) -> User
using (
insert User {
name := name,
joined_at := std::datetime_current(),
}
);

.. code-block:: edgeql-repl

db> select add_user('Jan') {name, joined_at};
{default::User {name: 'Jan', joined_at: <datetime>'2024-12-11T11:49:47Z'}}

Unlike other functions, the arguments of modifying functions **must** have a
:ref:`cardinality <_ref_reference_cardinality>` of ``One``.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Practical question: if some property that you're trying to insert or update is multi, does that mean you'll have to pass it as an array and unpack it? Maybe we should show this as an example?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added a more general section on passing in sets as arguments as well.


.. code-block:: edgeql-repl

db> select add_user({'Feb','Mar'});
edgedb error: QueryError: possibly more than one element passed into
modifying function
db> select add_user(<str>{});
edgedb error: QueryError: possibly an empty set passed as non-optional
argument into modifying function

Optional arguments can still accept empty sets. For example, if ``add_user``
was defined as:

.. code-block:: sdl

function add_user(name: str, joined_at: optional datetime) -> User
using (
insert User {
name := name,
joined_at := joined_at ?? std::datetime_current(),
}
);

then the following queries are valid:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
then the following queries are valid:
Then the following queries are valid:

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not entirely sure that's customary, since it's technically the continuation of the previous sentence.


.. code-block:: edgeql-repl

db> select add_user('Apr', <datetime>{}) {name, joined_at};
{default::User {name: 'Apr', joined_at: <datetime>'2024-12-11T11:50:51Z'}}
db> select add_user('May', <datetime>'2024-12-11T12:00:00-07:00') {name, joined_at};
{default::User {name: 'May', joined_at: <datetime>'2024-12-11T12:00:00Z'}}

In order to insert or update a multi parameter, the desired arguments should be
aggregated into an array as described above:

.. code-block:: sdl

function add_user(name: str, nicknames: array<str>) -> User
using (
insert User {
name := name,
nicknames := array_unpack(nicknames),
}
);

.. list-table::
:class: seealso
Expand Down
2 changes: 2 additions & 0 deletions docs/reference/edgeql/cardinality.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ instance, when assigning to a ``required multi`` link, the value being
assigned in question *must* have a cardinality of ``One`` or ``AtLeastOne``
(as empty sets are not permitted).

.. _ref_reference_cardinality_functions_operators:

Functions and operators
-----------------------

Expand Down
5 changes: 5 additions & 0 deletions docs/reference/edgeql/volatility.rst
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,8 @@ The :ref:`cartesian product <ref_reference_cardinality_cartesian>` of a

``Modifying`` expressions are not allowed in a non-scalar argument to a
function, except for :ref:`standard set functions <ref_std_set>`.

The non-optional parameters of ``Modifying``
:ref:`functions <_ref_datamodel_functions_modifying>` must have a
:ref:`cardinality <_ref_reference_cardinality>` of ``One``. Optional
parameters must have a cardinality of ``AtMostOne``.
2 changes: 2 additions & 0 deletions docs/reference/sdl/functions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ This declaration defines a new constraint with the following options:
argument as a *whole set*, as opposed to being called on the input
product element-by-element.

User defined functions can not use ``set of`` arguments.

The ``optional`` qualifier indicates that the function will be called
if the argument is an empty set. The default behavior is to return
an empty set if the argument is not marked as ``optional``.
Expand Down
Loading