This is part two of a two-part series on transactions. Read Part 1 here: Transactions in FileMaker 19.6: Part 1.

The new transactions model in Claris FileMaker 19.6 has made using scripted transactions easier, more flexible, and more explicit. It greatly improves on the implicit transaction model we are familiar with, however, there are still some details developers should be aware of and features of the design they may need to work around.

Caveats

Caveats to the new transactions model generally fall into two areas:

  1. Understanding scripting behavior while a transaction is active
  2. Understanding the scope of what can be done within an active transaction

Script step behavior

While the number of script steps available within a transaction has expanded, there are some nuances to how those script steps behave.

The following script steps behave slightly differently within a transaction block:

Import Records – the summary dialog is not displayed after the records have been imported; if the import operation creates new fields or tables, those elements are deleted if the transaction is reverted.

Delete All Records – records are deleted in a loop – which is a slower method – to allow for the transaction to be reverted.

Truncate Table – this script step requires Full Access and does not support cascading deletes, the same as when used outside of a transaction.

Script Steps That End the Transaction

As with the legacy model, some script steps will attempt to commit the transaction when executed:

  • Re-Login
  • Close File
  • Save a Copy As
  • Open Manage Database
  • Open Manage Containers
  • Open Manage Data Sources

Invoking the script steps above will cause the database engine to attempt to commit the transaction, with success being dependent on the same rules as invoking the Commit Transaction step. 

In addition to these, some script steps cause the transaction to automatically abort when an error is encountered.

  • Re-Lookup Field Contents
  • If the database engine encounters a record access error (error 200) the Transaction will be aborted
  • Replace Field Contents / Set Field / Set Field by Name
  • If the database engine encounters a field write access error (error 201) or validation errors (errors 500-513) the transaction will be aborted
  • Delete Record / Delete All Records / Delete Portal Row / New Record / Duplicate Record
  • If the database engine encounters a record access error (error 200) the Transaction will be aborted
  • Import Records
  • If the database engine encounters an access error for the target table (error 723) or the Import Record command fails for another reason (error 729) the transaction will be aborted.

Interaction of New Steps and Old

One of the first considerations when adopting the new transaction script steps is how this will interact with the legacy script steps. When the Open Transaction command has been issued, any record modifications within the transaction block will remain uncommitted. If you issue a Commit Records/Requests or Revert Record/Request command, it will be ignored and will not lead to an error being generated.

Transaction scope

There are some caveats to transaction scope in the new model that can trip up developers starting to use the new script steps. Similar to the legacy implementation, transactions in FileMaker Pro 19.6 remain scoped to the window where the Open Transaction command was first issued. However, the legacy transactions model allows you to open multiple transactions simultaneously by using multiple windows. The new transactions model only allows a single transaction at a time for each file and can not be nested. Therefore if your design relies on multiple, concurrent transactions you must use the legacy method. Consider the following script that merges two CONTACT records:

This script reads data from the “Source” CONTACT, writes the data to the “Target” CONTACT, and then deletes the “Source” Contact record. You might assume that if there is a problem committing the transaction (for example, if a validation error prevented the “Target” record from being written to the database) that the entire operation would fail, and the “Source” record would not be deleted since it was “inside” of the transaction block. However, because the transaction was opened within the context of the “Target” window, any operations in the “Source” window happen outside the Transaction Scope. This means the “Source” record would have been permanently deleted if the transaction were rolled back.

While the legacy script steps (Commit Records/Requests, Revert Record/Request) are ignored within a transaction block, you still have the ability to mix new and legacy techniques. While there’s no reason to change something that is tested and working, when refactoring code you can quickly and easily adopt the new functionality and the transactional processing will continue to work.

Simply add the new Open Transaction step at the beginning and the Commit Transaction script step in place of the Commit Records/Requests script step. If your script creates or deletes related records using a relationship, these modifications will continue to work. However, you will not be able to access the records the same way as if they were created using the New Record command, where they are added to your current Found Set. A new record created via relationship will not be added to the Found Set of records for that table occurrence, nor will you be able to “Find” the records using attributes you may have set. You can Show All Records and scroll through the record to locate the open record by attribute, but it will likely be easier to switch from creating the record via relationship to a method using Go To Layout and New Record.

Subscripts, Errors, and Abort

While the new transaction script steps add a level of control to your scripts, many scripting patterns rely on calling other scripts to perform tasks as part of a transactional operation. Because a transaction can only be aborted in the script where the Open Transaction command was issued, you cannot rely on the Revert Transaction command to exit out to the end of the transaction. Instead, to abort an open transaction from a script that did not create the transaction you will need the subscript to return an error code to the calling script.

Capturing errors and passing those errors back up the script call stack is an integral part of defensive programming. It allows us to control the transaction where FileMaker’s model does not provide a direct way of doing so. The following script opens a transaction and then creates a new record. Instead of editing that record directly, it calls an existing script to perform the edits.

On lines 10 through 12 it receives a result from the edit script and on line 15 examines that result to see if an error was returned. If so, it will Revert the transaction with a custom error code and custom error message derived from the subscript.

The Edit Record script can be called directly or called from another script. If called directly it will open a transaction before setting the record data. If a transaction was already open the step on line 11 has no effect.

If the transaction was opened by the Edit Record script then on line 20 it will abort the transaction. Otherwise, it returns the error back to the calling script which will handle aborting the transaction.

As can be expected, the new transactions functionality doesn’t deliver everything a developer might need for their transactional processing. Plenty of arguments can and have been made for different design choices (such as allowing transactions to be aborted in subscripts) or for the functionality to be expanded more generally (for example, emulating the Try/Catch/Throw pattern in JavaScript). But in most cases the new pattern is far easier to use, and the caveats here simply provide guidance for behavior to look out for and how to account for it. Notably, the new transactions functionality has been added without impacting the existing functionality. If the old way of using transactions worked for you, you can continue to use that model. For new projects, the new transactions model is a compelling option moving forward.

If you’d like to learn more about using transactions, check out this video demo: Transactions in Claris FileMaker 19.6 with Corn Walker.