Vitaliy Serdtsev · Feb 13, 2023 go to post

There are a couple of points:

  • could you please publish the source code of the class, and not the SQL script? The fact is that the command
    CREATE INDEX BITMAP_INDEX_ST_SEARCH_VISIT_BLOOD_TYPE_CODE ON SQLUser.ST_SEARCH_VISIT (BLOOD_TYPE_CODE)

    creates a regular index, not a bitmap index as expected. I'm afraid my code may not match yours.

  • I created a test class with test data on Caché 2018.x and IRIS 2023.1FT and I have your query executed very quickly. Details below.
 

User.STSEARCHVISIT.cls

/// 
Class User.STSEARCHVISIT Extends %Persistent ClassType = persistent, DdlAllowedFinalProcedureBlockSqlRowIdPrivateSqlTableName ST_SEARCH_VISIT ]
{

Property HQORGCODE As %Library.String(MAXLEN 32) [ SqlColumnNumber = 2, SqlFieldName HQ_ORG_CODE ];

Property HQORGNAME As %Library.String(MAXLEN 32) [ SqlColumnNumber = 3, SqlFieldName HQ_ORG_NAME ];

Property TENANTID As %Library.String(MAXLEN 32) [ SqlColumnNumber = 4, SqlFieldName TENANT_ID ];

Property GROUPPATIENTSN As %Library.String(MAXLEN 32) [ SqlColumnNumber = 5, SqlFieldName GROUP_PATIENT_SN ];

Property ORGPATIENTSN As %Library.String(MAXLEN 32) [ SqlColumnNumber = 6, SqlFieldName ORG_PATIENT_SN ];

Property NAME As %Library.String(MAXLEN 64) [ SqlColumnNumber = 7 ];

Property SEXCODE As %Library.String(MAXLEN 2) [ SqlColumnNumber = 8, SqlFieldName SEX_CODE ];

Property SEXNAME As %Library.String(MAXLEN 16) [ SqlColumnNumber = 9, SqlFieldName SEX_NAME ];

Property BIRTHDATE As %Library.Date SqlColumnNumber = 10, SqlFieldName BIRTH_DATE ];

Property MARRYCODE As %Library.String(MAXLEN 2) [ SqlColumnNumber = 11, SqlFieldName MARRY_CODE ];

Property MARRYNAME As %Library.String(MAXLEN 16) [ SqlColumnNumber = 12, SqlFieldName MARRY_NAME ];

Property IDENTIFYTYPECODE As %Library.String(MAXLEN 5) [ SqlColumnNumber = 13, SqlFieldName IDENTIFY_TYPE_CODE ];

Property IDENTIFYTYPENAME As %Library.String(MAXLEN 32) [ SqlColumnNumber = 14, SqlFieldName IDENTIFY_TYPE_NAME ];

Property IDENTIFYNUMBER As %Library.String(MAXLEN 50) [ SqlColumnNumber = 15, SqlFieldName IDENTIFY_NUMBER ];

Property BLOODTYPECODE As %Library.String(MAXLEN 2) [ SqlColumnNumber = 16, SqlFieldName BLOOD_TYPE_CODE ];

Property BLOODTYPENAME As %Library.String(MAXLEN 12) [ SqlColumnNumber = 17, SqlFieldName BLOOD_TYPE_NAME ];

Property MOBILE As %Library.String(MAXLEN 50) [ SqlColumnNumber = 18 ];

Property MAILINGADDRESS As %Library.String(MAXLEN 127) [ SqlColumnNumber = 19, SqlFieldName MAILING_ADDRESS ];

Property VISITSERIALNO As %Library.String(MAXLEN 64) [ SqlColumnNumber = 20, SqlFieldName VISIT_SERIAL_NO ];

Property TABLEFLAG As %Library.String(MAXLEN 1) [ SqlColumnNumber = 21, SqlFieldName TABLE_FLAG ];

Property VISITTYPECODE As %Library.String(MAXLEN 24) [ SqlColumnNumber = 22, SqlFieldName VISIT_TYPE_CODE ];

Property VISITTYPENAME As %Library.String(MAXLEN 64) [ SqlColumnNumber = 23, SqlFieldName VISIT_TYPE_NAME ];

Property VISITDEPTCODE As %Library.String(MAXLEN 32) [ SqlColumnNumber = 24, SqlFieldName VISIT_DEPT_CODE ];

Property VISITDEPTNAME As %Library.String(MAXLEN 64) [ SqlColumnNumber = 25, SqlFieldName VISIT_DEPT_NAME ];

Property INOUTVISITNO As %Library.String(MAXLEN 32) [ SqlColumnNumber = 26, SqlFieldName IN_OUT_VISIT_NO ];

Property VISITTIME As %Library.PosixTime SqlColumnNumber = 27, SqlFieldName VISIT_TIME ];

Property DISCHARGETIME As %Library.PosixTime SqlColumnNumber = 28, SqlFieldName DISCHARGE_TIME ];

Property INHOSPITALTIME As %Library.PosixTime SqlColumnNumber = 29, SqlFieldName IN_HOSPITAL_TIME ];

Property ICDCODE As %Library.String(MAXLEN 20) [ SqlColumnNumber = 30, SqlFieldName ICD_CODE ];

Property ICDNAME As %Library.String(MAXLEN 64) [ SqlColumnNumber = 31, SqlFieldName ICD_NAME ];

Property HEALTHCARDNO As %Library.String(MAXLEN 32) [ SqlColumnNumber = 32, SqlFieldName HEALTH_CARD_NO ];

Property HEALTHCARDTYPE As %Library.String(MAXLEN 64) [ SqlColumnNumber = 33, SqlFieldName HEALTH_CARD_TYPE ];

Property SURGCODE As %Library.String(MAXLEN 20) [ SqlColumnNumber = 34, SqlFieldName SURG_CODE ];

Property SURGNAME As %Library.String(MAXLEN 64) [ SqlColumnNumber = 35, SqlFieldName SURG_NAME ];

Property AGE As %Library.String(MAXLEN 10) [ SqlColumnNumber = 36 ];

Property DISEASECODE As %Library.Integer(MAXVAL 2147483647MINVAL -2147483648) [ SqlColumnNumber = 37, SqlFieldName DISEASE_CODE ];

Property DISEASENAME As %Library.String(MAXLEN 64) [ SqlColumnNumber = 38, SqlFieldName DISEASE_NAME ];

Property LastChangedTime As %Library.PosixTime SqlColumnNumber = 39 ];

Property LastCreateTime As %Library.PosixTime SqlColumnNumber = 40 ];

Property GROUPORG As %Library.String(MAXLEN 50) [ SqlColumnNumber = 41 ];

Parameter USEEXTENTSET = 0;

/// Bitmap Extent Index auto-generated by DDL CREATE TABLE statement.  Do not edit the SqlName of this index.
Index DDLBEIndex [ ExtentSqlName "%%DDLBEIndex"Type = bitmap ];

Index BITMAPINDEXSTSEARCHVISITBLOODTYPECODE On BLOODTYPECODE [ SqlName BITMAP_INDEX_ST_SEARCH_VISIT_BLOOD_TYPE_CODEType = bitmap ];

Index BITMAPINDEXSTSEARCHVISITHQORGCODE On HQORGCODE [ SqlName BITMAP_INDEX_ST_SEARCH_VISIT_HQ_ORG_CODEType = bitmap ];

Index BITMAPINDEXSTSEARCHVISITIDENTIFYTYPECODE On IDENTIFYTYPECODE [ SqlName BITMAP_INDEX_ST_SEARCH_VISIT_IDENTIFY_TYPE_CODEType = bitmap ];

Index BITMAPINDEXSTSEARCHVISITMARRYCODE On MARRYCODE [ SqlName BITMAP_INDEX_ST_SEARCH_VISIT_MARRY_CODEType = bitmap ];

Index BITMAPINDEXSTSEARCHVISITSEXCODE On SEXCODE [ SqlName BITMAP_INDEX_ST_SEARCH_VISIT_SEX_CODEType = bitmap ];

Index BITMAPINDEXSTSEARCHVISITTABLEFLAG On TABLEFLAG [ SqlName BITMAP_INDEX_ST_SEARCH_VISIT_TABLE_FLAGType = bitmap ];

Index BITMAPINDEXSTSEARCHVISITVISITDEPTCODE On VISITDEPTCODE [ SqlName BITMAP_INDEX_ST_SEARCH_VISIT_VISIT_DEPT_CODEType = bitmap ];

Index BITMAPINDEXSTSEARCHVISITVISITTYPECODE On VISITTYPECODE [ SqlName BITMAP_INDEX_ST_SEARCH_VISIT_VISIT_TYPE_CODEType = bitmap ];

Index INDEXSTSEARCHVISITBIRTHDATE On BIRTHDATE [ SqlName INDEX_ST_SEARCH_VISIT_BIRTH_DATEType = index ];

Index INDEXSTSEARCHVISITDISCHARGETIME On DISCHARGETIME [ SqlName INDEX_ST_SEARCH_VISIT_DISCHARGE_TIMEType = index ];

Index INDEXSTSEARCHVISITGROUPPATIENTSN On GROUPPATIENTSN [ SqlName INDEX_ST_SEARCH_VISIT_GROUP_PATIENT_SNType = index ];

Index INDEXSTSEARCHVISITIDENTIFYNUMBER On IDENTIFYNUMBER [ SqlName INDEX_ST_SEARCH_VISIT_IDENTIFY_NUMBERType = index ];

Index INDEXSTSEARCHVISITINHOSPITALTIME On INHOSPITALTIME [ SqlName INDEX_ST_SEARCH_VISIT_IN_HOSPITAL_TIMEType = index ];

Index INDEXSTSEARCHVISITINOUTVISITNO On INOUTVISITNO [ SqlName INDEX_ST_SEARCH_VISIT_IN_OUT_VISIT_NOType = index ];

Index INDEXSTSEARCHVISITMOBILE On MOBILE [ SqlName INDEX_ST_SEARCH_VISIT_MOBILEType = index ];

Index INDEXSTSEARCHVISITNAME On NAME [ SqlName INDEX_ST_SEARCH_VISIT_NAMEType = index ];

Index INDEXSTSEARCHVISITORGPATIENTSN On ORGPATIENTSN [ SqlName INDEX_ST_SEARCH_VISIT_ORG_PATIENT_SNType = index ];

Index INDEXSTSEARCHVISITVISITSERIALNO On VISITSERIALNO [ SqlName INDEX_ST_SEARCH_VISIT_VISIT_SERIAL_NOType = index ];

Index INDEXSTSEARCHVISITVISITTIME On VISITTIME [ SqlName INDEX_ST_SEARCH_VISIT_VISIT_TIMEType = index ];

Index IdxMapOrg On HQORGCODE [ SqlName IdxMapOrgType = index ];

Index LastChangedTimeIndex On LastChangedTime [ SqlName LastChangedTimeIndexType = index ];

Index LastCreateTimeIndex On LastCreateTime [ SqlName LastCreateTimeIndexType = index ];

Index idxGO On GROUPORG [ SqlName idxGOType = index ];

Index INDEXPIPATIENTINFOHQORGCODE On (HQORGCODE, GROUPPATIENTSN) [ SqlName INDEX_PI_PATIENT_INFO_HQ_ORG_CODEType = index ];

Index IdxGpsnorg On (GROUPPATIENTSN, HQORGCODE) [ SqlName IdxGpsnorgType = index ];

Index IdxVisitorg On (VISITSERIALNO, HQORGCODE) [ SqlName IdxVisitorgType = index ];

ClassMethod Fill(50)
{
  
  ; bulk insert via SQL. This is convenient if USEEXTENTSET = 1
  /*
  d ..%KillExtent()
  f i=1:1:N &sql(insert %NOLOCK %NOCHECK %NOINDEX %NOTRIGGER %NOJOURN into ST_SEARCH_VISIT(HQ_ORG_CODE,VISIT_SERIAL_NO)values(:i#4,:i#5))
  */
  
  ; bulk insert via globals
  DISABLE^%NOJRN
  
  ^User.STSEARCHVISITD,^User.STSEARCHVISITI

  i=1:1:{
    s $li(^User.STSEARCHVISITD(i),1)=i#4, ;HQ_ORG_CODE
      $li(^User.STSEARCHVISITD(i),19)=i#5 ;VISIT_SERIAL_NO
  }
  ^User.STSEARCHVISITD=N
  
  ENABLE^%NOJRN
  
  
  "insert - OK!",!
  ..%BuildIndices(,,,$$$NO)
  "BuildIndices - OK!",!
  
  d $system.SQL.TuneTable("ST_SEARCH_VISIT",$$$YES)
  d $system.OBJ.Compile($classname(),"cu-d")
  "OK",!
}

}

Generating 6000000 records

USER>##class(User.STSEARCHVISIT).Fill(6e6)
OK
explain select count(distinct by(VISIT_SERIAL_NO,HQ_ORG_CODE) 1) from ST_SEARCH_VISIT

<plans>
  <plan>
    <sql>
      select count(distinct by(VISIT_SERIAL_NO,HQ_ORG_CODE) 1) from ST_SEARCH_VISIT /*#OPTIONS {"DynamicSQL":1} */
    </sql>
    <cost value="29794316"/>
    Call module B. Output the row.
    <module name="B" top="1">
      Read index map ST_SEARCH_VISIT.IdxVisitorg, looping on %SQLUPPER(VISIT_SERIAL_NO), %SQLUPPER(HQ_ORG_CODE), and ID. For each row: Check distinct values for %SQLUPPER(HQ_ORG_CODE) and %SQLUPPER(VISIT_SERIAL_NO) using a temp-file. For each distinct row: Accumulate the count([value]).
    </module>
  </plan>
</plans>

select count(distinct by(VISIT_SERIAL_NO,HQ_ORG_CODE) 1) from ST_SEARCH_VISIT

Row count: 1 Performance: 2.8704 seconds 6003078 global references 36016391 lines executed

explain select count(1) from (select distinct by (VISIT_SERIAL_NO,HQ_ORG_CODE) VISIT_SERIAL_NO,HQ_ORG_CODE  from ST_SEARCH_VISIT)

<plans>
  <plan>
    <sql>
      select count(1) from (select distinct by (VISIT_SERIAL_NO,HQ_ORG_CODE) VISIT_SERIAL_NO,HQ_ORG_CODE from ST_SEARCH_VISIT) /*#OPTIONS {"DynamicSQL":1} */
    </sql>
    <cost value="21000"/>
    Call module B. Output the row.
    <module name="B" top="1">
      Read index map ST_SEARCH_VISIT.IdxVisitorg, looping on %SQLUPPER(VISIT_SERIAL_NO) and %SQLUPPER(HQ_ORG_CODE). For each row: Call module I. Accumulate the count([value]).
    </module>
    <module name="I" top="1">
      Read index map ST_SEARCH_VISIT.IdxVisitorg, using the given %SQLUPPER(VISIT_SERIAL_NO) and %SQLUPPER(HQ_ORG_CODE), and looping on ID. For each row: Accumulate the [value].
    </module>
  </plan>
</plans>

select count(1) from (select distinct by (VISIT_SERIAL_NO,HQ_ORG_CODE) VISIT_SERIAL_NO,HQ_ORG_CODE from ST_SEARCH_VISIT)

Row count: 1 Performance: 0.0269 seconds 3079 global references 17711 lines executed

Vitaliy Serdtsev · Jan 31, 2023 go to post

Is there any harm in putting in a massive number into the len parameter of the Read() method?

You cannot read more than 3641144 characters from a stream to a string, as this is the limit for long strings: String Length Limit

From the documentation for the Read() method:

If no len is passed in, ie. 'Read()' then it is up to the Read implementation as to
how much data to return. Some stream classes use this to optimize the amount of
data returned to align this with the underlying storage of the stream.

So you can write like this:
Set inMsg %request.Content.Read($$$MaxLocalLength)

Macros are defined in %msql.inc:

#define MaxStringLength 3641144
#define MaxLocalLength $zutil(96,39)
Vitaliy Serdtsev · Jan 31, 2023 go to post

See the answers here.

In addition there are a few comments:

Vitaliy Serdtsev · Jan 31, 2023 go to post

there are a few comments:

  • you can write shorter:
    Property CarNumber As %String(TRUNCATE 1) [ SqlComputeCode = {{*}=$s(Clear:$$Decrypt({CAR_Number}),1:{CAR_Number})}, SqlComputedSqlFieldName CAR_Number ];
  • you can make a separate calculated field for the decrypted value, for example:
    Property CarNumber As %String(TRUNCATE 1) [ SqlFieldName CAR_Number ];
    
    Property CarNumberDecr As %String(TRUNCATE 1) [ CalculatedSqlComputeCode = {{*}=$s(Clear:$$Decrypt({CAR_Number}),1:{CAR_Number})}, SqlComputedSqlFieldName CAR_NumberDecr ];
  • where do you get the value of the Clear variable (see above)?
  • you can create your own data type for encrypted strings and override the corresponding methods there: How Data Type Classes Work

    In this case, you will not have to clutter up your queries with unnecessary encryption/decryption operations.

Vitaliy Serdtsev · Jan 25, 2023 go to post

There are a couple of points:

  • what's wrong with users, roles, privileges, applications, etc.?
    %SYS>do ^SECURITY
     
     
    1) User setup
    2) Role setup
    3) Service setup
    4) Resource setup
    5) Application setup
    6) Auditing setup
    8) SSL configuration setup
    9) Mobile phone service provider setup
    10) OpenAM Identity Services setup
    11) Encryption key setup
    12) System parameter setup
    13) X509 User setup
    14) KMIP server setup
    15) Exit
     
    Option? 12
     
    1) Edit system options
    2) Edit authentication options
    3) Edit LDAP options
    4) Display system options
    5) Export All Security settings
    6) Import All Security settings
    7) Exit
     
    Option? 5
     
    Export ALL security records? Yes => Yes
     
    Warning: Before importing SSL configurations into a different configuration
    the same certificate directories and certificate files must exist in
    the new configuration, otherwise the import will fail.
     
    Export to file name SecurityExport.xml =>
    Parameters? "WNS" =>
    Confirm export of selected security records to SecurityExport.xml? No => yes
     
    Exported x Application security records
    Exported x DocDB security records
    Exported x Event security records
    Exported x KMIPServer security records
    Exported x LDAPConfig security records
    Exported x OpenAMIdentityService security records
    Exported x PhoneProvider security records
    Exported x Resource security records
    Exported x Role security records
    Exported x SQLPrivileges security records
    Exported x SSLConfig security records
    Exported x Service security records
    Exported x System security records
    Exported x User security records
    Exported x X509Credential security records
    Exported x X509Users security records
     
    Export complete
     
    1) Edit system options
    2) Edit authentication options
    3) Edit LDAP options
    4) Display system options
    5) Export All Security settings
    6) Import All Security settings
    7) Exit
     
    Option?
  • to transfer JDBC/ODBC settings, you can still use external tools, for example DbVisualizer or SQL Data Lens, where you can choose the data format (CSV, XML, JSON, Excel, etc.), the necessary fields and much more.
Vitaliy Serdtsev · Jan 25, 2023 go to post

Did you copy/paste the query correctly here?

Select Books.nam,Books.print,Books.Relativename,Books.Firstpage,Books.Lastpage,Books.trn,Books.lastissue,
Books.firstissue,Books.person,Books.author,Books.price,Books.cd,Books.ab,Books.pf,Books.ju,Books.er,
Books.qw,Books.qt,Books.mn,
Records.qw,Records.er,Records.ty,Records.ui,Records.op,Records."as",
OrderBooks.mn,OrderBooks.bv,
OrderRecords.sd,OrderRecords.fg,OrderRecords.hj,
Orders.lastdate

From SQLUser.Books Books

INNER JOIN SQLUser.Records Records ON Books.id=Recordsid
INNER JOIN SQLUser.OrderedBooks OrderBooks ON Books.id=OrderBooks.id
INNER JOIN SQLUser.OrderedRecords OrderRecords ON Books.id=OrderRecords
INNER JOIN SQLUser.Orders Orders ON Books.id=Orders.id

where ((Records.qw=OrderBooks.qw) and (Records.er is null))

In addition to tuning tables, I would first look at the query plan and, accordingly, the indexes involved in it.

Vitaliy Serdtsev · Jan 24, 2023 go to post

If you select the text with the mouse, you will see spaces on the right in the second "Output".
In general, I think that such details should be enclosed in quotation marks.

Vitaliy Serdtsev · Jan 24, 2023 go to post

Ok. If the nuances of formatting spaces and line feed are unimportant, then can yet shorten Robert's code:

 

size = 40

ClassMethod Build(As %Integer)
{
 a="#" i=f:-1:1 !?i,a=a_"##"
}
Vitaliy Serdtsev · Jan 23, 2023 go to post

It is necessary to take into account the following points:

  • according to the documentation should be
    // add the columns to export
    Do mgr.ColumnNames.Insert("Closed")
    Do mgr.ColumnTypes.Insert("N")
       
    Do mgr.ColumnNames.Insert("DocumentType")
    Do mgr.ColumnTypes.Insert("S")
       
    Do mgr.ColumnNames.Insert("StatusCode")
    Do mgr.ColumnTypes.Insert("N")
       
    Do mgr.ColumnNames.Insert("StatusLastUpdated")
    Do mgr.ColumnTypes.Insert("TS")
  • StringQuote only affects when escaping the corresponding characters, for example:
    • Set mgr.StringQuote $c(34) // double quotes
      a"b -> "a""b"
    • Set mgr.StringQuote $c(39) // '
      a'b -> 'a''b'
  • DateFormat and TimeFormat are applicable only for fields of type D and T, respectively, but you have a field of type TS
  • TimeStampFormat is applicable only for import, but not for export
Vitaliy Serdtsev · Jan 23, 2023 go to post

I hope that Eduard will be formulate the conditions of the task more carefully in the future.

PS: Robert, you shouldn't have rushed to remove your solution.

In any case, your solution was the best. yes

Vitaliy Serdtsev · Jan 23, 2023 go to post

You are absolutely right.
There should be no discrepancies in the description of the task and in the code for checking the solution.

Vitaliy Serdtsev · Jan 23, 2023 go to post

I'm looking at the output validation code, not Output, where there are no spaces at all on the right. It is a pity that there is confusion because of this!

 

Class codeGolf.test.Pyramid

Vitaliy Serdtsev · Jan 23, 2023 go to post
 

size = 50

ClassMethod Build(As %Integer)
{
a="#" i=f:-1:1 ?i-1,a,?f*2-1,! a=a_"##"
}

PS: if you look at the class codeGolf.test.Pyramid, you can see that the format of the output data for f=3 should be as follows:

"  #  "
" ### "
"#####"

So be careful.

Vitaliy Serdtsev · Dec 21, 2022 go to post

Your example does not take into account which element is selected.

For example, if you select the last element, then the list wins instead of the delimited string.

L=1e4,N=1e5,a="1",b=$lb(1)
i=2:1:a=a_"_"_i,b=b_$lb(i)

t=$zh
f i=1:1:c=$p(a,"_",L)
w $zh-t," s.",!  

t=$zh
f i=1:1:c=$li(b,L)
w $zh-t," s.",!
Vitaliy Serdtsev · Dec 21, 2022 go to post

I'll put in my five cents too.

Firstly, Apache for Windows is installed very easily: you just need to unpack the archive and, if necessary (this is done once), register the service.
Secondly, it is not difficult to find the Apache distribution for Windows, for example here: Apache Haus Downloads
Thirdly, I always remove PWS and use my own Apache, so I welcome removing PWS from the IRIS distribution

Vitaliy Serdtsev · Dec 1, 2022 go to post

It is not entirely clear that you are using Caché or IRIS 2021.1:

#Caché

I have two tables: one a local table using cache and the other is via an SQL gateway..

Product version: IRIS 2021.1

The presence/absence of restrictions on the execution of heterogeneous queries depends on this:

Vitaliy Serdtsev · Nov 11, 2022 go to post
 

size = 79

ClassMethod Order(As %StringAs %String
{
 r=i=1:1:5e5{s=$p(a," ",i),w=$tr(s,1e20/17),$p(r," ",$tr(s,w))=wr
}
Vitaliy Serdtsev · Oct 24, 2022 go to post

Have you looked at the type of fields in the metadata?
For me, the INTEGER type (4) is returned for ID, and the BIGINT type (-5) is returned for %ID.

Try

SELECT idxyFROM some_table order by %id

and

rs.%GetMetadata().%Display()

What are the default values for AdaptiveMode, AllowRowIDUpdate, IdKeyCPF, PKEY_IS_IDKEY ?

Try disabling AdaptiveMode.

Vitaliy Serdtsev · Oct 24, 2022 go to post

There is a faster way without opening the object:

Class dc.test Extends %Persistent
{

ClassMethod Test()
{
  
  classname="dc.test"storagename="Default"
  w $$$defMemberKeyGet(classname,$$$cCLASSstorage,storagename,$$$cSDEFdatalocation)
}

Storage Default
{
<Data name="testDefaultData">
<Value name="1">
<Value>%%CLASSNAME</Value>
</Value>
</Data>
<DataLocation>^abc.1</DataLocation>
<DefaultData>testDefaultData</DefaultData>
<IdLocation>^dc.testD</IdLocation>
<IndexLocation>^dc.testI</IndexLocation>
<StreamLocation>^dc.testS</StreamLocation>
<Type>%Library.CacheStorage</Type>
}

}

Result:

^abc.1

Vitaliy Serdtsev · Oct 20, 2022 go to post

Here are two ways:

s="12162,CHAPTER I,Certain infectious and parasitic diseases (A00-B99),003 (A20-A28),Certain zoonotic bacterial diseases,A28,""Other zoonotic bacterial diseases, not elsewhere classified"",A28,""Other zoonotic bacterial diseases, not elsewhere classified"",N,N,N,N,N,,,,,,,,,,G"
##class(%DeepSee.TermList).%ParseCSVRecord(s,.arr1)
zw arr1

!

list=$$CSVtoList^%occLibrary(s)

##class(%ListOfDataTypes).BuildValueArray(list,.arr2)
zw arr2


Take a look at the class methods %SQL.Util.Procedures

Vitaliy Serdtsev · Oct 19, 2022 go to post

If there was a built-in function for expanding the list into a table, then the solution would be even shorter.

 

An example of such a function:

Class dc.golf.Kata Abstract ]
{

Query split(
  As %VarString,
  delim As %VarStringAs %Query(ROWSPEC "word:%String") [ SqlProc ]
{
}

ClassMethod splitExecute(
  ByRef qHandle As %Binary,
  As %VarString,
  delim As %VarStringAs %Status
{
  ##class(%ListOfDataTypes).BuildValueArray($lfs(s,delim),.qHandle)
  qHandle=0
  q $$$OK
}

ClassMethod splitFetch(
  ByRef qHandle As %Binary,
  ByRef Row As %List,
  ByRef AtEnd As %Integer 0As %Status PlaceAfter = splitExecute ]
{
  d=$o(qHandle(qHandle),1,v)
  d="" AtEnd=1 else Row=$lb(v),qHandle=}
  q $$$OK
}
}

Now you can do a variety of things with the string, for example:

select min(length(word)) "min",length(wordlen,word from dc_golf.Kata_split('bitcoin take over the world maybe who knows perhaps',' ')

Result:

min len word
3 7 bitcoin
3 4 take
3 4 over
3 3 the
3 5 world
3 5 maybe
3 3 who
3 5 knows
3 7 perhaps