mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-17 20:50:44 +00:00
87 lines
5.8 KiB
Plaintext
87 lines
5.8 KiB
Plaintext
== InsertAction
|
|
include::../variables.adoc[]
|
|
|
|
To insert (add, create) new records into any {link-table}, the `*InsertAction*` is used.
|
|
In SQL/RDBMS terms, it is analogous to a `INSERT` statement, where one or more records can be provided as input.
|
|
|
|
=== Examples
|
|
[source,java]
|
|
.Canonical InsertAction invocation
|
|
----
|
|
InsertInput insertInput = new InsertInput();
|
|
insertInput.setTableName("person");
|
|
insertInput.setRecords(personRecordList);
|
|
InsertOutput insertOutput = new InsertAction().execute(insertInput);
|
|
List<QRecord> insertedPersonRecords = insertOutput.getRecords();
|
|
----
|
|
|
|
=== Details
|
|
`InsertAction` does several things beyond just inserting records into the specified table.
|
|
A high-level flow of its internal logic is:
|
|
|
|
. For tables using an automation status field, set its value to `PENDING_INSERT_AUTOMATIONS` for all `records` that are going to be inserted.
|
|
. Perform the following validations, which include running the table's `PRE_INSERT_CUSTOMIZER`, if one is defined, at the time that is specified by the customizer's `WhenToRun` property (default is `AFTER_ALL_VALIDATIONS`):
|
|
.. Ensure that default values specified in the table's fields are present if needed.
|
|
.. Apply per-field behaviors, as defined in {link-field} meta-data, such as truncating strings that are longer than their specified max.
|
|
.. Check for unique key violations (done here instead of in the backend, to provide better error messaging, and to allow a subset of records to be stored while some fail).
|
|
_We might want to make an input control in the future to specify that either the full input set should succeed or fail..._
|
|
.. Validate that required fields (again, per {link-field} meta-data) are set, generating per-record errors if they are not.
|
|
.. Validate any security fields in the records - e.g., ensure that the user has permission to insert records with the values they are attempting to insert.
|
|
. Send the records to the table's backend module to actually insert them into the backend storage.
|
|
. If the table has any associations defined, and if associated records are present, then recursively run `InsertAction` on the associated records.
|
|
.. In particular, before these recursive `InsertAction` calls are made, values that were generated by the original insert may need to be propagated down into the associated records.
|
|
*** For example, if inserting `order` and `lineItem` records, where a {link-join} exists between the two tables on `order.id` and `lineItem.orderId`, and `order.id` values were generated in the first `InsertAction`, then those values are propagated down into the associated `lineItem.orderId` fields.
|
|
. If the {link-instance} has an `audit` table, then based on the {link-table}'s audit rules, audits about the inserted records are created.
|
|
. If the table has a `POST_INSERT_CUSTOMIZER`, it is executed.
|
|
|
|
=== Overloads
|
|
|
|
`InsertAction` can be called in a few alternate forms, mostly just for convenience:
|
|
|
|
[source,java]
|
|
.If inserting a single record, get that record back instead of the InsertOutput:
|
|
----
|
|
InsertInput insertInput = new InsertInput();
|
|
insertInput.setTableName("person");
|
|
insertInput.setRecords(List.of(personRecord));
|
|
QRecord insertedRecord = new InsertAction().executeForRecord(insertInput);
|
|
|
|
// or more compactly, using InsertInput.withRecord (instead of withRecords)
|
|
QRecord insertedRecord = new InsertAction()
|
|
.executeForRecord(new InsertInput("person").withRecord(personRecord));
|
|
----
|
|
|
|
[source,java]
|
|
.Taking QRecordEntity objects as inputs instead of QRecords:
|
|
----
|
|
// insert a list of person entities:
|
|
InsertInput insertInput = new InsertInput("person").withRecordEntities(personList);
|
|
InsertOutput insertOutput = new InsertAction().execute(insertInput);
|
|
|
|
// or for a single person entity (also mapping the output record back to an entity):
|
|
Person insertedPerson = new Person(new InsertAction()
|
|
.executeForRecord(new InsertInput("person").withRecordEntity(person)));
|
|
|
|
----
|
|
|
|
=== InsertInput
|
|
* `table` - *String, Required* - Name of the table that records are to be inserted into.
|
|
* `records` - *List of QRecord, Required* - List of records to be inserted into the table.
|
|
If the list is empty, the insert action does a `noop`.
|
|
|
|
.Less common options
|
|
* `inputSource` - *InputSource object, default: QInputSource.SYSTEM* - an indicator of what the source of the action is - generally, a `SYSTEM` triggered action, or a `USER` triggered action.
|
|
** `InsertAction` will call the `shouldValidateRequiredFields()` method on this object to determine if it should validate that required fields on the records have values.
|
|
Both `QInputSource.SYSTEM` and `QInputSource.USER` return `true` from this method, but application can define their own `InputSource` objects with different behavior.
|
|
** In addition, this field can be used in pre- and post-insert customizers to drive further custom logic.
|
|
* `skipUniqueKeyCheck` - *boolean, default: false* - control whether or not `InsertAction` should check for unique key violations before attempting to insert its records.
|
|
** In a context where one has previously done this validation, or is okay letting the backend provide such checks, they may wish to avoid re-doing this work, and thus may set this property to `true`.
|
|
* `omitDmlAudit` - *boolean, default: false* - control if the automatic DML audit that `InsertAction` generally performs should be omitted.
|
|
* `auditContext` - *String* - optional message which can be included in DML audit messages, to give users more context about why the insert occurred.
|
|
|
|
|
|
=== InsertOutput
|
|
* `records` - *List of QRecord* - Copy of the input list of records, with details added based on the results of the input action.
|
|
** If there were warnings or errors, the corresponding field (`warnings` or `errors`) will be set in the records.
|
|
** If the insert action generated any values (such as a serial id or a default value), those values will be in the record's `fields` map.
|