函數
CQL 支援 2 個主要類別的函數
在這兩種情況下,CQL 都提供多個原生「硬式編碼」函數,以及建立新的使用者定義函數的能力。
預設情況下,考量到安全性問題,預設會停用使用者定義函數(即使已啟用,使用者定義函數的執行也會受到沙盒保護,而且「流氓」函數不應被允許執行惡意行為,但沒有任何沙盒是完美的,因此使用使用者定義函數是選擇加入的)。請參閱 |
函數會根據其名稱來識別
function_name ::= [ keyspace_name'.' ] name
純量函數
原生函數
轉換
cast
函數可將一種原生資料類型轉換為另一種。
下表說明 cast
函數支援的轉換。Cassandra 會自動忽略任何將資料類型轉換為其本身資料類型的轉換。
從 | 轉換為 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
轉換嚴格依循 Java 的語意。例如,double 值 1 會轉換為文字值 '1.0'。例如
SELECT avg(cast(count as double)) FROM myTable
Token
token
函數會計算給定分區金鑰的 token。token 函數的確切簽章取決於相關的表格和叢集使用的分區器。
token
參數的類型取決於分區金鑰欄位類型。傳回的類型取決於定義的分區器
分區器 | 傳回的類型 |
---|---|
Murmur3Partitioner |
|
RandomPartitioner |
|
ByteOrderedPartitioner |
|
例如,考慮下列表格
CREATE TABLE users (
userid text PRIMARY KEY,
username text,
);
表格使用預設的 Murmur3Partitioner。token
函數使用單一參數 text
,因為分區金鑰是文字類型的 userid
。傳回的類型將會是 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')
。
|
Datetime 函數
擷取目前的日期/時間
下列函數可用於在函數被呼叫時擷取日期/時間
函數名稱 | 輸出類型 |
---|---|
|
|
|
|
|
|
|
|
例如,可以使用下列方式擷取過去兩天的資料
SELECT * FROM myTable WHERE date >= current_date() - 2d;
時間轉換函數
提供了一些函數,用於將 timeuuid
、timestamp
或 date
轉換成另一種 原生
類型。
函數名稱 | 輸入類型 | 說明 |
---|---|---|
|
|
將 |
|
|
將 |
|
|
將 |
|
|
將 |
|
|
將 |
|
|
將 |
|
|
將 |
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
$$;
CREATE FUNCTION
搭配選用的 OR REPLACE
關鍵字會建立函式或取代具有相同簽章的現有函式。如果已經存在具有相同簽章的函式,則不含 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 函式
、UDT
欄位、writetime
或 ttl
,則為其傳回的值將是符合查詢的第一列的值。
原生聚集
計數
count
函式可用於計數查詢傳回的列。
例如
SELECT COUNT (*) FROM plays;
SELECT COUNT (1) FROM plays;
它也可以計數特定欄位的非 Null 值
SELECT COUNT (scores) FROM plays;
最大值和最小值
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
會失敗。具有選用 IF NOT EXISTS
關鍵字的 CREATE AGGREGATE
命令會在聚合不存在時建立聚合。OR REPLACE
和 IF NOT EXISTS
短語不能一起使用。
STYPE
值定義狀態值的類型,且必須指定。選用的 INITCOND
定義聚合的初始狀態值;預設值為 null
。對於宣告為 RETURNS NULL ON NULL INPUT
的狀態函數,必須指定非 null
的 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
建立的聚合。如果有多個重載的聚合具有相同名稱但簽章不同,則您必須指定要刪除的聚合的引數類型。
包含選用 IF EXISTS
關鍵字的 DROP AGGREGATE
指令會在聚合存在時將其刪除,如果簽章中沒有函數,則不會執行任何動作。