Triggers¶
Triggers allow data to be manipulated as it is inserted, updated, or deleted. AMI provides 6 types of trigger for different situations:
- AMIScript, for running custom AMIScript whenever data is inserted, updated, or deleted
- Aggregation, for creating aggregation tables
- Projection, for creating filtered tables
- Join, for creating joined tables
- Decorate, for adding additional data from another table to the trigger table
- Relay, for sending messages through the Relay
CREATE TRIGGER¶
AMIScript¶
This command allows you to add script that can be executed as data is inserted, updated or deleted from a specified table. There are 5 different events that can cause the trigger to be executed, you must specify at least one of:
onInsertingScript
- This script will be executed before a row is inserted into table_name table. The values of the row to be inserted will available as local variables to the executing script.onInsertedScript
- This script will be executed after a row is inserted into table_name. The values of the row just inserted will available as local variables to the executing script.onUpdatingScript
- This script will be executed before an update on table_name table's rows. The values of the row prior to the update will be available as local variable with the form old_varname. The values of the row after the update will be available as local variable with the form new_varname.onUpdatedScript
- This script will be executed after an update on table_name table's rows. The values of the row just updated will be available as local variables to the executing script.onDeletingScript
- This script will be executed before a row is deleted from the table_name table. The values of the row to be deleted will available as local variables to the executing script.canMutateRow
- If true, then any values of the row changed inside the onInsertingScript will reflect back on the row to be inserted. For onUpdatingScript, any changes to the new_varname values will reflect on the row to be updated. Note, this only applies to the onInsertingScript and onUpdatingScript options, has no effect on onInsertedScript, onUpdatedScript, and onDeletingScript. See Mutating Trigger Example belowrowVar
- a placeholder (can be any custom variable name) that contains the map that reflects the row change in the table (either insert, update or delete). Note that rowVar is a read-only map and the available methods include:boolean containsValue()
,boolean containsKey()
. For onUpdatingScript, you must add the new_ or old_ prefix to the rowVar to use it. See rowVar Example (using onUpdatingScript) for more details.
-
trigger_name
: Name of the trigger to create, must be unique within the database -
table_name
: Name of the table(s) that will cause the trigger to execute -
priority
: A number, triggers with lowest value are executed first. This also controls the order in which triggers are started up/initialized
Example 1: Basic¶
In this example let us assume we have a table MyTable(id int,price double)
and a MyAlertTable(type String,id int,diff double)
. When a row is deleted from the MyTable this trigger will insert an alert into the MyAlert
Table including the id and price of the record deleted. In the case of an update, a row will be inserted into the MyAlert
table including the id and change in price due to the update.
Example 2: Mutating Trigger¶
px Double | qty Integer | val Double |
---|---|---|
125.2 | 100 | 12520.0 |
px Double | qty Integer | val Double |
---|---|---|
125.2 | 110 | 13772.0 |
Example 3: Mutating Trigger with Deferred Statement¶
In the case of using deferred statements (statements in the format of use ds=<your_datasource> execute ...
in the mutating trigger, It is strongly recommended that we put all the deferred statements at the end of the script after mutations occur. For example, adding a little tweak to the example before, if we also want to run a deferred statement against another datasource while mutation is happening:
Example 4: rowVar Example (Basic)¶
rows String | arg1 String | arg2 String |
---|---|---|
{"id":123,"sym":"aapl"} | 123 | aapl |
Example 5: rowVar Example (using onUpdatingScript)¶
-
Case 1: Upsert (insert causes update due to primary index)
comments String newrow: [id=order1, val=3]; oldrow: [id=order1, val=2]; containsVal?:true -
Case 2: Direct update, note that only columns that participate in the update clause will appear in the new_rowVar map
comments String newrow: [val=10]; oldrow: [id=order1, val=3]; containVal?:true
Aggregation¶
This command binds an existing source table and an existing target table together such that the target table will be an aggregate representation of the source table. The following rules apply:
- As the source table has rows inserted, updated or deleted the target table will be automatically updated accordingly
- The target table is no longer modifiable (inserts, updates and deletes to the target table will not succeed)
- Multiple aggregate triggers can share the same source table
- Multiple aggregate triggers can not share the same target table (a given table can only participate in one aggregate trigger as a target table)
- Streaming triggers can be daisy chained, meaning a given table can be a target for one aggregate trigger and a source for another aggregate trigger
- The creation of the trigger will clear out and rebuild the target table to properly reflect the aggregation of the source table's data
There are three USE options:
-
groupBys
- A comma delimited list of expressions to group rows by, each expression being of the form: -
selects
- A comma delimited list of expressions on how to populate target columns from source columns. -
allowExternalUpdates
- Optional. Value is either true or false (false by default). If true, then other processes (i.e triggers, UPDATEs) are allowed to perform UPDATEs on the target table. Please use precaution when using this feature, since updating cells controlled by the aggregate trigger will result into an undesirable state.
The following rules apply for the groupBys
and selects
use options:
targetTableColumns
must only reference columns in the target table's schemasourceTableColumns
must only reference columns in the source table's schema- A
targetTableColumn
can only be referenced once - For aggregate expressions only
count
,countUnique
,first
,last
,max
,min
,stdev
,stdevs
,sum
, andvar
functions are supported
trigger_name
- name of the trigger to create, must be unique within the databasesource_table_name
- name of the table that will cause the trigger to executetarget_table_name
- name of the table that will be updates by the triggerpriority
- a number, triggers with lowest value are executed first. Only considered when two or more triggers exist on the same table
Example¶
Projection¶
This command binds one or more existing source tables and an existing target table together such that the target table will be populated using the source table(s). The following rules then apply:
- As the source table(s) have rows inserted, updated or deleted the target table will automatically have it's corresponding projected rows inserted, updated, deleted accordingly.
- When there are multiple source tables, the resulting target is a UNION of the source tables (not a join)
- The target table's rows that are a result of this projection can not be modified (inserts, updates and deletes to the target table's managed rows will not succeed)
- Multiple projection triggers can share the same source table
- Multiple projection triggers can share the same target table
- The creation of the trigger will clear out and rebuild the target table to properly reflect the aggregation of the source table's data.
- If a source tables' row is updated such that the evaluation of the wheres clause changes, then the row will be inserted/deleted from the target table accordingly.
There are three USE options:
-
wheres
- A comma-delimited list of boolean expressions that must all be true on a source table's row in order for it to be projected into the target table: -
selects
- A comma-delimited list of expressions on how to populate target columns from source columns: -
allowExternalUpdates
- Optional. Value is either true or false (false by default). If true, then other processes (i.e triggers,UPDATE
s) are allowed to performUPDATE
s on the target table. Please use precaution when using this feature, since updating cells controlled by the aggregate trigger will result into an undesirable state.
There following rules apply for the selects
use options (important when there are multiple source tables):
- Using the form
tablename.columnname
will isolate the expression to only apply to the specified table. - Using the form
columnname
means that the expression will apply to all tables with the suppliedcolumnname
.
Note
wheres
applies only on same-table comparisons. You cannot cross-reference different tables in the same wheres
statement.
trigger_name
- name of the trigger to create, must be unique within the databasesource_table_name
- name of the tables that will cause the trigger to executetarget_table_name
- name of the table that will be updated by the triggerpriority
- a number, triggers with lowest value are executed first. Only considered when two or more triggers exist on the same table
Example¶
Join¶
This command allows for realtime joining across two tables.
- Changes to the leftTable or/or RightTable automatically update the targetTable, equivalent to using the ... JOIN ... ON ... syntax of the SELECT statement. See Join Examples for an illustration of the various types of joins
- Effectively, the target table can be considered a read only table, and can no longer be modified directly
- Multiple JOIN triggers can share the same source table
- Multiple JOIN triggers can not share the same target table.
- The creation of the trigger will clear out and rebuild the target table to properly reflect the JOIN of the left and right tables.
There are three USE options:
-
type
- How to join the left and right tables. Supported types include: LEFT, RIGHT, INNER, OUTER, LEFT ONLY, RIGHT ONLY, OUTER ONLY. (See Join Examples for details on the behavior of the various configurations). -
on
- An expression for how to relate the two tables in the form: -
selects
- A comma delimited list of expressions on how to populate target columns from columns of the left and right tables.
The following rules apply for the wheres
and selects
use options:
- Using the form
tablename.columnname
will explicitly determine which table (left or right) is to be referenced. - Using the form
columnname
means that the column name must be unique to either the left or right table.
trigger_name
- name of the trigger to create, must be unique within the databaseleft_table_name
- name of the left table to join againstright_table_name
- name of the right table to join againsttarget_table_name
- name of the table that will be updated by the triggerpriority
- a number, triggers with lowest value are executed first. Only considered when two or more triggers exist on the same table
Example¶
- See Join Examples for more details on
OUTER JOIN
Decorate¶
This trigger is used to automatically decorate (update) a target table based on changes from a source table
- When a row is updated/inserted in the source table all matching rows (based on the ON clause) in the target table are updated (based on the SELECTS clause).
- Multiple DECORATE triggers can share the same source table.
- Multiple DECORATE triggers can share the same target table.
- The creation of the trigger will immediately update the target table based on source table values.
- When a row is inserted into the target table the last known matching values (if any) from the source table will be used to immediately update the new row.
- Deletes from the source table will not affect the target table.
There are three USE options:
-
on
- An expression for how to relate the two tables in the form: -
selects
- A comma delimited list of expressions on how to populate target columns from columns of the left and right tables. -
keysChange
- Either true or false. Default is false. If it's expected that columns participating in the ON clause can change, then set to true. Note that setting to true adds additional overhead.
trigger_name
- name of the trigger to create, must be unique within the databasesource_table_name
- name of the table to listen for updates fromtarget_table_name
- name of the table to update on changespriority
- a number, triggers with lowest value are executed first. Only considered when two or more triggers exist on the same table
Example¶
Relay¶
Overview
This command allows messages to be sent through the relay when (a) specific action(s) (insert, update or delete) occurs from the source table.
Relay connection options:
host
- hostname of the relay instanceport
- port for the relay instance defined by the property ami.portlogin
- the unique id to identify the process/application, see the login command for more detailskeystoreFile
- optional, location of a keystore filekeystorePass
- optional, the keystore password, this will be encrypted using the strEncrypt method first
Other options (all optional):
target
- the name of the target table, if not defined assumes the same name as the sourcederivedValues
- key=expression,...[key=expression] pattern to map source columns to target columns, if the option is omitted, all source columns will map to the target columns of the same given name, if target columns are omitted, it will map the target column to a source column of the same given nameinserts
- comma delimited list of target columns to be sent on an onInserted event on the source table, if your target table has a unique constraint, in most cases you will want to add that column(s) to this listupdates
- comma delimited list of target columns to be sent on an onUpdated event on the source table, if your target table has a unique constraint, a unique identifier column(s) needs to be in this listdeletes
- comma delimited list of target columns to be sent on an onDeleted event on the source table, if your target table has a unique constraint, a unique identifier column(s) needs to be in this listwhere
- a conditional statement which needs to evaluate to a boolean expression on the source rows, filters what messages should be sent to the target table, false indicates the message will be skipped.
- Note inserts,updates and deletes options define what columns will be added to a relay message
- Note that if the derivedValues,inserts,updates or deletes options are omitted, all values are sent.
- Note if the inserts,updates or deletes options are set to "" then the event type is skipped.
- Note the trigger uses AmiClient to connect to the ami.port if it's unable to connect it will drop messages, it is configured to auto reconnect
Example¶
DROP TRIGGER¶
This command permanently drops one or more triggers.
Example¶
This example will drop the trigger MyTrigger from the database.
AMIScript Trigger Cases¶
AMISCRIPT type triggers can have up to 5 different trigger scripts, onInserting
, onInserted
, onUpdating
, onUpdated
, and ondDeleting
. When running a SQL command against a table with an AMISCRIPT trigger, some of these will run. Note that they run in the order displayed below from onInserting
to onDeleting
. The table below shows which script will run depending on the SQL command, whether the command changes anything, and whether there is a primary index on the table. We will be using the following table:
Description & Command | onInserting | onInserted | onUpdating | onUpdated | onDeleting |
---|---|---|---|---|---|
New Rowinsert into ORDERS values ("ord01", 100, 75.0); |
|||||
Existing Row No Changesinsert into ORDERS values ("ord01", 100, 75.0); |
|||||
Existing Row With Changesinsert into ORDERS values ("ord01", 100, 92.0); |
|||||
Update No Changesupdate ORDERS set AvgPx=75 where OrderID == "ord01"; |
|||||
Update With Changesupdate ORDERS set AvgPx=100 where OrderID == "ord02"; |
|||||
Delete Non-Existing Rowdelete from ORDERS where OrderID=="ord05"; |
|||||
Delete Rowdelete from ORDERS where OrderID=="ord03"; |
|||||
Sync No Changessync into ORDERS(OrderID, LeavesQty, AvgPx) from select "ord01", 100, 75.0; |
|||||
Sync With Changessync into ORDERS from select "ord02", 125, 75.0; |
|||||
Sync on (ID) No Changessync into ORDERS(OrderID, LeavesQty, AvgPx) on (OrderID) from select "ord01", 100, 75.0; |
|||||
Sync on (ID) With Changessync into ORDERS(OrderID, LeavesQty, AvgPx) on (OrderID) from select "ord02", 130, 75.0; |
|||||
Truncate/Delete fromtruncate ORDERS;/Delete from ORDER; |
|||||
Alter table Add Column(s)ALTER TABLE ORDERS ADD Sym String; |
|||||
Alter table With Default ValuesALTER TABLE ORDERS ADD Sym="ABC"; |
|||||
Alter table Drop Column(s)ALTER TABLE ORDERS DROP AvgPx; |
|||||
Rename ColumnALTER TABLE ORDERS RENAME LeavesQty To LeavesQuantity; |
|||||
Modify Column Data TypeALTER TABLE ORDERS MODIFY AvgPx AS AvgPrice Int; |
|||||
Drop TableDrop Table ORDERS; |
Notes:
- Mutating the row: when set
canMutateRow="true"
, Mutating the values in onInserted, onUpdated or onDeleting will not change the underlying value or row. - Trigger Event Return False: If you return false in the triggerEvents: onInserting, onUpdating and onDeleting, it will prevent the row from being inserted, updated or deleting and will also prevent further trigger events
- Return False with a Sync: If you do a sync command where the onDeleting trigger event returns false, onDeleting will fire but no deletes will occur and will be followed by onInserting, onUpdating and onUpdated
- Return False Sync without Primary Key:If you didn't have a primary key, that same action previously will insert another row, keeping the original and will also fire the onDeleting (with no deletes), onInserting and onInserted events.
- Changed vs Unchanged Row: For the onUpdating and onUpdated trigger events if the row hasn't changed, the trigger wont fire. The same hold true when you mutate the row back to it's original values, the next trigger event wont fire.