4.2 Annotation (NO)CHECK, To Include/Exclude Fields for ETAG Calculation
You declaratively specify the document parts to use for checking the state/version of a document when performing an updating operation, by annotating the definition of the duality view that supports such a document.
When an application updates a document it often needs to make sure that the version/state of the document being updated hasn't somehow changed since the document was last retrieved from the database.
One way to implement this is using optimistic concurrency
control, which is lock-free. By default, every document supported by a
duality view records a document-state signature in the form of an ETAG field,
etag
. The field value is constructed as a hash value of
the document content and some other information, and it is automatically renewed each
time a document is retrieved.
When your application writes a document that it has updated locally, the
database automatically computes an up-to-date ETAG value for the current state of the
stored document, and it checks this value against the etag
value
embedded in the document to be updated (sent by your application).
If the two values don't match then the update operation fails. In that case,
your application can then retrieve the latest version of the document from the database,
modify it as needed for the update (without changing the new value of field
etag
), and try again to write the (newly modified) document. See
Using Optimistic Concurrency Control With Duality Views.
By default, all fields of a document contribute to the calculation of the
value of field etag
. To exclude a given field from participating
in this calculation, annotate its column with keyword NOCHECK
(following WITH
, just as for the updatability annotations).
In the same way as for updatability annotations, you can specify
NOCHECK
in a FROM
clause, to have it apply to all
columns affected by that clause. In that case, you can use CHECK
to annotate a given column, to exclude it from the effect of the table-level
NOCHECK
.
Identifying columns, however, always have the default behavior of
contributing to ETAG calculation, regardless of any table-level annotations. To exclude
an identifying column from the ETAG calculation you must give it an explicit
column-level annotation of NOCHECK
.
In particular, this means that to exclude an entire document from
ETAG checking you need to explicitly annotate each identifying column with
NOCHECK
, as well as annotating all tables (or all other columns)
with NOCHECK
.
Note:
An attempt to update a column annotated with both NOCHECK
and
NOUPDATE
does not raise an error; the update request is simply
ignored. This is to prevent interfering with possible concurrency.
If an update operation succeeds, then all changes it defines are made, including any changes for a field that doesn't participate in the ETAG calculation, thus overwriting any changes for that field that might have been made in the meantime. That is, the field that is not part of the ETAG calculation is not ignored for the update operation.
For example, field team
of view driver_dv
is an object with the driver's team information, and field name
of this
team object is annotated NOCHECK
in the Example 3-3. This means that the team name doesn't
participate in computing an ETAG value for a driver document.
Because the team name doesn't participate in a driver-document ETAG calculation, changes
to the team information in the document are not taken into account. Table team is marked
NOUPDATE
in the definition of view driver_dv
, so
ignoring its team information when updating a driver document is not a problem.
But suppose table team
were instead marked UPDATE
. In
that case, updating a driver document could update the driver's team information, which
means modifying data in table team
.
Suppose also that a driver's team information was changed externally somehow since your
application last read the document for that driver — for example, the team was renamed
from "OLD Team Name"
to "NEW Team Name"
.
Then updating that driver document would not fail because of the team-name
conflict (it could fail for some other reason, of course). The previous change to
"NEW Team Name"
would simply be ignored; the team name would be
overwritten by the name
value specified in the
driver-document update operation (likely "OLD Team Name"
).
You can avoid this problem (which can only arise if table team
is
updatable through a driver document) by simply omitting the team
name
from the document or document fragment that you provide in the
update operation.
Similarly, field driver
of a team document is an
array of driver objects, and field points
of those objects
is annotated NOCHECK
(see Example 3-1), so changes to that field by another session (from any application)
don't prevent updating a team document. (The same caveat, about a field that's not part
of the ETAG calculation not being ignored for the update operation, applies here.)
A duality view as a whole has its documents ETAG-checked if no column is, in
effect, annotated NOCHECK
. If all columns are
NOCHECK
, then no document field contributes to ETAG computation.
This can improve performance, the improvement being more significant for larger
documents. Use cases where you might want to exclude a duality view from all ETAG
checking include these:
-
An application has its own way of controlling concurrency, so it doesn't need a database ETAG check.
-
An application is single-threaded, so no concurrent modifications are possible.
You can use PL/SQL function DBMS_JSON_SCHEMA.describe
to see whether a
duality view has its documents ETAG-checked. If so, top-level array field
properties
contains the element "check"
.