#Code Snippet

6 Followers · 303 Posts

Code snippet is a programming term for a small region of re-usable source code, machine code, or text.

Article Jose Ruperez · Oct 12, 2016 1m read

With a routine like this one, you can quickly calculate how many lines of code you are working with. And it is not only for routines, it works for classes because remember that classes generate routines !

Here you have the routine source code:

LinesOfCode ;
    new SQLCODE,tRoutine
    set tTotalLOC = 0
    &sql(DECLARE ROUTINES CURSOR FOR
     SELECT NAME 
FROM %Library.RoutineIndex 
WHERE TYPE = 'MAC'
ORDER BY NAME)
    &sql(OPEN ROUTINES)
    &sql(FETCH ROUTINES INTO :tRoutine)
    while (SQLCODE=0)
    {
        write !,$j($i(tCount),5),": ",tRoutine
        set tLOC = $get(^rMAC(tRoutine,0,0))
        write "("_tLOC_")"
        set tTotalLOC = tTotalLOC + tLOC
        &sql(FETCH ROUTINES INTO :tRoutine)
    }
    &sql(CLOSE ROUTINES)
    write !!,"Total lines of code = "_tTotalLOC
4
0 928
Article Ben Spead · Aug 25, 2016 4m read

Background

Caché 2016.1 introduced some very powerful JSON features.  Unfortunately, the syntax used in the 2016.1 release is going to be changed in the 2016.2 release to bring it closer to Caché ObjectScript syntax.  This will mean that code that works in 2016.1 may not be forwards compatible.   See this announcement and  for more details about the changes.

11
0 2170
Article Sylvain Guilbaud · Oct 4, 2016 6m read

This sample class will add parameter DSINTERVAL to each class containing the parameter DSTIME

To execute it from a Terminal :


SAMPLES>d ##class(adm.param).add(,,1)
[SAMPLES] parameter DSINTERVAL=5 added to class DeepSee.Study.CityRainfall (via adm.param)
[SAMPLES] parameter DSINTERVAL=5 added to class HoleFoods.Transaction (via adm.param)
[SAMPLES] parameter DSINTERVAL=5 added to class News.DeepSee.NewsArticle (via adm.param)
DSINTERVAL parameter was added to 3 classes

Class adm.param [ Abstract ]
{

/// this class will add DSINTERVAL parameter to each class containing DSTIME
/// in order to synchronize a cube that is based on a source table on a mirror system
/// see: http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=D2IMP_ch_current#D2IMP_current_dstime_enabling
ClassMethod add(name As %String = "DSINTERVAL", value As %String = "5", verbose As %Boolean = 0) As %Status
{
    set sc = $$$OK
    try {
        set statement = ##class(%SQL.Statement).%New()
        // %Dictionary classes are useful to select classes based on their content
        // here we use %Dictionary.ParameterDefinition class which contains all the parameters defined in all classes
        // then we will open the parent class to add the missing parameter
        set query="SELECT a.parent "
                 _"FROM %Dictionary.ParameterDefinition a "
                 _"WHERE a.name='DSTIME' "
                 _"AND substr(a.parent,1,1)<>'%' "
                 _"AND NOT EXISTS (SELECT null "
                 _"FROM %Dictionary.ParameterDefinition b "
                 _"WHERE b.name='"_name_"' and b.parent=a.parent)"
        set sc = statement.%Prepare(query)
        quit:$$$ISERR(sc)
        set classes="",nb=0
        set rs = statement.%Execute()
        while (rs.%Next(.sc)) {
            quit:$$$ISERR(sc)
            if (rs.parent '="") {
                // opening of the parent class 
                set class = ##class(%Dictionary.ClassDefinition).%OpenId(rs.parent)
                if $IsObject(class) {
                    // creating the new parameter
                    set param=##class(%Dictionary.ParameterDefinition).%New()
                    set param.Name=name
                    set param.Default=value
                    // adding the parameter to the parent class
                    do class.Parameters.Insert(param)
                    set sc=class.%Save()
                    // if parent class is successfully saved set the following message
                    set:sc msg="["_$namespace_"] parameter "_name_"="_value_" added to class "_rs.parent_" (via "_..%ClassName(1)_")",severity=0
                    // if parent class is not saved set the following message
                    set:'sc msg="["_$namespace_"] ERROR while saving "_rs.parent_" after having added the parameter "_name_"="_value_" (via "_..%ClassName(1)_") :"_$system.Status.GetErrorText(sc),severity=1
                    // if verbose=1 write the message to the terminal
                    write:verbose msg,!
                    // write the message to cconsole.log
                    do ##class(%SYS.System).WriteToConsoleLog(msg,verbose,severity)
                    // add the class name to compile 
                    set classes(rs.parent)="",nb=$increment(nb)
                }
            }
        }
        set:nb=0 msg=name_" parameter was not added to any class"
        set:nb=1 msg=name_" parameter was added to "_nb_" class"
        set:nb>1 msg=name_" parameter was added to "_nb_" classes"
        write:verbose msg,!
        // compile all modified classes 
        if nb>0 { 
            set sc=$system.OBJ.Compile(.classes,"ck"_$select(verbose:"d",1:"-d"))
            set:sc msg="["_$namespace_"] modified "_$select(nb=1:"class",1:"classes")_" successfully compiled",severity=0
            set:'sc msg="["_$namespace_"] ERROR while compiling classes : "_$system.Status.GetErrorText(sc),severity=1
            do ##class(%SYS.System).WriteToConsoleLog(msg,verbose,severity)
            write:verbose msg,!
        }    
    }
    catch(ex) {
        set sc = ex.AsStatus()
        set msg="["_$namespace_"] error while executing "_..%ClassName(1)_":add("_name_","_value_") : "_ex.DisplayString(),severity=1
        write:verbose msg,!
        do ##class(%SYS.System).WriteToConsoleLog(msg,1,severity)
    }
    return sc
}

}
6
1 1175
Article John Hotalen · Sep 29, 2016 1m read

Checking if Directory or File Exists:

Outlined below is an example of how to check if a directory exists:

Set directoryName="c:\temp\nosuchdir"

/* Check for existence of a directory - Return Value:  0 - directory does not exist;  1 - directory does exist  */

Set directoryExists=##class(%File).DirectoryExists(directoryName)

If ('directoryExists)  // do the processing for when a directory does not exist


Outlined below is an example of how to check if a file exists:

Set fileName="a_test_filename.txt"

/* Check for existence of a file- Return Value:  0 - filename does not exist;  1 - filename does exist  */

Set fileExists=##class(%File).Exists(fileName)

If ('fileExists)  // do the processing for when a filename does not exist
1
0 3393
Article Eduard Lebedyuk · Sep 26, 2016 2m read

We're developing Ensemble PoC and one day our frontend developer (who doesn't have Ensemble production running) said that Populate just doesn't cut it and he needs to see the real data. He needed only one object, but the problem was - it's a big object. Still, I checked ids of everything related and wrote this command (parts omitted, but you get the idea):

w
$SYSTEM.OBJ.Export("project.model.contract.ContractD(6456).gbl,project.model.coA7F9.ObjectAddressD(6741).gbl,project.model.meter.DeviceD(23398).gbl,project.model.StatusHistoryD(7977).gbl,project.model.StatusHistoryD(48006).gbl,project.model.StatusHistoryD(83906).gbl","C:\Users\eduard\Desktop\export.xml")
1
0 820
Article Eduard Lebedyuk · Aug 9, 2016 2m read

Process-private Globals  can be used as a data global in storage definition. That way, each process can have its own objects for the class with ppg storage. For example lets define a pool, which can:

  • add elements to a pool (ignoring duplicates)
  • check if an element exists in the pool

Here's the class:

/// Stores unique identifiers
Class Utils.Pool Extends %Persistent
{

Property Value As %String;

Index IDKEY On Value [ IdKey, PrimaryKey, Unique ];

Method %OnNew(Value As %String = "") As %Status [ Private, ServerOnly = 1 ]
{
    Set ..Value = Value
    Quit $$$OK
}

ClassMethod Add(Value As %String = "")
{
    Quit:..%ExistsId(Value)
    Set Obj = ..%New(Value)
    Do Obj.%Save()
}

Storage Default
{
<Data name="PoolDefaultData">
<Value name="1">
<Value>%%CLASSNAME</Value>
</Value>
</Data>
<DataLocation>^||Utils.PoolD</DataLocation>
<DefaultData>PoolDefaultData</DefaultData>
<IdLocation>^||Utils.PoolD</IdLocation>
<IndexLocation>^||Utils.PoolI</IndexLocation>
<StreamLocation>^||Utils.PoolS</StreamLocation>
<Type>%Library.CacheStorage</Type>
}
}
2
0 1036
Article Daniel Kutac · Jul 18, 2016 3m read

Cache tricks

Several years ago, long before Developer Community Portal was launched, I published a series of Caché tricks at one of Czech web sites. In this article, I’m posting translated version of one of them.

Capturing output of someone else’s methods or routines

Suppose you, or someone else created a useful method or routine, that was producing some computation that you’d like to benefit from, but the routine was writing output to process principal device.

You would like to use the data, but you need it not written to a device, but assigned to a variable. And, for any reason, you can’t modify the code. What can you do?

4
0 2953
Article Timur Safin · Jul 18, 2016 15m read

This article created as side effect of preparations to the longer set of articles about simple, but still handy MapReduce implementation in Caché. I was looking for relatively easy way to pass arguments to (potentially) multiple targets via remote calling facilities. And after several attempts I have realized that we do have very powerful mechanism in the Caché ObjectScript which might be of particular help here – dynamic dispatch for methods and properties.

Since Caché 5.

7
0 1354
Question Juliana Schallert · Jul 20, 2016

Hi,

I am new to Cache and I am trying to convert a JSON string (msgdata) that contains a JSON payload to an object to be saved into a Driver. Entity table.  I am running into 2 issues and would appreciate any help:

1) It seems that when the 1st element of a list within the payload (Choices) is an empty string, after I call %ConvertJSONToObject, the obj.%data("payload").Choices contains just 1 empty element, removing the next 3 valid values (10,20,30). The same does not happen if I change the input to [10,20,"",30], in this case it works correctly.

3
0 1160
Question Rustam Ibragimov · Jul 12, 2016

Hello, everyone!

I opened one project and there I found such lines as 

$$Export^%occXMLExport(filename,"-d /diffexport",InternalName)

Do DecomposeStatus^%apiOBJ(sc,,"d")

The problem is I can't go to their definition and find them in documentation. It says that they don't exist on the server. However, the project works and these routines execute. 

How can I import them into my project? 

3
0 858
Question Timothy Leavitt · Jul 8, 2016

I've been trying to write a method to compare two local variables, which may be arrays, for "equality" - that is, to see if they have all the same subscripts (if they're arrays) and values. This is the best I've come up with so far - are there any better/simpler approaches out there?

/// Returns true if arrays <var>first</var> and <var>second</var> have all the same subscripts and all
/// the same values at those subscripts. <br />
/// If <var>first</var> and <var>second</var> both happen to be either undefined or unsubscripted variables,
/// returns true if they're both undefined or have the same value.<br />
/// <var>pMessage</var> has details of the first difference found, if any.
Method CompareArrays(ByRef first, ByRef second, Output pMessage) As %Boolean [ ProcedureBlock = 0 ]
{
    New tEqual,tRef1,tRef2,tRef1Data,tRef1Value,tRef2Data,tRef2Value
    
    Set pMessage = ""
    Set tEqual = 1
    Set tRef1 = "first"
    Set tRef2 = "second"
    While (tRef1 '= "") || (tRef2 '= "") {
        #; See if the subscript is the same for both arrays.
        #; If not, one of them has a subscript the other doesn't, and they're not equal.
        If ($Piece(tRef1,"first",2) '= $Piece(tRef2,"second",2)) {
            Set tEqual = 0
            Set pMessage = "Different subscripts encountered by $Query: "_
                $Case(tRef1,"":"<end>",:tRef1)_"; "_$Case(tRef2,"":"<end>",:tRef2)
            Quit
        }
        
        Kill tRef1Value,tRef2Value
        Set tRef1Data = $Data(@tRef1,tRef1Value)
        Set tRef2Data = $Data(@tRef2,tRef2Value)
        #; See if the $Data values are the same for the two.
        #; This is really only useful to detect if one of the arrays is undefined on the first pass;
        #; $Query only returns subscripts with data.
        #; This will catch only one being defined, or one being an array and
        #; ​the other being a regular variable.
        If (tRef1Data '= tRef2Data) {
            Set tEqual = 0
            Set pMessage = "$Data("_tRef1_")="_tRef1Data_"; $Data("_tRef2_")="_tRef2Data
            Quit
        } ElseIf (tRef1Data#2) && (tRef2Data#2) {
            #; See if the value at the subscript is the same for both arrays.
            #; If not, they're not equal.
            If (tRef1Value '= tRef2Value) {
                Set tEqual = 0
                Set pMessage = tRef1_"="_@tRef1_"; "_tRef2_"="_@tRef2
                Quit
            }
        }
        
        Set tRef1 = $Query(@tRef1)
        Set tRef2 = $Query(@tRef2)
    }
    Quit tEqual
}
6
0 1666
Article Eduard Lebedyuk · Jun 28, 2016 1m read

Here's  a code snippet to calculate the length of a class or a package in lines of code:

ClassMethod ProjectLength(Mask As %String = "%Package%")
{
    Set count = 0
    Set sql =     "SELECT Name "_
                "FROM %Dictionary.ClassDefinition "_
                "WHERE NOT Name %STARTSWITH '%sqlcq' AND Name LIKE ? AND GeneratedBy IS NULL"
    Set rset = ##class(%SQL.Statement).%ExecDirect(, sql, Mask)
 
    While rset.%Next() {
        Set class = rset.%Get("Name")
        Do ##class(%Compiler.UDL.TextServices).GetTextAsArray(, class, .raw)
        Set lines = $ORDER(raw($CHAR(0)), -1)
        Write class, $JUSTIFY("", 40-$LENGTH(class)), $JUSTIFY(lines, 7), !
        Set count = count + lines
    }
    Write "Total ", $JUSTIFY("",34), $JUSTIFY(count, 7)
}
3
0 602
Article Evgeny Shvarov · Mar 9, 2016 2m read

Hi!

Here is small "How to" again.

Suppose you need to share something with source code. How can we manage it on DC?

Sharing code snippets

1. Add normal post (not Code Package).

2. Paste your code in the post and format it with highlighting as it is described here.

3. If you see that your COS code is highlighted wrong it means that autodetect missed with language. Open the post's HTML ("disable rich-text" button below the Editor) and put class=COS parameter into the code tag.

Example:

#dim test as %Library.Integer 
SET test = 123.099 
set ^global = %request.Content 
Write "Current date """, $ztimestamp, """, result: ", test + ^global = 125.099 
do ##class(Cinema.Utils).AddShow("test") // class method call do ##super() 
; another one-line comment 
d:(^global = 2) ..thisClassMethod(1, 2, "test") 
/* * Sub-languages support: */ 
 &sql( SELECT * FROM Cinema.Film WHERE Length > 2 )
 &js<for (var i = 0; i < String("test").split("").length); ++i) { 
   console.log(i); 
   }> 
 &html<<!DOCTYPE html> 
<html>
 <head>
 <meta name="test"/> 
</head> 
<body>
Test
</body> 
</html>>
 quit $$$OK

2
0 575
Article Evgeny Shvarov · Apr 16, 2016 1m read

Hi!

Want to share with you code snippet of try catch block I usually use in methods which should return %Status. 


{ 
 try {
  	$$$TOE(sc,StatusMethod())
 }
 catch e {
 	set sc=e.AsStatus()
 	do e.Log()
 }

Quit sc 
}

Here $$$TOE is a short form of $$$TROWONERROR macro.

Inside macro StatusMethod is any method you call which will return %Status value. This value will be placed into sc variable.

In case of sc contains error execution will be routed to try catch block. You can wrap any Status methods calls in your code if you need to catch the errors coming from them.

21
2 3620
Question Francis Galiegue · Apr 25, 2016

Hello,

Here's the code:


Method isTestClass(className As %String) As %Boolean
{
if (className = ..#UTCLASS) {
return 1
}
#dim c as %Dictionary.ClassDefinition
#dim status as %Status
	
set c = ##class(%Dictionary.ClassDefinition).%OpenId(className,,.status)

if ($$$ISERR(status)) {
	throw ##class(%Exception.StatusException).CreateFromStatus(status)
}

if ('c.SuperIsDefined()) {
	return 0
}

#dim children
#dim len as %Integer
#dim i as %Integer

set children = $listFromString(c.Super, ",")
set len = $listLength(children)

for i = 1:1:len {
	if ..isTestClass($listGet(children, i)) {
		return 1
	}
}

return 0
6
0 608
Question Jose Antonio Cañizares · Apr 1, 2016

Hi all,

I've been looking for a way to extract the sorting  from the  ^CacheTemp.zenData global that contain the tablePane snapshot data in order to use it on a report following the current UI sorting criteria.

I could see that if the column is sorted by one column, new entries with this structure are created:

^CacheTemp.zenData(<sessionId>,<snapShotId>,<tablePaneId>,"index",<columnId>,<value>,<dataId>)=""

These are created the first time that the sort criteria is applied (asc) and has the same amount of entries as the data being displayed.

6
0 633
Question Eduard Lebedyuk · Mar 28, 2016

Hello.

For debugging purposes I  sometimes need to display stack information to the current device or save it (to a global for example).

There is this snippet offered in documentation:

ClassMethod StackToDisplay()
{
    For loop = 0:1:$Stack(-1) {
        Write !, "Context level:", loop, ?25, "Context type: ", $Stack(loop)
        Write !, ?5, "Current place: ", $Stack(loop, "PLACE")
        Write !, ?5, "Current source: ", $Stack(loop, "MCODE")
        Write !
    }
}
11
0 1809
Question Josh Barney · Mar 24, 2016

I believe the I have followed the instructions to attach a document to the body of a post request but nothing is being sent out in the files{} port of the request.  I can either get the stream in "data", not visible at all, or visible but no form data. Any help would be appreciated, below is what I have:

ClassMethod SendFax(phone As %Stringcoverpath As %Stringdocpath As %StringAs %String
{
     Set req ##class(%Net.HttpRequest).%New()
    //test server
    Set req.Server "httpbin.org"
    Set req.SSLConfiguration "CardChoice"
    
    Do req.InsertFormData("Username",##class(HData.

3
0 2565
Article Timothy Leavitt · Mar 9, 2016 3m read

There have been a few use cases recently within InterSystems where we've needed to connect to Caché-based web services from PHP. The first of these was actually the Developer Community itself, which uses web services as part of Single Sign-On with other InterSystems sites/applications. The following example demonstrates how to connect to a Caché-based web service (particularly, the web service in the SAMPLES namespace) from PHP, using password authentication.

0
0 2828
Article Tom Fitzgibbon · Mar 4, 2016 2m read

RESTful API Call From Cache to Particle.io Electron

Tom Fitzgibbon | Multidata | 212-967-6700 x537 | tom@mul.com

Summary: Simple Blink Tutorial for Particle.io Electron Device from Cache

Electron device is a tiny ARM processor ($40-$60) that connects to Particle’s world wide leased 2G/3G network (about $3/mo) and runs off an included LiPo battery. Using Cache’s %Net.HttpRequest you can send/receive data, control hardware and read sensors.

Step by Step (about 1 hour)

1) Get the Electron from store.particle.io.

2) Set up the Electron from setup.particle.io.

0
0 1322
Article Sylvain Guilbaud · Feb 24, 2016 1m read

C:\data\backup.bat :

C:\InterSystems\Ensemble\bin\cache -s"C:\InterSystems\Ensemble\Mgr" -U%%SYS ##Class(Backup.General).ExternalFreeze() <C:\data\login.scr 

echo %ERRORLEVEL%

rem note that we need to check errorlevel from highest to lowest here.

0
0 1942
Article Alberto Fuentes · Feb 19, 2016 3m read

The attached file contains an example of code generation using ObjectGenerators which builds a very simple homemade RuleEngine. 

Code generation is an excellent way of increasing performance moving run-time calculations to compile-time.

We could generate code creating routines or implemeting methods using ObjectGenerators. In this example we are using ObjectGenerators.

Update: Rule Engine is now on GitHub https://github.com/intersystems-ib/cache-iat-ruleengine

0
0 993
Question Scott Beeson · Feb 16, 2016

Here is my original query:

SELECT EventType, InitiatedAt, COUNT(*) as cnt
FROM HS_IHE_ATNA_Repository.Aggregation
WHERE EventType = 'LOGIN'
AND LocalDateTime > '2016-02-16 11:00:00'
GROUP BY EventType, InitiatedAt

This gives me data like this:

LOGIN %SYSTEM 69918
LOGIN OTHER 39


However, I need to get the data back as two columns with all but the last concatenated and delimited, more like this:

LOGIN;%SYSTEM 69918
LOGIN;OTHER 39

I tried this:

SELECT EventType + ';' + InitiatedAt as k, COUNT(*) as cnt
FROM HS_IHE_ATNA_Repository.Aggregation
WHERE EventType = 'LOGIN'
AND LocalDateTime > '2016-02-16 11:00:00'
GROUP BY EventType, InitiatedAt
3
0 7205
Question Scott Beeson · Feb 11, 2016

I'm writing some custom functions for use in a routing rule.  I have a few that are working, but right now I'm trying to use one that has no parameters.  Typically this would be a sub instead of a function, but I'm not familiar enough with Cache to know what I need to do here. 

Here is the code:

Class Custom.MHC.Common.CustomFunctions Extends Ens.Rule.
6
0 593
Question Scott Beeson · Feb 8, 2016

Given the following code:

start
    set tstVar = "Green"
    do TestIt()
 
TestIt() {
    write tstVar
}

I get <UNDEFINED>start+4^DeploymentTool *tstVar
 

I also tried setting the variable outside the start method but that doesn't work either.  I realize I could pass tstVar to the TestIt() routine but I'm trying to create a couple variables that will be reused repeatedly so that doesn't really work.

11
0 749