A result set filter is invoked (potentially) for every row in a result set. The filter can modify the row, add more rows, drop the row, or return an error. This filter works for all result sets, whether they result from SQL statements or from the execution of a stored procedure.
All parameters are optional. If no parameter is specified, then the filter will be invoked for every row of every result set.
If specified, a comma-separated (or line break separated) list of database user names or regular expressions for database user names.
A comma-separated (or line-break separated) list of IP4 or IP6 addresses or regular expressions for IP addresses. If specified, this filter will only be invoked when the client's IP address matches.
If specified, the filter will not be invoked unless it contains at least one column from a table in the specified schema. Can be a string or a regular expression.
If specified, the filter will not be invoked unless it contains at least one column from the specified table. Can be a string or a regular expression.
A series of strings and/or regular expressions, separated by commas or newlines. If the current SQL does not match any of these, the filter will not be invoked. The current SQL is the last SQL command executed.
A series of name=value pairs, separated by commas or newlines. The value is a regular expression, which means special characters like period must be escaped.
If more than one column pattern is specified, this determines whether they must all be true (and) or any one of them (or).
Can be either code or hide. If it's code, then the code is executed. If it's hide, then the row is dropped from the result set, and the code is not executed.
The following examples use Vertica's demo database schema named store.
The requirement is that all stores in California (e.g. store_state = 'CA' ) should be taken out of the result set if their total square footage is over 2,000 sqft.
The actual data in the database can be seen with:
select * from store.store_dimension where store_state = 'CA'
which returns 15 rows.
We can create a result set filter with the proper parameters, and add a bit of code to hide the data.
The parameters for the filter are:
Schema pattern: store
Table pattern: store_dimension
Column patterns: store_state=CA
This will ensure that this filter will be invoked for any result set in which the store_state column is 'CA'.
Next we add a bit of code that checks the square footage and hides the row if necessary:
if (context.packet.total_square_footage > 2000) {
context.packet.remove();
}
If we now re-run the query:
select * from store.store_dimension where store_state = 'CA'
we only see 5 rows. The database is of course untouched -- all we changed was the result set on its way to the client.
Let's say there is a query that returns data that should not be seen by some users. The rule is:
For users in France and Germany (i.e. users whose user name starts with "fr_" or "de_"), the store address should be hidden if the store is in the West region.
We can create a result set with the proper parameters, and add a bit of code to hide the data.
The parameters for the filter are:
User pattern: regex:fr_.*,de_.*
Schema pattern: store
Table pattern: store_dimension
Column patterns: store_region=West
The code for the filter will be invoked when these conditions are satisfied, and can hide the store's address with:
if (context.packet.store_address) {
context.packet.store_address = "#########";
}
We can add new rows to the result set by cloning the current row and modifying it.
We create a filter with the parameters:
Schema pattern: store
Table pattern: store_dimension
Column patterns: store_key=4
This will ensure that the code for the filter will only be executed for store #4, which we'll duplicate with the following code:
for (var i = 1; i <= 3; i++) {
let newRow = context.packet.clone();
newRow.store_key = 1000000 + i;
newRow.store_name = 'Made-up store #' + i;
newRow.store_address = i + " Fake Ave";
context.packets.addPacket(newRow);
}