Does Embedded SQL support Table Hints?
Hi everyone.
I have a function that may end up being called from a number of transformations at the same time, and within the function there's some Embedded SQL to first check if a local table has an entry, and then adds the entry if it doesn't exist.
To prevent a race condition where the function is called by two transformations and they both end up attempting to insert the same value, I'm looking to use the table hint "WITH TABLOCK" on the insert, but this seems to be failing the syntax checks within vscode.
Are table hints supported with embedded sql?
If not, is there a way to prevent the scenario from unfolding? The code I'm working with for the function is:
Class Example.Functions Extends Ens.Rule.FunctionSet
{
ClassMethod VisitIDShortener(inVisitID As%String, SourceSystem As%String) As%String
{
//Firstly, check to see if the table we're working with exists | This should only be an issue on first deployment to a new environmentSet tSC = $SYSTEM.SQL.Schema.TableExists("Example.VisitIDLookup")
If tSC'=1{
//Buid table if it doesn't exist
&SQL(CREATETABLE Example.VisitIDLookup
(SourceSystem varchar(10), SourceVisitID varchar(250), TargetVisitID varchar(15))
)
}
//Secondly, check to see if the Global we're using for our increment exist, and create if it doesn't existSet GBLCHK = $DATA(^$GLOBAL("^EMPVisitID"))
If GBLCHK = 0{
Set^EMPVisitID = 0
}
//Check table for entry
&SQL(Select TargetVisitID into :pTargetID
FROM Example.VisitIDLookup
Where SourceVisitID = :inVisitID And SourceSystem = :SourceSystem
)
//If SQLCODE is 0, we have an entry and we wnat to simply return the resultIf SQLCODE=0 {
Set outVisitID = pTargetID
}
Else{
//Increment the GlobalDo$INCREMENT(^EMPVisitID)
//Use incremented value for output (with a prefix)Set outVisitID = "TIEGEN"_^EMPVisitID//Add new entry to table
&SQL(InsertINTO Example.VisitIDLookup
Set SourceSystem=:SourceSystem, SourceVisitID = :inVisitID, TargetVisitID = :outVisitID
)
}
Quit outVisitID
}
}
Comments
I'm not sure about TABLOCK specifically, but there are a couple other features that might help you solve this:
First, there is the LOCK TABLE statement: https://docs.intersystems.com/iris20241/csp/docbook/Doc.View.cls?KEY=RS…
There's also the objectscript LOCK command: https://docs.intersystems.com/iris20241/csp/docbook/Doc.View.cls?KEY=RC…
You could use either of these to block the method while other instances of it are running and prevent the race condition. I'm not sure how efficient this method would be compared to TABLOCK, but it would fix the bug.
I hope this helps!
Thanks Nick.
Having done some tests (and reading the link shared), the table locking still allows SELECT statements to be executed so the objectscript locking will be my approach.
In the above code just insert a Lock and Unlock, and the problem is solved
//Buid table if it doesn't existlock +^LockOutOthers// or any other name you wish// No timeout! At this point everybody has to wait// as long as the current job does a table check/update
&SQL(
...
...
}
lock -^LockOutOthers // let the others in
Quit outVisitID
Thanks Julius - exactly what I'm looking for!