Merge branch 'cassandra-5.0' into trunk

This commit is contained in:
Stefan Miklosovic 2024-02-16 10:08:08 +01:00
commit 3483fc0683
No known key found for this signature in database
GPG Key ID: 32F35CB2F546D93E
21 changed files with 306 additions and 253 deletions

View File

@ -1 +0,0 @@
ALTER TABLE patients ALTER name MASKED WITH mask_default();

View File

@ -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()
);

View File

@ -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
);

View File

@ -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;

View File

@ -1 +0,0 @@
ALTER TABLE patients ALTER name DROP MASKED;

View File

@ -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');

View File

@ -1 +0,0 @@
REVOKE UNMASK ON TABLE patients FROM privileged;

View File

@ -1,6 +0,0 @@
SELECT name, birth FROM patients;
// name | birth
// -------+------------
// a**** | 1970-01-01
// b** | 1970-01-01

View File

@ -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

View File

@ -1,7 +0,0 @@
LOGIN privileged
SELECT name, birth FROM patients;
// name | birth
// -------+------------
// alice | 1984-01-02
// bob | 1982-02-03

View File

@ -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"

View File

@ -1,7 +0,0 @@
LOGIN unprivileged
SELECT name, birth FROM patients;
// name | birth
// -------+------------
// a**** | 1970-01-01
// b** | 1970-01-01

View File

@ -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[]

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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]

View File

@ -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 };

View File

@ -20,10 +20,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]

View File

@ -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: