go to post Vitaliy Serdtsev · Oct 7, 2020 Source code Class mp.test Extends %Persistent { Property prop1; Property prop2; Property prop3; Index idx3 On (prop3, prop1, prop2) [ Type = bitmap ]; ClassMethod Fill(total = 5000000) { d ..%KillExtent() f i=1:1:total s ^mp.testD(i)=$lb("","name","prop2",$r(30)) s ^mp.testD=total d ..%BuildIndices() } ClassMethod Query() { s N=5 &sql(SELECT count(*) into :count FROM mp.test WHERE prop1='name' AND prop2='prop2' AND prop3>='1' AND prop3<='30') w "count=",count,!! s sql=##class(%SQL.Statement).%New() d sql.%Prepare("SELECT %ID,prop3 FROM mp.test WHERE %ID IN ("_ " SELECT * FROM ("_ " SELECT TOP ALL %ID FROM mp.test WHERE prop1='name' AND prop2='prop2' AND prop3>='1' AND prop3<='30' ORDER BY prop3 DESC"_ " ) WHERE %VID BETWEEN ? AND ?"_ ") ORDER BY prop3 DESC") w "first 5 [1:5]",! s rset=sql.%Execute(1,5) s time=$zh d rset.%Display() w !,$zh-time," secs",!! w $$$FormatText("last 5 [%1:%2]",count-N+1,count),! s rset=sql.%Execute(count-N+1,count) s time=$zh d rset.%Display() w !,$zh-time," secs" } } USER>d ##class(mp.test).Fill(5000000) USER>d ##class(mp.test).Query() count=3833346 first 5 [1:5] ID prop3 3 3 4 3 24 3 30 3 97 3 5 Rows(s) Affected .000328 secs last 5 [3833342:3833346] ID prop3 4999798 1 4999817 1 4999836 1 4999866 1 4999947 1 5 Rows(s) Affected 2.884304 secs PS: for those who put a minus. May I ask why?
go to post Vitaliy Serdtsev · Sep 11, 2020 There is at least one case where this encoding style is acceptable - it is a generator method. Just look at the code generated by &sql() or CSP, for example. No wonder there are two versions for javascript libraries: for the developer and for production (processed by the minimizer).
go to post Vitaliy Serdtsev · Sep 8, 2020 And what if the answer is given, but the author either does not want to accept the answer at all or does not make a more elegant decision? https://community.intersystems.com/post/there-way-defermine-column-jsono... https://community.intersystems.com/post/creating-json-objects-objectscri...
go to post Vitaliy Serdtsev · Aug 5, 2020 My EAV implementation is the same as your Approach 3, so it will work fine even with fully filled 4.000.000 attributes. Since the string has a limit of 3,641,144, approaches with serial and %List are dropped. All other things being equal, everything depends on the specific technical task: speed, support for Objects/SQL, the ability to name each attribute, the number of attributes, and so on.
go to post Vitaliy Serdtsev · Aug 5, 2020 Entity–attribute–value model is usually used for this purpose. I have already written about this at the time: SQL index for array property elements.
go to post Vitaliy Serdtsev · Jul 9, 2020 select *, case when a is JSON then 1 else 0 end aa, case when b is JSON then 1 else 0 end bb, case when c is JSON then 1 else 0 end cc from (SELECT 1 a, JSON_OBJECT('id':1) b, '{"id":1}' c)
go to post Vitaliy Serdtsev · Jun 10, 2020 Here is a ready-made example (works even in last Caché): Class dc.test Extends %Persistent { Property title As %VarString; Property author As %VarString; /// do ##class(dc.test).test() ClassMethod test() { &sql(truncate table dc.test) &sql(insert into dc.test(title,author) select 'For Whom the Bell Tolls','Hemmingway' union select 'The Invisible Man','Ellison' union select 'Tender is the Night','Fitzgerald') set provider=##class(%ZEN.Auxiliary.altJSONSQLProvider).%New(), provider.sql="select title,author from dc.test", provider.arrayName="items", provider.maxRows = 0, provider.%Format = "tw" do provider.%WriteJSONStreamFromSQL(.stream,,,,,provider) set json={}.%FromJSON(stream), json.results=json.items.%Size() write json.%ToJSON() } }Result: USER>do ##class(dc.test).test() {"items":[{"title":"For Whom the Bell Tolls","author":"Hemmingway"},{"title":"The Invisible Man","author":"Ellison"},{"title":"Tender is the Night","author":"Fitzgerald"}],"results":3}
go to post Vitaliy Serdtsev · May 28, 2020 Google the JDBC Driver for Excel. Here is a good option: HXTT Excel Pure Java JDBC (1.2, 2.0, 3.0, 4.0, 4.1, 4.2, 4.3) Drivers for MS Excel (XLS, XLSX)
go to post Vitaliy Serdtsev · May 22, 2020 Added several more types: Class dc.test [ Abstract ] { ClassMethod ValType(ByRef var) As %String { s a(-1)="undefined",a(0)="empty",a(1)="string",a(2)="integer",a(3)="float",a(4)="double",a(5)="object",a(6)="list",a(7)="array",a(8)="bitstring" s r=$s('$d(var):-1, $isobject(var):5, $d(var)>9:7, var="":0, $lv(var):6, $l(var)>254:1, 1:$tr($a($lb(var),2),1245678,1122334)) i r=1 { s s=##class(%Utility).FormatString(var) s:($f(s,"$c(")=4)||($f(s,"$zwc(")=6) r=8 } q a(r) } /// d ##class(dc.test).test() ClassMethod test() { s old=$system.Process.Undefined(2) try{ w ##class(%Utility).FormatString(undef)," => ",..ValType(.undef),! f i="","1",1,1.1,$double(1.1),##class(%ListOfDataTypes).%New(),$lb(),$factor(1),$c(7) { w ##class(%Utility).FormatString(i)," => ",..ValType(.i),! } s (i,i(1))="" w ##class(%Utility).FormatString(i)," => ",..ValType(.i),! }catch{ } d $system.Process.Undefined(old) } } Result: USER>d ##class(dc.test).test() "" => undefined "" => empty 1 => string 1 => integer 1.1 => float $double(1.1000000000000000888) => double "1@%Library.ListOfDataTypes" => object $lb() => list $zwc(128,4)_$c(1,0,0,0)/*$bit(1)*/ => bitstring $c(7) => bitstring "" => array
go to post Vitaliy Serdtsev · May 22, 2020 InterSystems IRIS Community Edition Limitations Also see %SYSTEM.License, e.g. method MaxConnections
go to post Vitaliy Serdtsev · May 20, 2020 Extending the reply of @Robert Cemper The following query compiles without errors, even though Studio highlights the error &sql(select :fieldname into :fieldvar from :tablename)Everything is fine in Caché: the error occurs at the compilation-time. In order for an error to occur in IRIS Studio too you need to use the flag /compileembedded=1 It is strange that the documentation mentions field name, but there is no mention of table name: A host variable cannot be used to pass a field name or keyword into an SQL statement. proof
go to post Vitaliy Serdtsev · May 20, 2020 In MUMPS, not everything is so simple, so specify technical task ;) Example: USER>set v1=1,v2="1" zzdump v1,v2 0000: 31 1 0000: 31 1 what to do with dates: 30000 is a number or date 20.02.1923? or "20.02.1923" - is it a date or a string? what about numbers: 0 is %TinyInt, %SmallInt, or %Integer? what about boolean: 1 is %Boolean or %Integer? In addition, you mix MUMPS (variable) and InterSystems ObjectScript (%Library.XXX): see Variable Types
go to post Vitaliy Serdtsev · May 20, 2020 It can be simpler: Property HowManyRecords As %Integer [ Calculated, ReadOnly, Required, SqlComputeCode = {n r,SQLCODE &sql(select count(*) into :r from schema_package.table) s {*}=$s(SQLCODE:-1,1:r)}, SqlComputed ];
go to post Vitaliy Serdtsev · May 18, 2020 Absolutely true. InterSystems SQL uses this index to improve performance of COUNT(*), which returns the number of records (rows) in the table. proof
go to post Vitaliy Serdtsev · May 18, 2020 Are a couple of points: The macro "ClassSQLTable" is defined in the method %Library.EnsembleMgr:UpgradeUTCIndices I would prefer to use ##class(%DeepSee.Utils).%GetSQLTableName(pClass As %String, pVerifyExists=0)
go to post Vitaliy Serdtsev · Apr 30, 2020 Unfortunately, there are errors in the methods GenExportBinaryStream/GenImportBinaryStream in the class %JSON.Generator.
go to post Vitaliy Serdtsev · Apr 30, 2020 Thank you for asking. It seems that no one has tried my code in all this time, or it's just that no one is interested in it. There are two ways to solve the issue: configure Undefined=2. I have historically set this value. This can be done programmatically or via SMP fix the code: ClassMethod NewQuery1Fetch( ByRef qHandle As %Binary, ByRef Row As %List, ByRef AtEnd As %Integer = 0) As %Status [ PlaceAfter = NewQuery1Execute ] { if qHandle>1 { set Row=qHandle($increment(qHandle,-1)) } else { set AtEnd=1 } quit $$$OK }
go to post Vitaliy Serdtsev · Apr 11, 2020 Example Class dc.test [ Abstract ] { /// Encode a stream as BASE64 ClassMethod Base64EncodeStream( pStream As %Stream.Object, Output pEncoded As %Stream.Object) As %Status { try{ $$$ThrowOnError(pStream.Rewind()) s pEncoded=##class(%Stream.TmpCharacter).%New() while 'pStream.AtEnd { s tLen=5700 s sc=pEncoded.Write($system.Encryption.Base64Encode(pStream.Read(.tLen))) return:$$$ISERR(sc) sc } s sc=pEncoded.Rewind() }catch(ex) { s sc=ex.AsStatus() } q sc } ClassMethod AESCBCBase64EncryptStream( Plaintext As %Stream.Object, Output Base64text As %Stream.Object, Key As %String, IV As %String) As %Status { try{ $$$ThrowOnError(Plaintext.Rewind()) s length=$$$MaxLocalLength, wasWide=$$$NO i $System.Version.IsUnicode() { while 'Plaintext.AtEnd && 'wasWide { s wasWide=$ZISWIDE(Plaintext.Read(length,.sc)) return:$$$ISERR(sc) sc } $$$ThrowOnError(Plaintext.Rewind()) } i wasWide { s tmp=##class(%IO.StringStream).%New() s tmp.CharEncoding="UTF8" d tmp.CopyFrom(Plaintext,,$$$YES,.sc) return:$$$ISERR(sc) sc s tmp.CharEncoding="Binary" $$$ThrowOnError(Plaintext.Clear()) $$$ThrowOnError(Plaintext.CopyFrom(tmp)) } s chiperstream=##class(%Stream.TmpCharacter).%New() $$$ThrowOnError($system.Encryption.AESCBCEncryptStream(Plaintext,chiperstream,Key,IV)) s sc=..Base64EncodeStream(chiperstream,.Base64text) }catch(ex) { s sc=ex.AsStatus() } q sc } /// d ##class(dc.test).Test() ClassMethod Test(plaintext = {"test"_$c(768)}) { s key=$tr($j("",16)," ","0"), IV="", plainstream=##class(%Stream.TmpCharacter).%New() d plainstream.Write(plaintext) ;w $system.Encryption.Base64Encode($system.Encryption.AESCBCEncrypt($zcvt(plaintext,"O","UTF8"),key,IV)),! d $system.OBJ.DisplayError(..AESCBCBase64EncryptStream(plainstream,.base64stream,key,IV)) w base64stream.Read(),! } } Result: USER>d ##class(dc.test).Test("test"_$c(68)) gTNg0UMkvQ3o+ehJkvr6lA== USER>d ##class(dc.test).Test("test"_$c(768)) R8UuZkjDVZidYckYMTpnVg== USER>d ##class(dc.test).Test("测试") lsYxFAQgNtiXHyaeGTWJ0A==