函数
CQL 支持两大类函数
在这两种情况下,CQL 都提供了一些本地的“硬编码”函数,以及创建新的用户定义函数的能力。
默认情况下,出于安全考虑,用户定义函数默认情况下是禁用的(即使启用,用户定义函数的执行也是沙盒化的,并且“恶意”函数不应该被允许做坏事,但没有沙盒是完美的,因此使用用户定义函数是选择加入的)。请参阅 |
函数由其名称标识
function_name ::= [ keyspace_name'.' ] name
标量函数
原生函数
强制转换
cast
函数可用于将一种原生数据类型转换为另一种数据类型。
下表描述了 cast
函数支持的转换。Cassandra 会静默忽略将数据类型转换为其自身数据类型的任何强制转换。
从 | 到 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
转换严格依赖于 Java 的语义。例如,双精度值 1 将转换为文本值 '1.0'。例如
SELECT avg(cast(count as double)) FROM myTable
令牌
token
函数计算给定分区键的令牌。令牌函数的确切签名取决于所关注的表和集群使用的分区器。
token
的参数类型取决于分区键列类型。返回类型取决于定义的分区器
分区器 | 返回类型 |
---|---|
Murmur3Partitioner |
|
RandomPartitioner |
|
ByteOrderedPartitioner |
|
例如,考虑以下表
CREATE TABLE users (
userid text PRIMARY KEY,
username text,
);
该表使用默认的 Murmur3Partitioner。token
函数使用单个参数 text
,因为分区键是 userid
,类型为 text。返回类型将为 bigint
。
Timeuuid 函数
now
now
函数不接受任何参数,并在协调器节点上生成一个新的唯一 timeuuid,时间为函数被调用时的时间。请注意,此方法对于插入很有用,但在 WHERE
子句中基本上没有意义。
例如,以下形式的查询
SELECT * FROM myTable WHERE t = now();
将不会返回结果,因为设计使然,因为 now()
返回的值保证是唯一的。
current_timeuuid
是 now
的别名。
min_timeuuid
和 max_timeuuid
min_timeuuid
函数接受一个 timestamp
值 t
,可以是时间戳或日期字符串。它返回一个伪timeuuid
,对应于时间戳 t
的最小可能 timeuuid
。max_timeuuid
的工作原理类似,但返回最大可能 timeuuid
。
例如
SELECT * FROM myTable
WHERE t > max_timeuuid('2013-01-01 00:05+0000')
AND t < min_timeuuid('2013-02-02 10:00+0000');
将选择 timeuuid
列 t
在 '2013-01-01 00:05+0000'
之后且在 '2013-02-02 10:00+0000'
之前的所有行。子句 t >= maxTimeuuid('2013-01-01 00:05+0000')
仍然不会选择在 '2013-01-01 00:05+0000' 处生成的 timeuuid
,并且本质上等效于 t > maxTimeuuid('2013-01-01 00:05+0000')
。
|
日期时间函数
检索当前日期/时间
以下函数可用于检索函数被调用时的日期/时间
函数名称 | 输出类型 |
---|---|
|
|
|
|
|
|
|
|
例如,可以使用以下方法检索过去两天的数据
SELECT * FROM myTable WHERE date >= current_date() - 2d;
时间转换函数
提供了一些函数,用于将 timeuuid
、timestamp
或 date
转换为其他 native
类型。
函数名称 | 输入类型 | 描述 |
---|---|---|
|
|
将 |
|
|
将 |
|
|
将 |
|
|
将 |
|
|
将 |
|
|
将 |
|
|
将 |
Blob 转换函数
提供了一些函数,用于将原生类型转换为二进制数据或 blob
。对于 CQL 支持的每种 类型,函数 type_as_blob
接受类型为 type
的参数,并将其作为 blob
返回。相反,函数 blob_as_type
接受一个 64 位 blob
参数,并将其转换为 bigint
值。例如,bigint_as_blob(3)
返回 0x0000000000000003
,而 blob_as_bigint(0x0000000000000003)
返回 3
。
数学函数
Cql 提供以下数学函数:abs
、exp
、log
、log10
和 round
。这些函数的返回类型始终与输入类型相同。
函数名称 | 描述 |
---|---|
|
返回输入的绝对值。 |
|
返回 e 的输入次方。 |
|
返回输入的自然对数。 |
|
返回输入以 10 为底的对数。 |
|
使用舍入模式 |
集合函数
提供了一些函数,用于对集合列进行操作。
函数名称 | 输入类型 | 描述 |
---|---|---|
|
|
获取 |
|
|
获取 |
|
|
获取集合参数中的元素数量。 |
|
|
获取集合参数中的最小元素。 |
|
|
获取集合参数中的最大元素。 |
|
数值 |
计算集合参数中所有元素的总和。返回值与输入集合元素的类型相同,因此如果值的总和超过类型所能表示的最大值,则存在数据类型溢出的风险。 |
|
数值 |
计算集合参数中所有元素的平均值。空集合的平均值为零。返回值与输入集合元素的类型相同,可能包含舍入和截断。例如, |
数据屏蔽函数
一些函数允许隐藏包含敏感数据的列的真实内容。
函数 | 描述 |
---|---|
|
将第一个参数替换为 示例
|
|
将它的参数替换为相同类型的任意固定默认值。对于文本值,这将是 可变长度多值类型(如列表、集合和映射)被屏蔽为空集合。 固定长度多值类型(如元组、用户定义类型 (UDT) 和向量)通过将每个值替换为值类型的默认屏蔽值来屏蔽。 示例
|
|
将第一个参数替换为第二个参数上的替换值。替换值需要与被替换值具有相同的类型。 示例
|
|
返回第一个 示例
|
|
返回第一个 示例
|
|
返回包含第一个参数哈希值的 示例
|
向量相似度函数
一些函数允许获取浮点数向量的相似度得分。
函数 | 描述 |
---|---|
|
计算两个相同维度的浮点数向量的余弦相似度得分。 示例
|
|
计算两个相同维度的浮点数向量的欧几里得距离。 示例
|
|
计算两个相同维度的浮点数向量的点积。 示例
|
用户定义的标量函数
用户定义函数 (UDF) 在 Cassandra 中执行用户提供的代码。默认情况下,Cassandra 支持在 Java 中定义函数。
UDF 是 Cassandra 架构的一部分,并自动传播到集群中的所有节点。UDF 可以 重载,因此具有不同参数类型的多个 UDF 可以具有相同的函数名。
JavaScript 用户定义函数在 Cassandra 4.1 中已被弃用。为了准备 Cassandra 5.0,它们的移除工作已经开始。有关更多信息,请参阅 CASSANDRA-17281、CASSANDRA-18252。 |
例如
CREATE FUNCTION sample ( arg int ) ...;
CREATE FUNCTION sample ( arg text ) ...;
UDF 容易受到所选编程语言的所有常见问题的困扰。因此,实现应该对空指针异常、非法参数或任何其他潜在的异常来源是安全的。函数执行期间的异常将导致整个语句失败。UDF 使用的有效查询是 SELECT
、INSERT
和 UPDATE
语句。
复杂 类型(如集合、元组类型和用户定义类型)是 UDF 中有效的参数和返回值类型。元组类型和用户定义类型使用 DataStax Java 驱动程序转换函数。有关处理元组类型和用户定义类型的详细信息,请参阅 Java 驱动程序文档。
函数的参数可以是字面量或项。准备好的语句占位符也可以使用。
请注意使用双美元符号语法来包含 UDF 源代码。
例如
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"); $$;
隐式可用的 udfContext
字段(或脚本 UDF 的绑定)提供了创建新的 UDT 和元组值所需的必要功能
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;
$$;
UDFContext
接口的定义可以在 Apache Cassandra 源代码中找到,用于 org.apache.cassandra.cql3.functions.UDFContext
。
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 UDF 已经包含一些用于定义常见接口和类的导入。这些导入是
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;
请注意,这些便捷导入不适用于脚本 UDF。
CREATE FUNCTION 语句
创建新的用户定义函数使用 CREATE FUNCTION
语句
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 )*
例如
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
$$;
带有可选 OR REPLACE
关键字的 CREATE FUNCTION
创建一个函数或用具有相同签名的函数替换现有函数。没有 OR REPLACE
的 CREATE FUNCTION
如果已经存在具有相同签名的函数,则会失败。如果使用可选的 IF NOT EXISTS
关键字,则只有在不存在具有相同签名的其他函数时才会创建函数。OR REPLACE
和 IF NOT EXISTS
不能一起使用。
必须为每个函数定义 null
输入值的处理方式
-
RETURNS NULL ON NULL INPUT
声明如果任何输入参数为null
,则函数将始终返回null
。 -
CALLED ON NULL INPUT
声明函数将始终被执行。
DROP FUNCTION 语句
删除函数使用 DROP FUNCTION
语句
drop_function_statement::= DROP FUNCTION [ IF EXISTS ] function_name [ '(' arguments_signature ')' ]
arguments_signature::= cql_type ( ',' cql_type )*
例如
DROP FUNCTION myfunction;
DROP FUNCTION mykeyspace.afunction;
DROP FUNCTION afunction ( int );
DROP FUNCTION afunction ( text );
如果存在多个具有相同名称但不同签名的重载函数,则必须在删除命令中指定函数的参数类型,即 arguments_signature。带有可选 IF EXISTS
关键字的 DROP FUNCTION
如果函数存在则删除函数,但如果不存在则不会抛出错误。
聚合函数
聚合函数作用于一组行。每个行的值作为输入,以返回为聚合的行集返回的单个值。
如果 normal
列、scalar functions
、UDT
字段、writetime
或 ttl
与聚合函数一起被选中,则为它们返回的值将是与查询匹配的第一行的值。
原生聚合
Count
count
函数可用于计算查询返回的行数。
例如
SELECT COUNT (*) FROM plays;
SELECT COUNT (1) FROM plays;
它还可以计算给定列的非空值数量
SELECT COUNT (scores) FROM plays;
Max 和 Min
max
和 min
函数计算查询为给定列返回的最大值和最小值。
例如
SELECT MIN (players), MAX (players) FROM plays WHERE game = 'quake';
用户定义的聚合函数 (UDA)
用户定义的聚合允许创建自定义聚合函数。用户定义的聚合可以在 SELECT
语句中使用。
每个聚合函数需要一个类型为 STYPE
的初始状态,由 INITCOND
值定义(默认值为 null
)。状态函数的第一个参数必须为 STYPE
类型。状态函数的其余参数必须与用户定义的聚合函数参数的类型匹配。状态函数对每行调用一次,状态函数返回的值将成为新的状态。处理完所有行后,可选的 FINALFUNC
将使用最后一个状态值作为其参数执行。
STYPE
值是强制性的,以便区分状态和/或最终函数的可能重载版本,因为重载可能在创建聚合函数后出现。
用户定义聚合函数的完整工作示例(假设已使用 USE
语句选择了一个键空间)
CREATE OR REPLACE FUNCTION test.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 test.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 test.average(int)
SFUNC averageState
STYPE tuple
FINALFUNC averageFinal
INITCOND (0, 0);
CREATE TABLE test.atable (
pk int PRIMARY KEY,
val int
);
INSERT INTO test.atable (pk, val) VALUES (1,1);
INSERT INTO test.atable (pk, val) VALUES (2,2);
INSERT INTO test.atable (pk, val) VALUES (3,3);
INSERT INTO test.atable (pk, val) VALUES (4,4);
SELECT test.average(val) FROM atable;
CREATE AGGREGATE 语句
创建(或替换)用户定义的聚合函数使用 CREATE AGGREGATE
语句
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 ]
有关完整示例,请参见上文。
CREATE AGGREGATE
命令使用可选的 OR REPLACE
关键字创建聚合函数,或者用具有相同签名的聚合函数替换现有聚合函数。如果已存在具有相同签名的聚合函数,则不带 OR REPLACE
的 CREATE AGGREGATE
命令将失败。CREATE AGGREGATE
命令使用可选的 IF NOT EXISTS
关键字创建聚合函数(如果不存在)。OR REPLACE
和 IF NOT EXISTS
短语不能一起使用。
STYPE
值定义状态值的类型,必须指定。可选的 INITCOND
定义聚合函数的初始状态值;默认值为 null
。对于声明为 RETURNS NULL ON NULL INPUT
的状态函数,必须指定非空 INITCOND
。
SFUNC
值引用一个现有的函数,用作修改状态的函数。状态函数的第一个参数必须为 STYPE
类型。状态函数的其余参数必须与用户定义的聚合函数参数的类型匹配。状态函数对每行调用一次,状态函数返回的值将成为新的状态。对于声明为 RETURNS NULL ON NULL INPUT
并使用 null
调用的状态函数,状态不会更新。处理完所有行后,可选的 FINALFUNC
将使用最后一个状态值作为其参数执行。它必须只接受一个类型为 STYPE
的参数,但 FINALFUNC
的返回类型可能不同。声明为 RETURNS NULL ON NULL INPUT
的最终函数意味着如果最后一个状态为 null
,则聚合函数的返回值将为 null
。
如果未定义 FINALFUNC
,则聚合函数的总体返回类型为 STYPE
。如果定义了 FINALFUNC
,则为该函数的返回类型。
DROP AGGREGATE 语句
删除用户定义的聚合函数使用 DROP AGGREGATE
语句
drop_aggregate_statement::= DROP AGGREGATE [ IF EXISTS ] function_name[ '(' arguments_signature ')'
]
例如
DROP AGGREGATE myAggregate;
DROP AGGREGATE myKeyspace.anAggregate;
DROP AGGREGATE someAggregate ( int );
DROP AGGREGATE someAggregate ( text );
DROP AGGREGATE
语句删除使用 CREATE AGGREGATE
创建的聚合函数。如果存在多个具有相同名称但签名不同的重载聚合函数,则必须指定要删除的聚合函数的参数类型。
DROP AGGREGATE
命令使用可选的 IF EXISTS
关键字删除聚合函数(如果存在),如果不存在具有该签名的函数,则不执行任何操作。