Continuation Message

Source Code

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