Some ideas for an Operation.
Expose the Comma delimited headings to be configurable via new property and settings.
Toggle the overwrite/append mode, if set to overwrite, to ensure the heading is added to new files
So code code might be something like:
/// The type of adapter used to communicate with external systems Parameter ADAPTER = "EnsLib.File.OutboundAdapter"; Property Adapter As EnsLib.File.OutboundAdapter; Property CSVHeaderRecord As %String; Parameter SETTINGS = "CSVHeaderRecord:Basic"; Method TestWrite(pRequest As Ens.StringContainer, pResponse As Ens.StringContainer) As %Status { set filename="OutputTest.csv" set originalOverwrite=..Adapter.Overwrite if ""'=..CSVHeaderRecord { if originalOverwrite { set tSC=..Adapter.PutLine(filename,..CSVHeaderRecord) set ..Adapter.Overwrite=0 } else { if '##class(%File).Exists(..Adapter.fixPath(..Adapter.FilePath)_pFilename) { set tSC=..Adapter.PutLine(filename,..CSVHeaderRecord) set ..Adapter.Overwrite=0 } } } set tSC=..Adapter.PutLine(filepath_filename,pRequest.StringValue) set ..Adapter.Overwrite=originalOverwrite Quit $$$OK }
For updating existing files using streams:
May need to consider stream line terminators and character encoding.
ClassMethod AddCSVHeader(filepath = "", headerText = "") { set tmpStream=##class(%Stream.TmpCharacter).%New() set updateStream=##class(%Stream.FileCharacter).%New() set tSC=updateStream.LinkToFile(filepath) set tSC=tmpStream.CopyFrom(updateStream) do updateStream.Rewind() do tmpStream.Rewind() do updateStream.WriteLine(headerText) do updateStream.CopyFrom(tmpStream) do updateStream.Flush() do updateStream.%Save() }
Hi Alexey,
Atomic read of a single global node.
In the questions example, the reference table can use a single global node.
Use cases are lookup table and application code tables (SELECT %NOLOCK ...)
Conversely for reading complex records spanning multiple global nodes, then yes the lock is needed for consistent full read:
1) During the full read
2) Just before the commit of the transaction from updating process.
However this is also much less than blocking for the full 30s seconds described in original scenario.
I had an experiment with making a CSP framework for using embedded python.
https://github.com/alexatwoodhead/PyNow
It has some utility code that converts the %request arguments and presents as a dictionary to Python method.
It also shows using XData blocks to use as a template with some Excel function+Django like expression support.
Might find something reusable in there.