The "getRecordsFromCursor" action efficiently retrieves records from the recordset of a previously opened cursor. A cursor can jump to the beginning or end of the recordset, skip forward or backward, and retrieve records forward or backward. This action works for all FairCom products that include the FairCom database engine.
A cursor always remembers its position; thus, you can repeatedly call "getRecordsFromCursor" to retrieve additional records starting where the cursor left off. This approach makes pagination easy to implement.
A cursor is created by a call to a "getRecords..." action. All "getRecords..." actions (except for "getRecordsByIds") let you set a "returnCursor" property to true, which causes them to create a cursor and return a reference to it in the "cursorId" property. You must use this "cursorId" property in the "getRecordsFromCursor" action to retrieve records from the cursor.
To free resources on the server, you must call "closeCursor" when you no longer need a cursor.
The server automatically closes a cursor when you do not retrieve records within the number of seconds specified by the "idleCursorTimeoutSeconds" property in the "createSession" and "alterSession" actions. When you call the "getRecordsFromCursor" action, the server resets the timeout. You can set "idleCursorTimeoutSeconds" to -1 to prevent a session's cursors from timing out, but you must not fail to call "closeCursor" when you no longer need it.
Request examples
For a list and detailed description of the common properties in an action request message, see JSON Action request.
Minimal
{
"action": "getRecordsFromCursor",
"params": {
"cursorId": "replaceWithCursorIdFromGetRecords",
"fetchRecords": 1
},
"authToken": "replaceWithAuthTokenFromCreateSession"
}Maximal
{
"api": "db",
"apiVersion": "1.0",
"requestId": "2",
"action": "getRecordsFromCursor",
"params": {
"cursorId": "replaceWithCursorIdFromGetRecords",
"startFrom": "beforeFirstRecord",
"id": 2084,
"bookmark": "000000FF",
"fixedLengthCharFormat": "sql",
"skipRecords": 3,
"fetchRecords": 2
},
"responseOptions": {
"includeBookmarks": false,
"binaryFormat": "hex",
"dataFormat": "objects",
"numberFormat": "string",
"includeFields": [],
"excludeFields": []
},
"debug": "max",
"authToken": "replaceWithAuthTokenFromCreateSession"
}
Response examples
Minimal
{
"result": {
"dataFormat": "objects",
"binaryFormat": "hex",
"fields": [
{
"name": "id",
"type": "bigint",
"length": null,
"scale": null,
"defaultValue": null,
"nullable": false,
"primaryKey": 1,
"autoValue": "incrementOnInsert"
},
{
"name": "changeId",
"type": "bigint",
"length": null,
"scale": null,
"defaultValue": null,
"nullable": true,
"primaryKey": 0,
"autoValue": "changeId"
},
{
"name": "name",
"type": "varchar",
"length": 30,
"scale": null,
"defaultValue": null,
"nullable": true,
"primaryKey": 0,
"autoValue": "none"
},
{
"name": "ranking",
"type": "smallint",
"length": null,
"scale": null,
"defaultValue": null,
"nullable": false,
"primaryKey": 0,
"autoValue": "none"
},
{
"name": "birthDate",
"type": "date",
"length": null,
"scale": null,
"defaultValue": null,
"nullable": true,
"primaryKey": 0,
"autoValue": "none"
},
{
"name": "playerNumber",
"type": "number",
"length": 32,
"scale": 6,
"defaultValue": null,
"nullable": true,
"primaryKey": 0,
"autoValue": "none"
},
{
"name": "livedPast2000",
"type": "bit",
"length": null,
"scale": null,
"defaultValue": null,
"nullable": true,
"primaryKey": 0,
"autoValue": "none"
},
{
"name": "earnings",
"type": "money",
"length": 32,
"scale": 4,
"defaultValue": null,
"nullable": true,
"primaryKey": 0,
"autoValue": "none"
},
{
"name": "favoriteSaying",
"type": "varchar",
"length": 500,
"scale": null,
"defaultValue": null,
"nullable": true,
"primaryKey": 0,
"autoValue": "none"
}
],
"data": [
{
"birthDate": "1963-02-17",
"changeId": 1291366,
"earnings": 1700000000,
"favoriteSaying": "There is no 'i' in team but there is in win.",
"id": 1,
"livedPast2000": true,
"name": "Michael Jordan",
"playerNumber": 23,
"ranking": 1
}
],
"primaryKeyFields": [
"id"
],
"changeIdField": "changeId",
"moreRecords": true,
"requestedRecordCount": 1,
"returnedRecordCount": 1
},
"errorCode": 0,
"errorMessage": "",
"authToken": "replaceWithAuthTokenFromCreateSession"
}Maximal
{
"result": {
"dataFormat": "objects",
"binaryFormat": "hex",
"fields": [
{
"name": "id",
"type": "bigint",
"length": null,
"scale": null,
"defaultValue": null,
"nullable": false,
"primaryKey": 1,
"autoValue": "incrementOnInsert"
},
{
"name": "changeId",
"type": "bigint",
"length": null,
"scale": null,
"defaultValue": null,
"nullable": true,
"primaryKey": 0,
"autoValue": "changeId"
},
{
"name": "name",
"type": "varchar",
"length": 30,
"scale": null,
"defaultValue": null,
"nullable": true,
"primaryKey": 0,
"autoValue": "none"
},
{
"name": "ranking",
"type": "smallint",
"length": null,
"scale": null,
"defaultValue": null,
"nullable": false,
"primaryKey": 0,
"autoValue": "none"
},
{
"name": "birthDate",
"type": "date",
"length": null,
"scale": null,
"defaultValue": null,
"nullable": true,
"primaryKey": 0,
"autoValue": "none"
},
{
"name": "playerNumber",
"type": "number",
"length": 32,
"scale": 6,
"defaultValue": null,
"nullable": true,
"primaryKey": 0,
"autoValue": "none"
},
{
"name": "livedPast2000",
"type": "bit",
"length": null,
"scale": null,
"defaultValue": null,
"nullable": true,
"primaryKey": 0,
"autoValue": "none"
},
{
"name": "earnings",
"type": "money",
"length": 32,
"scale": 4,
"defaultValue": null,
"nullable": true,
"primaryKey": 0,
"autoValue": "none"
},
{
"name": "favoriteSaying",
"type": "varchar",
"length": 500,
"scale": null,
"defaultValue": null,
"nullable": true,
"primaryKey": 0,
"autoValue": "none"
}
],
"data": [
{
"birthDate": "1940-10-23",
"changeId": "1291366",
"earnings": "115000000",
"favoriteSaying": "Everything is practice.",
"id": "4",
"livedPast2000": true,
"name": "Pele",
"playerNumber": "10",
"ranking": "4"
},
{
"birthDate": "1961-01-26",
"changeId": "1291366",
"earnings": "1720000",
"favoriteSaying": "You miss 100 percent of the shots you never take.",
"id": "5",
"livedPast2000": true,
"name": "Wayne Gretzky",
"playerNumber": "99",
"ranking": "5"
}
],
"primaryKeyFields": [
"id"
],
"changeIdField": "changeId",
"moreRecords": true,
"requestedRecordCount": 2,
"returnedRecordCount": 2
},
"requestId": "2",
"debugInfo": {
"request": {
"api": "db",
"action": "getRecordsFromCursor",
"params": {
"cursorId": "cursorId",
"startFrom": "beforeFirstRecord",
"skipRecords": 3,
"fetchRecords": 2
},
"apiVersion": "1.0",
"requestId": "2",
"responseOptions": {
"binaryFormat": "hex",
"dataFormat": "objects",
"numberFormat": "string",
"includeFields": [],
"excludeFields": []
},
"debug": "max",
"authToken": "replaceWithAuthTokenFromCreateSession"
},
"serverSuppliedValues": {
"databaseName": null,
"ownerName": null
},
"errorData": {
"errorData": null
},
"warnings": []
},
"errorCode": 0,
"errorMessage": "",
"authToken": "replaceWithAuthTokenFromCreateSession"
}
Properties
Request properties ("params")
| Property | Description | Default | Type | Limits (inclusive) |
|---|---|---|---|---|
bookmarkor _bookmark_ |
The "
The "
Using "bookmark" to position the starting record:
|
Optional with default of ""
|
string | 0 to 2048 bytes |
cursorId |
The
|
Required - No default value |
string | 0 to 225 bytes |
fetchRecords |
The
|
Optional with default of null
|
integer |
-2147483648 to 2147483647
|
fixedLengthCharFormat |
The
For more details, see |
Optional with default "sql"
|
string |
|
id |
The
|
Automatically generated by the server | integer |
|
skipRecords |
The "skipRecords" property specifies the number of records to skip over when paginating the results. It is used with "maxRecords" to paginate the results. If the value is not null or omitted, the server returns results from the beginning. If it is > 0, the server skips over the specified number of records and returns results starting from that point up until it returns the maximum number of results as defined by "maxRecords". |
Optional with default of 0
|
integer |
0 to 9223372036854775807
|
startFrom |
The
In |
Optional with default of "currentPosition"
|
string |
|
Response properties ("result")
| Property | Description | Type | Limits (inclusive) |
|---|---|---|---|
binaryFormat |
The "binaryFormat" property designates the format of binary values embedded in JSON strings. See binaryFormat for more details. |
string | One of the following: "base64", "hex", or "byteArray". |
changeIdField |
This property's value designates the name of the field used for change-tracking functionality if you are not using the
However, if you use the name |
string | 1 to 64 bytes |
cursorid |
The
|
string | 0 to 255 bytes |
data |
The |
array of objects | The action determines its contents. |
dataFormat |
The
|
string |
|
fields |
The
"fields": [
{
"autoValue": "none",
"name": "name",
"type": "varchar",
"length": 50,
"scale": null,
"defaultValue": null,
"nullable": false
}
] |
array |
updateRecords and deleteRecords only:
|
|
fields .autoValue |
The "autoValue" property indicates when and how the server automatically sets the field value. See autoValue for more details. |
string |
Some actions only:
|
|
fields .defaultValue |
The "defaultValue" property specifies the default value of a field. |
string | 0 to 65,500 bytes |
|
fields .length |
Identifies the length of the field. | integer |
1 to 65500 |
|
fields .name |
The The The
|
string | 1 to 64 bytes |
|
fields .nullable |
"nullable" identifies whether a field can contain a NULL value. |
Boolean |
|
|
fields .primaryKey |
When > 0, the "primaryKey" property identifies the ordinal position of the field within the table's primary key. |
integer |
0 to 32
|
|
fields .scale |
If the type is "number" or "money", the "scale" property identifies the number of places to the right of the decimal point,. |
integer |
0 to 32
|
|
fields .type |
Identifies the type of the field. See Data types. | string |
|
moreRecords |
The "moreRecords" property indicates if there are more records that match the filters in the request. |
Boolean |
|
primaryKeyFields |
This property specifies the fields of the table’s primary key when multiple fields are combined to form the primary key.
The order of fields in this property is the order of fields in the primary key index. The A primary key with multiple fields has an index named If only one field is used as the primary key, the
Example "primaryKeyFields": [
"a",
"b",
"c"
],
"fields": [
{
"name": "a",
"type": "tinyint"
},
{
"name": "b",
"type": "smallint"
},
{
"name": "c",
"type": "integer"
}
] |
array | an array |
requestedRecordCount |
The
|
integer |
|
returnedRecordCount |
The
|
integer |
|
totalRecordCount |
The
|
integer |
|
How to use a cursor
Each call to the "getRecordsFromCursor" can use the "fetchRecords", "skipRecords", and "startFrom", properties to reset the cursor position, skip records, fetch one or more records, or do all of the above.
To fetch forwards, assign a positive integer number to "fetchRecords".
To fetch backward, assign a negative integer number to "fetchRecords".
To skip forwards, assign a positive integer number to "skipRecords".
To skip backward, assign a negative integer number to "skipRecords".
To reset a cursor to the beginning of the recordset, set the "startFrom" property to "beforeFirstRecord".
To reset a cursor to the end of the recordset, set the "startFrom" property to "afterLastRecord".
Cursor recipes
Note Some cursors are forward only, such as cursors returned from the
"getRecordsFromTable"action when querying a table containing variable-length records.If you attempt to use a negative number for
"fetchRecords"and"skipRecords"on a forward-only cursor, the"getRecordsFromCursor"returns error48.If you need to fetch records backward, create a cursor based on an index, such as
"getRecordsByIndex","getRecordsByPartialKeyRange","getRecordsInKeyRange", and"getRecordsStartingAtKey".
Troubleshooting
When you receive a cursor error that stops the cursor from working, reset the cursor position by calling "getRecordsFromCursor" with the "startFrom" property set to "beforeFirstRecord" or "afterLastRecord".
Error examples that require you to reset the cursor position:
719: Can't move to previous record in table
14703 - JSONNAV_INTERNAL_ERROR, JSONNAV_NOTYET_PARAM - A JSON Action internal error was encountered. Report this to FairCom.
Call this code repeatedly to return another ten records.
{
"api": "db",
"action": "getRecordsFromCursor",
"params": {
"fetchRecords": 10,
"cursorId": "replaceWithValidCursorId"
},
"authToken": "replaceWithAuthTokenFromCreateSession"
}Call this code repeatedly to return another ten records.
{
"api": "db",
"action": "getRecordsFromCursor",
"params": {
"fetchRecords": -10,
"cursorId": "replaceWithValidCursorId"
},
"authToken": "replaceWithAuthTokenFromCreateSession"
}This code always returns the first ten records.
{
"api": "db",
"action": "getRecordsFromCursor",
"params": {
"startFrom": "beforeFirstRecord",
"fetchRecords": 10,
"cursorId": "replaceWithValidCursorId"
},
"authToken": "replaceWithAuthTokenFromCreateSession"
}This code always returns the last ten records in forward order.
{
"api": "db",
"action": "getRecordsFromCursor",
"params": {
"startFrom": "afterLastRecord",
"skipRecords": -11,
"fetchRecords": 10,
"cursorId": "replaceWithValidCursorId"
},
"authToken": "replaceWithAuthTokenFromCreateSession"
}This code always returns the last ten records in backward order.
{
"api": "db",
"action": "getRecordsFromCursor",
"params": {
"startFrom": "afterLastRecord",
"fetchRecords": -10,
"cursorId": "replaceWithValidCursorId"
},
"authToken": "replaceWithAuthTokenFromCreateSession"
}Call this code repeatedly to return another ten records.
{
"api": "db",
"action": "getRecordsFromCursor",
"params": {
"skipRecords": 10,
"fetchRecords": -10,
"cursorId": "replaceWithValidCursorId"
},
"authToken": "replaceWithAuthTokenFromCreateSession"
}Call this code repeatedly to return another ten records.
{
"api": "db",
"action": "getRecordsFromCursor",
"params": {
"skipRecords": -10,
"fetchRecords": 10,
"cursorId": "replaceWithValidCursorId"
},
"authToken": "replaceWithAuthTokenFromCreateSession"
}Call this code repeatedly to skip the cursor.
{
"api": "db",
"action": "getRecordsFromCursor",
"params": {
"skipRecords": 10,
"cursorId": "replaceWithValidCursorId"
},
"authToken": "replaceWithAuthTokenFromCreateSession"
}This code always returns the thousandth record in the table.
{
"api": "db",
"action": "getRecordsFromCursor",
"params": {
"startFrom": "beforeFirstRecord",
"skipRecords": 1000,
"fetchRecords": 1,
"cursorId": "replaceWithValidCursorId"
},
"authToken": "replaceWithAuthTokenFromCreateSession"
}
Additional information
- The following actions create forward-only cursors:
-
"getRecordsFromTable"creates a cursor that moves forward through every record in the table. -
"getRecordsUsingSQL"creates a cursor that moves forward through every record returned by the SQL query. - If you receive error 48 when using negative numbers for skip or fetch, it indicates the cursor is forward-only. A table cursor cannot skip or fetch backward when the table contains variable-length records. If you need to fetch records backward, create a cursor based on an index, such as
"getRecordsByIndex","getRecordsByPartialKeyRange","getRecordsInKeyRange", and"getRecordsStartingAtKey".
-
- The following actions create bidirectional cursors:
-
"getRecordsByIndex"creates a cursor that moves forward or backward through every record in the index. -
"getRecordsStartingAtKey"creates a cursor that moves forward or backward through every record in the index starting with the closest match to the key. -
"getRecordsByPartialKeyRange"creates a cursor that moves forward or backward through every record in the index that matches the partial key. -
"getRecordsInKeyRange"creates a cursor that moves forward or backward through every record in the index within the specified key range.
-
- A cursor is always positioned before or after a record, and the fetch direction determines the cursor position.
- When fetching forward, the cursor is positioned before a record to retrieve the record on its way forward.
- When fetching backward, the cursor is positioned after the current record to retrieve the record on its way backward.
- When a cursor is positioned before the first record, it cannot be moved backward.
- When a cursor is positioned after the last record, it cannot be moved forward.
- Calling
"getRecordsFromCursor"with an expired or closed cursor, returns an error response.