HistoryWalker - Scoped, Global

The HistoryWalker API uses the audit/history tables to generate a historical version of an existing record. It supports the ability to return a GlideRecord to a previous update count (walked GlideRecord) with the appropriate GlideElements populated. After the walked GlideRecord is retrieved, the API provides the ability to move forward and backward the update numbers navigating through its historical updates.

The associated methods can be used in scoped and global scripts. To use this class in scoped and global applications, use the sn_hw namespace identifier. The History Walker plugin (com.glide.history_walker) that is enabled by default is required to access the HistoryWalker API.

The HistoryWalker API provides two ways to retrieve the audit data:
  • Using History Set: A History Set entry is created (if not available or not up to date) from the data in the sys_audit table for the record that you are going to walk through. The History Set table contains records (History Lines) with the actual changes to field values that occurred. Methods of the HistoryWalker API retrieve the history data from the generated History Lines, instead of querying the sys_audit table.
  • Using Audit table: In this case, the HistoryWalker API extracts data directly querying the sys_audit table.

By default, it populates the data to support the “changes”, “changesFrom” and “changesTo” methods in the walked record, as well as provides record and field level security. Additionally, it can enable journal fields and variables to be also populated in the walked GlideRecord when walking through the updates.

This API enables you to:

  • apply the appropriate history/audit data to get an existing GlideRecord to the state it was in a specific update count.
  • instruct the HistoryWalker API to use sys_audit table instead of sys_history_set/sys_history_line tables to retrieve its data.
  • turn off row-level access control.
  • turn off field-level access control.
  • turn off retrieval and processing of “changes” data.
  • Enable journal fields.
  • Enable variables.

HistoryWalker - HistoryWalker(String tableName, String sysId)

Fetches the database record based on the parameters, using the History Sets to retrieve the historic data.

Table 1. Parameters
Name Type Description
tableName String Name of table containing the record to retrieve.
sydId String sys_id of the record to retrieve.

Example:

var incGr = new GlideRecord('incident');
incGr.get('number', 'INC0000015');

var hw = new sn_hw.HistoryWalker(incGr.getTableName(), incGr.getUniqueValue());
if (hw.walkTo(3)) {
    var oldPriority = hw.getWalkedRecord().priority;
    gs.info('Incident priority in update number ' + hw.getUpdateNumber() + ' was ' + oldPriority);
} else
    gs.info('Incident does not have update number 3');

Output:

Incident priority in update number 3 was 4

HistoryWalker - HistoryWalker(String tableName, String sysId, Boolean useAudit)

Fetches the database record based on the parameters, using the History Sets or Audit data to retrieve the historic data, depending on the third parameter.

Table 2. Parameters
Name Type Description
tableName String Name of table containing the record to retrieve.
sydId String sys_id of the record to retrieve.
useAudit Boolean
  • If set to true, uses audit data to retrieve historic date.
  • If set to false, uses history set to retrieve historic date.

Example

var incGr = new GlideRecord('incident');
incGr.get('number', 'INC0000015');

var hw = new sn_hw.HistoryWalker(incGr.getTableName(), incGr.getUniqueValue(), true);
if (hw.walkTo(3)) {
    var oldPriority = hw.getWalkedRecord().priority;
    gs.info('Incident priority in update number ' + hw.getUpdateNumber() + ' was ' + oldPriority);
} else
    gs.info('Incident does not have update number 3');

Output:

Incident priority in update number 3 was 4

HistoryWalker - getUpdateNumber()

Gets the update number of the current walked glide record.

Table 3. Parameters
Name Type Description
None
Table 4. Returns
Type Description
int Current update number or, -1 if record is not found

Example:

var incGr = new GlideRecord('incident');
incGr.get('number', 'INC0000015');

var hw = new sn_hw.HistoryWalker(incGr.getTableName(), incGr.getUniqueValue());
hw.walkTo(3);
gs.info('Update number: ' + hw.getUpdateNumber());

Output:

Update number: 3

HistoryWalker - getWalkedRecord()

Gets the record filled with the history/audit data after walking to an update number.

Table 5. Parameters
Name Type Description
None
Table 6. Returns
Type Description
GlideRecord The walked GlideRecord.

Example:

var incGr = new GlideRecord('incident');
incGr.get('number', 'INC0000015');

var hw = new sn_hw.HistoryWalker(incGr.getTableName(), incGr.getUniqueValue());
hw.walkTo(0);
var walkedRecord = hw.getWalkedRecord();
gs.info('Priority in update number 0: ' + walkedRecord.priority);
hw.walkTo(1);
walkedRecord = hw.getWalkedRecord();
gs.info('Short description in update number 1: ' + walkedRecord.short_description);

Output:

 Priority in update number 0: 4
Short description in update number 1: My monitor has stopped working

HistoryWalker - getWalkedRecordCopy()

Gets a copy of the record filled with the history/audit data after walking to an update number.

Note: The getWalkedRecord() API might modify the obtained walkedRecord after walking to another update number. The getWalkedRecordCopy() API gets a clone to the walked record to prevent that.
Table 7. Parameters
Name Type Description
None
Table 8. Returns
Type Description
GlideRecord A copy of the walked GlideRecord.

Example:

var incGr = new GlideRecord('incident');
incGr.get('number', 'INC0000015');

var walkedRecord = [];
var hw = new sn_hw.HistoryWalker(incGr.getTableName(), incGr.getUniqueValue());
hw.walkTo(0);
walkedRecord[0] = hw.getWalkedRecordCopy();
hw.walkTo(1);
walkedRecord[1] = hw.getWalkedRecordCopy();

gs.info('Priority in update number 0: ' + walkedRecord[0].priority);
gs.info('Short description in update number 1: ' + walkedRecord[1].short_description);

Output:

Priority in update number 0: 4
Short description in update number 1: My monitor has stopped working

HistoryWalker - isFieldLevelSecurity()

Specifies if the record-level read access is applied on the record when retrieving from the database.

Table 9. Parameters
Name Type Description
None
Table 10. Returns
Type Description
Boolean Returns true if field level security is enabled, else returns false.

Example:

var incGr = new GlideRecord('incident');
incGr.get('number', 'INC0000015');

var hw = new sn_hw.HistoryWalker(incGr.getTableName(), incGr.getUniqueValue());
gs.info('Field level security is active: ' + hw.isFieldLevelSecurity());

Output:

Field level security is active: true

HistoryWalker - isRecordLevelSecurity()

Specifies if the record-level read access is applied on the record when retrieving from the database.

Table 11. Parameters
Name Type Description
None
Table 12. Returns
Type Description
Boolean Returns true if the record-level security is enabled, else returns false.

Example:

var incGr = new GlideRecord('incident');
incGr.get('number', 'INC0000015');

var hw = new sn_hw.HistoryWalker(incGr.getTableName(), incGr.getUniqueValue());
gs.info('Record level security is active: ' + hw.isRecordLevelSecurity());

Output:

Record level security is active: true

HistoryWalker - isWithChanges()

Specifies if any of the methods that walk the record from one update to another, support the “changes” data for each element.

Table 13. Parameters
Name Type Description
None
Table 14. Returns
Type Description
Boolean Returns true if the changes support is enabled, else returns false.

Example:

var incGr = new GlideRecord('incident');
incGr.get('number', 'INC0000015');

var hw = new sn_hw.HistoryWalker(incGr.getTableName(), incGr.getUniqueValue());
gs.info('Changes is active: ' + hw.isWithChanges());

Output:

Changes is active: true

HistoryWalker - isWithJournalFields()

Specifies if journal type fields are populated from the historical values.

Table 15. Parameters
Name Type Description
None
Table 16. Returns
Type Description
Boolean Returns true if journal fields are populated, else returns false.

Example:

var incGr = new GlideRecord('incident');
incGr.get('number', 'INC0000015');

var hw = new sn_hw.HistoryWalker(incGr.getTableName(), incGr.getUniqueValue());
gs.info('Populating journal fields is active: ' + hw. isWithJournalFields());

Output:

Populating journal fields is active: false

HistoryWalker - isWithVariables()

Specifies if values are set for variables that are recorded in the history.

Table 17. Parameters
Name Type Description
None
Table 18. Returns
Type Description
Boolean Returns true if including values for variables, else returns false.

Example:

var incGr = new GlideRecord('incident');
incGr.get('number', 'INC0000015');

var hw = new sn_hw.HistoryWalker(incGr.getTableName(), incGr.getUniqueValue());
gs.info('Populating variables is active: ' + hw. isWithVariables());

Output:

Populating variables is active: false

HistoryWalker - setFieldLevelSecurity(Boolean fieldLevelSecurity)

Sets the field-level read access on each element before setting the historical value of that element in the GlideRecord. If the field-level security is enabled, it prevents the API to populate the fields of the walked record that the user of the API does not have access to.

Table 19. Parameters
Name Type Description
fieldLevelSecurity Boolean If set to true, field-level security is enabled. The default value is true.
Table 20. Returns
Type Description
void

Example:

var incGr = new GlideRecord('incident');
incGr.get('number', 'INC0000015');

var hw = new sn_hw.HistoryWalker(incGr.getTableName(), incGr.getUniqueValue());
hw.setFieldLevelSecurity(false);
hw.walkTo(0);

HistoryWalker - setRecordLevelSecurity(Boolean recordLevelSecurity)

Sets the record-level read access on the record when retrieving from the database. The record-level security prevents the API to retrieve the walked record if the user of the API does not have access to the GlideRecord.

Table 21. Parameters
Name Type Description
recordLevelSecurity Boolean If set to true, record-level read access security is enabled. The default value is true.
Table 22. Returns
Type Description
void

Example:

var incGr = new GlideRecord('incident');
incGr.get('number', 'INC0000015');

var hw = new sn_hw.HistoryWalker(incGr.getTableName(), incGr.getUniqueValue());
hw.setRecordLevelSecurity(false);
hw.walkTo(0);

HistoryWalker - setWithChanges(Boolean withChanges)

Sets the “changes” data support for each element for a method that walks the record from one update to another.

Table 23. Parameters
Name Type Description
withChanges Boolean If set to true, the “changes” data is supported for each element. The default value is true.
Table 24. Returns
Type Description
void

Example: With the Changes data support

var hw = new sn_hw.HistoryWalker(incGr.getTableName(), incGr.getUniqueValue());
hw.walkTo(0);
do {
    printChangedFields(hw);
} while (hw.walkForward());

function printChangedFields(hw) {
    var walkedGr = hw.getWalkedRecord();
    var fields = GlideScriptRecordUtil.get(walkedGr).getChangedFieldNames();
    gs.print("Fields changed at update " + hw.getUpdateNumber() + " were:");
    for (var j = 0; j < fields.size(); j++)
        gs.print(" " + fields.get(j));
    gs.print("");
}

Example: Without the Changes data support

var incGr = new GlideRecord('incident');
incGr.get('number', 'INC0000015');

var hw = new sn_hw.HistoryWalker(incGr.getTableName(), incGr.getUniqueValue());
hw.setWithChanges(false);
hw.walkTo(0);
do {
    var oldPriority = hw.getWalkedRecord().priority;
    gs.print('Incident priority in update number ' + hw.getUpdateNumber() + ' was ' + oldPriority);
} while (hw.walkForward());

HistoryWalker - setWithJournalFields(Boolean withJournalFields)

Specifies if journal type fields are populated from the historical values.

Table 25. Parameters
Name Type Description
withJournalFields Boolean If set to true, include journal-type fields. Th default value is false.
Table 26. Returns
Type Description
void

Example:

var incGr = new GlideRecord('incident');
incGr.get('number', 'INC0000015');

var hw = new sn_hw.HistoryWalker(incGr.getTableName(), incGr.getUniqueValue());
hw.setWithJournalFields(true);
if (hw.walkTo(0)) {
    var workNotes = hw.getWalkedRecord().work_notes;
    gs.info('Work Notes in update number ' + hw.getUpdateNumber() + ' was ' + workNotes);
}

HistoryWalker - setWithVariables(Boolean withVariables)

Specifies if variables are populated from the historical values.

Table 27. Parameters
Name Type Description
withVariables Boolean If set to true, values are populated for variables. The default value is false.
Table 28. Returns
Type Description
void

Example:

var incGr = new GlideRecord('incident');
incGr.get('number', 'INC0000015');

var hw = new sn_hw.HistoryWalker(incGr.getTableName(), incGr.getUniqueValue());
hw.setWithVariables(true);
hw.walkTo(0);
if (hw.walkTo(0)) {
    var varUrgency = hw.getWalkedRecord().variables.urgency;
    gs.info('Variable Urgency in update number ' + hw.getUpdateNumber() + ' was ' + varUrgency);
}

HistoryWalker - walkBackward()

Applies the appropriate history/audit data to get a walked GlideRecord to the state when it was one update number backward. If the previous update count is missing from the history/audit data, it will walk to the previous available update count.

Table 29. Parameters
Name Type Description
None
Table 30. Returns
Type Description
Boolean Returns true if walking to the specified update number was possible. Else, returns false, for example if already walked to the update number 0.

Example:

var incGr = new GlideRecord('incident');
incGr.get('number', 'INC0000015');

var hw = new sn_hw.HistoryWalker(incGr.getTableName(), incGr.getUniqueValue());
hw.walkTo(incGr.sys_mod_count);
do {
    var oldPriority = hw.getWalkedRecord().priority;
    gs.info('Incident priority in update number ' + hw.getUpdateNumber() + ' was ' + oldPriority);
} while (hw.walkBackward())

Output:

Incident priority in update number 5 was 2
Incident priority in update number 4 was 4
Incident priority in update number 3 was 4
Incident priority in update number 2 was 4
Incident priority in update number 1 was 4
Incident priority in update number 0 was 4

HistoryWalker - walkForward()

Applies the appropriate history/audit data to get a walked GlideRecord to the state when it was one update number forward. If next update count is missing from the history/audit data, it will walk to the next available update count.

Table 31. Parameters
Name Type Description
None
Table 32. Returns
Type Description
Boolean Returns true if walking to the specified update number was possible. Else, returns false, for example if already walked to the GlideRecord update count.

Example:

var incGr = new GlideRecord('incident');
incGr.get('number', 'INC0000015');

var hw = new sn_hw.HistoryWalker(incGr.getTableName(), incGr.getUniqueValue());
hw.walkTo(0);
do {
    var oldPriority = hw.getWalkedRecord().priority;
    gs.info('Incident priority in update number ' + hw.getUpdateNumber() + ' was ' + oldPriority);
} while (hw.walkForward())

Output:

Incident priority in update number 0 was 4
Incident priority in update number 1 was 4
Incident priority in update number 2 was 4
Incident priority in update number 3 was 4
Incident priority in update number 4 was 4
Incident priority in update number 5 was 2
 

HistoryWalker - walkTo(int updateCount)

Applies the appropriate history/audit data to get a GlideRecord to the state it was in a specific update count. Use getWalkedRecord() or getWalkedRecordCopy() after walking to an update number to retrieve the “walked” GlideRecord.

Table 33. Parameters
Name Type Description
updateCount Integer The update number to walk to.
Table 34. Returns
Type Description
Boolean true if walking to the specified update number was possible, false otherwise, for example if the requested update is greater than the update count of the GlideRecord, or if there is no history/audit data of the requested update number

Example:

var incGr = new GlideRecord('incident');
incGr.get('number', 'INC0000015');

var hw = new sn_hw.HistoryWalker(incGr.getTableName(), incGr.getUniqueValue());
if (hw.walkTo(3)) {
    var oldPriority = hw.getWalkedRecord().priority;
    gs.info('Incident priority in update number ' + hw.getUpdateNumber() + ' was ' + oldPriority);
} else
    gs.info('Incident does not have update number 3');

Output:

Incident priority in update number 3 was 4