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()
}
Class Test.Duplicates Extends %Persistent
{

Index iText On (Text(KEYS), Text(ELEMENTS)) [ Type = bitmap ];

Property Text As %String(MAXLEN 2000);

ClassMethod TextBuildValueArray(
  v,
  ByRef arrAs %Status
{
  #define sizeOfChunk 400

  i v="" {
    arr("null")=v
  }else{
    hasDupl=$$$YES
    f i=1:1:$l(v)\$$$sizeOfChunk+($l(v)#$$$sizeOfChunk>0) {
      arr(i)=$e(v,1,$$$sizeOfChunk),$e(v,1,$$$sizeOfChunk)=""
      s:hasDupl&&'$d(^Test.DuplicatesI("iText"," "_i,##class(%Collation).SqlUpper(arr(i)))) hasDupl=$$$NO
    }
    s:hasDupl arr("hasDupl")=""
  }
  q $$$OK
}

ClassMethod Test()
{
  ;d ##class(Test.Duplicates).Test()

  ..%KillExtent()
  
  text=##class(%PopulateUtils).StringMin(2000,2000)
  &sql(insert into Test.Duplicates(Text)
  select 'ab'
  union all select 'abc' union all select 'abc'
  union all select 'abe' union all select 'abe' union all select 'abe'
  union all select null  union all select null
  union all select :text union all select :text)
  
  d $SYSTEM.SQL.PurgeForTable($classname()),
    $system.SQL.TuneTable($classname(),$$$YES),
    $system.OBJ.Compile($classname(),"cu-d")
    
  sql(1)="select %ID,$extract(Text,1,10) Text10 from Test.Duplicates",
    sql(2)="select * from Test.Duplicates where FOR SOME %ELEMENT(Text) (%KEY='null')",
    sql(3)="select %ID,$extract(Text,1,10) HasDupl_Text10_All from Test.Duplicates where FOR SOME %ELEMENT(Text) (%KEY='hasdupl')",
    sql(4)="select distinct $extract(%exact(Text),1,10) HasDupl_Text10 from Test.Duplicates where FOR SOME %ELEMENT(Text) (%KEY='hasdupl')"
  
  i=1:1:$o(sql(""),-1) !,sql(i),!! ##class(%SQL.Statement).%ExecDirect(,sql(i)).%Display() !,"---------",!
}

}

Result:

USER>##class(Test.Duplicates).Test()
 
select %ID,$extract(Text,1,10) Text10 from Test.Duplicates
 
ID      Text10
1       ab
2       abc
3       abc
4       abe
5       abe
6       abe
7
8
9       QfgrABXjbT
10      QfgrABXjbT
 
10 Rows(s) Affected
---------
 
select * from Test.Duplicates where FOR SOME %ELEMENT(Text) (%KEY='null')
 
ID      Text
7
8
 
2 Rows(s) Affected
---------
 
select %ID,$extract(Text,1,10) HasDupl_Text10_All from Test.Duplicates where FOR SOME %ELEMENT(Text) (%KEY='hasdupl')
 
ID      HasDupl_Text10_All
3       abc
5       abe
6       abe
10      QfgrABXjbT
 
4 Rows(s) Affected
---------
 
select distinct $extract(%exact(Text),1,10) HasDupl_Text10 from Test.Duplicates where FOR SOME %ELEMENT(Text) (%KEY='hasdupl')
 
HasDupl_Text10
abc
abe
QfgrABXjbT
 
3 Rows(s) Affected
---------

Notes:

  • not used hashing, so there's no risk of collisions
  • support for strings of unlimited length up to 3641144 ($zu(96,39))
  • customizable chunk size
  • minimum code
  • should work for older versions of Caché
  • high performance
  • possible else more optimize code ;)

See Indexing of non-atomic attributes

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 }

Isn't it easier to use the built function StringMin, especially when its the code does exactly the same thing?

USER>w $length(##class(%PopulateUtils).StringMin(100,100))
100

Source code:

ClassMethod StringMin(
  minlen As %Integer 1,
  maxlen As %Integer 1As %String ProcedureBlock = 1 ]
{
 if maxlen '< minlen {
   set len=$$$PRand(maxlen-minlen+1)+minlen,
       string=""
   for i=1:1:len {
     Set charn=$s($$$PRand(2):$$$PRand(26)+65,1:$$$PRand(26)+97),
         string=string_$s(charn<123:$c(charn),1:" ")
   }
   quit string
 else quit "" }
}
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
    }