diff --git a/install/install-tk.iss b/install/install-tk.iss index cf39c1d2e..499b077c3 100644 --- a/install/install-tk.iss +++ b/install/install-tk.iss @@ -3,11 +3,11 @@ ; AppID can never be changed as subsequent installations require the same installation ID each time AppID=FHIRToolkit AppName=Health Intersections FHIR Toolkit -AppVerName=FHIRToolkit v3.4.13 +AppVerName=FHIRToolkit v3.4.15 ; compilation control OutputDir=..\install\build -OutputBaseFilename=fhirtoolkit-win64-3.4.13 +OutputBaseFilename=fhirtoolkit-win64-3.4.15 Compression=lzma2/ultra64 ; 64 bit @@ -32,11 +32,11 @@ UninstallFilesDir={app}\uninstall ; win2000+ add/remove programs support AppPublisher=Health Intersections P/L AppPublisherURL=http://www.healthintersections.com.au -AppVersion=3.4.13 +AppVersion=3.4.15 AppSupportURL=https://github.com/grahamegrieve/fhirserver AppUpdatesURL=https://github.com/grahamegrieve/fhirserver AppCopyright=Copyright (c) Health Intersections Pty Ltd 2020+ -VersionInfoVersion=3.4.13.0 +VersionInfoVersion=3.4.15.0 ; dialog support LicenseFile=..\license diff --git a/install/install.iss b/install/install.iss index b088dc192..e4ea6e29c 100644 --- a/install/install.iss +++ b/install/install.iss @@ -3,11 +3,11 @@ ; AppID can never be changed as subsequent installations require the same installation ID each time AppID=FHIRServer AppName=Health Intersections FHIR Server -AppVerName=FHIRServer v3.4.13 +AppVerName=FHIRServer v3.4.15 ; compilation control OutputDir=..\install\build -OutputBaseFilename=fhirserver-win64-3.4.13 +OutputBaseFilename=fhirserver-win64-3.4.15 Compression=lzma2/ultra64 ; 64 bit @@ -34,11 +34,11 @@ UninstallFilesDir={app}\uninstall ; win2000+ add/remove programs support AppPublisher=Health Intersections P/L AppPublisherURL=http://www.healthintersections.com.au -AppVersion=3.4.13 +AppVersion=3.4.15 AppSupportURL=https://github.com/grahamegrieve/fhirserver AppUpdatesURL=https://github.com/grahamegrieve/fhirserver AppCopyright=Copyright (c) Health Intersections Pty Ltd 2011+ -VersionInfoVersion=3.4.13.0 +VersionInfoVersion=3.4.15.0 ; dialog support LicenseFile=..\license diff --git a/library/fhir/fhir_tx.pas b/library/fhir/fhir_tx.pas index 28a823b4a..aeba98516 100644 --- a/library/fhir/fhir_tx.pas +++ b/library/fhir/fhir_tx.pas @@ -322,7 +322,8 @@ procedure TTerminologyOperationContext.addNote(vs : TFHIRValueSetW; note: String s : string; begin s := DescribePeriodMS(GetTickCount64 - FStartTime)+' '+vs.vurl+': '+note; - Logging.log(s); + if UnderDebugger then + Logging.log(s); FNotes.add(s); end; diff --git a/library/ftx/ftx_loinc_services.pas b/library/ftx/ftx_loinc_services.pas index 5a9de9245..8c890863d 100644 --- a/library/ftx/ftx_loinc_services.pas +++ b/library/ftx/ftx_loinc_services.pas @@ -170,7 +170,7 @@ TLOINCServices = class (TCodeSystemProvider) FRelationships : TDictionary; FProperties : TDictionary; FStatusKeys : TDictionary; - function filterBySQL(c : TFDBConnection; sql, lsql : String) : TCodeSystemProviderFilterContext; + function filterBySQL(c : TFDBConnection; sql, lsql : String; forIteration : boolean) : TCodeSystemProviderFilterContext; protected function sizeInBytesV(magic : integer) : cardinal; override; public @@ -196,6 +196,7 @@ TLOINCServices = class (TCodeSystemProvider) function Code(context : TCodeSystemProviderContext) : string; override; function Display(context : TCodeSystemProviderContext; langList : THTTPLanguageList) : string; override; procedure Designations(context : TCodeSystemProviderContext; list : TConceptDesignations); override; + function doesFilter(prop : String; op : TFhirFilterOperator; value : String) : boolean; override; function filter(forIteration : boolean; prop : String; op : TFhirFilterOperator; value : String; prep : TCodeSystemProviderFilterPreparationContext) : TCodeSystemProviderFilterContext; override; function FilterMore(ctxt : TCodeSystemProviderFilterContext) : boolean; override; function filterSize(ctxt : TCodeSystemProviderFilterContext) : integer; override; @@ -853,6 +854,44 @@ procedure TLOINCServices.Designations(context: TCodeSystemProviderContext; list: end; end; +function TLOINCServices.doesFilter(prop: String; op: TFhirFilterOperator; value: String): boolean; +var + ts : TStringList; + reg : TRegularExpression; +begin + result := false; + if (FRelationships.ContainsKey(prop) and (op = foEqual)) then + if FCodes.ContainsKey(value) then + result := true + else + result := true + else if (FProperties.ContainsKey(prop) and (op = foEqual)) then + result := true + else if (FRelationships.ContainsKey(prop) and (op = foExists)) then + if FCodes.ContainsKey(value) then + result := true + else + result := true + else if (FProperties.ContainsKey(prop) and (op = foExists)) then + result := true + else if (prop = 'STATUS') and (op = foEqual)and (FStatusKeys.ContainsKey(value)) then + result := true + else if (prop = 'LIST') and (op = foEqual) and (FCodes.ContainsKey(value)) then + result := true + else if (FRelationships.ContainsKey(prop)) and (op = foRegex) then + result := true + else if (FProperties.ContainsKey(prop)) and (op = foRegex) then + result := true + else if (prop = 'concept') and (op in [foIsA, foDescendentOf]) then + result := true + else if (prop = 'copyright') and (op = foEqual) and (value = 'LOINC') then + result := true + else if (prop = 'copyright') and (op = foEqual) and (value = '3rdParty') then + result := true + else + result := false; +end; + procedure TLOINCServices.extendLookup(factory : TFHIRFactory; ctxt: TCodeSystemProviderContext; langList : THTTPLanguageList; props: TArray; resp: TFHIRLookupOpResponseW); var c : TFDBConnection; @@ -960,25 +999,29 @@ function TLOINCServices.InFilter(ctxt: TCodeSystemProviderFilterContext; concept result := (ctxt as TLoincFilterHolder).HasKey((concept as TLoincProviderContext).Key); end; -function TLOINCServices.filterBySQL(c : TFDBConnection; sql, lsql: String): TCodeSystemProviderFilterContext; +function TLOINCServices.filterBySQL(c : TFDBConnection; sql, lsql: String; forIteration : boolean): TCodeSystemProviderFilterContext; var keys : TKeyArray; l : integer; begin - SetLength(keys, 1000); l := 0; - c.select(sql); - while c.fetchnext do + if (forIteration) then begin - if (c.ColKeyByName['Key'] <> 0) then + SetLength(keys, 1000); + l := 0; + c.select(sql); + while c.fetchnext do begin - if (l = length(keys)) then - SetLength(keys, l + 1000); - keys[l] := c.ColKeyByName['Key']; - inc(l); + if (c.ColKeyByName['Key'] <> 0) then + begin + if (l = length(keys)) then + SetLength(keys, l + 1000); + keys[l] := c.ColKeyByName['Key']; + inc(l); + end; end; + c.terminate; end; - c.terminate; SetLength(keys, l); result := TLoincFilterHolder.create; TLoincFilterHolder(result).FKeys := keys; @@ -997,29 +1040,29 @@ function TLOINCServices.filter(forIteration : boolean; prop: String; op: TFhirFi if (FRelationships.ContainsKey(prop) and (op = foEqual)) then if FCodes.ContainsKey(value) then result := FilterBySQL(c, 'select SourceKey as Key from Relationships where RelationshipTypeKey = '+FRelationships[prop]+' and TargetKey in (select CodeKey from Codes where Code = '''+sqlwrapString(value)+''') order by SourceKey ASC', - 'select count(SourceKey) from Relationships where RelationshipTypeKey = '+FRelationships[prop]+' and TargetKey in (select CodeKey from Codes where Code = '''+sqlwrapString(value)+''') and SourceKey = ') + 'select count(SourceKey) from Relationships where RelationshipTypeKey = '+FRelationships[prop]+' and TargetKey in (select CodeKey from Codes where Code = '''+sqlwrapString(value)+''') and SourceKey = ', forIteration) else result := FilterBySQL(c, 'select SourceKey as Key from Relationships where RelationshipTypeKey = '+FRelationships[prop]+' and TargetKey in (select CodeKey from Codes where Description = '''+sqlwrapString(value)+''' COLLATE NOCASE) order by SourceKey ASC', - 'select count(SourceKey) from Relationships where RelationshipTypeKey = '+FRelationships[prop]+' and TargetKey in (select CodeKey from Codes where Description = '''+sqlwrapString(value)+''' COLLATE NOCASE) and SourceKey = ') + 'select count(SourceKey) from Relationships where RelationshipTypeKey = '+FRelationships[prop]+' and TargetKey in (select CodeKey from Codes where Description = '''+sqlwrapString(value)+''' COLLATE NOCASE) and SourceKey = ', forIteration) else if (FProperties.ContainsKey(prop) and (op = foEqual)) then result := FilterBySQL(c, 'select CodeKey as Key from Properties, PropertyValues where Properties.PropertyTypeKey = '+FProperties[prop]+' and Properties.PropertyValueKey = PropertyValues.PropertyValueKey and PropertyValues.Value = '''+SQLWrapString(value)+''' COLLATE NOCASE order by CodeKey ASC', - 'select count(CodeKey) from Properties, PropertyValues where Properties.PropertyTypeKey = '+FProperties[prop]+' and Properties.PropertyValueKey = PropertyValues.PropertyValueKey and PropertyValues.Value = '''+SQLWrapString(value)+''' COLLATE NOCASE and CodeKey = ') + 'select count(CodeKey) from Properties, PropertyValues where Properties.PropertyTypeKey = '+FProperties[prop]+' and Properties.PropertyValueKey = PropertyValues.PropertyValueKey and PropertyValues.Value = '''+SQLWrapString(value)+''' COLLATE NOCASE and CodeKey = ', forIteration) else if (FRelationships.ContainsKey(prop) and (op = foExists)) then if FCodes.ContainsKey(value) then result := FilterBySQL(c, 'select SourceKey as Key from Relationships where RelationshipTypeKey = '+FRelationships[prop]+' and exists (select CodeKey from Codes where (Code = '''+sqlwrapString(value)+''')) order by SourceKey ASC', - 'select count(SourceKey) from Relationships where RelationshipTypeKey = '+FRelationships[prop]+' and exists (select CodeKey from Codes where (Code = '''+sqlwrapString(value)+''')) and SourceKey = ') + 'select count(SourceKey) from Relationships where RelationshipTypeKey = '+FRelationships[prop]+' and exists (select CodeKey from Codes where (Code = '''+sqlwrapString(value)+''')) and SourceKey = ', forIteration) else result := FilterBySQL(c, 'select SourceKey as Key from Relationships where RelationshipTypeKey = '+FRelationships[prop]+' and exists (select CodeKey from Codes where (Description = '''+sqlwrapString(value)+''' COLLATE NOCASE)) order by SourceKey ASC', - 'select count(SourceKey) from Relationships where RelationshipTypeKey = '+FRelationships[prop]+' and exists (select CodeKey from Codes where (Description = '''+sqlwrapString(value)+''' COLLATE NOCASE)) and SourceKey = ') + 'select count(SourceKey) from Relationships where RelationshipTypeKey = '+FRelationships[prop]+' and exists (select CodeKey from Codes where (Description = '''+sqlwrapString(value)+''' COLLATE NOCASE)) and SourceKey = ', forIteration) else if (FProperties.ContainsKey(prop) and (op = foExists)) then result := FilterBySQL(c, 'select distinct CodeKey as Key from Properties where Properties.PropertyTypeKey = '+FProperties[prop]+' order by CodeKey ASC', - 'select count(CodeKey) from Properties where Properties.PropertyTypeKey = '+FProperties[prop]+' and CodeKey = ') + 'select count(CodeKey) from Properties where Properties.PropertyTypeKey = '+FProperties[prop]+' and CodeKey = ', forIteration) else if (prop = 'STATUS') and (op = foEqual)and (FStatusKeys.ContainsKey(value)) then result := FilterBySQL(c, 'select CodeKey as Key from Codes where StatusKey = '+FStatusKeys[value]+' order by CodeKey ASC', - 'select count(CodeKey) from Codes where StatusKey = '+FStatusKeys[value]+' and CodeKey = ') + 'select count(CodeKey) from Codes where StatusKey = '+FStatusKeys[value]+' and CodeKey = ', forIteration) else if (prop = 'LIST') and (op = foEqual) and (FCodes.ContainsKey(value)) then result := FilterBySQL(c, 'select TargetKey as Key from Relationships where RelationshipTypeKey = '+FRelationships['Answer']+' and SourceKey in (select CodeKey from Codes where (Code = '''+sqlwrapString(value)+''')) order by SourceKey ASC', - 'select count(TargetKey) from Relationships where RelationshipTypeKey = '+FRelationships['Answer']+' and SourceKey in (select CodeKey from Codes where (Code = '''+sqlwrapString(value)+''')) and TargetKey = ') + 'select count(TargetKey) from Relationships where RelationshipTypeKey = '+FRelationships['Answer']+' and SourceKey in (select CodeKey from Codes where (Code = '''+sqlwrapString(value)+''')) and TargetKey = ', forIteration) else if (FRelationships.ContainsKey(prop)) and (op = foRegex) then begin reg := TRegularExpression.Create(value); @@ -1032,7 +1075,7 @@ function TLOINCServices.filter(forIteration : boolean; prop: String; op: TFhirFi ts.add(c.ColStringByName['Key']); c.terminate; result := FilterBySQL(c, 'select SourceKey as Key from Relationships where RelationshipTypeKey = '+FRelationships[prop]+' and TargetKey in ('+ts.CommaText+') order by SourceKey ASC', - 'select count(SourceKey) from Relationships where RelationshipTypeKey = '+FRelationships[prop]+' and TargetKey in ('+ts.CommaText+') and SourceKey = ') + 'select count(SourceKey) from Relationships where RelationshipTypeKey = '+FRelationships[prop]+' and TargetKey in ('+ts.CommaText+') and SourceKey = ', forIteration) finally ts.free; end; @@ -1052,7 +1095,7 @@ function TLOINCServices.filter(forIteration : boolean; prop: String; op: TFhirFi ts.add(c.ColStringByName['PropertyValueKey']); c.terminate; result := FilterBySQL(c, 'select CodeKey as Key from Properties where PropertyTypeKey = '+FProperties[prop]+' and PropertyValueKey in ('+ts.CommaText+') order by CodeKey ASC', - 'select count(CodeKey) from Properties where PropertyTypeKey = '+FProperties[prop]+' and PropertyValueKey in ('+ts.CommaText+') and CodeKey = ') + 'select count(CodeKey) from Properties where PropertyTypeKey = '+FProperties[prop]+' and PropertyValueKey in ('+ts.CommaText+') and CodeKey = ', forIteration) finally ts.free; end; @@ -1062,13 +1105,13 @@ function TLOINCServices.filter(forIteration : boolean; prop: String; op: TFhirFi end else if (prop = 'concept') and (op in [foIsA, foDescendentOf]) then result := FilterBySQL(c, 'select DescendentKey as Key from Closure where AncestorKey in (select CodeKey from Codes where Code = '''+sqlwrapString(value)+''') order by DescendentKey ASC', - 'select count(DescendentKey) from Closure where AncestorKey in (select CodeKey from Codes where Code = '''+sqlwrapString(value)+''') and DescendentKey = ') + 'select count(DescendentKey) from Closure where AncestorKey in (select CodeKey from Codes where Code = '''+sqlwrapString(value)+''') and DescendentKey = ', forIteration) else if (prop = 'copyright') and (op = foEqual) and (value = 'LOINC') then result := FilterBySQL(c, 'select CodeKey as Key from Codes where not CodeKey in (select CodeKey from Properties where PropertyTypeKey = 9) order by CodeKey ASC', - 'select count(CodeKey) from Codes where not CodeKey in (select CodeKey from Properties where PropertyTypeKey = 9) and CodeKey = ' ) + 'select count(CodeKey) from Codes where not CodeKey in (select CodeKey from Properties where PropertyTypeKey = 9) and CodeKey = ', forIteration) else if (prop = 'copyright') and (op = foEqual) and (value = '3rdParty') then result := FilterBySQL(c, 'select CodeKey as Key from Codes where CodeKey in (select CodeKey from Properties where PropertyTypeKey = 9) order by CodeKey ASC', - 'select count(CodeKey) from Codes where CodeKey in (select CodeKey from Properties where PropertyTypeKey = 9) and CodeKey = ') + 'select count(CodeKey) from Codes where CodeKey in (select CodeKey from Properties where PropertyTypeKey = 9) and CodeKey = ', forIteration) else result := nil; c.release; diff --git a/library/ftx/ftx_service.pas b/library/ftx/ftx_service.pas index 18b5f0806..679d8165f 100644 --- a/library/ftx/ftx_service.pas +++ b/library/ftx/ftx_service.pas @@ -751,7 +751,7 @@ function TConceptDesignations.langMatches(lang : THTTPLanguageEntry; stated: TIE if (lang.ietf = nil) then lang.ietf := FLanguages.parse(lang.lang); - if (lang.ietf <> nil) and lang.ietf.matches(stated, depthForMatchType(matchType)) then + if (lang.ietf <> nil) and lang.ietf.matches(actual, depthForMatchType(matchType)) then exit(true); end; end; diff --git a/library/version.inc b/library/version.inc index 0f5227e13..8a0ce275d 100644 --- a/library/version.inc +++ b/library/version.inc @@ -1,3 +1,3 @@ - FHIR_CODE_FULL_VERSION = '3.4.13'; - FHIR_CODE_RELEASE_DATE = '2024-09-23'; - FHIR_CODE_RELEASE_DATETIME = '20240923092555.964Z'; + FHIR_CODE_FULL_VERSION = '3.4.15'; + FHIR_CODE_RELEASE_DATE = '2024-09-24'; + FHIR_CODE_RELEASE_DATETIME = '20240924122536.288Z'; diff --git a/server/endpoint_storage.pas b/server/endpoint_storage.pas index 6ea060582..cf73aca65 100644 --- a/server/endpoint_storage.pas +++ b/server/endpoint_storage.pas @@ -2261,7 +2261,7 @@ procedure TStorageWebEndpoint.SendError(response: TIdHTTPResponseInfo; logid: st FContext.factory.setXhtml(issue.Resource, TFHIRXhtmlParser.Parse(langList, xppReject, [], '

' + FormatTextToXML(message, xmlText) + '

')); iss := FContext.factory.makeIssue(isError, code, '', message); try - // iss.diagnostics := ExceptionStack(e); + iss.diagnostics := diagnostics; issue.addIssue(iss, false); finally iss.free; diff --git a/server/fhirconsole.lpi b/server/fhirconsole.lpi index 5859bcf4b..c509c7932 100644 --- a/server/fhirconsole.lpi +++ b/server/fhirconsole.lpi @@ -18,7 +18,7 @@ - + diff --git a/server/fhirserver.dproj b/server/fhirserver.dproj index 25e25ae54..f657281b3 100644 --- a/server/fhirserver.dproj +++ b/server/fhirserver.dproj @@ -92,7 +92,7 @@ true 3 4 - 13 + 15 false @@ -167,7 +167,7 @@ true false 3 - 13 + 15 none 4 false diff --git a/server/fhirserver.lpi b/server/fhirserver.lpi index 61100e80c..8d98f318d 100644 --- a/server/fhirserver.lpi +++ b/server/fhirserver.lpi @@ -19,7 +19,7 @@ - + diff --git a/toolkit2/fhirtoolkit.lpi b/toolkit2/fhirtoolkit.lpi index 3cd06b13f..7839d5043 100644 --- a/toolkit2/fhirtoolkit.lpi +++ b/toolkit2/fhirtoolkit.lpi @@ -17,7 +17,7 @@ - +