Vitaliy Serdtsev · Apr 26, 2022 go to post

Try this (%Dialect):

Set sqlStatement=##class(%SQL.Statement).%New(,,"MSSQL")
 

Simple example

Class dc.test Extends %Persistent
{

Property As %Integer;

ClassMethod Test()
{
  
  ..%KillExtent()
  
  &sql(insert into dc.test(tvalues(30))
  &sql(insert into dc.test(tvalues(303))
  
  zw ^dc.testD

  !
  
  sql=2
  sql(1)="update dc.test set t=t+1 where ID=1"
  sql(2)="update dc.test set t=t+2 where ID=2"
  
  st=##class(%SQL.Statement).%New(,,"MSSQL")
  
  "SQLCODE=",st.%ExecDirect(.st,.sql).%SQLCODE,!!
  
  zw ^dc.testD
}

}

Output:

USER>##class(dc.test).Test()
^dc.testD=2
^dc.testD(1)=$lb("",30)
^dc.testD(2)=$lb("",303)
 
SQLCODE=0
 
^dc.testD=2
^dc.testD(1)=$lb("",31)
^dc.testD(2)=$lb("",305)
Vitaliy Serdtsev · Apr 13, 2022 go to post

Most likely, your locale uses TimeFormat = 2 (see tformat)

You can change your locale or explicitly specify the format of the field, for example like this:

Property PackingTimeSpent As %Time(FORMAT 1);
Vitaliy Serdtsev · Apr 13, 2022 go to post

What locale are you using? I use "rusw".

Try to do the following in SMP:

update MSDS_Serenity.KitlabelAssoc set PackingTimeSpent=35000 where label='00007IT4'

then

select

  PackingTimeSpent,   %internal(PackingTimeSpentptsLOGICAL,   %external(PackingTimeSpentptsDISPLAY,   %odbcout(PackingTimeSpent)  ptsODBC

from MSDS_Serenity.KitlabelAssoc where label='00007IT4'

What are your results?

I have the following displayed (for DISPLAY mode):

PackingTimeSpent = 09:43:20
ptsLOGICAL = 35000
ptsDISPLAY = 09:43:20
ptsODBC = 09:43:20

Vitaliy Serdtsev · Apr 13, 2022 go to post

Notes on Indices Defined in Classes

When working with indices in class definitions, here are some points to keep in mind:

• Index definitions are only inherited from the primary (first) superclass.
• ...
 

Simple sample

Class dc.Aclass Abstract ]
{

Index idxF On f;

Property As %Integer;

}

Class dc.test Extends (dc.Aclass%Persistent) [ ClassType = persistent ]
{

ClassMethod Test()
{
  ^dc.testD,^dc.testI
  
  &sql(insert into dc.test(fvalues(30))
  &sql(insert into dc.test(fvalues(303))
  
  zw ^dc.testD,^dc.testI
}

}

Output:

USER>##class(dc.test).Test()
^dc.testD=2
^dc.testD(1)=$lb("",30)
^dc.testD(2)=$lb("",303)
^dc.testI("idxF",30,1)=""
^dc.testI("idxF",303,2)=""
Vitaliy Serdtsev · Apr 13, 2022 go to post

having the field defined as integer would allow selecting avg but running a query in my Zen page wouldn’t show me a time format

If you the field is defined as %Integer or %String, then this is incorrect. The field type must be %Time. In this case, a time will be stored in the database as number, and the query will display the time as a string.

Here is a small example:

select 166 seconds,%external(cast(+166.5 as TIME)) "avg"

Output:

seconds = 166
avg = 00:02:46
 

Simple sample

Class dc.test Extends %Persistent
{

Property As %Time;

ClassMethod Test()
{
  
  ..%KillExtent()
  
  &sql(insert into dc.test(tvalues(30))
  &sql(insert into dc.test(tvalues(303))
  
  zw ^dc.testD

  !
  
  st=##class(%SQL.Statement).%New()
  st.%SelectMode=2
  st.%ExecDirect(.st,"select t, %internal(t) tINT, %external(t) tSTR, avg(t) average,CAST(+avg(t) as TIME) avgSTR from dc.test").%Display()

  ; or
  !!
  
  ##class(%SQL.Statement).%ExecDirect(,"select t, %internal(t) tINT, %external(t) tSTR, avg(t) average,%external(CAST(+avg(t) as TIME)) avgSTR from dc.test").%Display()
}

}

Output:

USER>##class(dc.test).Test()
^dc.testD=2
^dc.testD(1)=$lb("",30)
^dc.testD(2)=$lb("",303)
t tINT tSTR average avgSTR
00:00:30 30 00:00:30 166.5 00:02:46
00:05:03 303 00:05:03 166.5 00:02:46

  2 Rows(s) Affected

t tINT tSTR average avgSTR
30 30 00:00:30 166.5 00:02:46
303 303 00:05:03 166.5 00:02:46

  2 Rows(s) Affected

Vitaliy Serdtsev · Apr 12, 2022 go to post

By default, data in the global is stored as

glbD(ID)=$LB(%%CLASSNAME,prop1,prop2,..,propN)

The total size of the string cannot exceed 3641144. Therefore, if you have a field length >3.6E6, and there are several such fields, the limit is exceeded. To work around this, you need to change storage for your class.

For example so:

glbD(ID)=$LB(%%CLASSNAME)
glbD(ID,"prop1")=prop1
glbD(ID,"prop2")=prop2
...
glbD(ID,"propN")=propN
 

Simple example

Class dc.test Extends %Persistent
{

Index mySimilarityIndex On SettingsJSON(KEYS) [ Data = SettingsJSON(ELEMENTS) ];

Index mySimilaritybackupIndex On SettingsJSONbackup(KEYS) [ Data = SettingsJSONbackup(ELEMENTS) ];

Property SettingsJSON As %Text(LANGUAGECLASS "%Text.English"MAXLEN 3600000SIMILARITYINDEX "mySimilarityIndex");

Property SettingsJSONbackup As %Text(LANGUAGECLASS "%Text.English"MAXLEN 3600000SIMILARITYINDEX "mySimilaritybackupIndex");

ClassMethod Test()
{
  
  ..%KillExtent()
  
  json=$tr($j("",3600000)," ","0")
  &sql(insert into dc.test(SettingsJSON,SettingsJSONbackupvalues(:json,:json))
  
  w $l(json),":",SQLCODE
}

Storage Default
{
<Data name="backup">
  <Attribute>SettingsJSONbackup</Attribute>
  <Structure>node</Structure>
  <Subscript>"SettingsJSONbackup"</Subscript>
</Data>
<Data name="json">
  <Attribute>SettingsJSON</Attribute>
  <Structure>node</Structure>
  <Subscript>"SettingsJSON"</Subscript>
</Data>
<Data name="testDefaultData">
  <Value name="1">
    <Value>%%CLASSNAME</Value>
  </Value>
</Data>
<DataLocation>^dc.testD</DataLocation>
<DefaultData>testDefaultData</DefaultData>
<IdLocation>^dc.testD</IdLocation>
<IndexLocation>^dc.testI</IndexLocation>
<StreamLocation>^dc.testS</StreamLocation>
<Type>%Library.CacheStorage</Type>
}

}
Vitaliy Serdtsev · Apr 12, 2022 go to post

Choose according to your taste:

#include %systemInclude

s=$c(34,34)_"te""""st"_$c(34,34)
  
s,!,
  ##class(%Global).UndoubleInnerQuotes(s),!,
  $$$StripQuotes(s),!,
  $tr(s,$c(34),"")

Output:
USER>d ^test
""te""st""
"te"st"
"te"st"
test

Vitaliy Serdtsev · Apr 11, 2022 go to post

I'm not sure if it's %Text at all.

Made a small example:

Class dc.test Extends %Persistent
{

Index mySimilarityIndex On SettingsJSON(KEYS) [ Data = SettingsJSON(ELEMENTS) ];

Property SettingsJSON As %Text(LANGUAGECLASS "%Text.English"MAXLEN 3600000SIMILARITYINDEX "mySimilarityIndex");

ClassMethod Test()
{
  ..%KillExtent()
  
  json=$tr($j("",3600000)," ","0")
  &sql(insert into del.t(SettingsJSONvalues(:json))
  
  w $l(json),":",SQLCODE
}

}

Output:
3600000:0

Vitaliy Serdtsev · Apr 11, 2022 go to post

Here's what I found: IndexClass (%Dictionary.ClassDefinition) IndexClass (%Dictionary.CompiledClass)

That is, you can write something like this:

Class dc.test Extends %Persistent IndexClass dc.anothertest ]
{
}

The same applies to MemberSuper.

Unfortunately, I haven't found any examples of how to use it or if it works at all.

Vitaliy Serdtsev · Apr 11, 2022 go to post

Class dc.test Extends %Persistent
{

Property As %Integer;

ClassMethod Test() {

  ..%KillExtent()

  &sql(insert into dc.test(Fvalues(22))   &sql(insert into dc.test(Fvalues(11))

  label "00007I0Q"   &sql(select ID into :cnt from dc.test where ID :label)      SQLCODE,":",cnt }

}

Output for Caché 2018.1:

100:00007I0Q

Output for IRIS 2021.2:

100:

PS: it is a pity that my answer was ignored.

Vitaliy Serdtsev · Apr 11, 2022 go to post

Any event that occurs outside of the modal group (such as a mouse click) automatically hides the modal groupproof.

Use Popup windows with modal=yes or Dialogs.

PS: if you really need to use "Model Groups", then you need to do two things for this:

  1. override the method onCanEndModalHandler
  2. override the method hideGroup(). This is necessary to prohibit the close button in the upper right corner
 

Here is a small variant:

Class dс.test Extends %ZEN.Component.page
{

XData Contents [ XMLNamespace "http://www.intersystems.com/zen" ]
{
<page xmlns="http://www.intersystems.com/zen">
  <button caption="Show modal group" onclick="zenPage.show();"/>
  <modalGroup id="mgStatic" groupTitle="Popup">
    <text id="mgText" label="Value:" />
    <button caption="OK" onclick="zenPage.mgBtnClick();"/>
  </modalGroup>
</page>
}

ClientMethod show() [ Language = javascript ]
{
  zenPage.__canClose false;
  var mg zen('mgStatic');
  
  mg.onCanEndModalHandler this.onCanEndModalHandler();
  mg.hideGroup=this.hideGroup;

  mg.show();
}

ClientMethod mgBtnClick() [ Language = javascript ]
{
  zenPage.__canClose=true;
  zen('mgStatic').onCanEndModalHandler=null;

  zenAlert('User entered: ' +  zen('mgText').getValue());
  
  // hide the modal group
  zenPage.endModal();
}

ClientMethod onCanEndModalHandler() [ Language = javascript ]
{
  return true;
}

/// Hide the group.
ClientMethod hideGroup() [ Language = javascript ]
{
  if (!zenPage.__canClose) return;
  
  if (this.groupType == 'dialog'this._canClose true;
  var div this.getFloatingDiv();
  if (div) {
    div.style.opacity = 0;
  }
  if ((!zenIsHTML5) || (!window.TransitionEnd)) {
    if (!this._closing) {
      zenPage.endModal();
      this._closing true;
    }
  }
}

}
Vitaliy Serdtsev · Apr 11, 2022 go to post

Hi Ben.

For some reason, only IRIS 2021.1CE is available for Windows, although IRIS 2021.2CE is available for many other operating systems, such as MacOSX.

Is it possible for Windows to update the version to 2021.2 too?

Vitaliy Serdtsev · Apr 11, 2022 go to post

You should always check the SQLCODE after the embedded query.
If you do this, you will see that the SQLCODE returns the value 100 for your case. In this case, you should ignore host variables.

Host Variables

Vitaliy Serdtsev · Apr 7, 2022 go to post

Is it OK to use this partially rebuilt index if I don't care about data that isn't indexed? Did you do this before?

I didn't build indexes manually, except for tests. If the index is not built for all data, then the query will see only the data for which the index exists.

 

Try simple example:

Class dc.test Extends %Persistent
{

Index iF On F;

Property As %Integer;

ClassMethod Fill(10)
{
  ^dc.testD,^dc.testI

  ^dc.testD=4
  ^dc.testD(1)=$lb("",22)
  ^dc.testD(2)=$lb("",11)
  ^dc.testD(3)=$lb("",44)
  ^dc.testD(4)=$lb("",33)
  

  d $system.SQL.TuneTable($classname(),$$$YES)
  d $system.OBJ.Compile($classname(),"cu-d")
  
  ^dc.testI
  
  ##class(%SQL.Statement).%ExecDirect(,"select * from dc.test").%Display()

  ^dc.testI("iF",1,22)="" !!

  ##class(%SQL.Statement).%ExecDirect(,"select * from dc.test").%Display()

  ^dc.testI("iF",4,33)=""  !!

  ##class(%SQL.Statement).%ExecDirect(,"select * from dc.test").%Display()
}

}
Vitaliy Serdtsev · Apr 7, 2022 go to post

If we open the source code of the class for the Status field, we will see the following:

Class Ens.DataType.MessageStatus Extends %Integer
{

Parameter DISPLAYLIST = ",Created,Queued,Delivered,Discarded,Suspended,Deferred,Aborted,Error,Completed";

Parameter VALUELIST = ",1,2,3,4,5,6,7,8,9";

}

Therefore , the following conclusions can be drawn:

  1. For Embedded SQL the RuntimeMode is Logical
  2. For SQL Explorer (Portal) the RuntimeMode is Display

Hence the leapfrog in the results.

Vitaliy Serdtsev · Apr 7, 2022 go to post

Try this:

ClassMethod OnStartRequest() As %Status
{
  #dim %response As %CSP.Response
  
  ;s %response.ContentType="text/html",%response.Expires=-1
  %response.Status=##class(%CSP.REST).#HTTP403FORBIDDEN
  q $$$OK
}

Or this:

/// Event handler for <b>PreHTTP</b> event: this is invoked before
/// the HTTP headers for a CSP page have been sent.  All changes to the
/// <class>%CSP.Response</class> class, such as adding cookies, HTTP headers,
/// setting the content type etc. must be made from within the OnPreHTTP() method.
/// Also changes to the state of the CSP application such as changing
/// %session.EndSession or %session.AppTimeout must be made within the OnPreHTTP() method.
/// It is prefered that changes to %session.Preserve are also made in the OnPreHTTP() method
/// as this is more efficient, although it is supported in any section of the page.
/// Return <b>0</b> to prevent <method>OnPage</method> from being called.
ClassMethod OnPreHTTP() As %Boolean ServerOnly = 1 ]
{
  %response.Status="403 Forbidden"
  0
}
Vitaliy Serdtsev · Apr 7, 2022 go to post

We need to look at your full code, since there is nothing suspicious in the specified piece of code. I made a small example and there is no highlighting of the last line:

 

Source code

Class dс.test Extends %ZEN.Component.page
{

XData Contents [ XMLNamespace "http://www.intersystems.com/zen" ]
{
<page xmlns="http://www.intersystems.com/zen">
  <tablePane
      width="1200px"
      id="ItemsTable" 
      OnCreateResultSet="GetLog"
      maxRows="20000" 
      pageSize="20" 
      showRowNumbers="false"
      showRowSelector="false"
      showZebra="false"
      valueColumn="ID" 
      nowrap="false"
      showValueInTooltip="true"
      showFilters="true"
      autoExecute="true"
      initialExecute="false"
      useSnapshot="true" 
      onselectrow="">
  <parameter />
  <parameter />
  <parameter />
  <parameter />
  <parameter />
  <parameter />
  <parameter />
      <column colName="Sit" header="Sit name" width="50%" style="text-align:left;" filterType="text" filterOp="[" />
      <column colName="Label"  header="Label" width="10%" filterType="text" filterOp="["/>
      <column colName="userno" header="Packed By" width="10%" filterType="text" filterOp="["/>
      <column colName="LogedDate" header="Packed Date" width="10%" />
      <column colName="LogedTime" header="Packed Time" width="10%" />
      <column colName="TimeSpent" header="Spent Time" width="10%" style="text-align:left;"/>
    
  </tablePane>
  <tableNavigatorBar tablePaneId="ItemsTable"/>
</page>
}

Method GetLog(
  ByRef pSC,
  ByRef tParams)
{
  sql = 5
  sql(1)="SELECT 0 ID,'Sit' Sit,'Label' Label,'userno' userno,current_date LogedDate,current_date LogedTime,null TimeSpent"
  sql(2)="union"
  sql(3)="SELECT 1,'Sit','Label','userno',current_date,current_date,null"
  sql(4)="union"
  sql(5)="SELECT 2,'Sit','Label','userno',current_date,current_date,null"

  st=##class(%SQL.Statement).%New()
  st.%SelectMode=2
  ##class(%SQL.Statement).%ExecDirect(st,.sql)
}

}