发布新帖

查找

文章
· 三月 2, 2023 阅读大约需 5 分钟

Tutorial - Working with %Query #3

My previous article introduced you to the COS based Custom Class Query.
There were some features missing like more lines of the stream displayed
and numbered.

The basic idea is the same.
A new input parameter chunks is introduced that sets a limit of displayed
pieces of our stream.

/// pack all params into qHandle
/// called only once at start
ClassMethod Q2Execute(
	ByRef qHandle As %Binary,
	idfrom As %Integer = 1,
	idto As %Integer = 0,
	maxtxt As %Integer = 25,
	chunks As %Integer = 1) As %Status
{
  set qHandle={}
  set qHandle.id=0
  set qHandle.idfrom=idfrom
  set qHandle.idto=idto
  set qHandle.obj=0
  set qHandle.stream=0
  set qHandle.maxtxt=maxtxt
  set qHandle.chunks=chunks
  set qHandle.chcnt=1
  Quit $$$OK
}
  • I now have a limit and a counter of displayed chunks default is 1 chunk
  • the Stream Object is kept open in qHandle to avoid reload
  • once the stream is empty I jump to the next available object.

and it looks like that:
 

[SQL]USER>>call rcc.Q2(1,,,3)
11.     call rcc.Q2(1,,,3)

Dumping result #1
ID      City    Name    Age     chunk   Stream
1       Bensonh Kovalev 16      1       Building shareholder valu
_       _       _       _       2       e by delivering secure di
_       _       _       _       3       stributed devices and med
2       Queensb Yeats   15      1       Spearheading the next gen
_       _       _       _       2       eration of high-performan
_       _       _       _       3       ce genetic virtualized in
4       Newton  Evans   61      1
5       Hialeah Zemaiti 47      1       Resellers of premise-base
_       _       _       _       2       d secure XML services for
_       _       _       _       3        social networks.||TwoToL
6       Elmhurs Jenkins 29      1       Enabling individuals and
_       _       _       _       2       businesses to manage ente
_       _       _       _       3       rprise models for social
7       Islip   Drabek  61      1       Building shareholder valu
_       _       _       _       2       e by delivering open crow
_       _       _       _       3       d-sourced voice-enabled c
8       Islip   Kovalev 88      1       Experts in standards-base
_       _       _       _       2       d distributed voice-enabl
_       _       _       _       3       ed services for social ne
 
19 Rows(s) Affected
statement prepare time(s)/globals/lines/disk: 0.0069s/2022/14949/0ms
          execute time(s)/globals/lines/disk: 0.0025s/48/5520/0ms
                          cached query class: %sqlcq.USER.cls82
---------------------------------------------------------------------------

for shorter streams it terminates when stream ends

[SQL]USER>>call rcc.Q2(,4,70,20)
22.     call rcc.Q2(,4,70,20)
 
Dumping result #1
ID      City    Name    Age     chunk   Stream
1       Bensonh Kovalev 16      1       Building shareholder value by delivering secure distributed devices an
_       _       _       _       2       d media for the Health Care community.||Scope ||An AmAn LoIcA On||Iso|
_       _       _       _       3       |PlasmA||Atic CoLoIO||IcOpIon An Lo||Re||Ies Tw||Lo Dyna I||Atic To Ly
_       _       _       _       4       ||Ecto O||AticL||Ism IAn Look||Plasm ||A||A Cop||Two IRe ||Two ||I||Dy
_       _       _       _       5       na Much LoN||Ion AmQuoAn Ec||OpOc||IcTwoCycl||A ComRe||I||GeoPedeLo ||
_       _       _       _       6       Pus EndoPyro||IesIsoIsmCom Te||A||Pyro||I On An I Tr||Syn AIcA||Gyro P
_       _       _       _       7       ho||AmCo UniTe||AScope ComQuo IH||Two A Ect||Graph ||A ||Pyro Heli AnR
_       _       _       _       8       eAn||Muc||Range IcTri||IonIsoIonAnC||A Wave Lo I||PusAt||To||Able ||Lo
_       _       _       _       9       Ati||A||Quo||Ly LyIc||***Done***
2       Queensb Yeats   15      1       Spearheading the next generation of high-performance genetic virtualiz
_       _       _       _       2       ed instruments for the Fortune 500.||LoI||IesMorphSy||Re Uni ||CoQuoEc
_       _       _       _       3       to||Tech IesOn ||Invent Vi||To LyIonGeoIc||Able||Ion Ect||Co I Ic Quo
_       _       _       _       4       U||AOn Much Ly To||Iso Much G||Am||LoIsmGraph Pus ||ReOp ViaComLo||OpI
_       _       _       _       5        TheticOn R||Ly OpCopter Mil||Quo Am Te||T||Plasm Type||On IsoIOpIcOp
_       _       _       _       6       P||I Dyna Tech Q||IGeo Dyna ||An AmLyCo Ion||Ic AnIsm Phot||IesAmI Am
_       _       _       _       7       OpA||KiloAnLo Am Co||Op ATr||TheticGraph||P||IcIc IOnTwoT||Ped||On On
_       _       _       _       8       QuoAnGrap||I||Copter LyQuo||ALookIcMuch Dyn||Abl||Re CoIcMuchCo A||ReO
_       _       _       _       9       nMuchAnToGr||TheticToTec||Ism Ies A||An AIAbleCo ||Q||LoI||Pus Ly ATri
_       _       _       _       10      On G||SoundU||To Heli Com||AOn||Ly Re||ComInventLoR||***Done***
4       Newton  Evans   61      1
20 Rows(s) Affected
statement prepare time(s)/globals/lines/disk: 0.0065s/2020/15410/0ms
          execute time(s)/globals/lines/disk: 0.0021s/33/5048/0ms
                          cached query class: %sqlcq.USER.cls84
---------------------------------------------------------------------------
  • the next step is to honor the separators and display segments
  • and also allow groups of segments
  • As the basic functionality is there it's more a matter of chopping the streams 

Follow me on to the next chapter for the extension of this example that
will show and control more result lines.

Just a reminder:
All test data are generated using the System method %Populate
So your output will be different. I suggest you run our tests also with other parameters
than the shown examples to get the full power of this tool.

The full code example is again available on GitHub  

The Video is available now. See section Custom Class Query 

For immediate access, you can use Demo Server WebTerminal  
and the related system Management Portal on Demo Server SMP

I hope you liked it so far and I can count on your votes.

1 Comment
讨论 (1)1
登录或注册以继续
文章
· 三月 2, 2023 阅读大约需 5 分钟

Tutorial - Working with %Query #2

My previous article introduced you to SQL based Basic Class Query
where a clever wizard created all the required code for you and your essential
contribution was an SQL statement. 

Now we enter the real Custom Class Query that provides more freedom but
requires a deeper understanding of the mechanic behind the scene.
The full code example is again on GitHub

Some things haven't changed:

  • demo data are the same
  • consumption of the query is also unchanged
  • all handling of ODBC / JDBC protocol is still generated.

So what is different?

  • You need a header QUERY statement to declare your input parameters but
    • also the record layout for your output. ROWSPEC
  • you have to provide an Execute method to initialize your query and consume your input parameters
  • a Close method to clean up your environment
  • and a Fetch method that does the Job.
    • it is called row by row until you set AtEnd=1. (it is passed by reference)
    • and you return variable Row (also passed by reference) as $LB() structure
    • so it is obvious that the resulting Row is shorter than MAXSTRING
    • and this is our challenge to present your stream

so we take our choice: 
as before we use the Studio's Query Wizard

we have 3 parameters: idfrom (first ID), isto (last ID), maxtxt (maxim text from stream)

and new the layout of our output (ROWSPEC), similar to above

for our Stream, we need to overwrite %String defaults to match ODBC / JDBC
The type needs to be %String(EXTERNALSQLTYPE = "LONGVARCHAR", MAXLEN = "")​​​
This is the generated code framework:

Query Q1(
    idfrom As %Integer = 1,
    idto As %Integer = 0,
    maxtxt As %Integer = 25) As %Query
    (ROWSPEC = "ID:%Integer,City:%String,
               Name:%String,Age:%Integer,
               Stream:%String(EXTERNALSQLTYPE=""LONGVARCHAR"", MAXLEN = """")")
{
}
ClassMethod Q1Execute(
    ByRef qHandle As %Binary,
    idfrom As %Integer = 1,
    idto As %Integer = 0,
    maxtxt As %Integer = 25) As %Status
{
    Quit $$$OK
}
ClassMethod Q1Close(ByRef qHandle As %Binary) As %Status [ PlaceAfter = Q1Execute ]
{
    Quit $$$OK
}
ClassMethod Q1Fetch(
    ByRef qHandle As %Binary,
    ByRef Row As %List,
    ByRef AtEnd As %Integer = 0) As %Status [ PlaceAfter = Q1Execute ]
{
    Quit $$$OK
}

we still need to add CONTAINID=1 and   [ SqlName = Q1, SqlProc ]

  • Query Q1() is the descriptor used by the interface support
  • qHandle is the common data structure for all 3 methods
    • whatever you pass along to the next row for processing needs to be stored there.
    • e.g. first ID, last ID, actual ID, ...... 
    • In past this was typically a subscripted variable or some oref
    • As a personal experiment, I tried a JSON object and it worked fine
  • The query takes 3 simple input parameters:
    • idfrom = first ID to show
    • idto = last ID to show - missing shos al higher IDs available
    • maxtxt = maximum text from the beginning of the stream. Default = 25
  •  
    ClassMethod Q1Execute(
        ByRef qHandle As %Binary,
        idfrom As %Integer = 1,
        idto As %Integer = 0,
        maxtxt As %Integer = 25) As %Status
    {
      set qHandle={}
      set qHandle.id=0
      set qHandle.idfrom=idfrom
      set qHandle.idto=idto
      set qHandle.obj=0
      set qHandle.stream=0
      set qHandle.maxtxt=maxtxt
      Quit $$$OK
    }
  • Q1Fetch is the biggest working bloc
    • I used object access in this example to keep it more readable
    • Accessing the Globals for Date and Stream directly was remarkably faster but really hard to read and to follow. 
    • The more important point is that you can do whatever you like, not just collect or select data.
    • Many management routines use it to display Processes, actual Users,  ... whatever can be presented as a table. 
    • The point is to compose the $LB() for Row and return it and once you are done,
    • Set AtEnd=1, and the query terminates.
    • In this example, the major challenge is to skip nonexisting objects and to skip no existing streams
    • to avoid empty result lines.
  • /// that's where the music plays
    /// called for evey row delivered
    ClassMethod Q1Fetch(
    	ByRef qHandle As %Binary,
    	ByRef Row As %List,
    	ByRef AtEnd As %Integer = 0) As %Status [ PlaceAfter = Q1Execute ]
    {
      /// first access
      if qHandle.id<qHandle.idfrom set qHandle.id=qHandle.idfrom
      ///
    nextrec
      if qHandle.idto,qHandle.idto<qHandle.id set AtEnd=1
      if qHandle.id>^rcc.TUD set AtEnd=1
      if AtEnd quit $$$OK
      if 'qHandle.obj {
        set obj=##class(rcc.TU).%OpenId(qHandle.id)
          ,qHandle.obj=obj
          ,qHandle.stream=0
      } 
      if 'obj set qHandle.id=qHandle.id+1 goto nextrec
      if 'qHandle.stream set qHandle.stream=qHandle.obj.Stream
      set text=qHandle.stream.Read(qHandle.maxtxt)
      set Row=$lb(qHandle.id,qHandle.obj.City,qHandle.obj.Name,qHandle.obj.Age,text)
    /// row completed
      set qHandle.id=qHandle.id+1
      set qHandle.stream=0
      set qHandle.obj=0
      Quit $$$OK
    }
  • and here is a short test
    [SQL]USER>>call rcc.Q1(4,7)
    8.      call rcc.Q1(4,7)
    
    Dumping result #1
    ID      City    Name    Age     Stream
    4       Newton  Evans   61
    5       Hialeah Zemaiti 47      Resellers of premise-base
    6       Elmhurs Jenkins 29      Enabling individuals and
    7       Islip   Drabek  61      Building shareholder valu
     
    4 Rows(s) Affected
    statement prepare time(s)/globals/lines/disk: 0.0003s/11/685/0ms
              execute time(s)/globals/lines/disk: 0.0010s/18/2156/0ms
                              cached query class: %sqlcq.USER.cls59
    ---------------------------------------------------------------------------

Getting just the beginning of our stream is not always sufficient.

Follow me on to the next chapter for the extension of this example that
will show and control more result lines.

Just a reminder:
All test data are generated using the System method %Populate
So your output will be different. I suggest you run our tests also with other parameters
than the shown examples to get the full power of this tool.

The full code example is again available on GitHub

 

The full code example is again available on GitHub  

The Video is available now. See section Custom Class Query 

For immediate access, you can use Demo Server WebTerminal  
and the related system Management Portal on Demo Server SMP

I hope you liked it so far and I can count on your votes.

1 Comment
讨论 (1)1
登录或注册以继续
文章
· 三月 2, 2023 阅读大约需 5 分钟

Tutorial - Working with %Query #1

    

The title of the contest subject is not quite precise but addresses the %Library.classes involved.
What is meant is officially named Class Query and is dating back to the early days of Caché.
CLASS is used because it is embedded in a COS class.
Though there is a precise description in the official documentation it remains rather abstract.
My tutorial should guide you step-by-step through a simple example in COS to make it tangible to you

  • All code examples are available on GitHub
  • All examples can be exercised from Terminal, Console, or WebTerminal.
  • I use a personal command ZZQ homed in %ZLANGC00.INT for test and demo which runs the SQL Shell  >>>  "DO $system.SQL.Shell()"
  • SQL Shell runs interactive and allows simple debugging of your code
  • Finally, I use Studio as it includes a very comfortable wizard for ClassQueries

Intro

For any demo or tutorial, some test data are required.
My simple table/class design just has 4 columns:

  • Id
  • City
  • Name
  • Age
  • Stream

While the first 4 are rather normal data types easily mapped to SQL
Stream provides the challenge to use a Class Query for display.
The idea in background: If this is a patient record then some big
stream documents might be directly attached to it.
The class is defined as [Final] to keep the Global more readable.

The demo content is generated using %Populate Utility.
Therefore your data content will look different than here
Except for the Stream that is not serviced by %Populate.
Here I generate some text that is randomly split into sections
using || (double pipe) as a segment separator.  
(! it is not a tutoriral on %Populate Utility!)

In order to simulate  missing content I removed
the stream for ID=4 and also the whole ID=3 .

It's simply
USER>Do ##class(rcc.TU).Populate(8)
USER>kill ^rcc.TUD(3)                   ;; make a gap
USER>set $LI(^rcc.TUD(4),4)=""  ;; no stream

So this is the demo Table / Class

USER>zwrite ^rcc.TUD
^rcc.TUD=8
^rcc.TUD(1)=$lb("Bensonhurst","Kovalev",16,"1")
^rcc.TUD(2)=$lb("Queensbury","Yeats",15,"2")
^rcc.TUD(4)=$lb("Newton","Evans",61,"")
^rcc.TUD(5)=$lb("Hialeah","Zemaitis",47,"5")
^rcc.TUD(6)=$lb("Elmhurst","Jenkins",29,"6")
^rcc.TUD(7)=$lb("Islip","Drabek",61,"7")
^rcc.TUD(8)=$lb("Islip","Kovalev",88,"8")


The case %SQLquery

You create an empty class frame  (rcc.TU0) and let the wizard add a Query

And it guides you through all the required parameters:
We first create a Basic Class Query 

and add our input parameters  (I have just 1)

and

that's the result

That's not so impressive yet and you need to add some more parameters + your Query!
you may do it just by typing or using Studio's Inspector which knows all quotes and brackets

  •  CONTAINID defines the column of your ID in the resulting row
  • SqlProc indicates that your query may be used as Procedure  (which we will do)
  • SqlName = Q0  assigns a name within your class package (mostly simpler)
  • most important: your SQL statement applying your input parameters as host variables

so it looks like this:

WHAT IS THIS GOOD FOR ?

  • This is, of course, the most simple statement. Normally  you would use it for rather complex SQL statements that are frozen now and as SQLprocedure available anywhere internal or from some external ODBC or JDBC client 
  • all ODBC/JDBC protocol is precompiled for your query. 
  • It looks like embedded SQL but you are not caught in your classmethod.
  • internal it is available for %ResultSet, or  %SQL.Statement or $system.SQL.Shell()
  • either direct using CALL rcc.Q0(4)  or as sub-select  SELECT Id, name FROM rcc.Q0(99) where AGE > 21 

And it looks like this:

  • 
    USER>do $system.SQL.Shell()
    SQL Command Line Shell
    ----------------------------------------------------
    The command prefix is currently set to: <<nothing>>.
    Enter q to quit, ? for help.
    [SQL]USER>>call rcc.q0(4)
    3.      call rcc.q0(4)
    
    Dumping result #1
    ID      Age     City    Name    Stream
    1       16      Bensonhurst     Kovalev "1%Stream.GlobalCharacter
                                                                       ^rcc.TUS"
    2       15      Queensbury      Yeats   "2%Stream.GlobalCharacter
                                                                       ^rcc.TUS"
    4       61      Newton  Evans
    5       47      Hialeah Zemaitis        "5%Stream.GlobalCharacter
                                                       ^rcc.TUS"
    4 Rows(s) Affected
    statement prepare time(s)/globals/lines/disk: 0.0003s/11/583/0ms
              execute time(s)/globals/lines/disk: 0.0006s/4/1515/0ms
                              cached query class: %sqlcq.USER.cls77
    ---------------------------------------------------------------------------
  • [SQL]USER>>SELECT Id, age, name FROM rcc.Q0(99) where AGE > 21 
    6.      SELECT Id, age, name FROM rcc.Q0(99) where AGE > 21 
     
    ID      Age     Name
    4       61      Evans
    5       47      Zemaitis
    6       29      Jenkins
    7       61      Drabek
    8       88      Kovalev
     
    5 Rows(s) Affected
    statement prepare time(s)/globals/lines/disk: 0.0726s/45969/214801/0ms
              execute time(s)/globals/lines/disk: 0.0016s/123/2486/0ms
                              cached query class: %sqlcq.USER.cls81
    ---------------------------------------------------------------------------

It's immediately obvious to you that instead of the Stream content you get a mystic StreamReference

Follow me on to the next chapter of a custom code-based Query.

Just a reminder:
All test data are generated using the System method %Populate
So your output will be different. I suggest you run our tests also with other parameters
than the shown examples to get the full power of this tool.

The full code example is again available on GitHub  

The Video is available now.

For immediate access, you can use Demo Server WebTerminal  
and the related system Management Portal on Demo Server SMP

I hope you liked it so far and I can count on your votes.

4 Comments
讨论 (4)1
登录或注册以继续
问题
· 三月 2, 2023

How Does InterSystems FHIR profile validation works?

Hi folks!

Examining FHIR profile validation with InterSystems FHIR server. FHIR profiles is a very useful feature of FHIR standard that helps an organization or solution to establish constraints to a very disperse FHIR standards that are relevant to a particular business solution. Learn more on FHIR profiles.

I created a very simple FHIR profile with the following JSON:

 
Spoiler

As you can see in "differential" section it makes mandatory fields of id, name and gender.

I managed to successfully submit the profile via the POST request to:

localhost:52773/fhir/r4/StructureDefinition

Then I submitted the following test Patient profile, where I omitted the "id" field and included the FHIR profile link in the meta section to:

localhost:52773/fhir/r4/Patient

 

{

"resourceType": "Patient",

"meta": {

"profile": [

"http://example.org/fhir/StructureDefinition/TutorialPatient"
]

},

"text": {

"div": "‹div xmlns=\"http://ww.w3.org/1999/xhtml\"><h1>Elon Musk</hi>/div>",

"status": "generated"
},

"name": [

{

"use": "official",

"given": [

"Elon"
],

"family": "Ramesh"
}

],

"gender": "male",

"birthDate": "1997-09-08",

"telecom": [

{

"value": "9876543210",

"use": "mobile",

"system": "phone"
},

{

"system": "email",

"value": "elon.musk@gmai.com"
}

]

}

And instead of the expected error I'm getting the successfully created patient.

What am i doing wrong? How are the FHIR validation profiles supposed to be used in InterSystems FHIR server?

9 Comments
讨论 (9)2
登录或注册以继续
InterSystems 官方
· 二月 28, 2023

InterSystems announces availability of InterSystems IRIS, IRIS for Health, & HealthShare Health Connect 2021.1.3

InterSystems is pleased to announce that the extended maintenance release of InterSystems IRIS, InterSystems IRIS for Health, and HealthShare Health Connect 2021.1.3 is now available. This release provides a few selected features and bug fixes for the previous 2021.1.x releases.

You can find additional information about what has changed on these pages:

Please share your feedback through the Developer Community so we can build a better product together.

 

How to get the software

The software is available as both classic installation packages and container images.  For the complete list of available installers and container images, please refer to the Supported Platforms webpage.

Full installation packages for each product are available from the WRC's Software Distribution pageContainer images  are available from the InterSystems Container Registry.

There are no Community Edition kits or containers available for this release.

The number of all kits & containers in this release is 2021.1.3.389.0.

2 Comments
讨论 (2)2
登录或注册以继续