mirror of https://github.com/apache/cassandra
582 lines
23 KiB
ReStructuredText
582 lines
23 KiB
ReStructuredText
.. Licensed to the Apache Software Foundation (ASF) under one
|
|
.. or more contributor license agreements. See the NOTICE file
|
|
.. distributed with this work for additional information
|
|
.. regarding copyright ownership. The ASF licenses this file
|
|
.. to you under the Apache License, Version 2.0 (the
|
|
.. "License"); you may not use this file except in compliance
|
|
.. with the License. You may obtain a copy of the License at
|
|
..
|
|
.. http://www.apache.org/licenses/LICENSE-2.0
|
|
..
|
|
.. Unless required by applicable law or agreed to in writing, software
|
|
.. distributed under the License is distributed on an "AS IS" BASIS,
|
|
.. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
.. See the License for the specific language governing permissions and
|
|
.. limitations under the License.
|
|
|
|
.. highlight:: cql
|
|
|
|
.. _cql-functions:
|
|
|
|
.. Need some intro for UDF and native functions in general and point those to it.
|
|
.. _udfs:
|
|
.. _native-functions:
|
|
|
|
Functions
|
|
---------
|
|
|
|
CQL supports 2 main categories of functions:
|
|
|
|
- the :ref:`scalar functions <scalar-functions>`, which simply take a number of values and produce an output with it.
|
|
- the :ref:`aggregate functions <aggregate-functions>`, which are used to aggregate multiple rows results from a
|
|
``SELECT`` statement.
|
|
|
|
In both cases, CQL provides a number of native "hard-coded" functions as well as the ability to create new user-defined
|
|
functions.
|
|
|
|
.. note:: By default, the use of user-defined functions is disabled by default for security concerns (even when
|
|
enabled, the execution of user-defined functions is sandboxed and a "rogue" function should not be allowed to do
|
|
evil, but no sandbox is perfect so using user-defined functions is opt-in). See the ``enable_user_defined_functions``
|
|
in ``cassandra.yaml`` to enable them.
|
|
|
|
A function is identifier by its name:
|
|
|
|
.. productionlist::
|
|
function_name: [ `keyspace_name` '.' ] `name`
|
|
|
|
.. _scalar-functions:
|
|
|
|
Scalar functions
|
|
^^^^^^^^^^^^^^^^
|
|
|
|
.. _scalar-native-functions:
|
|
|
|
Native functions
|
|
~~~~~~~~~~~~~~~~
|
|
|
|
Cast
|
|
````
|
|
|
|
The ``cast`` function can be used to converts one native datatype to another.
|
|
|
|
The following table describes the conversions supported by the ``cast`` function. Cassandra will silently ignore any
|
|
cast converting a datatype into its own datatype.
|
|
|
|
=============== =======================================================================================================
|
|
From To
|
|
=============== =======================================================================================================
|
|
``ascii`` ``text``, ``varchar``
|
|
``bigint`` ``tinyint``, ``smallint``, ``int``, ``float``, ``double``, ``decimal``, ``varint``, ``text``,
|
|
``varchar``
|
|
``boolean`` ``text``, ``varchar``
|
|
``counter`` ``tinyint``, ``smallint``, ``int``, ``bigint``, ``float``, ``double``, ``decimal``, ``varint``,
|
|
``text``, ``varchar``
|
|
``date`` ``timestamp``
|
|
``decimal`` ``tinyint``, ``smallint``, ``int``, ``bigint``, ``float``, ``double``, ``varint``, ``text``,
|
|
``varchar``
|
|
``double`` ``tinyint``, ``smallint``, ``int``, ``bigint``, ``float``, ``decimal``, ``varint``, ``text``,
|
|
``varchar``
|
|
``float`` ``tinyint``, ``smallint``, ``int``, ``bigint``, ``double``, ``decimal``, ``varint``, ``text``,
|
|
``varchar``
|
|
``inet`` ``text``, ``varchar``
|
|
``int`` ``tinyint``, ``smallint``, ``bigint``, ``float``, ``double``, ``decimal``, ``varint``, ``text``,
|
|
``varchar``
|
|
``smallint`` ``tinyint``, ``int``, ``bigint``, ``float``, ``double``, ``decimal``, ``varint``, ``text``,
|
|
``varchar``
|
|
``time`` ``text``, ``varchar``
|
|
``timestamp`` ``date``, ``text``, ``varchar``
|
|
``timeuuid`` ``timestamp``, ``date``, ``text``, ``varchar``
|
|
``tinyint`` ``tinyint``, ``smallint``, ``int``, ``bigint``, ``float``, ``double``, ``decimal``, ``varint``,
|
|
``text``, ``varchar``
|
|
``uuid`` ``text``, ``varchar``
|
|
``varint`` ``tinyint``, ``smallint``, ``int``, ``bigint``, ``float``, ``double``, ``decimal``, ``text``,
|
|
``varchar``
|
|
=============== =======================================================================================================
|
|
|
|
The conversions rely strictly on Java's semantics. For example, the double value 1 will be converted to the text value
|
|
'1.0'. For instance::
|
|
|
|
SELECT avg(cast(count as double)) FROM myTable
|
|
|
|
Token
|
|
`````
|
|
|
|
The ``token`` function allows to compute the token for a given partition key. The exact signature of the token function
|
|
depends on the table concerned and of the partitioner used by the cluster.
|
|
|
|
The type of the arguments of the ``token`` depend on the type of the partition key columns. The return type depend on
|
|
the partitioner in use:
|
|
|
|
- For Murmur3Partitioner, the return type is ``bigint``.
|
|
- For RandomPartitioner, the return type is ``varint``.
|
|
- For ByteOrderedPartitioner, the return type is ``blob``.
|
|
|
|
For instance, in a cluster using the default Murmur3Partitioner, if a table is defined by::
|
|
|
|
CREATE TABLE users (
|
|
userid text PRIMARY KEY,
|
|
username text,
|
|
)
|
|
|
|
then the ``token`` function will take a single argument of type ``text`` (in that case, the partition key is ``userid``
|
|
(there is no clustering columns so the partition key is the same than the primary key)), and the return type will be
|
|
``bigint``.
|
|
|
|
Uuid
|
|
````
|
|
The ``uuid`` function takes no parameters and generates a random type 4 uuid suitable for use in ``INSERT`` or
|
|
``UPDATE`` statements.
|
|
|
|
.. _timeuuid-functions:
|
|
|
|
Timeuuid functions
|
|
``````````````````
|
|
|
|
``now``
|
|
#######
|
|
|
|
The ``now`` function takes no arguments and generates, on the coordinator node, a new unique timeuuid at the
|
|
time the function is invoked. Note that this method is useful for insertion but is largely non-sensical in
|
|
``WHERE`` clauses. For instance, a query of the form::
|
|
|
|
SELECT * FROM myTable WHERE t = now()
|
|
|
|
will never return any result by design, since the value returned by ``now()`` is guaranteed to be unique.
|
|
|
|
``currentTimeUUID`` is an alias of ``now``.
|
|
|
|
``minTimeuuid`` and ``maxTimeuuid``
|
|
###################################
|
|
|
|
The ``minTimeuuid`` (resp. ``maxTimeuuid``) function takes a ``timestamp`` value ``t`` (which can be `either a timestamp
|
|
or a date string <timestamps>`) and return a *fake* ``timeuuid`` corresponding to the *smallest* (resp. *biggest*)
|
|
possible ``timeuuid`` having for timestamp ``t``. So for instance::
|
|
|
|
SELECT * FROM myTable
|
|
WHERE t > maxTimeuuid('2013-01-01 00:05+0000')
|
|
AND t < minTimeuuid('2013-02-02 10:00+0000')
|
|
|
|
will select all rows where the ``timeuuid`` column ``t`` is strictly older than ``'2013-01-01 00:05+0000'`` but strictly
|
|
younger than ``'2013-02-02 10:00+0000'``. Please note that ``t >= maxTimeuuid('2013-01-01 00:05+0000')`` would still
|
|
*not* select a ``timeuuid`` generated exactly at '2013-01-01 00:05+0000' and is essentially equivalent to ``t >
|
|
maxTimeuuid('2013-01-01 00:05+0000')``.
|
|
|
|
.. note:: We called the values generated by ``minTimeuuid`` and ``maxTimeuuid`` *fake* UUID because they do no respect
|
|
the Time-Based UUID generation process specified by the `RFC 4122 <http://www.ietf.org/rfc/rfc4122.txt>`__. In
|
|
particular, the value returned by these 2 methods will not be unique. This means you should only use those methods
|
|
for querying (as in the example above). Inserting the result of those methods is almost certainly *a bad idea*.
|
|
|
|
Datetime functions
|
|
``````````````````
|
|
|
|
Retrieving the current date/time
|
|
################################
|
|
|
|
The following functions can be used to retrieve the date/time at the time where the function is invoked:
|
|
|
|
===================== ===============
|
|
Function name Output type
|
|
===================== ===============
|
|
``currentTimestamp`` ``timestamp``
|
|
``currentDate`` ``date``
|
|
``currentTime`` ``time``
|
|
``currentTimeUUID`` ``timeUUID``
|
|
===================== ===============
|
|
|
|
For example the last 2 days of data can be retrieved using::
|
|
|
|
SELECT * FROM myTable WHERE date >= currentDate() - 2d
|
|
|
|
Time conversion functions
|
|
#########################
|
|
|
|
A number of functions are provided to “convert” a ``timeuuid``, a ``timestamp`` or a ``date`` into another ``native``
|
|
type.
|
|
|
|
===================== =============== ===================================================================
|
|
Function name Input type Description
|
|
===================== =============== ===================================================================
|
|
``toDate`` ``timeuuid`` Converts the ``timeuuid`` argument into a ``date`` type
|
|
``toDate`` ``timestamp`` Converts the ``timestamp`` argument into a ``date`` type
|
|
``toTimestamp`` ``timeuuid`` Converts the ``timeuuid`` argument into a ``timestamp`` type
|
|
``toTimestamp`` ``date`` Converts the ``date`` argument into a ``timestamp`` type
|
|
``toUnixTimestamp`` ``timeuuid`` Converts the ``timeuuid`` argument into a ``bigInt`` raw value
|
|
``toUnixTimestamp`` ``timestamp`` Converts the ``timestamp`` argument into a ``bigInt`` raw value
|
|
``toUnixTimestamp`` ``date`` Converts the ``date`` argument into a ``bigInt`` raw value
|
|
``dateOf`` ``timeuuid`` Similar to ``toTimestamp(timeuuid)`` (DEPRECATED)
|
|
``unixTimestampOf`` ``timeuuid`` Similar to ``toUnixTimestamp(timeuuid)`` (DEPRECATED)
|
|
===================== =============== ===================================================================
|
|
|
|
Blob conversion functions
|
|
`````````````````````````
|
|
A number of functions are provided to “convert” the native types into binary data (``blob``). For every
|
|
``<native-type>`` ``type`` supported by CQL (a notable exceptions is ``blob``, for obvious reasons), the function
|
|
``typeAsBlob`` takes a argument of type ``type`` and return it as a ``blob``. Conversely, the function ``blobAsType``
|
|
takes a 64-bit ``blob`` argument and convert it to a ``bigint`` value. And so for instance, ``bigintAsBlob(3)`` is
|
|
``0x0000000000000003`` and ``blobAsBigint(0x0000000000000003)`` is ``3``.
|
|
|
|
.. _user-defined-scalar-functions:
|
|
|
|
User-defined functions
|
|
~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
User-defined functions allow execution of user-provided code in Cassandra. By default, Cassandra supports defining
|
|
functions in *Java* and *JavaScript*. Support for other JSR 223 compliant scripting languages (such as Python, Ruby, and
|
|
Scala) can be added by adding a JAR to the classpath.
|
|
|
|
UDFs are part of the Cassandra schema. As such, they are automatically propagated to all nodes in the cluster.
|
|
|
|
UDFs can be *overloaded* - i.e. multiple UDFs with different argument types but the same function name. Example::
|
|
|
|
CREATE FUNCTION sample ( arg int ) ...;
|
|
CREATE FUNCTION sample ( arg text ) ...;
|
|
|
|
User-defined functions are susceptible to all of the normal problems with the chosen programming language. Accordingly,
|
|
implementations should be safe against null pointer exceptions, illegal arguments, or any other potential source of
|
|
exceptions. An exception during function execution will result in the entire statement failing.
|
|
|
|
It is valid to use *complex* types like collections, tuple types and user-defined types as argument and return types.
|
|
Tuple types and user-defined types are handled by the conversion functions of the DataStax Java Driver. Please see the
|
|
documentation of the Java Driver for details on handling tuple types and user-defined types.
|
|
|
|
Arguments for functions can be literals or terms. Prepared statement placeholders can be used, too.
|
|
|
|
Note that you can use the double-quoted string syntax to enclose the UDF source code. For example::
|
|
|
|
CREATE FUNCTION some_function ( arg int )
|
|
RETURNS NULL ON NULL INPUT
|
|
RETURNS int
|
|
LANGUAGE java
|
|
AS $$ return arg; $$;
|
|
|
|
SELECT some_function(column) FROM atable ...;
|
|
UPDATE atable SET col = some_function(?) ...;
|
|
|
|
CREATE TYPE custom_type (txt text, i int);
|
|
CREATE FUNCTION fct_using_udt ( udtarg frozen )
|
|
RETURNS NULL ON NULL INPUT
|
|
RETURNS text
|
|
LANGUAGE java
|
|
AS $$ return udtarg.getString("txt"); $$;
|
|
|
|
User-defined functions can be used in ``SELECT``, ``INSERT`` and ``UPDATE`` statements.
|
|
|
|
The implicitly available ``udfContext`` field (or binding for script UDFs) provides the necessary functionality to
|
|
create new UDT and tuple values::
|
|
|
|
CREATE TYPE custom_type (txt text, i int);
|
|
CREATE FUNCTION fct\_using\_udt ( somearg int )
|
|
RETURNS NULL ON NULL INPUT
|
|
RETURNS custom_type
|
|
LANGUAGE java
|
|
AS $$
|
|
UDTValue udt = udfContext.newReturnUDTValue();
|
|
udt.setString("txt", "some string");
|
|
udt.setInt("i", 42);
|
|
return udt;
|
|
$$;
|
|
|
|
The definition of the ``UDFContext`` interface can be found in the Apache Cassandra source code for
|
|
``org.apache.cassandra.cql3.functions.UDFContext``.
|
|
|
|
.. code-block:: java
|
|
|
|
public interface UDFContext
|
|
{
|
|
UDTValue newArgUDTValue(String argName);
|
|
UDTValue newArgUDTValue(int argNum);
|
|
UDTValue newReturnUDTValue();
|
|
UDTValue newUDTValue(String udtName);
|
|
TupleValue newArgTupleValue(String argName);
|
|
TupleValue newArgTupleValue(int argNum);
|
|
TupleValue newReturnTupleValue();
|
|
TupleValue newTupleValue(String cqlDefinition);
|
|
}
|
|
|
|
Java UDFs already have some imports for common interfaces and classes defined. These imports are:
|
|
|
|
.. code-block:: java
|
|
|
|
import java.nio.ByteBuffer;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
import org.apache.cassandra.cql3.functions.UDFContext;
|
|
import com.datastax.driver.core.TypeCodec;
|
|
import com.datastax.driver.core.TupleValue;
|
|
import com.datastax.driver.core.UDTValue;
|
|
|
|
Please note, that these convenience imports are not available for script UDFs.
|
|
|
|
.. _create-function-statement:
|
|
|
|
CREATE FUNCTION
|
|
```````````````
|
|
|
|
Creating a new user-defined function uses the ``CREATE FUNCTION`` statement:
|
|
|
|
.. productionlist::
|
|
create_function_statement: CREATE [ OR REPLACE ] FUNCTION [ IF NOT EXISTS]
|
|
: `function_name` '(' `arguments_declaration` ')'
|
|
: [ CALLED | RETURNS NULL ] ON NULL INPUT
|
|
: RETURNS `cql_type`
|
|
: LANGUAGE `identifier`
|
|
: AS `string`
|
|
arguments_declaration: `identifier` `cql_type` ( ',' `identifier` `cql_type` )*
|
|
|
|
For instance::
|
|
|
|
CREATE OR REPLACE FUNCTION somefunction(somearg int, anotherarg text, complexarg frozen<someUDT>, listarg list)
|
|
RETURNS NULL ON NULL INPUT
|
|
RETURNS text
|
|
LANGUAGE java
|
|
AS $$
|
|
// some Java code
|
|
$$;
|
|
|
|
CREATE FUNCTION IF NOT EXISTS akeyspace.fname(someArg int)
|
|
CALLED ON NULL INPUT
|
|
RETURNS text
|
|
LANGUAGE java
|
|
AS $$
|
|
// some Java code
|
|
$$;
|
|
|
|
``CREATE FUNCTION`` with the optional ``OR REPLACE`` keywords either creates a function or replaces an existing one with
|
|
the same signature. A ``CREATE FUNCTION`` without ``OR REPLACE`` fails if a function with the same signature already
|
|
exists.
|
|
|
|
If the optional ``IF NOT EXISTS`` keywords are used, the function will
|
|
only be created if another function with the same signature does not
|
|
exist.
|
|
|
|
``OR REPLACE`` and ``IF NOT EXISTS`` cannot be used together.
|
|
|
|
Behavior on invocation with ``null`` values must be defined for each
|
|
function. There are two options:
|
|
|
|
#. ``RETURNS NULL ON NULL INPUT`` declares that the function will always
|
|
return ``null`` if any of the input arguments is ``null``.
|
|
#. ``CALLED ON NULL INPUT`` declares that the function will always be
|
|
executed.
|
|
|
|
Function Signature
|
|
##################
|
|
|
|
Signatures are used to distinguish individual functions. The signature consists of:
|
|
|
|
#. The fully qualified function name - i.e *keyspace* plus *function-name*
|
|
#. The concatenated list of all argument types
|
|
|
|
Note that keyspace names, function names and argument types are subject to the default naming conventions and
|
|
case-sensitivity rules.
|
|
|
|
Functions belong to a keyspace. If no keyspace is specified in ``<function-name>``, the current keyspace is used (i.e.
|
|
the keyspace specified using the ``USE`` statement). It is not possible to create a user-defined function in one of the
|
|
system keyspaces.
|
|
|
|
.. _drop-function-statement:
|
|
|
|
DROP FUNCTION
|
|
`````````````
|
|
|
|
Dropping a function uses the ``DROP FUNCTION`` statement:
|
|
|
|
.. productionlist::
|
|
drop_function_statement: DROP FUNCTION [ IF EXISTS ] `function_name` [ '(' `arguments_signature` ')' ]
|
|
arguments_signature: `cql_type` ( ',' `cql_type` )*
|
|
|
|
For instance::
|
|
|
|
DROP FUNCTION myfunction;
|
|
DROP FUNCTION mykeyspace.afunction;
|
|
DROP FUNCTION afunction ( int );
|
|
DROP FUNCTION afunction ( text );
|
|
|
|
You must specify the argument types (:token:`arguments_signature`) of the function to drop if there are multiple
|
|
functions with the same name but a different signature (overloaded functions).
|
|
|
|
``DROP FUNCTION`` with the optional ``IF EXISTS`` keywords drops a function if it exists, but does not throw an error if
|
|
it doesn't
|
|
|
|
.. _aggregate-functions:
|
|
|
|
Aggregate functions
|
|
^^^^^^^^^^^^^^^^^^^
|
|
|
|
Aggregate functions work on a set of rows. They receive values for each row and returns one value for the whole set.
|
|
|
|
If ``normal`` columns, ``scalar functions``, ``UDT`` fields, ``writetime`` or ``ttl`` are selected together with
|
|
aggregate functions, the values returned for them will be the ones of the first row matching the query.
|
|
|
|
Native aggregates
|
|
~~~~~~~~~~~~~~~~~
|
|
|
|
.. _count-function:
|
|
|
|
Count
|
|
`````
|
|
|
|
The ``count`` function can be used to count the rows returned by a query. Example::
|
|
|
|
SELECT COUNT (*) FROM plays;
|
|
SELECT COUNT (1) FROM plays;
|
|
|
|
It also can be used to count the non null value of a given column::
|
|
|
|
SELECT COUNT (scores) FROM plays;
|
|
|
|
Max and Min
|
|
```````````
|
|
|
|
The ``max`` and ``min`` functions can be used to compute the maximum and the minimum value returned by a query for a
|
|
given column. For instance::
|
|
|
|
SELECT MIN (players), MAX (players) FROM plays WHERE game = 'quake';
|
|
|
|
Sum
|
|
```
|
|
|
|
The ``sum`` function can be used to sum up all the values returned by a query for a given column. For instance::
|
|
|
|
SELECT SUM (players) FROM plays;
|
|
|
|
Avg
|
|
```
|
|
|
|
The ``avg`` function can be used to compute the average of all the values returned by a query for a given column. For
|
|
instance::
|
|
|
|
SELECT AVG (players) FROM plays;
|
|
|
|
.. _user-defined-aggregates-functions:
|
|
|
|
User-Defined Aggregates
|
|
~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
User-defined aggregates allow the creation of custom aggregate functions. Common examples of aggregate functions are
|
|
*count*, *min*, and *max*.
|
|
|
|
Each aggregate requires an *initial state* (``INITCOND``, which defaults to ``null``) of type ``STYPE``. The first
|
|
argument of the state function must have type ``STYPE``. The remaining arguments of the state function must match the
|
|
types of the user-defined aggregate arguments. The state function is called once for each row, and the value returned by
|
|
the state function becomes the new state. After all rows are processed, the optional ``FINALFUNC`` is executed with last
|
|
state value as its argument.
|
|
|
|
``STYPE`` is mandatory in order to be able to distinguish possibly overloaded versions of the state and/or final
|
|
function (since the overload can appear after creation of the aggregate).
|
|
|
|
User-defined aggregates can be used in ``SELECT`` statement.
|
|
|
|
A complete working example for user-defined aggregates (assuming that a keyspace has been selected using the ``USE``
|
|
statement)::
|
|
|
|
CREATE OR REPLACE FUNCTION averageState(state tuple<int,bigint>, val int)
|
|
CALLED ON NULL INPUT
|
|
RETURNS tuple
|
|
LANGUAGE java
|
|
AS $$
|
|
if (val != null) {
|
|
state.setInt(0, state.getInt(0)+1);
|
|
state.setLong(1, state.getLong(1)+val.intValue());
|
|
}
|
|
return state;
|
|
$$;
|
|
|
|
CREATE OR REPLACE FUNCTION averageFinal (state tuple<int,bigint>)
|
|
CALLED ON NULL INPUT
|
|
RETURNS double
|
|
LANGUAGE java
|
|
AS $$
|
|
double r = 0;
|
|
if (state.getInt(0) == 0) return null;
|
|
r = state.getLong(1);
|
|
r /= state.getInt(0);
|
|
return Double.valueOf(r);
|
|
$$;
|
|
|
|
CREATE OR REPLACE AGGREGATE average(int)
|
|
SFUNC averageState
|
|
STYPE tuple
|
|
FINALFUNC averageFinal
|
|
INITCOND (0, 0);
|
|
|
|
CREATE TABLE atable (
|
|
pk int PRIMARY KEY,
|
|
val int
|
|
);
|
|
|
|
INSERT INTO atable (pk, val) VALUES (1,1);
|
|
INSERT INTO atable (pk, val) VALUES (2,2);
|
|
INSERT INTO atable (pk, val) VALUES (3,3);
|
|
INSERT INTO atable (pk, val) VALUES (4,4);
|
|
|
|
SELECT average(val) FROM atable;
|
|
|
|
.. _create-aggregate-statement:
|
|
|
|
CREATE AGGREGATE
|
|
````````````````
|
|
|
|
Creating (or replacing) a user-defined aggregate function uses the ``CREATE AGGREGATE`` statement:
|
|
|
|
.. productionlist::
|
|
create_aggregate_statement: CREATE [ OR REPLACE ] AGGREGATE [ IF NOT EXISTS ]
|
|
: `function_name` '(' `arguments_signature` ')'
|
|
: SFUNC `function_name`
|
|
: STYPE `cql_type`
|
|
: [ FINALFUNC `function_name` ]
|
|
: [ INITCOND `term` ]
|
|
|
|
See above for a complete example.
|
|
|
|
``CREATE AGGREGATE`` with the optional ``OR REPLACE`` keywords either creates an aggregate or replaces an existing one
|
|
with the same signature. A ``CREATE AGGREGATE`` without ``OR REPLACE`` fails if an aggregate with the same signature
|
|
already exists.
|
|
|
|
``CREATE AGGREGATE`` with the optional ``IF NOT EXISTS`` keywords either creates an aggregate if it does not already
|
|
exist.
|
|
|
|
``OR REPLACE`` and ``IF NOT EXISTS`` cannot be used together.
|
|
|
|
``STYPE`` defines the type of the state value and must be specified.
|
|
|
|
The optional ``INITCOND`` defines the initial state value for the aggregate. It defaults to ``null``. A non-\ ``null``
|
|
``INITCOND`` must be specified for state functions that are declared with ``RETURNS NULL ON NULL INPUT``.
|
|
|
|
``SFUNC`` references an existing function to be used as the state modifying function. The type of first argument of the
|
|
state function must match ``STYPE``. The remaining argument types of the state function must match the argument types of
|
|
the aggregate function. State is not updated for state functions declared with ``RETURNS NULL ON NULL INPUT`` and called
|
|
with ``null``.
|
|
|
|
The optional ``FINALFUNC`` is called just before the aggregate result is returned. It must take only one argument with
|
|
type ``STYPE``. The return type of the ``FINALFUNC`` may be a different type. A final function declared with ``RETURNS
|
|
NULL ON NULL INPUT`` means that the aggregate's return value will be ``null``, if the last state is ``null``.
|
|
|
|
If no ``FINALFUNC`` is defined, the overall return type of the aggregate function is ``STYPE``. If a ``FINALFUNC`` is
|
|
defined, it is the return type of that function.
|
|
|
|
.. _drop-aggregate-statement:
|
|
|
|
DROP AGGREGATE
|
|
``````````````
|
|
|
|
Dropping an user-defined aggregate function uses the ``DROP AGGREGATE`` statement:
|
|
|
|
.. productionlist::
|
|
drop_aggregate_statement: DROP AGGREGATE [ IF EXISTS ] `function_name` [ '(' `arguments_signature` ')' ]
|
|
|
|
For instance::
|
|
|
|
DROP AGGREGATE myAggregate;
|
|
DROP AGGREGATE myKeyspace.anAggregate;
|
|
DROP AGGREGATE someAggregate ( int );
|
|
DROP AGGREGATE someAggregate ( text );
|
|
|
|
The ``DROP AGGREGATE`` statement removes an aggregate created using ``CREATE AGGREGATE``. You must specify the argument
|
|
types of the aggregate to drop if there are multiple aggregates with the same name but a different signature (overloaded
|
|
aggregates).
|
|
|
|
``DROP AGGREGATE`` with the optional ``IF EXISTS`` keywords drops an aggregate if it exists, and does nothing if a
|
|
function with the signature does not exist.
|