Source Code
Contents
The code is specific to SQLite and will need tweaking to work with other databases.
This is the SQL used to create the Continuation table for SQLite. We could have generated the table from the VMD file, but as it will never change it is simpler to hard code it.
Because SQLite uses a “dynamic type system” the the Message field will happily store a string of any length. In fact in SQLite the datatype is only a recommendation and if we had declared Message as an integer we could still store string data in it. For more information see Datatypes In SQLite Version 3.
Other databases use strict static typing, something like this should work with most other database servers:
CREATE TABLE Continuation ( ContinuationId VARCHAR(100) NOT NULL, Message VARCHAR(100000), PRIMARY KEY (ContinuationId) );
Sample Data
Here’s an example of the first part of the message where the presence of a DSC segment indicates that more data is to follow:
MSH|^~&|SOFTMED^DIS|MGH|EGATE||20101110061841||MDM^T04|101110061841784|P|2.3.1|| EVN| PID||1234567^^^MGH|||SMITH^THEODORE^E^^^^L^A||19350212|M|||||||||||| PV1|||W12^W1236^B||||018840|075325|||||||||018840|||||||||||||||||||||||||||20101025|20101103| TXA|1|DIS||201011101818||201011030000|201011031346||018840||DEX|1307506|||||LA|||||^201011101818| OBX|1|FT|&ZCR||DISCHARGE SUMMARY.br.brNAME: SMITH THEODORE E UNIT NUMBER: 123-45-67.br FLOOR: W12 W1236B.brADMISSION DATE: 10/25/2010 DISCHARGE DATE: 11/03/2010.br.br.br.br.brPRINCIPAL DIAGNOSIS.brAVM.br.brASSOCIATED DIAGNOSES.brAltered mental status, Abnormal gait, Seizure disorder, Respiratory.brinsufficiency, Aphasia, Edema, Headache.br.brOPERATIONS AND PROCEDURES.br10/25/10: PROCEDURE: Left temporal craniotomy with microsurgical.brresection of arteriovenous malformation using BrainLab stereotactic.brguidance. Post-operative cerebral angiogram..br.br.brALLERGIES.brHCTZ (Unknown).brHeparin (Severe bleeding).brAspirin (severe bleeding).brALFUZOSIN (Unknown).brAMINOCAPROIC ACID (rhabdomyolysis).brALTEPLASE (severe bleeding).br.br.brHISTORY AND REASON FOR HOSPITALIZATION AND SIGNIFICANT FINDINGS.brThe patient is a 76yoM in for elective craniotomy for clipping of.brarteriovenous malformation with Dr. Ogilvy..br.brHPI: The patient has a complicated medical history including a h/o.brhereditary hemorrhagic telangiectasia (HHT) c/b cerebral, GI and.brpulmonary AVMs, chronic GIB, and progressive dyspnea. He is s/p.brBillroth II, duodenal resection for bleeding AVMs 6/19/2009 and s/p.brcoil embolization of left occipital artery to external jugular vein.brshunt vessel on 9/14/2010. He is transfusion dependent with chronic.brmelena/BRBPR and s/p cerebral bleed with resultant seizure. Pt. now.brpresents for surgical intervention for a temporal arteriovenous.brmalformation..br.brExam on admission:.brBP: 163/78 mm Hg.brAP: 95 bpm.brO2 Sat: 99%.brTemp: 97.8.brResp: 18.brHt: 66 inches.brWt: 153 lbs.brGeneral: Patients is a well appearing, well nourished male in no.brapparent distress..brSkin: Warm and dry to touch. No sores, lesions, rashes, bruising or.brpetecchiae noted..brHEENT: Normocephalic, face symmetricalADD| DSC|MGH-SM-1307506-20101110061841-1
This is the continuation part which indicates that it is a follow on message by having the continuation ID in it’s MSH message header segment:
MSH|^~&|SOFTMED^DIS|MGH|EGATE||20101110061841||MDM^T04|101110061841784|P|2.3.1||MGH-SM-1307506-20101110061841-1 ADD|until cleared by this MD at follow-up..br.br.br||||||S|||201011031346| PR1|||||| ZTR|||||SOFTMED|MGH||||DE^DEX Discharge Summary^MGH-RPTL-REPTYPE|This article has not been written.
Sample Code
This is vmd file used in the example: Continuation.vmd
This is the main routine:
require 'cont' -- change the locations of the VMD and DB files as required -- in this case (no path specified) the path defaults to the Iguana install directory SQLITE_DB='continuation.sqlite' -- vmd must be in XML format VMD_FILE='Continuation.vmd' conn = db.connect{ api=db.SQLITE, name=SQLITE_DB } function main(Data) -- create the database file and tables if it does not exist local r=conn:query('SELECT * FROM sqlite_master') if #r==0 then CreateTable() end local Msg = hl7.parse{data=Data, vmd=VMD_FILE} if not Msg.DSC:isNull() then PushContinuation(Msg, Data) return end if Msg.MSH[14] then trace('We have a continuation.') local T = FetchContinuation(Msg) end ---------------------------------------------------- -- add code here to process the concatenated message ---------------------------------------------------- end function PushContinuation(Msg,Data) local Id = Msg.DSC[1]:nodeValue() trace("Encountered continuation segment, ID = "..Id) cont.put(Id, Data) end function FetchContinuation(Msg) local OrigMsg = cont.get(Msg.MSH[14]:nodeValue()) if not OrigMsg then error("Could not find original message for "..Msg.MSH[14]:nodeValue()) end local Orig = hl7.parse{vmd=VMD_FILE, data=OrigMsg} local Text = MergeText(Orig, Msg) return Text end function MergeText(Msg1, Msg2) local T = Msg1.OBX[5][1][1]:nodeValue() T = T:sub(1, #T-3) trace(Msg2.ADD[1]:nodeValue()) T = T.." "..Msg2.ADD[1] T = T:gsub(".br", "n") return T end -- create continuation table - the SQL used is ***SQLite*specific*** function CreateTable() local Sql= 'CREATE TABLE IF NOT EXISTS Continuationn'.. '(n'.. 'ContinuationId TEXT(255) NOT NULL PRIMARY KEY,n'.. 'Message TEXT(255) NULLn'.. ');' trace(Sql) conn:execute{sql=Sql,live=true} end
This is the cont module:
cont = {} function cont.get(Id, DbName) local Sql = 'SELECT * FROM Continuation WHERE ContinuationId = '..conn:quote(Id) local R = conn:query(Sql) if (#R == 0) then return nil end return R[1].Message:nodeValue() end function cont.put(Id, Data) trace(Esc,conn) local Sql = "REPLACE INTO Continuation(ContinuationId, Message)".. " VALUES("..conn:quote(Id)..","..conn:quote(Data)..")" trace(Sql) conn:execute{sql=Sql,live=true} end