Vitaliy Serdtsev · Mar 20, 2019 go to post

For example, you can export them all to a single file:

SAMPLES>d $system.OBJ.ExportPattern("*.dfi","c:\exportAllDFI.xml",,,"UTF8")

You can get the list as follows (doc):
select Name from %Library.RoutineMgr_StudioOpenDialog('*.dfi')

Vitaliy Serdtsev · Mar 20, 2019 go to post

First, I would not use the input values directly in the query text, but would use Input Host Variables
Second, if it is necessary, it is more elegant to use the following syntax:

Set stmt ##CLASS(%SQL.Statement).%New()
Set query $$$FormatText("Select Val1, Val2 FROM Table WHERE Val1=%1",$$$quote("SomeCondition"))

Ideally these should be :
&SQL(SELECT Val1, Val2
INTO :val1, :val2
FROM Table
WHERE Val1='SomeCondition')

This is and now works:

&SQL(SELECT Val1Val2
               INTO :val1:val2
               FROM "Table"
               WHERE "Val1"='SomeCondition')
Vitaliy Serdtsev · Mar 14, 2019 go to post

Let's try to guess the return value of method t1().
Is that supposed to be hard? I immediately visually determined the result 20.

To be honest I don't really understand the point which the author wanted to convey. Maybe it's the lack of English.

In this case, the t3 method code is equivalent to the following code:
ClassMethod t3(ByRef pAByRef pB) [ ProcedureBlock = 1 ]
{
  set pA=4, pB=5
  set x=$increment(pA)*$increment(pB)
}
PS: by the way, absolutely nothing will change fundamentally if you replace "return" with "quit" (and "ByRef" with "Output").

Vitaliy Serdtsev · Mar 12, 2019 go to post

Hi Ponnumani.

I would like to make a number of clarifications:

  • VALUELIST "A A- B B- O" -> VALUELIST " A A- B B- O"
  • it is necessary to consider the order of the fields in the global on the basis of Storage. For example, I have following Storage:
    <Data name="samplexlsconversionDefaultData">
    <Value name="1">
    <Value>%%CLASSNAME</Value>
    </Value>
    <Value name="2">
    <Value>name</Value>
    </Value>
    <Value name="3">
    <Value>DOB</Value>
    </Value>
    <Value name="4">
    <Value>address</Value>
    </Value>
    <Value name="5">
    <Value>PhoneNumber</Value>
    </Value>
    <Value name="6">
    <Value>BloodGroup</Value>
    </Value>
    </Data>
  • need to add check for the presence of double quotes in strings, e.g. bla"bla
  • the date format for CSV should not be in the internal Caché format, because the date 37893 to users of other system/DBMS nothing says unlike e.g. 1944-09-30.

I still prefer to use built-in tools when they are there, rather than reinventing the wheel.

Class User.samplexlsconversion Extends (%Persistent%Populate)
{

Property name As %String;

Property DOB As %Date;

Property address As %String;

Property PhoneNumber As %Numeric;

Property BloodGroup As %String(VALUELIST " A A- B B- O");

ClassMethod TestExport2CSV()
{
  
  ..%KillExtent()
  ..Populate(1000)
  
  tmp=..%OpenId(1)
  tmp.name=tmp.name_$c(34)
  tmp.%Save()
  
  tmp=..%OpenId(2)
  tmp.name=$c(34)_tmp.name_$c(34)
  tmp.%Save()

  mgr ##class(%SQL.Export.Mgr).%New()
  mgr.FileName "c:\Temp\test.csv"
  mgr.ClassName = ..%ClassName(1)
  mgr.TableName $$$CLASSsqltablename($$$gWRK,mgr.ClassName)
  mgr.Delimiter ","
  mgr.StringQuote $c(34)
  mgr.DateFormat = 3
  mgr.TimeFormat = 1
  mgr.TimeStampFormat = 1
  mgr.NoCheck $$$YES
  s mgr.HasHeaders $$$YES
  
  s cols="Name:S;Address:S;PhoneNumber:N;BloodGroup:S;DOB:D"
  i=1:1:$l(cols,";"{
    c=$p(cols,";",i)
    mgr.ColumnNames.Insert($p(c,":",1))
    mgr.ColumnTypes.Insert($p(c,":",2))
  }
  
  mgr.Export()
}
}
Vitaliy Serdtsev · Mar 11, 2019 go to post

Hi Robert.

Exactly.

Programmatically Managing Roles:

This command can only be invoked either from a routine that is part of the CACHESYS database or if the current privileges held include Write permission for the CACHESYS database (%DB_CACHESYS:W).

Note that setting $ROLES only alters a process’s added roles, not its login roles.

There is a third way, but I specifically did not publish it.

Vitaliy Serdtsev · Mar 11, 2019 go to post

Below are two ways without additional permissions on %DB_CACHESYS:

  #include %systemInclude
  n
  try{

    sslName="Test"

    "1) GetSSLConfigList^%SYS.SECURITY1(.SSLConfigs)",!!
    w $$Test1(sslName)
    
    !!,"2) $$ListSSLConfigs^%SYS.SECURITY(Client/Server)",!!
    w $$Test2(sslName)
    
  }catch(ex){
    "Error "ex.DisplayString(),!
  }

Test1(ssl) {
  GetSSLConfigList^%SYS.SECURITY1(.SSLConfigs)
  i=1:1:SSLConfigs return:SSLConfigs(i)=ssl $$$YES
  q $$$NO
}

Test2(ssl) {
  ''$lf($lfs($$ListSSLConfigs^%SYS.SECURITY("Client")_","_
               $$ListSSLConfigs^%SYS.SECURITY("Server"))
          ,ssl)
}
Vitaliy Serdtsev · Mar 6, 2019 go to post

And if so?

CREATE TABLE test (
  identifier   VARCHAR(200NOT NULL,
  value        INTEGER COMPUTEONCHANGE("%%UPDATE"COMPUTECODE {&sql(select max(value)+1 into :{*} from test where identifier=:{identifier})},
  PRIMARY KEY (identifier)
)
Vitaliy Serdtsev · Feb 28, 2019 go to post

Working example:

Class dc.test Abstract ]
{

/// d ##class(dc.test).Test1()
ClassMethod Test1() [ ProcedureBlock = 0 ]
{
  new active,reactive,info,i
  
  kill info

  set active = 1
  set reactive = 2

  for i="active","reactive" {
    set info(i)= @i
  }

  zw info
}

/// d ##class(dc.test).Test2()
ClassMethod Test2() [ PublicList = (active, reactive) ]
{
  new activereactive
  kill info

  set active = 1
  set reactive = 2

  for i="active","reactive" {
    set info(i)= @i
  }

  zw info
}

}
Vitaliy Serdtsev · Feb 22, 2019 go to post

What will the following code output?

resptext="{""access_token"":""4SDFDSFDSF-aSDASDASD"",""expires_in"":""3300"",""refresh_token"":"""",""scope"":""sms_send"",""token_type"":""Bearer""}"

sc ##class(%ZEN.Auxiliary.jsonProvider).%ParseJSON(resptext,,.pObject,1)
i $$$ISOK(sc{
  pObject,!!,
    pObject."access_token",!,
    pObject."expires_in",!
  arr arr="" pObject.%CopyToArray(.arrzw arr
}else{
  d $system.OBJ.DisplayError(sc)
}

My result (2018.1):

USER>^test
1@%ZEN.proxyObject
 
4SDFDSFDSF-aSDASDASD
3300
arr("access_token")="4SDFDSFDSF-aSDASDASD"
arr("expires_in")=3300
arr("refresh_token")=""
arr("scope")="sms_send"
arr("token_type")="Bearer"
Vitaliy Serdtsev · Feb 22, 2019 go to post

What will the following code output?

USER>arr pObject.%CopyToArray(.arrzw arr

PS: "in" ≠ "expires_in"

Vitaliy Serdtsev · Feb 18, 2019 go to post

Hi Adrian.

Made a small example:

#dim rs As %ResultSet
   
pid=4652
   
rs=##class(%ResultSet).%New("%SYS.ProcessQuery:VariableByPid")
   
filter="","a*" {
 !,"Filter = ",$$$quote(filter),!
 rs.Execute(pid,,,,filter)
 while rs.Next() {
   "Name = ",rs.Get("Name"),", Value = ",rs.Get("Value"),!
 }
}

Result:

USER:4652>a="11",b="22",a1="33" w $job
4652

USER:1392>w $job,! ^dc
1392
 
Filter = ""
Name = a, Value = 11
Name = a1, Value = 33
Name = b, Value = 22
 
Filter = "a*"
Name = a, Value = 11
Name = a1, Value = 33
Vitaliy Serdtsev · Feb 16, 2019 go to post

The presence of a potential opportunity to read the documentation via "Class Reference". For macros from *.inc this is not possible.

Vitaliy Serdtsev · Feb 14, 2019 go to post

Still another option:

Class dc.test Extends %Persistent
{

Property JSONData As list Of %String SqlListType = SUBNODE ];

ClassMethod Test()
{
  ..%KillExtent()
  
  l=$lb("apple","pear","plum"),$lb({"Name":"Kyle"}.%ToJSON(),{"Name":"Evgeny"}.%ToJSON()) {
    t=..%New()
    t.JSONData.InsertList(l)
    t.%Save()
  }

  zw @$system.Dictionary.comMemberKeyGet($this,$$$cCLASSstorage,$$$nameDefaultStorageNameGet,$$$cSDEFdatalocation)
  
  rs=##class(%SQL.Statement).%ExecDirect(,"select distinct json_arrayagg(JSONData %foreach(test)) from dc.test_JSONData")
  while rs.%Next() {
    jsonStr=rs.%GetData(1),
      json=[].%FromJSON(jsonStr)

    !,jsonStr,", %Size()=",json.%Size(),!
  }
}

}

Result:

USER>##class(dc.test).Test()
^dc.testD=2
^dc.testD(1)=$lb("")
^dc.testD(1,"JSONData")=3
^dc.testD(1,"JSONData",1)="apple"
^dc.testD(1,"JSONData",2)="pear"
^dc.testD(1,"JSONData",3)="plum"
^dc.testD(2)=$lb("")
^dc.testD(2,"JSONData")=2
^dc.testD(2,"JSONData",1)="{""Name"":""Kyle""}"
^dc.testD(2,"JSONData",2)="{""Name"":""Evgeny""}"
 
["apple","pear","plum"], %Size()=3
 
[{"Name":"Kyle"},{"Name":"Evgeny"}], %Size()=2

Doc:

Vitaliy Serdtsev · Jan 16, 2019 go to post

if I call giveMeAFalseMe from Cache when it's returning "true" or "false", Cache will translate "true" into a truthy %Boolean return value, right?

No, it does zenBool, which is on the client side.

The important thing is that #server()# always returns a string, for example:

<script language="cache" method="giveMeAFalse" arguments="" procedureblock='1' returntype="%Integer">return 4</script>

var bool #server(..giveMeAFalse())#; console.log("bool = " bool); console.log("typeof bool = "typeof bool);

Result: bool = 4 typeof bool = string

PS: you can further explore the sources of the #server()# -> cspHttpServerMethod() -> cspProcessResponse(), which are in the file cspxmlhttp.js.

Vitaliy Serdtsev · Jan 15, 2019 go to post

See zenConvertType() [///Converts a typed value returned from the server to an appropriate JS type] from zenutils.js.

Try this:

<script src="zenutils.js"></script>

<script language="javascript">
function isItActuallyFalse() {

var bool zenConvertType('BOOLEAN',#server(..giveMeAFalse())#);

...
}

</script>

<script language="cache" method="giveMeAFalse" arguments="" returntype="%Boolean" procedureblock='1'>return $$$NO</script>

or

var bool zenBool(#server(..giveMeAFalse())#);
...
<script language="cache" method="giveMeAFalse" arguments="" returntype="%Boolean" procedureblock='1'>return "false"</script>
Vitaliy Serdtsev · Dec 31, 2018 go to post

tags=$lb("a","b","c"),
  str="c,a1,d,b,f"
   
l=$lfs(str),ptr=0
while $listnext(tags,ptr,tag{
  w:$lf(l,tagtag,!
}
Result
b
c

Vitaliy Serdtsev · Nov 2, 2018 go to post

No.
If you beware to use %occLibrary, you may look into side %Regex.Matcher

Here is another documented solution:

#include %systemInclude
  n
  try{

    #define TAB $c(9)
    
    s csv="""ABC,"_$c(10)_" Company,"",""123 Main St, Ste 102"",""Anytown, DC"",10001,234-567-8901,""Anytown"_$$$TAB_"DC"""

    ##class(%DeepSee.TermList).%ParseCSVRecord(csv,.arr)

    csv,!!,$$WriteCSVRecord(.arr,$$$TAB)

  }catch(ex){
    "Error "ex.DisplayString(),!
  }


WriteCSVRecord(&pRecord, pDelim=",", pEncode=$$$YES{
  // made on the basis of the method %WriteCSVRecord
  Set ""
  Set $O(pRecord(""))
  While (k'=""{
    Set tValue $G(pRecord(k))
    Set:$G(pEncodetValue $ZCVT(tValue,"O","UTF8") 

    Set $S((tValue["""")||(tValue[",")||(tValue[pDelim):$$$quote(tValue),1:tValue)
    Set $O(pRecord(k))
    Set:k'="" pDelim
  }
  Quit r
}

Result:

USER>^dc
"ABC,
      Company,","123 Main St, Ste 102","Anytown, DC",10001,234-567-8901,"Anytown        DC"
 
"ABC,
      Company," "123 Main St, Ste 102"  "Anytown, DC"   10001   234-567-8901    "Anytown        DC"
Vitaliy Serdtsev · Nov 1, 2018 go to post

#include %systemInclude

    csv="ABC Company,""123 Main St, Ste 102"",""Anytown, DC"",10001,234-567-8901"     list=$$CSVtoList^%occLibrary(csv)

    i=1:1:$ll(lists:$li(list,i)["," $li(list,i)=$$$quote($li(list,i))              csv,!,$lts(list,$c(9))

Result:
USER>^test
ABC Company,"123 Main St, Ste 102","Anytown, DC",10001,234-567-8901
ABC Company     "123 Main St, Ste 102"  "Anytown, DC"   10001   234-567-8901