関数
CQL は、2 つの主要なカテゴリの関数をサポートしています。
どちらの場合も、CQL は多数のネイティブな「ハードコーディングされた」関数と、新しいユーザー定義関数を生成する機能を提供します。
デフォルトでは、セキュリティ上の懸念から、ユーザー定義関数の使用は無効になっています(有効にしても、ユーザー定義関数の実行はサンドボックス化され、「不正な」関数による悪質な行為は許可されませんが、完璧なサンドボックスはないため、ユーザー定義関数の使用はオプトインです)。それらを有効にするには、 |
関数は、その名前で識別されます。
function_name ::= [ keyspace_name'.' ] name
スカラー関数
ネイティブ関数
キャスト
cast
関数は、ネイティブデータ型を別の型に変換するために使用できます。
次の表は、cast
関数がサポートする変換を示しています。Cassandra は、データ型をそれ自身のデータ型に変換するキャストを黙って無視します。
変換元 | 変換先 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
変換は、Java のセマンティクスに厳密に従います。たとえば、double 値の 1 は、text 値 '1.0' に変換されます。たとえば
SELECT avg(cast(count as double)) FROM myTable
トークン
token
関数は、指定されたパーティションキーのトークンを計算します。token
関数の正確なシグネチャは、対象のテーブルとクラスタで使用されるパーティショナーによって異なります。
token
の引数の型は、パーティションキーの列の型によって異なります。戻り値の型は、定義されたパーティショナーによって異なります。
パーティショナー | 戻り値の型 |
---|---|
Murmur3Partitioner |
|
RandomPartitioner |
|
ByteOrderedPartitioner |
|
たとえば、次のテーブルを考えてみます。
CREATE TABLE users (
userid text PRIMARY KEY,
username text,
);
このテーブルは、デフォルトのMurmur3Partitionerを使用しています。パーティションキーがtext型のuserid
であるため、token
関数は単一の引数text
を使用します。戻り値の型はbigint
になります。
Timeuuid関数
now
now
関数は引数を取らず、コーディネータノードで、関数が呼び出された時点の新しい一意のtimeuuidを生成します。このメソッドは挿入には便利ですが、WHERE
句ではほとんど意味がありません。
たとえば、次の形式のクエリは
SELECT * FROM myTable WHERE t = now();
設計上、結果は返されません。これは、now()
によって返される値が一意であることが保証されているためです。
current_timeuuid
はnow
のエイリアスです。
min_timeuuid
とmax_timeuuid
min_timeuuid
関数は、タイムスタンプまたは日付文字列のいずれかのタイムスタンプ値t
を取ります。タイムスタンプt
の*最小*の可能なtimeuuid
に対応する*偽の*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')
と同等です。
|
日付時刻関数
現在の日付時刻の取得
関数が呼び出された時点の日付時刻を取得するには、次の関数を使用できます。
関数名 | 出力型 |
---|---|
|
|
|
|
|
|
|
|
たとえば、過去2日間のデータは次のように取得できます。
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)、ベクトルなどの固定長多値型は、それぞれの値を値型のデフォルトマスキング値に置き換えることでマスクされます。 例
|
|
最初の引数を、2番目の引数の置換値に置き換えます。置換値は、置き換えられる値と同じ型である必要があります。 例
|
|
最初の 例
|
|
最初の 例
|
|
最初の引数のハッシュを含む 例
|
ベクトル類似度関数
浮動小数点ベクトル間の類似度スコアを取得できる多くの関数が用意されています。
関数 | 説明 |
---|---|
|
同じ次元の2つの浮動小数点ベクトル間のコサイン類似度スコアを計算します。 例
|
|
同じ次元の2つの浮動小数点ベクトル間のユークリッド距離を計算します。 例
|
|
同じ次元の2つの浮動小数点ベクトル間のドット積を計算します。 例
|
ユーザー定義関数
ユーザー定義関数(UDF)は、Cassandraでユーザー提供のコードを実行します。デフォルトでは、CassandraはJavaで関数の定義をサポートしています。
UDFはCassandraスキーマの一部であり、クラスタ内のすべてのノードに自動的に伝播されます。UDFはオーバーロードできるので、異なる引数型の複数のUDFが同じ関数名を持つことができます。
Cassandra 4.1では、JavaScriptユーザー定義関数は非推奨になりました。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 Driver変換関数を使用します。タプル型とユーザー定義型の処理の詳細については、Java Driverのドキュメントを参照してください。
関数の引数は、リテラルまたは項にすることができます。プリペアドステートメントプレースホルダーも使用できます。
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
列、スカラー関数
、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
ステートメントで使用できます。
各集約関数には、INITCOND
値(デフォルト値:null
)で定義された、STYPE
型の初期状態が必要です。状態関数の最初の引数の型はSTYPE
でなければなりません。状態関数の残りの引数は、ユーザー定義集約関数の引数の型と一致しなければなりません。状態関数は行ごとに1回呼び出され、状態関数によって返された値が新しい状態になります。すべての行が処理された後、オプションの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 ]
完全な例については上記を参照してください。
オプションのOR REPLACE
キーワード付きのCREATE AGGREGATE
コマンドは、集約関数を作成するか、同じシグネチャを持つ既存の集約関数を置換します。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
でなければなりません。状態関数の残りの引数は、ユーザー定義集約関数の引数の型と一致しなければなりません。状態関数は行ごとに1回呼び出され、状態関数によって返された値が新しい状態になります。RETURNS NULL ON NULL INPUT
で宣言され、null
で呼び出された状態関数については、状態は更新されません。すべての行が処理された後、オプションのFINALFUNC
が最後の状態値を引数として実行されます。これは、STYPE
型の引数を1つだけ取る必要がありますが、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
コマンドは、集約関数が存在する場合に削除し、そのシグネチャを持つ関数が存在しない場合は何も行いません。