806 lines
36 KiB
Plaintext
806 lines
36 KiB
Plaintext
Function Database_Services_Orig(@Service, @Params)
|
|
/***********************************************************************************************************************
|
|
|
|
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
|
|
permission from SRP Computer Solutions, Inc.
|
|
|
|
Name : Database_Services
|
|
|
|
Description : Handler program for all Database services.
|
|
|
|
Notes : Application errors should be logged using the Error Services module. There are a few methodological
|
|
assumptions built into way errors are managed which are important to understand in order to properly
|
|
work with Error Services:
|
|
|
|
Parameters :
|
|
Service [in] -- Name of the service being requested
|
|
Param1-10 [in/out] -- Additional request parameter holders
|
|
Response [out] -- Response to be sent back to the Controller (MCP) or requesting procedure
|
|
|
|
Metadata :
|
|
|
|
History : (Date, Initials, Notes)
|
|
03/27/17 dmb Original programmer.
|
|
05/02/17 dmb Add error if WriteDatabaseRow is unable to lock row.
|
|
10/31/17 dmb Add CalculateColumn and GetTableCommuter services.
|
|
05/25/18 dmb Add GetUserLocks service.
|
|
05/29/18 dmb Add IsKeyIDLocked, IsKeyIDSelfLocked, and UnlockKeyID services.
|
|
10/09/18 djs Added ActivateRecord service, which sets @ID, @Record, and @DICT to enable {} shorthand.
|
|
|
|
***********************************************************************************************************************/
|
|
|
|
#pragma precomp SRP_PreCompiler
|
|
|
|
$insert LOGICAL
|
|
$insert SERVICE_SETUP
|
|
$insert VOL_TABLE_EQUATES
|
|
$insert RTI_LH_INFO_EQUATES
|
|
|
|
Declare function Memory_Services, Database_Services, SRP_Encode, RetStack, RTI_LH_Info, SRP_Path
|
|
Declare subroutine Memory_Services, Database_Services, Verify_LH, SRP_Stopwatch, Btree.Extract, Update_Index, Set_Status
|
|
Declare subroutine RTI_LH_Info
|
|
|
|
GoToService else
|
|
Error_Services('Add', Service : ' is not a valid service request within the ' : ServiceModule : ' module.')
|
|
end
|
|
|
|
Return Response OR ''
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Service Parameter Options
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
Options BOOLEAN = True$, False$
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Services
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// VerifyLHAll
|
|
//
|
|
// Performs a health check againsts all attached tables and returns back any issues. Returns two lists which are
|
|
// delimited by an @RM. The first list is an @FM list of attached tables. The second list is an @FM list of results
|
|
// (groups that have GFEs or an empty string if there are none). Items in each list correspond which each other based on
|
|
// their list position.
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
Service VerifyLHAll()
|
|
|
|
VerifyResults = ''
|
|
TableNames = @TABLES(0)
|
|
NumTables = DCount(TableNames, @FM)
|
|
|
|
For TableCnt = 1 to NumTables
|
|
TableName = TableNames<TableCnt>
|
|
VerifyResults := Database_Services('VerifyLH', TableName) : @FM
|
|
Next TableCnt
|
|
VerifyResults[-1, 1] = '' ; // Strip off the last @FM
|
|
|
|
Response = TableNames : @RM : VerifyResults
|
|
|
|
end service
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// VerifyLH
|
|
//
|
|
// TableNames. One or more linear hash database tables to verify. List should be @FM delimited. - [OPTIONAL]
|
|
// SaveList. Name of a saved selection of linear hash database tables to verify. This argument will be ignored
|
|
// if TableNames is populated. - [OPTIONAL]
|
|
//
|
|
// Performs a health check against the indicated tables and returns back any issues. Note: This uses the Verify_LH
|
|
// subroutine to check for GFEs. All results are stored in the SYSLHVERIFY table with a KeyID of
|
|
// VolumeLabel*DatabaseID*TableName. Returns the list of groups that have GFEs or returns an empty string if there are
|
|
// none. The list of GFEs or empty strings will themselves be @FM delimited to correspond with the tables passed into
|
|
// this service.
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
Service VerifyLH(Tablenames, SaveList)
|
|
|
|
VerifyResults = ''
|
|
|
|
If TableNames EQ '' then
|
|
TableNames = Xlate('SYSLISTS', SaveList, '', 'X')
|
|
If Index(TableNames<1>, @TM, 1) then
|
|
// This saved select has metadata in attribute 1. Remove it.
|
|
TableNames = Delete(TableNames, 1, 0, 0)
|
|
end
|
|
end
|
|
|
|
If TableNames NE '' then
|
|
NumTables = DCount(TableNames, @FM)
|
|
For TableCnt = 1 to NumTables
|
|
TableName = TableNames<TableCnt>
|
|
TableProperties = Database_Services('GetTableProperties', TableName)
|
|
If Error_Services('NoError') then
|
|
rv = Set_Status(0)
|
|
Verify_LH('', TableName, True$, False$, False$)
|
|
Open 'SYSLHVERIFY' to hSysLHVerify then
|
|
DatabaseID = TableProperties<1>
|
|
VolumeLabel = TableProperties<3>
|
|
LHVerifyKeyID = VolumeLabel : '*' : DatabaseID : '*' : TableName
|
|
Read LHVerifyRec from hSysLHVerify, LHVerifyKeyID then
|
|
VerifyResults<TableCnt> = LHVerifyRec<2>
|
|
end
|
|
end else
|
|
Error_Services('Add', 'Error opening the SYSLHVERIFY table in the ' : Service : ' service.')
|
|
end
|
|
Begin Case
|
|
Case @File_Error NE ''
|
|
Error_Services('Add', 'Error verifying table ' : TableName : ': FS Error = ' : @File_Error<1>)
|
|
Case Get_Status()
|
|
Error_Services('Add', 'Get_Status error: ' : Get_Status())
|
|
End Case
|
|
end
|
|
Next TableCnt
|
|
end else
|
|
Error_Services('Add', 'The TableName argument was missing in the ' : Service : ' service.')
|
|
end
|
|
|
|
Response = VerifyResults
|
|
|
|
end service
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// GetTableProperties
|
|
//
|
|
// TableName. The linear hash database table name. - [REQUIRED]
|
|
//
|
|
// Returns an array of information related to the database table being passed in.
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
Service GetTableProperties(TableName)
|
|
|
|
TableProperties = ''
|
|
|
|
If TableName NE '' then
|
|
rv = Set_Status(0)
|
|
Locate TableName in @TABLES(0) using @FM setting fPos then
|
|
TableProperties<1> = @TABLES(3)<fPos> ; // DatabaseID
|
|
TableProperties<2> = @TABLES(4)<fPos> ; // MFS/BFS List
|
|
VolumeID = @TABLES(1)<fPos> ; // Volume ID
|
|
Locate VolumeID in @VOLUMES(0) using @FM setting fPos then
|
|
TableProperties<3> = @VOLUMES(1)<fPos> ; // Volume Label
|
|
TableProperties<4> = @VOLUMES(2)<fPos> ; // Volume Path
|
|
TableProperties<5> = @VOLUMES(4)<fPos> ; // BFS
|
|
end
|
|
end else
|
|
Error_Services('Add', 'The ' : TableName : ' table is not attached and available to the ' : Service : ' service.')
|
|
end
|
|
end else
|
|
Error_Services('Add', 'TableName argument was missing in the ' : Service : ' service.')
|
|
end
|
|
|
|
Response = TableProperties
|
|
|
|
end service
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// GetTableHandle
|
|
//
|
|
// TableName. The linear hash database table name. - [REQUIRED]
|
|
//
|
|
// Returns an array of information related to the database table being passed in.
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
Service GetTableHandle(TableName)
|
|
|
|
ServiceKeyID := '*' : TableName
|
|
TableHandle = Memory_Services('GetValue', ServiceKeyID, True$, 360)
|
|
|
|
If TableHandle EQ '' then
|
|
rv = Set_Status(0)
|
|
Open TableName to TableHandle then
|
|
Memory_Services('SetValue', ServiceKeyID, TableHandle)
|
|
end else
|
|
Error_Services('Add', 'Unable to open the ' : TableName : ' table in the ' : Service : ' service. Error = ' : @File_Error<1>)
|
|
end
|
|
end
|
|
|
|
Response = TableHandle
|
|
|
|
end service
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// ReadDataRow
|
|
//
|
|
// TableName. The linear hash database table name. - [REQUIRED]
|
|
// KeyID. The KeyID to the database table. - [REQUIRED]
|
|
//
|
|
// Reads a data row for the indicated Key ID and database table.
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
Service ReadDataRow(TableName, KeyID, NotExpired, ExpirationDuration, IgnoreMFSRoutines)
|
|
|
|
If NotExpired NE False$ then NotExpired = True$
|
|
If (ExpirationDuration EQ '') OR (Not(Num(ExpirationDuration))) then ExpirationDuration = 0
|
|
If IgnoreMFSRoutines NE True$ then IgnoreMFSRoutines = False$
|
|
|
|
ServiceKeyID := '*' : TableName : '*' : KeyID
|
|
DataRow = Memory_Services('GetValue', ServiceKeyID, NotExpired, ExpirationDuration)
|
|
|
|
If TableName NE '' AND KeyID NE '' then
|
|
If DataRow EQ '' then
|
|
TableHandle = Database_Services('GetTableHandle', TableName)
|
|
If Error_Services('NoError') then
|
|
If IgnoreMFSRoutines then
|
|
MFSList = TableHandle<1, 1> ; // MFS routines are @SVM delimited.
|
|
NumMFS = DCount(MFSList, @SVM)
|
|
For MFSCnt = NumMFS to 1 Step -1
|
|
MFSRoutine = MFSList<0, 0, MFSCnt>
|
|
If MFSRoutine NE 'RTP57' then
|
|
MFSList = Delete(MFSList, 0, 0, MFSCnt)
|
|
end
|
|
Next MFSCnt
|
|
TableHandle<1, 1> = MFSList
|
|
end
|
|
Read DataRow from TableHandle, KeyID then
|
|
Memory_Services('SetValue', ServiceKeyID, DataRow)
|
|
end else
|
|
Error_Services('Add', 'Error reading ' : KeyID : ' from the ' : TableName : ' table in the ' : Service : ' service.')
|
|
end
|
|
end
|
|
end
|
|
end else
|
|
Error_Services('Add', 'TableName or KeyID argument was missing in the ' : Service : ' service.')
|
|
end
|
|
|
|
Response = DataRow
|
|
|
|
end service
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// ReadDataColumn
|
|
//
|
|
// TableName. The linear hash database table name. - [REQUIRED]
|
|
// KeyID. The KeyID to the database table. - [REQUIRED]
|
|
// ColumnNo. The index of the column that is to be read. - [REQUIRED]
|
|
//
|
|
// Reads a data column for the indicated Key ID and database table.
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
Service ReadDataColumn(TableName, KeyID, ColumnNo, NotExpired, ExpirationDuration, IgnoreMFSRoutines)
|
|
|
|
If NotExpired NE False$ then NotExpired = True$
|
|
If (ExpirationDuration EQ '') OR (Not(Num(ExpirationDuration))) then ExpirationDuration = 0
|
|
If IgnoreMFSRoutines NE True$ then IgnoreMFSRoutines = False$
|
|
|
|
ServiceKeyID := '*' : TableName : '*' : KeyID : '*' : ColumnNo
|
|
DataColumn = Memory_Services('GetValue', ServiceKeyID, NotExpired, ExpirationDuration)
|
|
|
|
If Num(ColumnNo) AND (ColumnNo GT 0) then
|
|
If TableName NE '' AND KeyID NE '' then
|
|
If DataColumn EQ '' then
|
|
TableHandle = Database_Services('GetTableHandle', TableName)
|
|
If Error_Services('NoError') then
|
|
If IgnoreMFSRoutines then
|
|
MFSList = TableHandle<1, 1> ; // MFS routines are @SVM delimited.
|
|
NumMFS = DCount(MFSList, @SVM)
|
|
For MFSCnt = NumMFS to 1 Step -1
|
|
MFSRoutine = MFSList<0, 0, MFSCnt>
|
|
If MFSRoutine NE 'RTP57' then
|
|
MFSList = Delete(MFSList, 0, 0, MFSCnt)
|
|
end
|
|
Next MFSCnt
|
|
TableHandle<1, 1> = MFSList
|
|
end
|
|
ReadV DataColumn from TableHandle, KeyID, ColumnNo then
|
|
Memory_Services('SetValue', ServiceKeyID, DataColumn)
|
|
end else
|
|
ErrorMsg = 'Error reading ' : KeyID : ' column number ' : ColumnNo : ' from the ' |
|
|
: TableName : ' table in the ' : Service : ' service.'
|
|
Error_Services('Add', ErrorMsg)
|
|
end
|
|
end
|
|
end
|
|
end else
|
|
Error_Services('Add', 'TableName or KeyID argument was missing in the ' : Service : ' service.')
|
|
end
|
|
end else
|
|
Error_Services('Add', 'ColumnNo was not a number or was not greater than zero in the ' : Service : ' service.')
|
|
end
|
|
|
|
Response = DataColumn
|
|
|
|
end service
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// ActivateRecord
|
|
//
|
|
// TableName. The linear hash database table name. - [REQUIRED]
|
|
// KeyID. The KeyID to the database table. - [REQUIRED]
|
|
//
|
|
// Reads a data row for the indicated Key ID and database table. Sets @ID, @Record, and @DICT to enable {} shorthand.
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
Service ActivateRecord(TableName, KeyID, NotExpired, ExpirationDuration, IgnoreMFSRoutines)
|
|
|
|
If TableName NE '' AND KeyID NE '' then
|
|
@ID = KeyID
|
|
DictTable = ''
|
|
If TableName[1,5] _EQC 'DICT.' then
|
|
DictTable = TableName
|
|
TableName = TableName[-1, 'B.']
|
|
end else
|
|
DictTable = 'DICT.':TableName
|
|
end
|
|
@DICT = Database_Services('GetTableHandle', DictTable)
|
|
If Error_Services('NoError') then
|
|
@Record = Database_Services('ReadDataRow',TableName,KeyID,NotExpired,ExpirationDuration,IgnoreMFSRoutines)
|
|
If Not(Error_Services('NoError')) then
|
|
Error_Services('Add','Error reading ':KeyID:' from the ':TableName:' table in the ':Service:' service.')
|
|
end
|
|
end else
|
|
Error_Services('Add', 'Error retrieving handle for the ':TableName:' table in the ':Service:' service.')
|
|
end
|
|
end
|
|
|
|
Response = @Record
|
|
|
|
end service
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// WriteDataRow
|
|
//
|
|
// TableName. The linear hash database table name. - [REQUIRED]
|
|
// KeyID. The KeyID to the database table. - [REQUIRED]
|
|
//
|
|
// Writes a data row for the indicated Key ID and database table.
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
Service WriteDataRow(TableName, KeyID, DataRow, IgnoreSelfLock, IgnoreMFSRoutines, IgnoreAllLocks)
|
|
|
|
If TableName NE '' AND KeyID NE '' then
|
|
If IgnoreSelfLock NE True$ then IgnoreSelfLock = False$
|
|
If IgnoreMFSRoutines NE True$ then IgnoreMFSRoutines = False$
|
|
If IgnoreAllLocks NE True$ then IgnoreAllLocks = False$
|
|
If IgnoreAllLocks then
|
|
HaveLock = True$
|
|
end else
|
|
HaveLock = Database_Services('GetKeyIDLock', TableName, KeyID, IgnoreSelfLock)
|
|
end
|
|
If HaveLock EQ True$ then
|
|
TableHandle = Database_Services('GetTableHandle', TableName)
|
|
If IgnoreMFSRoutines then
|
|
MFSList = TableHandle<1, 1> ; // MFS routines are @SVM delimited.
|
|
NumMFS = DCount(MFSList, @SVM)
|
|
For MFSCnt = NumMFS to 1 Step -1
|
|
MFSRoutine = MFSList<0, 0, MFSCnt>
|
|
If (MFSRoutine NE 'SI.MFS') AND (MFSRoutine NE 'RTP57') then
|
|
MFSList = Delete(MFSList, 0, 0, MFSCnt)
|
|
end
|
|
Next MFSCnt
|
|
TableHandle<1, 1> = MFSList
|
|
end
|
|
If Error_Services('NoError') then
|
|
Write DataRow to TableHandle, KeyID then
|
|
Memory_Services('SetValue', ServiceModule : '*' : 'ReadDatarow' : '*' : TableName : '*' : KeyID, DataRow)
|
|
end else
|
|
Error_Services('Add', 'Error writing ' : KeyID : ' to the ' : TableName : ' table in the ' : Service : ' service.')
|
|
end
|
|
end
|
|
If IgnoreAllLocks EQ False$ then
|
|
Database_Services('ReleaseKeyIDLock', TableName, KeyID)
|
|
end
|
|
end else
|
|
Error_Services('Add', 'Unable to lock ' : KeyID : ' for the ' : TableName : ' table in the ' : Service : ' service.')
|
|
end
|
|
end else
|
|
Error_Services('Add', 'TableName or KeyID argument was missing in the ' : Service : ' service.')
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// DeleteDataRow
|
|
//
|
|
// TableName. The linear hash database table name. - [REQUIRED]
|
|
// KeyID. The KeyID to the database table. - [REQUIRED]
|
|
//
|
|
// Deletes a data row for the indicated Key ID and database table.
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
Service DeleteDataRow(TableName, KeyID, IgnoreSelfLock, IgnoreMFSRoutines)
|
|
|
|
If TableName NE '' AND KeyID NE '' then
|
|
If IgnoreSelfLock NE True$ then IgnoreSelfLock = False$
|
|
If IgnoreMFSRoutines NE True$ then IgnoreMFSRoutines = False$
|
|
HaveLock = Database_Services('GetKeyIDLock', TableName, KeyID, IgnoreSelfLock)
|
|
If HaveLock EQ True$ then
|
|
TableHandle = Database_Services('GetTableHandle', TableName)
|
|
If IgnoreMFSRoutines then
|
|
MFSList = TableHandle<1, 1> ; // MFS routines are @SVM delimited.
|
|
NumMFS = DCount(MFSList, @SVM)
|
|
For MFSCnt = NumMFS to 1 Step -1
|
|
MFSRoutine = MFSList<0, 0, MFSCnt>
|
|
If (MFSRoutine NE 'SI.MFS') AND (MFSRoutine NE 'RTP57') then
|
|
MFSList = Delete(MFSList, 0, 0, MFSCnt)
|
|
end
|
|
Next MFSCnt
|
|
TableHandle<1, 1> = MFSList
|
|
end
|
|
If Error_Services('NoError') then
|
|
Delete TableHandle, KeyID then
|
|
Memory_Services('SetValue', ServiceModule : '*' : 'ReadDatarow' : '*' : TableName : '*' : KeyID, '')
|
|
end else
|
|
Error_Services('Add', 'Error deleting ' : KeyID : ' from the ' : TableName : ' table in the ' : Service : ' service.')
|
|
end
|
|
end
|
|
Database_Services('ReleaseKeyIDLock', TableName, KeyID)
|
|
end else
|
|
Error_Services('Add', 'Unable to lock ' : KeyID : ' for the ' : TableName : ' table in the ' : Service : ' service.')
|
|
end
|
|
end else
|
|
Error_Services('Add', 'TableName or KeyID argument was missing in the ' : Service : ' service.')
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// GetKeyIDLock
|
|
//
|
|
// Attempts to perform a semaphore lock on the indicated tablename and Key ID.
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
Service GetKeyIDLock(TableName, KeyID, IgnoreSelfLock)
|
|
|
|
HaveLock = False$ ; // Assume false for now.
|
|
|
|
If TableName NE '' AND KeyID NE '' then
|
|
If IgnoreSelfLock NE True$ then IgnoreSelfLock = False$
|
|
TableHandle = Database_Services('GetTableHandle', TableName)
|
|
If Error_Services('NoError') then
|
|
Lock Tablehandle, KeyID then
|
|
HaveLock = True$
|
|
end else
|
|
If IgnoreSelfLock EQ True$ then
|
|
Status = Status()
|
|
If Status EQ 1 then
|
|
HaveLock = True$
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end else
|
|
Error_Services('Add', 'TableName or KeyID argument was missing in the ' : Service : ' service.')
|
|
end
|
|
|
|
Response = HaveLock
|
|
|
|
end service
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// ReleaseKeyIDLock
|
|
//
|
|
// Attempts to release a semaphore lock on the indicated tablename and Key ID.
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
Service ReleaseKeyIDLock(TableName, KeyID)
|
|
|
|
LockReleased = False$ ; // Assume false for now.
|
|
|
|
If TableName NE '' AND KeyID NE '' then
|
|
TableHandle = Database_Services('GetTableHandle', TableName)
|
|
If Error_Services('NoError') then
|
|
UnLock Tablehandle, KeyID then
|
|
LockReleased = True$
|
|
end else
|
|
Error_Services('Add', 'Unable to unlock the ' : KeyID : ' Key ID from the ' : TableName : ' table in the ' : Service : ' service. Error = ' : @File_Error<1>)
|
|
end
|
|
end
|
|
end else
|
|
Error_Services('Add', 'TableName or KeyID argument was missing in the ' : Service : ' service.')
|
|
end
|
|
|
|
Response = LockReleased
|
|
|
|
end service
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// SearchIndex
|
|
//
|
|
// TableName. The linear hash database table name. - [REQUIRED]
|
|
// ColumnName. The indexed column to search against. - [REQUIRED]
|
|
// SearchValue. The value being searched for. - [REQUIRED]
|
|
// UpdateIndex. Boolean flag to determine if the index for the indicated column should be updated before searching.
|
|
// - [OPTIONAL]
|
|
//
|
|
// Returns an @FM delimited list of Key IDs that match the search value.
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
Service SearchIndex(TableName, ColumnName, SearchValue, UpdateIndex)
|
|
|
|
If UpdateIndex NE True$ then UpdateIndex = False$
|
|
|
|
ServiceKeyID := '*' : TableName : '*' : ColumnName : '*' : SearchValue
|
|
ServiceKeyID = SRP_Encode(ServiceKeyID, 'BASE64')
|
|
* KeyIDList = Memory_Services('GetValue', ServiceKeyID, True$, 5)
|
|
KeyIDList = ''
|
|
|
|
If TableName NE '' AND ColumnName NE '' AND SearchValue NE '' then
|
|
If KeyIDList EQ '' then
|
|
DictTableHandle = Database_Services('GetTableHandle', 'DICT.' : TableName)
|
|
If Error_Services('NoError') then
|
|
Set_Status(0)
|
|
If UpdateIndex then Update_Index(TableName, ColumnName 0)
|
|
Set_Status(0)
|
|
Btree.Extract(ColumnName : @VM : SearchValue : @FM, Tablename, DictTableHandle, KeyIDList, 'S', Flag)
|
|
If Flag EQ 0 then
|
|
Convert @VM to @FM in KeyIDList
|
|
Memory_Services('SetValue', ServiceKeyID, KeyIDList)
|
|
end else
|
|
Error_Services('Add', 'Error in Btree.Extract search from the ' : TableName : ' table in the ' : Service : ' service.')
|
|
end
|
|
end
|
|
end
|
|
end else
|
|
Error_Services('Add', 'TableName, ColumnName, or SearchValue argument was missing in the ' : Service : ' service.')
|
|
end
|
|
|
|
Response = KeyIDList
|
|
|
|
end service
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// CalculateColumn
|
|
//
|
|
// Called directly from within a calculation column. The name of the table and column is derived from the call stack
|
|
// and the associated table commuter, if it exists, is called with the appropriate arguments.
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
Service CalculateColumn()
|
|
|
|
Response = ''
|
|
ColumnName = ''
|
|
RetStack = RetStack()
|
|
For Each Item in RetStack using @FM
|
|
If Index(Item, 'DICT.MFS', 1) then
|
|
ColumnName = Item[2, \00\, 1]
|
|
CharPos = BCol2() + 1
|
|
TableHandle = Item[CharPos, GetByteSize(Item), 1]
|
|
Locate TableHandle<1, 2> in @TABLES(TAB_HANDLE$) using @FM setting fPos then
|
|
TableName = @TABLES(0)<fPos> ; // This technically returns the dictionary, but DICT. will be removed.
|
|
TableName[1, 5] = ''
|
|
end
|
|
end
|
|
Until (ColumnName NE '') OR (Item EQ '')
|
|
Next Item
|
|
|
|
If TableName NE '' then
|
|
TableCommuter = Database_Services('GetTableCommuter', TableName)
|
|
If TableCommuter NE '' then
|
|
Response = Function(@TableCommuter('CalculateColumn', ColumnName))
|
|
end
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// GetTableCommuter
|
|
//
|
|
// Returns the name of the indicated table's commuter module if it exists. If it does not exist then an empty string
|
|
// will be returned.
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
Service GetTableCommuter(TableName)
|
|
|
|
ServiceKeyID := '*' : TableName
|
|
TableCommuter = Memory_Services('GetValue', ServiceKeyID)
|
|
|
|
If TableCommuter EQ '' then
|
|
ObjExists = False$ ; // Assume the object code for the action handler does not exist for now.
|
|
For Each AppID in @AppId
|
|
If AppID _EQC 'SYSPROG' then
|
|
SysObjKey = '$' : TableName : '_ACTIONS'
|
|
end else
|
|
SysObjKey = '$' : TableName : '_ACTIONS' : '*' : AppID
|
|
end
|
|
ObjExists = Memory_Services('KeyExists', SysObjKey)
|
|
Until ObjExists
|
|
Next AppID
|
|
|
|
If Not(ObjExists) then
|
|
For Each AppID in @AppId
|
|
If AppID _EQC 'SYSPROG' then
|
|
SysObjKey = '$' : TableName : '_ACTIONS'
|
|
end else
|
|
SysObjKey = '$' : TableName : '_ACTIONS' : '*' : AppID
|
|
end
|
|
OrigFileError = @FILE.ERROR
|
|
@FILE.ERROR = ''
|
|
BFS = 'RTP57'
|
|
// The handle to SYSOBJ is used to find object code before it gets called
|
|
Call @BFS(2, BFS, @FILE_SYSOBJ<1, 2>, SysObjKey, FMC, SysObjRecord, ActionStatus)
|
|
@FILE.ERROR = OrigFileError
|
|
If ActionStatus then ObjExists = True$
|
|
Until ObjExists
|
|
Next AppID
|
|
end
|
|
|
|
If (ObjExists) then
|
|
TableCommuter = TableName : '_ACTIONS'
|
|
Memory_Services('SetValue', ServiceKeyID, TableCommuter)
|
|
end
|
|
end
|
|
|
|
Response = TableCommuter
|
|
|
|
end service
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// GetUserLocks
|
|
//
|
|
// Returns a dynamic array of user lock information. Note, this can only be done with the UD 5. This can also cause
|
|
// instability with the current session and may require the Task Manager to close the session.
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
Service GetUserLocks()
|
|
|
|
UserLocks = RTI_LH_Info(CMD_LOCKS_INFO$, '')
|
|
|
|
Response = UserLocks
|
|
|
|
end service
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// IsKeyIDLocked
|
|
//
|
|
// Returns a Boolean flag of the lock status for the indicated table and Key ID.
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
Service IsKeyIDLocked(TableName, KeyID, IgnoreSelfLock=BOOLEAN)
|
|
|
|
If IgnoreSelfLock NE True$ then IgnoreSelfLock = False$
|
|
|
|
KeyIDLocked = False$ ; // Assume false for now.
|
|
|
|
If (TableName NE '') AND (KeyID NE '') then
|
|
Open TableName to hTable then
|
|
Lock hTable, KeyID then
|
|
// Able to lock Key ID. Unlock it right away.
|
|
Unlock hTable, KeyID else Null
|
|
end else
|
|
// Unable to lock Key ID. Evaluate the type of lock.
|
|
LockType = Status()
|
|
If LockType EQ 0 then
|
|
// Lock exists on another station.
|
|
KeyIDLocked = True$
|
|
end else
|
|
// Lock exists on this station. Check to see if the Ignore Self Lock flag is set.
|
|
If Not(IgnoreSelfLock) then KeyIDLocked = True$
|
|
end
|
|
end
|
|
end else
|
|
Error_Services('Add', 'Error opening the ' : TableName : ' table in the ' : Service : ' service.')
|
|
end
|
|
end else
|
|
Error_Services('Add', 'TableName or KeyID argument was missing in the ' : Service : ' service.')
|
|
end
|
|
|
|
Response = KeyIDLocked
|
|
|
|
end service
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// IsKeyIDSelfLocked
|
|
//
|
|
// Returns a Boolean flag of the self-lock status for the indicated table and Key ID.
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
Service IsKeyIDSelfLocked(TableName, KeyID)
|
|
|
|
KeyIDSelfLocked = False$ ; // Assume false for now.
|
|
|
|
If (TableName NE '') AND (KeyID NE '') then
|
|
Open TableName to hTable then
|
|
Lock hTable, KeyID then
|
|
// Able to lock Key ID. Unlock it right away.
|
|
Unlock hTable, KeyID else Null
|
|
end else
|
|
// Unable to lock Key ID. Evaluate the type of lock.
|
|
LockType = Status()
|
|
If LockType EQ 1 then
|
|
// This Key ID is self-locked.
|
|
KeyIDSelfLocked = True$
|
|
end
|
|
end
|
|
end else
|
|
Error_Services('Add', 'Error opening the ' : TableName : ' table in the ' : Service : ' service.')
|
|
end
|
|
end else
|
|
Error_Services('Add', 'TableName or KeyID argument was missing in the ' : Service : ' service.')
|
|
end
|
|
|
|
Response = KeyIDSelfLocked
|
|
|
|
end service
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// UnlockKeyID
|
|
//
|
|
// Attempts to unlock the indicated Key ID from the indicated Table Name. Note, this can only be done with the UD 5.
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
Service UnlockKeyID(TableName, KeyID)
|
|
|
|
KeyIDUnlocked = False$ ; // Assume false for now.
|
|
|
|
Convert @Lower_Case to @Upper_Case in TableName
|
|
|
|
If (TableName NE '') AND (KeyID NE '') then
|
|
// First, do a sanity check to confirm that there is a lock on this Key ID.
|
|
IsKeyIDLocked = Database_Services('IsKeyIDLocked', TableName, KeyID, False$)
|
|
If Error_Services('NoError') AND (IsKeyIDLocked EQ False$) then
|
|
// Key ID was not locked.
|
|
KeyIDUnlocked = True$
|
|
end
|
|
If KeyIDUnlocked NE True$ then
|
|
// Key ID is still presumed to be locked.
|
|
VolumePath = ''
|
|
FileName = ''
|
|
|
|
// Resolve the volume path for this table.
|
|
hTableFull = Database_Services('ReadDataRow', 'SYSTABLES', TableName)
|
|
VolumeName = hTableFull<1>
|
|
VolumeRow = Database_Services('ReadDataRow', 'SYSVOLUMES', VolumeName)
|
|
VolumePath = VolumeRow[-1, 'B' : @FM]
|
|
VolumePath = VolumePath[-1, 'B' : \0D\]
|
|
VolumePath[1, 12] = '' ; // Strip off the preceding bytes.
|
|
If SRP_Path('IsRelative', VolumePath) then
|
|
VolumePath = SRP_Path('Combine', Drive(), VolumePath)
|
|
// Check for only a single '\' character. Add another if necessary so this is a proper UNC path.
|
|
// This is a workaround for this version of SRP_Path.
|
|
If VolumePath[1, 1] EQ '\' AND VolumePath[2, 1] NE '\' then VolumePath = '\' : VolumePath
|
|
end
|
|
VolumePath = SRP_Path('RemoveFilename', VolumePath)
|
|
// Make sure there is a backslash since the RTI_LH_INFO API seems to use this.
|
|
VolumePath = SRP_Path('AddBackslash', VolumePath)
|
|
|
|
// Resolve the filename for this table.
|
|
hTableFull = Database_Services('ReadDataRow', 'SYSTABLES', TableName)
|
|
FileName = hTableFull[-1, 'B' : @FM]
|
|
FileName = FileName[-1, 'B' : \0D\]
|
|
FileName = FileName[1, @VM]
|
|
If FileName _NEC 'SYSREPOS' then FileName[1, 12] = '' ; // Strip off the preceding bytes.
|
|
FileName = FileName[-1, 'B' : '\']
|
|
// Make sure the filename is well formed.
|
|
Begin Case
|
|
Case (FileName[-3, 3] _EQC '.LK') OR (FileName[-3, 3] _EQC '.OV')
|
|
FileName[-3, 3] = ''
|
|
Case FileName _EQC 'SYSREPOS'
|
|
FileName = 'REVREPOS'
|
|
End Case
|
|
|
|
If (VolumePath NE '') AND (FileName) NE '' then
|
|
// Attempt to unlocked the Key ID.
|
|
RTI_LH_Info(CMD_UNLOCK$, VolumePath, FileName, KeyID, FileName)
|
|
// Confirm that the Key ID was unlocked.
|
|
IsKeyIDLocked = Database_Services('IsKeyIDLocked', TableName, KeyID, False$)
|
|
If Error_Services('NoError') AND (IsKeyIDLocked EQ False$) then
|
|
// Key ID was not locked.
|
|
KeyIDUnlocked = True$
|
|
end else
|
|
// Unable to unlock the Key ID which could be because it is locked by this station. Try using the
|
|
// Unlock statement.
|
|
KeyIDUnlocked = Database_Services('ReleaseKeyIDLock', TableName, KeyID)
|
|
end
|
|
end else
|
|
Error_Services('Add', 'No valid VolumePath or FileName was available in the ' : Service : ' service.')
|
|
end
|
|
end
|
|
end else
|
|
Error_Services('Add', 'TableName or KeyID argument was missing in the ' : Service : ' service.')
|
|
end
|
|
|
|
Response = KeyIDUnlocked
|
|
|
|
end service
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Internal GoSubs
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|