diff --git a/docs/datamodel/computeds.rst b/docs/datamodel/computeds.rst index 865c9e2b54b9..fc3468e2627d 100644 --- a/docs/datamodel/computeds.rst +++ b/docs/datamodel/computeds.rst @@ -53,9 +53,9 @@ 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 + Volatile and modifying 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 :eql:func:`datetime_of_transaction` or :eql:func:`datetime_of_statement`. This does *not* apply to computed properties outside of schema. diff --git a/docs/datamodel/functions.rst b/docs/datamodel/functions.rst index 7fab884b1c88..c9d9cf86d881 100644 --- a/docs/datamodel/functions.rst +++ b/docs/datamodel/functions.rst @@ -32,6 +32,67 @@ This function accepts a :eql:type:`str` as an argument and produces a test> select exclamation({'Hello', 'World'}); {'Hello!', 'World!'} +.. _ref_datamodel_functions_modifying: + +Modifying Functions +^^^^^^^^^^^^^^^^^^ + +.. versionadded:: 6.0 + +User-defined functions can contain DML (i.e., +:ref:`insert `, :ref:`update `, +:ref:`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: '2024-12-11T11:49:47Z'}} + +Unlike other functions, the arguments of modifying functions **must** have a +:ref:`cardinality <_ref_reference_cardinality>` of ``One``. + +.. 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({}); + 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: + +.. code-block:: edgeql-repl + + db> select add_user('Apr', {}) {name, joined_at}; + {default::User {name: 'Apr', joined_at: '2024-12-11T11:50:51Z'}} + db> select add_user('May', '2024-12-11T12:00:00-07:00') {name, joined_at}; + {default::User {name: 'May', joined_at: '2024-12-11T12:00:00Z'}} + .. list-table:: :class: seealso diff --git a/docs/reference/edgeql/volatility.rst b/docs/reference/edgeql/volatility.rst index 7534329b082d..75ea46a70460 100644 --- a/docs/reference/edgeql/volatility.rst +++ b/docs/reference/edgeql/volatility.rst @@ -132,3 +132,8 @@ The :ref:`cartesian product ` of a ``Modifying`` expressions are not allowed in a non-scalar argument to a function, except for :ref:`standard set functions `. + +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``.