mirror of https://github.com/apache/cassandra
Dynamic Data Masking cleanup language, rearrange code examples.
patch by Lorina Poland; reviewed by Stefan Miklosovic for CASSANDRA-18230
This commit is contained in:
parent
a04dc83cfc
commit
0f2da96c6c
|
|
@ -1 +0,0 @@
|
|||
ALTER TABLE patients ALTER name MASKED WITH mask_default();
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
CREATE TABLE patients (
|
||||
id timeuuid PRIMARY KEY,
|
||||
name text MASKED WITH mask_inner(1, null),
|
||||
birth date MASKED WITH mask_default()
|
||||
);
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
CREATE FUNCTION redact(input text)
|
||||
CALLED ON NULL INPUT
|
||||
RETURNS text
|
||||
LANGUAGE java
|
||||
AS 'return "redacted";';
|
||||
|
||||
CREATE TABLE patients (
|
||||
id timeuuid PRIMARY KEY,
|
||||
name text MASKED WITH redact(),
|
||||
birth date
|
||||
);
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
CREATE USER privileged WITH PASSWORD 'xyz';
|
||||
GRANT SELECT ON TABLE patients TO privileged;
|
||||
GRANT UNMASK ON TABLE patients TO privileged;
|
||||
|
||||
CREATE USER unprivileged WITH PASSWORD 'xyz';
|
||||
GRANT SELECT ON TABLE patients TO unprivileged;
|
||||
|
|
@ -1 +0,0 @@
|
|||
ALTER TABLE patients ALTER name DROP MASKED;
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
INSERT INTO patients(id, name, birth) VALUES (now(), 'alice', '1984-01-02');
|
||||
INSERT INTO patients(id, name, birth) VALUES (now(), 'bob', '1982-02-03');
|
||||
|
|
@ -1 +0,0 @@
|
|||
REVOKE UNMASK ON TABLE patients FROM privileged;
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
SELECT name, birth FROM patients;
|
||||
|
||||
// name | birth
|
||||
// -------+------------
|
||||
// a**** | 1970-01-01
|
||||
// b** | 1970-01-01
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
CREATE USER trusted_user WITH PASSWORD 'xyz';
|
||||
GRANT SELECT, SELECT_MASKED ON TABLE patients TO trusted_user;
|
||||
LOGIN trusted_user
|
||||
SELECT name, birth FROM patients WHERE name = 'Alice' ALLOW FILTERING;
|
||||
|
||||
// name | birth
|
||||
// -------+------------
|
||||
// a**** | 1970-01-01
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
LOGIN privileged
|
||||
SELECT name, birth FROM patients;
|
||||
|
||||
// name | birth
|
||||
// -------+------------
|
||||
// alice | 1984-01-02
|
||||
// bob | 1982-02-03
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
CREATE USER untrusted_user WITH PASSWORD 'xyz';
|
||||
GRANT SELECT ON TABLE patients TO untrusted_user;
|
||||
LOGIN untrusted_user
|
||||
SELECT name, birth FROM patients WHERE name = 'Alice' ALLOW FILTERING;
|
||||
|
||||
// Unauthorized: Error from server: code=2100 [Unauthorized] message="User untrusted_user has no UNMASK nor SELECT_UNMASK permission on table k.patients"
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
LOGIN unprivileged
|
||||
SELECT name, birth FROM patients;
|
||||
|
||||
// name | birth
|
||||
// -------+------------
|
||||
// a**** | 1970-01-01
|
||||
// b** | 1970-01-01
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
// tag::table-create-ddm[]
|
||||
CREATE TABLE patients (
|
||||
id timeuuid PRIMARY KEY,
|
||||
name text MASKED WITH mask_inner(1, null),
|
||||
birth date MASKED WITH mask_default()
|
||||
);
|
||||
// end::table-create-ddm[]
|
||||
|
||||
// tag::table-create-ddm-udt[]
|
||||
CREATE FUNCTION redact(input text)
|
||||
CALLED ON NULL INPUT
|
||||
RETURNS text
|
||||
LANGUAGE java
|
||||
AS 'return "redacted";';
|
||||
|
||||
CREATE TABLE patients (
|
||||
id timeuuid PRIMARY KEY,
|
||||
name text MASKED WITH redact(),
|
||||
birth date
|
||||
);
|
||||
// end::table-create-ddm-udt[]
|
||||
|
||||
// tag::table-alter-ddm[]
|
||||
ALTER TABLE patients ALTER name
|
||||
MASKED WITH mask_default();
|
||||
// end::table-alter-ddm[]
|
||||
|
||||
// tag::table-alter-ddm-drop-mask[]
|
||||
ALTER TABLE patients ALTER name
|
||||
DROP MASKED;
|
||||
// end::table-alter-ddm-drop-mask[]
|
||||
|
||||
// tag::users-grant-ddm[]
|
||||
CREATE USER privileged WITH PASSWORD 'xyz';
|
||||
GRANT SELECT ON TABLE patients TO privileged;
|
||||
GRANT UNMASK ON TABLE patients TO privileged;
|
||||
|
||||
CREATE USER unprivileged WITH PASSWORD 'xyz';
|
||||
GRANT SELECT ON TABLE patients TO unprivileged;
|
||||
// end::users-grant-ddm[]
|
||||
|
||||
// tag::users-revoke-ddm[]
|
||||
REVOKE UNMASK ON TABLE patients
|
||||
FROM privileged;
|
||||
// end::users-revoke-ddm[]
|
||||
|
||||
// tag::data-insert-ddm[]
|
||||
INSERT INTO patients(id, name, birth) VALUES (now(), 'alice', '1984-01-02');
|
||||
INSERT INTO patients(id, name, birth) VALUES (now(), 'bob', '1982-02-03');
|
||||
// end::data-insert-ddm[]
|
||||
|
||||
// tag::select-with-masked-column[]
|
||||
SELECT name, birth FROM patients;
|
||||
|
||||
// name | birth
|
||||
// -------+------------
|
||||
// a**** | 1970-01-01
|
||||
// b** | 1970-01-01
|
||||
// end::select-with-masked-column[]
|
||||
|
||||
// tag::select-without-unmask-permission[]
|
||||
LOGIN unprivileged
|
||||
SELECT name, birth FROM patients;
|
||||
|
||||
// name | birth
|
||||
// -------+------------
|
||||
// a**** | 1970-01-01
|
||||
// b** | 1970-01-01
|
||||
// end::select-without-unmask-permission[]
|
||||
|
||||
// tag::select-with-unmask-permission[]
|
||||
LOGIN privileged
|
||||
SELECT name, birth FROM patients;
|
||||
|
||||
// name | birth
|
||||
// -------+------------
|
||||
// alice | 1984-01-02
|
||||
// bob | 1982-02-03
|
||||
// end::select-with-unmask-permission[]
|
||||
|
||||
// tag::select-without-select-masked[]
|
||||
CREATE USER untrusted_user WITH PASSWORD 'xyz';
|
||||
GRANT SELECT ON TABLE patients TO untrusted_user;
|
||||
LOGIN untrusted_user
|
||||
SELECT name, birth FROM patients WHERE name = 'Alice' ALLOW FILTERING;
|
||||
|
||||
// Unauthorized: Error from server: code=2100 [Unauthorized] message="User untrusted_user has no UNMASK nor SELECT_UNMASK permission on table k.patients"
|
||||
// end::select-without-select-masked[]
|
||||
|
||||
// tag::select-with-select-masked[]
|
||||
CREATE USER trusted_user WITH PASSWORD 'xyz';
|
||||
GRANT SELECT, SELECT_MASKED ON TABLE patients TO trusted_user;
|
||||
LOGIN trusted_user
|
||||
SELECT name, birth FROM patients WHERE name = 'Alice' ALLOW FILTERING;
|
||||
|
||||
// name | birth
|
||||
// -------+------------
|
||||
// a**** | 1970-01-01
|
||||
// end::select-with-select-masked[]
|
||||
|
|
@ -40,6 +40,7 @@
|
|||
*** xref:cassandra:developing/cql/types.adoc[Data types]
|
||||
*** xref:cassandra:developing/cql/ddl.adoc[Data definition (DDL)]
|
||||
*** xref:cassandra:developing/cql/dml.adoc[Data manipulation (DML)]
|
||||
*** xref:cassandra:developing/cql/dynamic-data-masking.adoc[]
|
||||
*** xref:cassandra:developing/cql/operators.adoc[Operators]
|
||||
*** xref:cassandra:developing/cql/indexing/indexing-concepts.adoc[]
|
||||
// SAI
|
||||
|
|
|
|||
|
|
@ -0,0 +1,179 @@
|
|||
= Dynamic Data Masking (DDM)
|
||||
:description: Dynamic Data Masking (DDM) is a method for making sensitive data unavailable to non-privileged users.
|
||||
|
||||
Dynamic data masking (DDM) obscures sensitive information while still allowing access to the masked columns.
|
||||
DDM doesn't alter the stored data.
|
||||
Instead, it just presents the data in its obscured form during `SELECT` queries.
|
||||
This aims to provide some degree of protection against accidental data exposure. However, anyone with direct access to the SSTable files will be able to read the clear data.
|
||||
|
||||
== Masking functions
|
||||
|
||||
DDM is based on a set of CQL native functions that obscure sensitive information.
|
||||
The available functions are:
|
||||
|
||||
include::partial$masking_functions.adoc[]
|
||||
|
||||
Those functions can be used on `SELECT` queries to get an obscured view of the data.
|
||||
For example:
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/select-with-mask-functions.cql[]
|
||||
----
|
||||
|
||||
== Attaching masking functions to table columns
|
||||
|
||||
A masking function can be permanently attached to any column of a table.
|
||||
If a masking column is defined, `SELECT` queries will always return the column values in their masked form.
|
||||
The masking will be transparent to the users running `SELECT` queries.
|
||||
The only way to know that a column is masked is to consult the table definition.
|
||||
|
||||
This is an optional feature that is disabled by default.
|
||||
To use the feature, enable the `dynamic_data_masking_enabled` property in `cassandra.yaml`.
|
||||
|
||||
The masks of the columns of a table can be defined in the `CREATE TABLE` to create the table schema. This example uses the `mask_inner` function with two arguments:
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/dynamic-data-masking.cql[tag=table-create-ddm]
|
||||
----
|
||||
|
||||
When using a `SELECT` query on this data, three arguments are required for the `mask_inner` function, but the first argument is always omitted when attaching the function to the table schema.
|
||||
The value of that first argument is always interpreted as the value of the masked column, in this case a `text` column.
|
||||
|
||||
For the same reason, using the masking function `mask_default` doesn't have any argument when creating the table schema, but it requires one argument when used on `SELECT` queries.
|
||||
|
||||
Data can be normally inserted into the masked table without alteration.
|
||||
For example:
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/dynamic-data-masking.cql[tag=data-insert-ddm]
|
||||
----
|
||||
|
||||
The `SELECT` query will return the masked data.
|
||||
The masking function will be automatically applied to the column values.
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/dynamic-data-masking.cql[tag=select-with-masked-column]
|
||||
----
|
||||
|
||||
An `ALTER TABLE` query can be used to make changes to a masking function on a table column.
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/dynamic-data-masking.cql[tag=table-alter-ddm]
|
||||
----
|
||||
|
||||
In a similar way, a masking function can be detached from a column with an `ALTER TABLE` query:
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/dynamic-data-masking.cql[tag=table-alter-ddm-drop-mask]
|
||||
----
|
||||
|
||||
== Permissions
|
||||
|
||||
Ordinary users are created without the `UNMASK` permission and will see masked values.
|
||||
Giving a user the `UNMASK` permission allows them to retrieve the unmasked values of masked columns.
|
||||
Superusers are automatically created with the `UNMASK` permission,
|
||||
and will see the unmasked values in a `SELECT` query results.
|
||||
|
||||
For example, suppose that we have a table with masked columns:
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/dynamic-data-masking.cql[tag=table-create-ddm]
|
||||
----
|
||||
|
||||
And we insert some data into the table:
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/dynamic-data-masking.cql[tag=data-insert-ddm]
|
||||
----
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/dynamic-data-masking.cql[tag=select-without-unmask-permission]
|
||||
----
|
||||
|
||||
Then we create two users with `SELECT` permission for the table, but we only grant the `UNMASK` permission to one of the users:
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/dynamic-data-masking.cql[tag=users-grant-ddm]
|
||||
----
|
||||
|
||||
The user with the `UNMASK` permission can see the clear, unmasked data:
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/dynamic-data-masking.cql[tag=select-with-unmask-permission]
|
||||
----
|
||||
|
||||
The user without the `UNMASK` permission can only see the masked data:
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/dynamic-data-masking.cql[tag=select-without-unmask-permission]
|
||||
----
|
||||
|
||||
The `UNMASK` permission works like any other permission, and can be revoked at will:
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/dynamic-data-masking.cql[tag=users-revoke-ddm]
|
||||
----
|
||||
|
||||
Please note that, when authentication is disabled, the anonymous default user has all the permissions, including the `UNMASK` permission, and can see the unmasked data.
|
||||
In other words, attaching data masking functions to columns only makes sense if authentication is enabled.
|
||||
|
||||
Only users with the `UNMASK` permission are allowed to use masked columns in the `WHERE` clause of a `SELECT` query.
|
||||
Users without the `UNMASK` permission cannot use this feature.
|
||||
This feature prevents malicious users seeing clear data by running exhaustive, brute force queries.
|
||||
The user without the `UNMASK` permission will see the following:
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/dynamic-data-masking.cql[tag=select-without-select-masked]
|
||||
----
|
||||
|
||||
There are some use cases where a trusted database user needs to produce masked data that untrusted external users will query.
|
||||
For instance, a trusted app can connect to the database and with a query extract masked data that will be displayed to its end users.
|
||||
In that case, the trusted user (the app) can be given the `SELECT_MASKED` permission.
|
||||
This permission lets the user query masked columns in the `WHERE` clause of a `SELECT` query,
|
||||
while still only seeing the masked data in the query results:
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/dynamic-data-masking.cql[tag=select-with-select-masked]
|
||||
----
|
||||
|
||||
== Custom functions
|
||||
|
||||
xref:developing/cql/functions.adoc#user-defined-functions[User-defined functions (UDFs)] can be attached to a table column.
|
||||
The UDFs used for masking should belong to the same keyspace as the masked table.
|
||||
The column value to mask will be passed as the first argument of the attached UDF.
|
||||
Thus, the UDFs attached to a column should have at least one argument,
|
||||
and that argument should have the same type as the masked column.
|
||||
Also, the attached UDF should return values of the same type as the masked column:
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/dynamic-data-masking.cql[tag=table-create-ddm-udt]
|
||||
----
|
||||
|
||||
This creates a dependency between the table schema and the functions.
|
||||
Any attempt to drop the function will be rejected while this dependency exists.
|
||||
Consequently, you must drop the mask column in the table before dropping the function:
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/dynamic-data-masking.cql[tag=table-alter-ddm-drop-mask]
|
||||
----
|
||||
|
||||
Dropping the column, or its containing table, or its containing keyspace will also remove the dependency.
|
||||
|
||||
xref:developing/cql/functions.adoc#aggregate-functions[Aggregate functions] cannot be used as masking functions.
|
||||
|
|
@ -1,179 +0,0 @@
|
|||
= Dynamic Data Masking
|
||||
|
||||
Dynamic data masking (DDM) allows to obscure sensitive information while still allowing access to the masked columns.
|
||||
DDM doesn't change the stored data. Instead, it just presents the data in its obscured form during `SELECT` queries.
|
||||
This aims to provide some degree of protection against accidental data exposure. However, it's important to know that
|
||||
anyone with direct access to the sstable files will be able to read the clear data.
|
||||
|
||||
== Masking functions
|
||||
|
||||
DDM is based on a set of CQL native functions that obscure sensitive information. The available functions are:
|
||||
|
||||
include::partial$masking_functions.adoc[]
|
||||
|
||||
Those functions can be discretionarily used on `SELECT` queries to get an obscured view of the data. For example:
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/select_with_mask_functions.cql[]
|
||||
----
|
||||
|
||||
== Attaching masking functions to table columns
|
||||
|
||||
The masking functions can be permanently attached to any column of a table.
|
||||
If a masking columns is defined, `SELECT` queries will always return the column values in their masked form.
|
||||
The masking will be transparent to the users running `SELECT` queries,
|
||||
so their only way to know that a column is masked will be to consult the table definition.
|
||||
|
||||
This is an optional feature that should be enabled with the `dynamic_data_masking_enabled` property in `cassandra.yaml`,
|
||||
since it's disabled by default.
|
||||
|
||||
The masks of the columns of a table can be defined on `CREATE TABLE` queries:
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/ddm_create_table.cql[]
|
||||
----
|
||||
|
||||
Note that in the example above we are referencing the `mask_inner` function with two arguments.
|
||||
However, that CQL function actually has three arguments when explicitely used on `SELECT` queries.
|
||||
The first argument is always ommitted when attaching the function to a schema column.
|
||||
The value of that first argument is always interpreted as the value of the masked column, in this case a `text` column.
|
||||
For the same reason the call to `mask_default` attached to the column doesn't have any argument,
|
||||
even when that function requires one argument when explicitely used on `SELECT` queries.
|
||||
|
||||
Data can be inserted into the masked table as usual. For example:
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/ddm_insert_data.cql[]
|
||||
----
|
||||
|
||||
The attached column masks will make `SELECT` queries automatically return masked data,
|
||||
without the need of including the masking function on the query:
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/ddm_select_with_masked_columns.cql[]
|
||||
----
|
||||
|
||||
The masking function attached to a column can be changed with an `ALTER TABLE` query:
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/ddm_alter_mask.cql[]
|
||||
----
|
||||
|
||||
In a similar way, a masking function can be dettached from a column with an `ALTER TABLE` query:
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/ddm_drop_mask.cql[]
|
||||
----
|
||||
|
||||
== Permissions
|
||||
|
||||
The `UNMASK` permission allows users to retrieve the unmasked values of masked columns.
|
||||
Ordinary users are created without the `UNMASK` permission and will see masked values.
|
||||
Superusers are created with the `UNMASK` permission,
|
||||
and will be able to see the unmasked values in a SELECT query results.
|
||||
|
||||
As an example, suppose that we have a table with masked columns:
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/ddm_create_table.cql[]
|
||||
----
|
||||
|
||||
And we insert some data into the table:
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/ddm_insert_data.cql[]
|
||||
----
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/ddm_select_without_unmask_permission.cql[]
|
||||
----
|
||||
|
||||
Then we create two users with `SELECT` permission for the table, but we only grant the `UNMASK` permission to one of
|
||||
the users:
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/ddm_create_users.cql[]
|
||||
----
|
||||
|
||||
We can now see that the user with the `UNMASK` permission can see the clear data, unmasked:
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/ddm_select_with_unmask_permission.cql[]
|
||||
----
|
||||
|
||||
However, the user without the `UNMASK` permission can only see the masked data:
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/ddm_select_without_unmask_permission.cql[]
|
||||
----
|
||||
|
||||
The `UNMASK` permission works as any other permission. Thus, it can be revoked in any moment:
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/ddm_revoke_unmask.cql[]
|
||||
----
|
||||
|
||||
Please note that the anonymous user that is used when authentication is disabled has all the permissions.
|
||||
Since it includes the `UNMASK` permission, that anonymous user will always see the clear data.
|
||||
In other words, attaching data masking functions to columns only makes sense if authentication is enabled.
|
||||
|
||||
Users without the `UNMASK` permission are not allowed to use masked columns in the `WHERE` clause of a `SELECT` query.
|
||||
This prevents malicious users from figuring out the clear data by running exhaustive queries. For example:
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/ddm_select_without_select_masked.cql[]
|
||||
----
|
||||
|
||||
However, there are some use cases where trusted database users just need a useful way to produce masked data
|
||||
that will be served to untrusted external users.
|
||||
For example, a trusted app can connect to the database and extract masked data that will be served to its end users.
|
||||
In that case the trusted user (the app) can be given the `SELECT_MASKED` permission.
|
||||
That permission allows to use masked columns in the `WHERE` clause of a `SELECT` query,
|
||||
while still seeing the masked data in the query results. For instance:
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/ddm_select_with_select_masked.cql[]
|
||||
----
|
||||
|
||||
== Custom functions
|
||||
|
||||
xref:developing/cql/functions.adoc#user-defined-scalar-functions[User-defined functions (UDFs)] can be attached to a table column.
|
||||
The UDFs used for masking should belong to the same keyspace as the masked table.
|
||||
The column value to mask will be passed as the first argument of the attached UDF.
|
||||
Thus, the UDFs attached to a column should have at least one argument,
|
||||
and that argument should have the same type as the masked column.
|
||||
Also, the attached UDF should return values of the same type as the maked column. For instance:
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/ddm_create_table_with_udf.cql[]
|
||||
----
|
||||
|
||||
This creates a dependency between the table schema and the functions.
|
||||
Any attempt to drop the function will be rejected while this dependency exists.
|
||||
Thus, to drop the function you should first drop the mask.
|
||||
This can be done with:
|
||||
|
||||
[source,cql]
|
||||
----
|
||||
include::example$CQL/ddm_drop_mask.cql[]
|
||||
----
|
||||
|
||||
Dropping the column, or its containing table, or its containing keyspace would also remove the dependency.
|
||||
|
||||
xref:developing/cql/functions.adoc#aggregate-functions[Aggregate functions] cannot be used as masking functions.
|
||||
|
|
@ -13,13 +13,13 @@ For that reason, when used in this document, these terms (tables, rows and colum
|
|||
* xref:developing/cql/types.adoc[Data types]
|
||||
* xref:developing/cql/ddl.adoc[Data definition language]
|
||||
* xref:developing/cql/dml.adoc[Data manipulation language]
|
||||
* xref:developing/cql/dynamic-data-masking.adoc[Dynamic data masking]
|
||||
* xref:developing/cql/operators.adoc[Operators]
|
||||
* xref:developing/cql/indexing/indexing-concepts.adoc[Indexing]
|
||||
* xref:developing/cql/mvs.adoc[Materialized views]
|
||||
* xref:developing/cql/functions.adoc[Functions]
|
||||
* xref:developing/cql/json.adoc[JSON]
|
||||
* xref:developing/cql/security.adoc[CQL security]
|
||||
* xref:developing/cql/dynamic_data_masking.adoc[Dynamic data masking]
|
||||
* xref:developing/cql/triggers.adoc[Triggers]
|
||||
* xref:developing/cql/appendices.adoc[Appendices]
|
||||
* xref:developing/cql/changes.adoc[Changes]
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
The xref:cassandra:getting-started/sai-quickstart.adoc[SAI quickstart] focuses only on defining multiple indexes based on non-primary key columns (a very useful feature).
|
||||
Let's explore other options using some examples of how you can run queries on tables that have differently defined SAI indexes.
|
||||
|
||||
include::developing:partial$sai/sai-only-select.adoc[]
|
||||
include::cassandra:partial$sai/sai-only-select.adoc[]
|
||||
|
||||
// IS THERE AN EXAMPLE OF
|
||||
// WITH OPTIONS = {'case_sensitive': false, 'normalize': true };
|
||||
|
|
|
|||
|
|
@ -12,10 +12,10 @@ This section covers the new features in Apache Cassandra 5.0.
|
|||
* More guardrails: https://github.com/apache/cassandra/blob/trunk/NEWS.txt[NEWS.txt]
|
||||
* TTL and writetime on collections and UDTs: xref:cassandra:developing/cql/dml.html#writetime-and-ttl-function[Docs], https://issues.apache.org/jira/browse/CASSANDRA-8877[JIRA ticket]
|
||||
* New vector data type: xref:cassandra:reference/vector-data-type.adoc[Docs], https://cwiki.apache.org/confluence/display/CASSANDRA/CEP-30%3A+Approximate+Nearest+Neighbor%28ANN%29+Vector+Search+via+Storage-Attached+Indexes[CEP-30], https://issues.apache.org/jira/browse/CASSANDRA-18504[JIRA ticket]
|
||||
* New vector similarity functions: xref:cassandra:vector-search/overview.adoc[Docs], https://cwiki.apache.org/confluence/display/CASSANDRA/CEP-30%3A+Approximate+Nearest+Neighbor%28ANN%29+Vector+Search+via+Storage-Attached+Indexes[CEP-30],https://issues.apache.org/jira/browse/CASSANDRA-18640[JIRA ticket]
|
||||
* Unified Compaction Strategy: xref:cassandra:managing/operating/compaction/ucs.adoc[Docs], https://cwiki.apache.org/confluence/display/CASSANDRA/CEP-26%3A+Unified+Compaction+Strategy[CEP-26], (https://issues.apache.org/jira/browse/CASSANDRA-18397)[CASSANDRA-18397]
|
||||
* New vector similarity functions: xref:cassandra:vector-search/overview.adoc[Docs], https://cwiki.apache.org/confluence/display/CASSANDRA/CEP-30%3A+Approximate+Nearest+Neighbor%28ANN%29+Vector+Search+via+Storage-Attached+Indexes[CEP-30], https://issues.apache.org/jira/browse/CASSANDRA-18640[JIRA ticket]
|
||||
* Unified Compaction Strategy: xref:cassandra:managing/operating/compaction/ucs.adoc[Docs], https://cwiki.apache.org/confluence/display/CASSANDRA/CEP-26%3A+Unified+Compaction+Strategy[CEP-26], https://issues.apache.org/jira/browse/CASSANDRA-18397[JIRA ticket]
|
||||
* New Mathematical CQL functions: abs, exp, log, log10 and round: xref:cassandra:developing/cql/functions.adoc[Docs], https://issues.apache.org/jira/browse/CASSANDRA-17221[JIRA ticket]
|
||||
* Dynamic Data Masking: xref:cassandra:developing/cql/dynamic_data_masking.adoc[Docs], https://cwiki.apache.org/confluence/display/CASSANDRA/CEP-20%3A+Dynamic+Data+Masking[CEP-20], https://issues.apache.org/jira/browse/CASSANDRA-17940[CASSANDRA-17940]
|
||||
* Dynamic Data Masking: xref:cassandra:developing/cql/dynamic-data-masking.adoc[Docs], https://cwiki.apache.org/confluence/display/CASSANDRA/CEP-20%3A+Dynamic+Data+Masking[CEP-20], https://issues.apache.org/jira/browse/CASSANDRA-17940[JIRA ticket]
|
||||
* New CIDR authorizer: https://cwiki.apache.org/confluence/display/CASSANDRA/CEP-33%3A+CIDR+filtering+authorizer[CEP-33], https://issues.apache.org/jira/browse/CASSANDRA-18592[JIRA ticket]
|
||||
* Extend maximum expiration date (TTL): https://github.com/apache/cassandra/blob/trunk/NEWS.txt[NEWS.txt], https://issues.apache.org/jira/browse/CASSANDRA-14227[JIRA ticket]
|
||||
* New CQL native scalar functions for collections: https://issues.apache.org/jira/browse/CASSANDRA-18060[JIRA ticket]
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@
|
|||
|===
|
||||
|Function | Description
|
||||
|
||||
| `mask_null(value)` | Replaces the first argument with a `null` column. The returned value is always a non-existent column, and not a not-null column representing a `null` value.
|
||||
| `mask_null(value)`
|
||||
| Replaces the first argument with a `null` column.
|
||||
The returned value is always a non-existent column, and not a not-null column representing a `null` value.
|
||||
|
||||
Examples:
|
||||
|
||||
|
|
@ -10,12 +12,13 @@ Examples:
|
|||
|
||||
`mask_null(123)` -> `null`
|
||||
|
||||
| `mask_default(value)` | Replaces its argument by an arbitrary, fixed default value of the same type.
|
||||
| `mask_default(value)`
|
||||
| Replaces its argument by an arbitrary, fixed default value of the same type.
|
||||
This will be `\***\***` for text values, zero for numeric values, `false` for booleans, etc.
|
||||
|
||||
Variable-length multivalued types such as lists, sets and maps are masked as empty collections.
|
||||
Variable-length multi-valued types such as lists, sets and maps are masked as empty collections.
|
||||
|
||||
Fixed-length multivalued types such as tuples, UDTs and vectors are masked by replacing each of their values by the default masking value of the value type.
|
||||
Fixed-length multi-valued types such as tuples, user-defined types (UDTs) and vectors are masked by replacing each of their values by the default masking value of the value type.
|
||||
|
||||
Examples:
|
||||
|
||||
|
|
@ -27,7 +30,9 @@ Examples:
|
|||
|
||||
`mask_default((vector<int, 3>) [1, 2, 3])` -> `[0, 0, 0]`
|
||||
|
||||
| `mask_replace(value, replacement])` | Replaces the first argument by the replacement value on the second argument. The replacement value needs to have the same type as the replaced value.
|
||||
| `mask_replace(value, replacement])`
|
||||
| Replaces the first argument by the replacement value on the second argument.
|
||||
The replacement value needs to have the same type as the replaced value.
|
||||
|
||||
Examples:
|
||||
|
||||
|
|
@ -35,7 +40,10 @@ Examples:
|
|||
|
||||
`mask_replace(123, -1)` -> `-1`
|
||||
|
||||
| `mask_inner(value, begin, end, [padding])` | Returns a copy of the first `text`, `varchar` or `ascii` argument, replacing each character except the first and last ones by a padding character. The 2nd and 3rd arguments are the size of the exposed prefix and suffix. The optional 4th argument is the padding character, `\*` by default.
|
||||
| `mask_inner(value, begin, end, [padding])`
|
||||
| Returns a copy of the first `text`, `varchar` or `ascii` argument, replacing each character except the first and last ones by a padding character.
|
||||
The second and third arguments are the size of the exposed prefix and suffix.
|
||||
The optional fourth argument is the padding character, `\*` by default.
|
||||
|
||||
Examples:
|
||||
|
||||
|
|
@ -47,7 +55,10 @@ Examples:
|
|||
|
||||
`mask_inner('Alice', 2, 1, '\#')` -> `'Al##e'`
|
||||
|
||||
| `mask_outer(value, begin, end, [padding])` | Returns a copy of the first `text`, `varchar` or `ascii` argument, replacing the first and last character by a padding character. The 2nd and 3rd arguments are the size of the exposed prefix and suffix. The optional 4th argument is the padding character, `\*` by default.
|
||||
| `mask_outer(value, begin, end, [padding])`
|
||||
| Returns a copy of the first `text`, `varchar` or `ascii` argument, replacing the first and last character by a padding character.
|
||||
The second and third arguments are the size of the exposed prefix and suffix.
|
||||
The optional fourth argument is the padding character, `\*` by default.
|
||||
|
||||
Examples:
|
||||
|
||||
|
|
@ -59,7 +70,10 @@ Examples:
|
|||
|
||||
`mask_outer('Alice', 2, 1, '\#')` -> `'##ic#'`
|
||||
|
||||
| `mask_hash(value, [algorithm])` | Returns a `blob` containing the hash of the first argument. The optional 2nd argument is the hashing algorithm to be used, according the available Java security provider. The default hashing algorithm is `SHA-256`.
|
||||
| `mask_hash(value, [algorithm])`
|
||||
| Returns a `blob` containing the hash of the first argument.
|
||||
The optional second argument is the hashing algorithm to be used, according the available Java security provider.
|
||||
The default hashing algorithm is `SHA-256`.
|
||||
|
||||
Examples:
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue