See Sample.Person in "SAMPLES".

/// Person's age.<br>
/// This is a calculated field whose value is derived from <property>DOB</property>.
Property Age As %Integer CalculatedSqlComputeCode = { Set {Age}=##class(Sample.Person).CurrentAge({DOB})}, SqlComputedSqlComputeOnChange = DOB ];

/// This class method calculates a current age given a date of birth <var>date</var>.
ClassMethod CurrentAge(date As %Date ""As %Integer CodeMode = expression ]
{
$Select(date="":"",1:($ZD($H,8)-$ZD(date,8)\10000))
}
  1. Asynchronous uploading only one file
    Class upload.fileOne Extends %ZEN.Component.page
    {
    
    Parameter DOMAIN = "DC";
    
    XData Style
    {
      <style type="text/css">
      </style>
    }
    
    XData Contents [ XMLNamespace "http://www.intersystems.com/zen" ]
    {
    <page xmlns="http://www.intersystems.com/zen" title="Upload file using XMLHttpRequest" labelPosition="left">
      <hgroup cellVAlign="bottom">
        <fileUpload label="Select the file" id="fileToUpload" onchange="zenPage.fileSelected()"/>
        <button caption="Upload" onclick="zenPage.uploadFile();"/>
      </hgroup>
      <label id="fileType" label="Type: "/>
      <label id="fileName" label="Name: "/>
      <label id="fileSize" label="Size: "/>
      <html>
        <div id="progressNumber">%</div>
        <progress id="progressValue" value="0" max="100.0"></progress>
      </html>
    </page>
    }
    
    ClientMethod uploadFile() [ Language = javascript ]
    {
      var fd new FormData();
      fd.append('fUpload', zen('fileToUpload').findElement('control').files[0]);
      var xhr new XMLHttpRequest();
      xhr.upload.addEventListener('progress'this.uploadProgress, false);
      xhr.addEventListener('load'this.uploadComplete, false);
      xhr.addEventListener('error'this.uploadFailed, false);
      xhr.addEventListener('abort'this.uploadCanceled, false);
      xhr.open('POST''upload.fileOne.cls');
      xhr.send(fd);
    }
    
    ClientMethod uploadProgress(evt) [ Language = javascript ]
    {
      if (evt.lengthComputable) {
        var percentComplete Math.round(evt.loaded * 100 / evt.total);
    
        document.getElementById('progressNumber').innerHTML percentComplete.toString() '%';
        document.getElementById('progressValue').value percentComplete;
      }
      else {
        document.getElementById('progressNumber').innerHTML $$$Text('Cannot compute');
      }
    }
    
    ClientMethod uploadComplete(evt) [ Language = javascript ]
    {
      zenAlert($$$Text('The upload is complete.'));
    }
    
    ClientMethod uploadFailed(evt) [ Language = javascript ]
    {
      zenAlert($$$Text('An error occurred when trying to upload the file.'));
    }
    
    ClientMethod uploadCanceled(evt) [ Language = javascript ]
    {
      zenAlert($$$Text('The upload was canceled by the user or the browser dropped the connection.'));
    }
    
    ClientMethod fileSelected() [ Language = javascript ]
    {
      var file zen('fileToUpload').findElement('control').files[0];
      if (file) {
    
        var fileSize = 0;
        if (file.size > 1024 * 1024)
           fileSize (Math.round(file.size * 100 / (1024 * 1024)) / 100).toString() $$$Text('MB');
        else
           fileSize (Math.round(file.size * 100 / 1024/ 100).toString() $$$Text('KB');
    
        zenSetProp('fileType','value',file.type);
        zenSetProp('fileName','value',file.name);
        zenSetProp('fileSize','value',fileSize);
         
      }
    }
    
    ClassMethod %OnPreHTTP() As %Boolean ServerOnly = 1 ]
    {
      #dim %request As %CSP.Request
      #dim stream As %CSP.BinaryStream=%request.GetMimeData("fUpload")
      if $IsObject(stream{
        
        #; here you do with the received file useful work
        
        /*
        set ^tmp("filename")=stream.FileName
        set ^tmp("filesize")=stream.Size
        */
        
        quit $$$NO
      }
      quit $$$YES
    }
    
    }
  2. Asynchronous uploading immediately of several files
    Class upload.fileMany Extends %ZEN.Component.page
    {
    
    Parameter DOMAIN = "DC";
    
    XData Style
    {
    <style type="text/css">
      .ok {
        color:green;
      }
    
      #dropZone {
        width: 360px;
        height: 125px;
        borderdashed 2px #ccc;
        background-color: #fefefe;
        color: #ccc;
        text-aligncenter;
        padding: 125px 0 0 0;
      }
    
    </style>
    }
    
    XData Contents [ XMLNamespace "http://www.intersystems.com/zen" ]
    {
    <page xmlns="http://www.intersystems.com/zen" title="Upload immediately multiple files using XMLHttpRequest">
      <html id="dropZone">Drag files here or click below</html>
      <hgroup cellVAlign="bottom">
        <html id="selectFiles" label="Choose the files">
          <input type="file" class="fileUpload" id="fileToUpload" onchange="zenPage.fileSelected(document.getElementById('fileToUpload').files)" multiple="multiple" />
        </html>
        <button caption="Clear" title="Clear the queue" onclick="zenPage.clearList();"/>
        <spacer width="10"/>
        <button caption="Upload" title="Upload files to the server" onclick="zenPage.uploadFile();"/>
      </hgroup>
      <fieldSet legend="Files waiting to upload">
        <html id="holder"/>
      </fieldSet>
    </page>
    }
    
    ClientMethod clearList() [ Language = javascript ]
    {
      fileQueue=[];
      zen('holder').getEnclosingDiv().innerHTML='';
      zen('selectFiles').refreshContents();
    }
    
    ClientMethod fileSelected(files) [ Language = javascript ]
    {
      var holder zen('holder').getEnclosingDiv();
      for (var = 0; i files.length; i++) {
      
        var file files[i];
    
        var fileSize = 0;
        if (file.size > 1024 * 1024)
          fileSize (Math.round(file.size * 100 / (1024 * 1024)) / 100).toString() $$$Text('MB');
        else
          fileSize (Math.round(file.size * 100 / 1024/ 100).toString() $$$Text('KB');
      
        var divInfo document.createElement('div');
        divInfo.innerHTML=file.name+' ('+file.type+') - '+fileSize;
        holder.appendChild(divInfo);
    
        var divProgN document.createElement('div');
        divProgN.id='progressNumber'+i;
        divProgN.innerHTML='%';
        holder.appendChild(divProgN);
    
        var prog document.createElement('progress');
        prog.id='progressValue'+i;
        prog.max='100.0';
        prog.value='0';
        holder.appendChild(prog);
    
        fileQueue.push({i:i,file:file});
      }
    }
    
    ClientMethod uploadFile() [ Language = javascript ]
    {
      while (fileQueue.length > 0) {
        var item=fileQueue.pop();
        uploadFile(item.file,item.i);
      }
    }
    
    ClientMethod onloadHandler() [ Language = javascript ]
    {
      if (typeof FileReader == "undefined") zenAlert($$$Text('Sorry, your browser does not support File API, so this demo will not work correctly'));
      fileQueue new Array();
    
      uploadFile function (file, i) {
        var xhr new XMLHttpRequest(), upload xhr.upload, fd new FormData();
        
        fd.append('fUpload', file);
    
        upload.addEventListener('progress',
        function (evt) {
          if (evt.lengthComputable) {
            var percentComplete Math.round(evt.loaded * 100 / evt.total);
    
            document.getElementById('progressNumber'+i).innerHTML percentComplete.toString() '%';
            document.getElementById('progressValue'+i).value percentComplete;
            
          }
          else {
            document.getElementById('progressNumber'+i).innerHTML $$$Text('Cannot compute');
          }
          
        }, false);
        upload.addEventListener('load'function (ev) {
          var c=document.getElementById('progressNumber'+i);
          c.className='ok';
          c.innerHTML='OK';
        }, false);
        upload.addEventListener('error'function (ev) {zenAlert($$$Text('An error occurred when trying to upload the file.'));}, false);
        upload.addEventListener('abort'function (ev) {zenAlert($$$Text('The upload was canceled by the user or the browser dropped the connection.'));}, false);
        xhr.open('POST','upload.fileMany.cls');
        xhr.setRequestHeader('Cache-Control''no-cache');
        xhr.setRequestHeader('X-Requested-With''XMLHttpRequest');
        xhr.send(fd);
      }
      
      dropZone=zen('dropZone').getEnclosingDiv();
      dropZone.addEventListener('dragenter',  function(ev){
        ev.stopPropagation();
        ev.preventDefault();
      }, false);
      dropZone.addEventListener('dragleave',  function(ev){
        ev.stopPropagation();
        ev.preventDefault();
        this.style['backgroundColor''#FEFEFE';
        this.style['borderColor''#CCC';
        this.style['color''#CCC';
      }, false);
      dropZone.addEventListener('dragover',  function(ev){
        ev.stopPropagation();
        ev.preventDefault();
        this.style['backgroundColor''#F0FCF0';
        this.style['borderColor''#3DD13F';
        this.style['color''#3DD13F';
      }, false);
      dropZone.addEventListener('drop',  function(ev){
      ev.stopPropagation();
      ev.preventDefault();
      this.style['backgroundColor''#FEFEFE';
      this.style['borderColor''#CCC';
      this.style['color''#CCC';
      zenPage.fileSelected(ev.dataTransfer.files);
      }, false);
    }
    
    ClassMethod %OnPreHTTP() As %Boolean ServerOnly = 1 ]
    {
      #dim %request As %CSP.Request
      #dim stream As %CSP.BinaryStream=%request.GetMimeData("fUpload")
      if $IsObject(stream{
        
        #; here you do with the received file useful work
        
        /*
        set ^tmp("filename")=stream.FileName
        set ^tmp("filesize")=stream.Size
        */
        
        quit $$$NO
      }
      quit $$$YES
    }
    
    }

Of course you can do the same on CSP.

See aside iFind.

I long ago did the tests, using Bible, at searching for of any substring.

  1. without an index
    select IdPara from BookPara where Para like '%огон%'
  2. with index
    select IdPara from BookPara where id %FIND search_index(ParaStemmedI,'*огон*',1)

The number of found rows Performance (sec.) Global references
The result:
without an index 287 0.518 151845
with index 287 0.009 1006

The difference is obvious.

  1. <html>
    <body>
    <script language="cache" runat="server">
     if %request.ContentType="multipart/form-data" {
      stream=%request.MimeData("oFile1",1)
      file=##class(%Stream.FileBinary).%New()
      file.Filename="c:\InterSystems\"_##class(%File).GetFilename(stream.FileName)
      file.CopyFromAndSave(stream)
     }
    </script>
    <br>
    <FORM NAME="oForm" ENCTYPE="multipart/form-data" METHOD="post">
    <INPUT TYPE="file" NAME="oFile1"/>
    <INPUT TYPE="submit" VALUE="Upload File">
    </FORM>
    </body>
    </html>
  2. <!DOCTYPE html>
    <html>
      <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
        <meta name="viewport" content="width=device-width, initial-scale=1.0,maximum-scale=1, user-scalable=no"/>
    
        <title>Uploading a file from the client to the server without reloading the page</title>
    
        <script type="text/javascript" src="jquery.min.js"></script>
        <script type="text/javascript" src="js/vendor/jquery.ui.widget.js"></script>
        <script type="text/javascript" src="js/jquery.iframe-transport.js"></script>
        <script type="text/javascript" src="js/jquery.fileupload.js"></script>
        <script type="text/javascript">
        $(function(){
          $('#fileupload').fileupload();
        });
        
      </script>
        <script language="cache" runat="server">
          if (%request.IsDefinedMimeData("files[]",1) ) {
            
            stream=%request.GetMimeData("files[]")
            
            file=##class(%Stream.FileBinary).%New()
            file.Filename="c:\InterSystems\"_stream.FileName
            d file.CopyFromAndSave(stream)
          }
    
        </script>
      </head>
    
      <body>
        #($H)#<input id="fileupload" type="file" name="files[]" data-url="#(%request.PageName)#multiple data-sequential-uploads="false">
      </body>
    </html>
  3. Class dc.fileuploadajax Extends %ZEN.Component.page
    {
    
    XData Contents [ XMLNamespace "http://www.intersystems.com/zen" ]
    {
    <page xmlns="http://www.intersystems.com/zen" title="Uploading a file from the client to the server without reloading the page">
      <group labelPosition="left">
        <text label="Current date/time on the server:" value="#(%this.%Eval($ZDT($H)))#"/>
      </group>
      <form enctype="multipart/form-data" target="upload_target" labelPosition="left">
        <text label="Name:" name="proc"/>
        <fileUpload name="file" label="Select a file:"/>
        <submit caption="Upload"/>
        <iframe name="upload_target" hidden="true"/>
      </form>
      <fieldSet legend="Information about a previously uploaded file" labelPosition="left">
        <text id="proc" label="Name"/>
        <text id="fileSize" label="File size"/>
        <text id="fileName" label="File name"/>
        <button caption="Refresh" onclick="zenPage.GetFileInfo();"/>
      </fieldSet>
    </page>
    }
    
    ClassMethod %OnSubmit(pSubmit As %ZEN.SubmitAs %Status
    {
      #dim %session As %CSP.Session
      #dim stream As %CSP.BinaryStream=pSubmit.%GetStream("file")
    
      if $IsObject(stream{
        set %session.Data("fileSize")=stream.Size
        set %session.Data("fileName")=stream.FileName
      }
      set %session.Data("proc")=pSubmit.%GetValue("proc")
      quit $$$OK
    }
    
    ClassMethod GetFileInfo() [ ZenMethod ]
    {
      &js<
      zenSetProp('proc','value',#(..QuoteJS(%session.Data("proc")))#);
      zenSetProp('fileSize','value',#(..QuoteJS(%session.Data("fileSize")))#);
      zenSetProp('fileName','value',#(..QuoteJS(%session.Data("fileName")))#);
      >
    }
    }

If you want, I can give ZEN-examples of asynchronous uploading of immediately several files using the File API, but this will only work in new browsers.

The following corrected code works for me:

ClassMethod WriteNodes(myfile As %String)
{
  set status=##class(%XML.TextReader).ParseFile(myfile,.textreader)
  if $$$ISERR(status{do $System.Status.DisplayError(statusquit}

  set ptemp=##class(%Stream.FileCharacter).%New()
  set ptemp.Filename="C:\IT\50_TestIn\warddata1.txt"
  //check status
  //iterate through document, node by node
  while textreader.Read()
  {
    Do ptemp.Write("Node " textreader.seq " is a(n) ")
    Do ptemp.Write(textreader.NodeType " ")
    If textreader.Name'=""
    {
      Do ptemp.Write"named: "textreader.Name)
    }
    Else
    {
      Do ptemp.Write"and has no name")
    }
    Do ptemp.Write" path: " textreader.Path)
    If textreader.Value'="" 
    {
      Do ptemp.Write" value: " textreader.Value)
    }
    Do ptemp.WriteLine()
  }

  Do ptemp.%Save()
}

Another variants:

#Dim sc As %Status $$$OK
s:SQLCODE sc ##class(%Exception.SQL).CreateFromSQLCODE(SQLCODE,%msg).AsStatus()
s:SQLCODE sc $system.Error.FromSQLCode(SQLCODE,%msg).Status

It should also be noted the %sqlcontext, so final code will look as follows:

if SQLCODE {
 set:$IsObject($get(%sqlcontext)) %sqlcontext.%SQLCODE=SQLCODE%sqlcontext.%Message=$get(%msg)
 set sc=$$$ERROR($$$SQLCode,SQLCODE,$g(%msg))
else set sc=$$$OK }
Class dc.demo Extends %Persistent
{

Property ChildPrice As %Library.Float;

ClassMethod Test()
{
  ;d ##class(dc.demo).Test()

  ..%KillExtent()
  obj=..%New()
  obj.ChildPrice=2.56
  obj.%Save()
  
  &sql(select ChildPrice into :ChildPrice from dc.demo where %ID=1)
  ChildPrice,!
}

}

My result:
USER>##class(dc.demo).Test()
2.56

What will be the result you have?
Also check the settings for the format of the data types in your tool (DbVisualizer, Caché Monitor, WinSQL, SQuirreL SQL, etc.), in which you make a selection.

Synchronous and Asynchronous Methods

  1. ClientMethod onunloadHandler() [ Language = javascript ]
    {
      this.SomeZenMethod();
    }
    
    ClassMethod SomeZenMethod() As %Status ZenMethod ]
    {
      // to do some work
      quit $$$OK
    }
  2. ClientMethod onunloadHandler() [ Language = javascript ]
    {
      var old zenSynchronousMode;
      zenSynchronousMode true;
      this.SomeZenMethod();
      zenSynchronousMode old;
    }
    
    ClassMethod SomeZenMethod() [ ZenMethod ]
    {
      // to do some work
    }

    The following code has been tested on versions 2015.2 and 2017.2:

    Class dc.demo Extends %RegisteredObject
    {
    
    Property f1 As %String;
    
    Property f2 As %Integer;
    
    Property f3 As %ListOfDataTypes;
    
    Method GetTarget(
      ByRef pParms As %String,
      Output pObj As %RegisteredObjectAs %Status
    {
      pObj = ..%New()
      
      i $g(pParms(1))="a" {
        pObj.f1 "Peter"
        pObj.f2 = 21
      }else{
        pObj.f1 "Bob"
        pObj.f2 = 12
        pObj.f3 ##class(%ListOfDataTypes).%New()
        pObj.f3.InsertList($lb("a","b","c"))
      }
      q $$$OK
    }
    
    ClassMethod Obj2Json()
    {
      ;d ##class(dc.demo).Obj2Json()
      
      parms(1)="a"
      ##class(%ZEN.Auxiliary.jsonProvider).%WriteJSONStreamFromObject(.stream,..%New(),"GetTarget",.parms,$$$YES,"aeloq")
      "1) ",stream.Read($$$MaxLocalLength),!
      
      parms
      ##class(%ZEN.Auxiliary.jsonProvider).%WriteJSONStreamFromObject(.stream,..%New(),"GetTarget",.parms,$$$YES,"aeloq")
      "2) ",stream.Read($$$MaxLocalLength),!
    }
    
    ClassMethod Json2Obj()
    {
      ;d ##class(dc.demo).Json2Obj()
      
      ##class(%ZEN.Auxiliary.jsonProvider).%ConvertJSONToObject("{""f1"":""Peter"",""f2"":21,""f3"":[]}",$classname(),.obj)
      obj.f1," : ",obj.f3.Count(),!
    
      ##class(%ZEN.Auxiliary.jsonProvider).%ConvertJSONToObject("{""f1"":""Bob"",""f2"":12,""f3"":[""a"",""b"",""c""]}",$classname(),.obj)
      obj.f1," : ",obj.f3.Count(),!
    }
    
    }

    Result:

    USER>##class(dc.demo).Obj2Json()
    1) {"f1":"Peter","f2":21,"f3":[]}
    2) {"f1":"Bob","f2":12,"f3":["a","b","c"]}
     
    USER>##class(dc.demo).Json2Obj()
    Peter : 0
    Bob : 3
    Class dc.SomeClass
    {
    
    Parameter SOMENAME = "Name1";
    
    Query SomeQuery(SOMENAME = {..#SOMENAME}) As %SQLQuery
    {
      SELECT ID || :SOMENAME || Name FROM Table1
    }
    
    Query SomeQuery1() As %SQLQuery
    {
      #define SOMENAME ##Expression("'"_$parameter("dc.SomeClass","SOMENAME")_"'")
      SELECT ID || $$$SOMENAME || Name FROM Table1
    }
    
    Query SomeQuery2() As %SQLQuery
    {
      #define SOMENAME ##Expression("'"_##class(dc.SomeClass).#SOMENAME_"'")
      SELECT ID || $$$SOMENAME || Name FROM Table1
    }
    
    ClassMethod Test()
    {
      ;d ##class(dc.SomeClass).Test()
      
      rs=##class(%ResultSet).%New("dc.SomeClass:SomeQuery")
      sc=rs.Execute()
      i $$$ISERR(sc{
        d $System.Status.DisplayError(sc)
      else {
        rs.%Display()
      }
    }
    }

    Client Side Callback Methods for the Page

    ///  This client event, if present, is fired when the page is unloaded.
    ///  If this method returns a string value, then that is used as the
    ///  return value of the HTML page's onbeforeunload handler (if more than
    ///  one component returns a string, the first one encountered is used).
    ClientMethod onunloadHandler() [ Language = javascript ]
    {
      return 'Are you sure you want to leave?';
    }

    The following query produces zero results:

    select bar.name from foo join bar on bar.id %INLIST MyBars

    This is because MyBars is stored as a $lb($lb(id1),$lb(id2),...,$lb(idN)), and you try to query the data stored in the form $lb(id1,id2,...,idN).

    Your query need some change to make it work, namely:

    select name from foo join bar b on $listbuild(b.%ID) %INLIST MyBars

    For passing array by reference try to use the class $system.WorkMgr instead of job.

    Sample:

    Class demo.test Abstract ]
    {
    
    ClassMethod Test(arrayAs %Status
    {
      ^CacheTempUser.dbg
      ^CacheTempUser.dbg($zp)=array
      ^CacheTempUser.dbg($zp,"$j")=$j
      q $$$OK
    }
    
    }
    
    demo()
      queue,arr
    
      arr(1)="qwe"
      arr(2)="asd"
      
      "$j = ",$j,!
      queue=$system.WorkMgr.Initialize("/multicompile=1",,1)
      queue.Queue("##class(demo.test).Test",.arr)
      queue.WaitForComplete()
      
      zw ^CacheTempUser.dbg
      q

    Result:

    USER>^demo
    $j = 7600
    ^CacheTempUser.dbg(8488,1)="qwe"
    ^CacheTempUser.dbg(8488,2)="asd"
    ^CacheTempUser.dbg(8488,"$j")=8348

    In addition to the above.

    Fill the array tArray can be charged a method %ListOfDataTypes:BuildValueArray().
    But I still prefer the next option (unless you count every tick of CPU :) ):

    list=##class(%ListOfDataTypes).%New()
    list.InsertList(tInputList)
     
    ; method #1
    key="" {value=list.GetPrevious(.key)while (key'="")
     
    ; method #2 (better way)
    key=list.Size:-1:1 value=list.GetAt(key)

    You can fix this error directly now, if you don't want to wait for the release of version 2018.1.1.

    To do this, follow these steps:

    1. make export the locale "deuw"
      %SYS>Locales("deuw")="" d $system.OBJ.DisplayError(##class(Config.NLS.Locales).ExportList("loc_deuw.xml",.t,.Locales)) zw Locales,t
    2. fix the file loc_deuw.xml (by default located in the folder %CACHEHOME%\Mgr)
      Name of subtable
      (Where to insert)
      New lines
      (That to insert)
      Add the following lines to the appropriate subtables:
      COL-German3-Unicode <FromToItem FromToKey="55,55,1">83,83;</FromToItem>
      <FromToItem FromToKey="55,55,2">7838;</FromToItem>
      <FromToItem FromToKey="55,55,3">83,7838;</FromToItem>
      COL-Unicode-German3 <FromToItem FromToKey="7838">55,55;2</FromToItem>
      <FromToItem FromToKey="83,83">55,55;1</FromToItem>
      <FromToItem FromToKey="83,7838">55,55;3</FromToItem>
      LowerCase-Unicode-Unicode <FromToItem FromToKey="7838">223</FromToItem>
      UpperCase-Unicode-Unicode <FromToItem FromToKey="223">7838</FromToItem>
    3. import fixed loc_deuw.xml:
      %SYS>d $system.OBJ.DisplayError(##class(Config.NLS.Locales).ImportAll("loc_deuw.xml",.t,1+2+4)) zw t
      %SYS>d $system.OBJ.DisplayError(##class(Config.NLS.Locales).Compile("deuw"))
      %SYS>Locale^NLSLOAD("deuw")

      Just in case, restart Caché.

    Now, run a small test

    #include %systemInclude
    #include %occErrors
    #include %syNLS
    test() public {
      
      #dim ex As %Exception.AbstractException
    
      try {
        $$$AddAllRoleTemporaryInTry
        n $namespace
        s $namespace="%SYS"
        
        oldLocale=$$$LOCALENAME
        w "Old locale = ",oldLocale,!
        ##class(Config.NLS.Locales).Install("deuw")
        "Current locale = ",$$$LOCALENAME,!!
        
        ^||low,^||up
    
        w="wei"_$c(223)_"er","weiter","weiser" {
          ^||low($zcvt(w,"L"))=1
          ^||up($zcvt(w,"U"))=1
        }
        zw ^||low,^||up
        
        low=$c(223)
        up=$zcvt(low,"U")
        zw low,up
        zzdump low,up
        
      }catch(ex{
        "Error "ex.DisplayString(),!
      }
      ##class(Config.NLS.Locales).Install(oldLocale)
    
    }

    My result:

    USER>d ^test
    Old locale = rusw
    Current locale = deuw
     
    ^||low("weiser")=1
    ^||low("weißer")=1
    ^||low("weiter")=1
    ^||up("WEISER")=1
    ^||up("WEIẞER")=1
    ^||up("WEITER")=1
    low="ß"
    up="ẞ"
     
    0000: DF                                                      ß
    0000: 1E9E                                                    ẞ