Skip to content

Commit 7096977

Browse files
committed
Pass insertOption through triggers beforeInsert/Update
1 parent d162044 commit 7096977

File tree

12 files changed

+66
-45
lines changed

12 files changed

+66
-45
lines changed

api/src/org/labkey/api/data/AbstractTableInfo.java

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@
6363
import org.labkey.api.security.UserPrincipal;
6464
import org.labkey.api.security.permissions.Permission;
6565
import org.labkey.api.security.permissions.ReadPermission;
66-
import org.labkey.api.settings.AppProps;
6766
import org.labkey.api.sql.LabKeySql;
6867
import org.labkey.api.study.assay.FileLinkDisplayColumn;
6968
import org.labkey.api.util.ConfigurationException;
@@ -1952,7 +1951,7 @@ public final void resetTriggers(Container c)
19521951
}
19531952

19541953
@Override
1955-
public final void fireBatchTrigger(Container c, User user, TriggerType type, boolean before, BatchValidationException batchErrors, Map<String, Object> extraContext)
1954+
public final void fireBatchTrigger(Container c, User user, TriggerType type, @Nullable QueryUpdateService.InsertOption insertOption, boolean before, BatchValidationException batchErrors, Map<String, Object> extraContext)
19561955
throws BatchValidationException
19571956
{
19581957
assert batchErrors != null;
@@ -1971,9 +1970,19 @@ public final void fireBatchTrigger(Container c, User user, TriggerType type, boo
19711970
}
19721971

19731972
@Override
1974-
public void fireRowTrigger(Container c, User user, TriggerType type, boolean before, int rowNumber,
1975-
@Nullable Map<String, Object> newRow, @Nullable Map<String, Object> oldRow, Map<String, Object> extraContext, @Nullable Map<String, Object> existingRecord, boolean manageColumns)
1976-
throws ValidationException
1973+
public void fireRowTrigger(
1974+
Container c,
1975+
User user,
1976+
TriggerType type,
1977+
@Nullable QueryUpdateService.InsertOption insertOption,
1978+
boolean before,
1979+
int rowNumber,
1980+
@Nullable Map<String, Object> newRow,
1981+
@Nullable Map<String, Object> oldRow,
1982+
Map<String, Object> extraContext,
1983+
@Nullable Map<String, Object> existingRecord,
1984+
boolean manageColumns
1985+
) throws ValidationException
19771986
{
19781987
ValidationException errors = new ValidationException();
19791988
errors.setSchemaName(getPublicSchemaName());
@@ -1998,7 +2007,7 @@ public void fireRowTrigger(Container c, User user, TriggerType type, boolean bef
19982007
if (trackedRow != null)
19992008
trackedRow.resetTracking();
20002009

2001-
script.rowTrigger(this, c, user, type, before, rowNumber, newRowTracked, oldRow, errors, extraContext, existingRecord);
2010+
script.rowTrigger(this, c, user, type, insertOption, before, rowNumber, newRowTracked, oldRow, errors, extraContext, existingRecord);
20022011
if (errors.hasErrors())
20032012
break;
20042013

api/src/org/labkey/api/data/SchemaTableInfo.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -907,13 +907,13 @@ public Collection<QueryService.ParameterDecl> getNamedParameters()
907907
}
908908

909909
@Override
910-
public void fireBatchTrigger(Container c, User user, TriggerType type, boolean before, BatchValidationException errors, Map<String, Object> extraContext)
910+
public void fireBatchTrigger(Container c, User user, TriggerType type, @Nullable QueryUpdateService.InsertOption insertOption, boolean before, BatchValidationException errors, Map<String, Object> extraContext)
911911
{
912912
throw new UnsupportedOperationException("Table triggers not yet supported on schema tables");
913913
}
914914

915915
@Override
916-
public void fireRowTrigger(Container c, User user, TriggerType type, boolean before, int rowNumber, Map<String, Object> newRow, Map<String, Object> oldRow, Map<String, Object> extraContext, @Nullable Map<String, Object> existingRecord, boolean manageColumns)
916+
public void fireRowTrigger(Container c, User user, TriggerType type, @Nullable QueryUpdateService.InsertOption insertOption, boolean before, int rowNumber, Map<String, Object> newRow, Map<String, Object> oldRow, Map<String, Object> extraContext, @Nullable Map<String, Object> existingRecord, boolean manageColumns)
917917
{
918918
throw new UnsupportedOperationException("Table triggers not yet supported on schema tables");
919919
}

api/src/org/labkey/api/data/TableInfo.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,7 @@ enum TriggerMethod
509509

510510
/**
511511
* Executes any trigger scripts for this table.
512-
*
512+
* <p>
513513
* The trigger should be called once before and once after an entire set of rows for each of the
514514
* INSERT, UPDATE, DELETE trigger types. A trigger script may set up data structures to be used
515515
* during validation. In particular, the trigger script might want to do a query to populate a set of
@@ -556,12 +556,13 @@ enum TriggerMethod
556556
* @param c The current Container.
557557
* @param user the current user
558558
* @param type The TriggerType for the event.
559+
* @param insertOption The insertOption that invoked this trigger. Will be null when invoked outside a data iterator.
559560
* @param before true if the trigger is before the event, false if after the event.
560561
* @param errors Any errors created by the validation script will be added to the errors collection.
561562
* @param extraContext Optional additional bindings to set in the script's context when evaluating.
562563
* @throws BatchValidationException if the trigger function returns false or the errors map isn't empty.
563564
*/
564-
void fireBatchTrigger(Container c, User user, TriggerType type, boolean before, BatchValidationException errors, Map<String, Object> extraContext)
565+
void fireBatchTrigger(Container c, User user, TriggerType type, @Nullable QueryUpdateService.InsertOption insertOption, boolean before, BatchValidationException errors, Map<String, Object> extraContext)
565566
throws BatchValidationException;
566567

567568
default void fireRowTrigger(Container c, User user, TriggerType type, boolean before, int rowNumber,
@@ -570,7 +571,7 @@ default void fireRowTrigger(Container c, User user, TriggerType type, boolean be
570571
{
571572
// In production, columns are not managed for non-data iterator invoked triggers and will log a warning.
572573
// In development, columns are managed for all non-data iterator triggers and will throw an error.
573-
fireRowTrigger(c, user, type, before, rowNumber, newRow, oldRow, extraContext, null, AppProps.getInstance().isDevMode());
574+
fireRowTrigger(c, user, type, null, before, rowNumber, newRow, oldRow, extraContext, null, AppProps.getInstance().isDevMode());
574575
}
575576

576577
/**
@@ -603,6 +604,7 @@ default void fireRowTrigger(Container c, User user, TriggerType type, boolean be
603604
* @param c The current Container.
604605
* @param user the current user
605606
* @param type The TriggerType for the event.
607+
* @param insertOption The insertOption that invoked this trigger. Will be null when invoked outside a data iterator.
606608
* @param before true if the trigger is before the event, false if after the event.
607609
* @param newRow The new row for INSERT and UPDATE.
608610
* @param oldRow The previous row for UPDATE and DELETE
@@ -615,6 +617,7 @@ void fireRowTrigger(
615617
Container c,
616618
User user,
617619
TriggerType type,
620+
@Nullable QueryUpdateService.InsertOption insertOption,
618621
boolean before,
619622
int rowNumber,
620623
@Nullable Map<String, Object> newRow,

api/src/org/labkey/api/data/triggers/ScriptTrigger.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.labkey.api.data.PHI;
2525
import org.labkey.api.data.TableInfo;
2626
import org.labkey.api.query.BatchValidationException;
27+
import org.labkey.api.query.QueryUpdateService;
2728
import org.labkey.api.query.ValidationException;
2829
import org.labkey.api.script.ScriptReference;
2930
import org.labkey.api.security.User;
@@ -173,7 +174,7 @@ public void complete(TableInfo table, Container c, User user, TableInfo.TriggerT
173174

174175
@Override
175176
public void beforeInsert(TableInfo table, Container c,
176-
User user, @Nullable Map<String, Object> newRow,
177+
User user, @Nullable QueryUpdateService.InsertOption insertOption, @Nullable Map<String, Object> newRow,
177178
ValidationException errors, Map<String, Object> extraContext)
178179
{
179180
invokeTableScript(table, c, user, "beforeInsert", errors, extraContext, filterErrorDetailByPhi(table, () -> "New row data: " + newRow), newRow);

api/src/org/labkey/api/data/triggers/Trigger.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.labkey.api.data.Container;
2323
import org.labkey.api.data.TableInfo;
2424
import org.labkey.api.query.BatchValidationException;
25+
import org.labkey.api.query.QueryUpdateService;
2526
import org.labkey.api.query.ValidationException;
2627
import org.labkey.api.security.User;
2728
import org.labkey.api.util.UnexpectedException;
@@ -135,8 +136,13 @@ public static ManagedColumns empty()
135136
return null;
136137
}
137138

138-
default void setInsertManagedColumns(Map<String, Object> newRow)
139+
default void setInsertManagedColumns(Map<String, Object> newRow, @Nullable Map<String, Object> existingRecord, @Nullable QueryUpdateService.InsertOption insertOption)
139140
{
141+
// If this is a merge operation and the existingRecord is not supplied,
142+
// then throw an error to avoid overwriting managed values to null.
143+
if (insertOption != null && insertOption.mergeRows && (existingRecord == null || existingRecord.isEmpty()))
144+
throw new IllegalArgumentException("existingRecord must be non-null for MERGE triggers");
145+
140146
setManagedColumns(newRow, null, TableInfo.TriggerType.INSERT);
141147
}
142148

@@ -189,7 +195,8 @@ default void complete(TableInfo table, Container c, User user, TableInfo.Trigger
189195
{
190196
}
191197

192-
default void rowTrigger(TableInfo table, Container c, User user, TableInfo.TriggerType event, boolean before, int rowNumber,
198+
default void rowTrigger(TableInfo table, Container c, User user, TableInfo.TriggerType event,
199+
@Nullable QueryUpdateService.InsertOption insertOption, boolean before, int rowNumber,
193200
@Nullable Map<String, Object> newRow, @Nullable Map<String, Object> oldRow,
194201
ValidationException errors, Map<String, Object> extraContext,
195202
@Nullable Map<String, Object> existingRecord) throws ValidationException
@@ -199,7 +206,7 @@ default void rowTrigger(TableInfo table, Container c, User user, TableInfo.Trigg
199206
switch (event)
200207
{
201208
case INSERT:
202-
beforeInsert(table, c, user, newRow, errors, extraContext, existingRecord);
209+
beforeInsert(table, c, user, insertOption, newRow, errors, extraContext, existingRecord);
203210
break;
204211
case UPDATE:
205212
beforeUpdate(table, c, user, newRow, oldRow, errors, extraContext);
@@ -227,16 +234,16 @@ default void rowTrigger(TableInfo table, Container c, User user, TableInfo.Trigg
227234
}
228235

229236
default void beforeInsert(TableInfo table, Container c,
230-
User user, @Nullable Map<String, Object> newRow,
237+
User user, @Nullable QueryUpdateService.InsertOption insertOption, @Nullable Map<String, Object> newRow,
231238
ValidationException errors, Map<String, Object> extraContext) throws ValidationException
232239
{
233240
}
234241

235242
default void beforeInsert(TableInfo table, Container c,
236-
User user, @Nullable Map<String, Object> newRow,
243+
User user, @Nullable QueryUpdateService.InsertOption insertOption, @Nullable Map<String, Object> newRow,
237244
ValidationException errors, Map<String, Object> extraContext, @Nullable Map<String, Object> existingRecord) throws ValidationException
238245
{
239-
beforeInsert(table, c, user, newRow, errors, extraContext);
246+
beforeInsert(table, c, user, insertOption, newRow, errors, extraContext);
240247
}
241248

242249
default void beforeUpdate(TableInfo table, Container c,

api/src/org/labkey/api/dataiterator/TriggerDataBuilderHelper.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ public boolean next() throws BatchValidationException
212212
TableInfo.TriggerType triggerType = getTriggerType();
213213
if (_firstRow)
214214
{
215-
_target.fireBatchTrigger(_c, _user, triggerType, true, getErrors(), _extraContext);
215+
_target.fireBatchTrigger(_c, _user, triggerType, _context.getInsertOption(), true, getErrors(), _extraContext);
216216
firedInit = true;
217217
_firstRow = false;
218218
}
@@ -223,7 +223,7 @@ public boolean next() throws BatchValidationException
223223
_currentRow = getInput().getMap();
224224
try
225225
{
226-
_target.fireRowTrigger(_c, _user, triggerType, true, rowNumber, _currentRow, getOldRow(), _extraContext, getExistingRecord(), true);
226+
_target.fireRowTrigger(_c, _user, triggerType, _context.getInsertOption(), true, rowNumber, _currentRow, getOldRow(), _extraContext, getExistingRecord(), true);
227227
return true;
228228
}
229229
catch (ValidationException vex)
@@ -290,7 +290,7 @@ public boolean next() throws BatchValidationException
290290
Map<String,Object> newRow = getInput().getMap();
291291
try
292292
{
293-
_target.fireRowTrigger(_c, _user, getTriggerType(), false, rowNumber, newRow, getOldRow(), _extraContext, getExistingRecord(), true);
293+
_target.fireRowTrigger(_c, _user, getTriggerType(), _context.getInsertOption(), false, rowNumber, newRow, getOldRow(), _extraContext, getExistingRecord(), true);
294294
}
295295
catch (ValidationException vex)
296296
{
@@ -302,7 +302,7 @@ public boolean next() throws BatchValidationException
302302
finally
303303
{
304304
if (!hasNext && firedInit && !getErrors().hasErrors())
305-
_target.fireBatchTrigger(_c, _user, getTriggerType(), false, getErrors(), _extraContext);
305+
_target.fireBatchTrigger(_c, _user, getTriggerType(), _context.getInsertOption(), false, getErrors(), _extraContext);
306306
}
307307
}
308308
}

api/src/org/labkey/api/query/AbstractQueryUpdateService.java

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@
7777
import org.labkey.api.files.FileContentService;
7878
import org.labkey.api.gwt.client.AuditBehaviorType;
7979
import org.labkey.api.ontology.OntologyService;
80-
import org.labkey.api.ontology.Quantity;
8180
import org.labkey.api.pipeline.PipeRoot;
8281
import org.labkey.api.pipeline.PipelineService;
8382
import org.labkey.api.reader.TabLoader;
@@ -605,7 +604,7 @@ protected List<Map<String, Object>> _insertRowsUsingInsertRow(User user, Contain
605604

606605
errors.setExtraContext(extraScriptContext);
607606
if (hasTableScript)
608-
getQueryTable().fireBatchTrigger(container, user, TableInfo.TriggerType.INSERT, true, errors, extraScriptContext);
607+
getQueryTable().fireBatchTrigger(container, user, TableInfo.TriggerType.INSERT, null, true, errors, extraScriptContext);
609608

610609
List<Map<String, Object>> result = new ArrayList<>(rows.size());
611610
List<Map<String, Object>> providedValues = new ArrayList<>(rows.size());
@@ -659,7 +658,7 @@ else if (SqlDialect.isTransactionException(sqlx) && errors.hasErrors())
659658
}
660659

661660
if (hasTableScript)
662-
getQueryTable().fireBatchTrigger(container, user, TableInfo.TriggerType.INSERT, false, errors, extraScriptContext);
661+
getQueryTable().fireBatchTrigger(container, user, TableInfo.TriggerType.INSERT, null, false, errors, extraScriptContext);
663662

664663
addAuditEvent(user, container, QueryService.AuditAction.INSERT, null, result, null, providedValues);
665664

@@ -837,7 +836,7 @@ public List<Map<String, Object>> updateRows(User user, Container container, List
837836
assert(getQueryTable().supportsInsertOption(InsertOption.UPDATE));
838837

839838
errors.setExtraContext(extraScriptContext);
840-
getQueryTable().fireBatchTrigger(container, user, TableInfo.TriggerType.UPDATE, true, errors, extraScriptContext);
839+
getQueryTable().fireBatchTrigger(container, user, TableInfo.TriggerType.UPDATE, null, true, errors, extraScriptContext);
841840

842841
List<Map<String, Object>> result = new ArrayList<>(rows.size());
843842
List<Map<String, Object>> oldRows = new ArrayList<>(rows.size());
@@ -889,7 +888,7 @@ public List<Map<String, Object>> updateRows(User user, Container container, List
889888
}
890889

891890
// Fire triggers, if any, and also throw if there are any errors
892-
getQueryTable().fireBatchTrigger(container, user, TableInfo.TriggerType.UPDATE, false, errors, extraScriptContext);
891+
getQueryTable().fireBatchTrigger(container, user, TableInfo.TriggerType.UPDATE, null, false, errors, extraScriptContext);
893892
afterInsertUpdate(null==result?0:result.size(), errors, true);
894893

895894
if (errors.hasErrors())
@@ -961,7 +960,7 @@ public List<Map<String, Object>> deleteRows(User user, Container container, List
961960

962961
BatchValidationException errors = new BatchValidationException();
963962
errors.setExtraContext(extraScriptContext);
964-
getQueryTable().fireBatchTrigger(container, user, TableInfo.TriggerType.DELETE, true, errors, extraScriptContext);
963+
getQueryTable().fireBatchTrigger(container, user, TableInfo.TriggerType.DELETE, null, true, errors, extraScriptContext);
965964

966965
// TODO: Support update/delete without selecting the existing row -- unfortunately, we currently get the existing row to check its container matches the incoming container
967966
boolean streaming = false; //_queryTable.canStreamTriggers(container) && _queryTable.getAuditBehavior() != AuditBehaviorType.NONE;
@@ -1006,7 +1005,7 @@ public List<Map<String, Object>> deleteRows(User user, Container container, List
10061005
}
10071006

10081007
// Fire triggers, if any, and also throw if there are any errors
1009-
getQueryTable().fireBatchTrigger(container, user, TableInfo.TriggerType.DELETE, false, errors, extraScriptContext);
1008+
getQueryTable().fireBatchTrigger(container, user, TableInfo.TriggerType.DELETE, null, false, errors, extraScriptContext);
10101009

10111010
addAuditEvent(user, container, QueryService.AuditAction.DELETE, configParameters, result, null, null);
10121011

@@ -1028,11 +1027,11 @@ public int truncateRows(User user, Container container, @Nullable Map<Enum, Obje
10281027

10291028
BatchValidationException errors = new BatchValidationException();
10301029
errors.setExtraContext(extraScriptContext);
1031-
getQueryTable().fireBatchTrigger(container, user, TableInfo.TriggerType.TRUNCATE, true, errors, extraScriptContext);
1030+
getQueryTable().fireBatchTrigger(container, user, TableInfo.TriggerType.TRUNCATE, null, true, errors, extraScriptContext);
10321031

10331032
int result = truncateRows(user, container);
10341033

1035-
getQueryTable().fireBatchTrigger(container, user, TableInfo.TriggerType.TRUNCATE, false, errors, extraScriptContext);
1034+
getQueryTable().fireBatchTrigger(container, user, TableInfo.TriggerType.TRUNCATE, null, false, errors, extraScriptContext);
10361035
addAuditEvent(user, container, QueryService.AuditAction.TRUNCATE, configParameters, null, null, null);
10371036

10381037
return result;

assay/src/org/labkey/assay/plate/data/WellTriggerFactory.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import org.labkey.api.data.triggers.TriggerFactory;
1818
import org.labkey.api.query.BatchValidationException;
1919
import org.labkey.api.query.QueryService;
20+
import org.labkey.api.query.QueryUpdateService;
2021
import org.labkey.api.query.SimpleValidationError;
2122
import org.labkey.api.query.UserSchema;
2223
import org.labkey.api.query.ValidationException;
@@ -148,13 +149,15 @@ public void beforeInsert(
148149
TableInfo table,
149150
Container c,
150151
User user,
152+
@Nullable QueryUpdateService.InsertOption insertOption,
151153
@Nullable Map<String, Object> newRow,
152154
ValidationException errors,
153-
Map<String, Object> extraContext
155+
Map<String, Object> extraContext,
156+
@Nullable Map<String, Object> existingRecord
154157
)
155158
{
156159
addTypeSample(c, user, newRow, null, extraContext);
157-
setInsertManagedColumns(newRow);
160+
setInsertManagedColumns(newRow, existingRecord, insertOption);
158161
}
159162

160163
@Override

0 commit comments

Comments
 (0)