Just to add - I'm successfully using both source control and non-source control extensions (all using the %Studio.Extension framework) from VSCode. If there are specific issues you see, I'd be curious to hear about them.
- Log in to post comments
Just to add - I'm successfully using both source control and non-source control extensions (all using the %Studio.Extension framework) from VSCode. If there are specific issues you see, I'd be curious to hear about them.
@Utsavi Gajjar in case you end up reaching out to InterSystems Support about this (which I'd recommend if you're blocked on the issue), the internal Jira reference for the wrong level of %DynamicObject being passed to %JSONNew is DP-406169
This is a little messy and I'm going to report part of the answer as a bug internally. But regardless, here's one way to make it work - in short, have all of the things that could be listed as a recipient extend a common parent class, and in that class override %JSONNew to detect which type it is.
Class DC.Demo.Container Extends (%RegisteredObject, %JSON.Adaptor)
{
Property recipient As DC.Demo.Recipient;
ClassMethod Demo()
{
for json = {"recipient":{"dob":"2021-06-10"}}, {"recipient":{"reference":"foo"}} {
set inst = ..%New()
do inst.%JSONImport(json)
write !,json.%ToJSON(),!,$classname(inst.recipient),!
}
}
}
Class DC.Demo.Recipient Extends (%RegisteredObject, %JSON.Adaptor)
{
/// Get an instance of an JSON enabled class.<br><br>
///
/// You may override this method to do custom processing (such as initializing
/// the object instance) before returning an instance of this class.
/// However, this method should not be called directly from user code.<br>
/// Arguments:<br>
/// dynamicObject is the dynamic object with thee values to be assigned to the new object.<br>
/// containerOref is the containing object instance when called from JSONImport.
ClassMethod %JSONNew(dynamicObject As %DynamicObject, containerOref As %RegisteredObject = "") As %RegisteredObject
{
// This is weird: shouldn't need to reference .recipient here
if dynamicObject.recipient.%IsDefined("dob") {
quit ##class(DC.Demo.Patient).%New()
} elseif dynamicObject.recipient.%IsDefined("reference") {
quit ##class(DC.Demo.Reference).%New()
} else {
quit ..%New()
}
}
}
Class DC.Demo.Reference Extends DC.Demo.Recipient
{
Property reference As %String;
}
Class DC.Demo.Patient Extends DC.Demo.Recipient
{
Property dob As %Date;
}Output is:
d ##class(DC.Demo.Container).Demo()
{"recipient":{"dob":"2021-06-10"}}
DC.Demo.Patient
{"recipient":{"reference":"foo"}}
DC.Demo.ReferenceOnly problem is, %JSONNew (as advertised in class reference documentation) should get the %DynamicObject representing the object itself, not the parent %DynamicObject. This would only really work if each type is used in exactly one context like this, which seems unlikely.
First off, it's generally best to avoid xecute. ;)
In the first case, routine is private (it isn't visible in the xecute stack frame). In the second, it's public, so it is visible there.
You could get the best of both worlds with:
ClassMethod Run()
{
set routine="variable"
set call="(routine) write routine,!"
xecute (call, routine)
quit
}For more info see https://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KE…
I recently wrote up an example here: https://community.intersystems.com/post/making-most-query
Perhaps pass the object ID into something like:
Query GetInfo(refId As %String) As %SQLQuery(CONTAINID = 1, ROWSPEC = "IdList:%String,IdProcess:%String,Duration:%String")
{
SELECT list.IdList, list.IdProcess, list.Duration
FROM Kurro.MyClass list
JOIN Kurro.MyClass ref on ref.ID = :refId
AND ref.KeyProcess = list.KeyProcess
AND ref.CodeSpecialist = list.CodeSpecialist
AND ref.CodeProvider = list.CodeProvider
AND ref.CodeCenter = list.CodeCenter
AND ref.Date = list.Date
}This is really interesting - I've been starting on a similar project with the same starting point.
I filed it June 18, 2019.
Worldwide Response Center (WRC)
For Immediate Response
Phone:
+1-617-621-0700
+44 (0) 844 854 2917
0800615658 (NZ Toll Free)
1800 628 181 (Aus Toll Free)
Email:
support@intersystems.com
Online:
WRC Direct
Email support@intersystems.com for a login.
This is the right answer. It would be nice if there was a more built-in way to include row IDs in %JSONExport without having to do this though.
The closest thing to what you're looking for is %VID (link to documentation)
You can use this even without an actual view as follows (for example):
select %VID "RowNumber",* from (select top all AirportLocation, FAADistrictOffice from Aviation.Event order by FAADistrictOffice, AirportLocation)
@Tani Frankel this is a nice solution! I'd still like to see this there automatically somehow though.
With what we've done the syntax ends up looking like:
Class DC.Demo.Hierarchy Extends %Persistent [ MemberSuper = AppS.Index.Methods ]
{
Property message As %String;
Property login As %String;
Property parentId As DC.Demo.Hierarchy [ SqlFieldName = parent_id ];
Index parentId On parentId [ Type = bitmap ];
ClassMethod RunDemo()
{
Do ..%KillExtent()
&sql(insert into DC_Demo.Hierarchy (message, login, parent_id)
values ('Bacon ipsum dolor amet pork shoulder ribs', 'User 1', null))
&sql(insert into DC_Demo.Hierarchy (message, login, parent_id)
values ('BGouda croque monsieur emmental.', 'User 2', 1))
&sql(insert into DC_Demo.Hierarchy (message, login, parent_id)
values ('Manchego fromage frais airedale', 'User 3', 2))
Do ##class(%SQL.Statement).%ExecDirect(,
"select id, message, parent_id from DC_Demo.Hierarchy "_
"where id %FIND DC_Demo.Hierarchy_parentIdFind(2,'all descendants')").%Display()
Do ##class(%SQL.Statement).%ExecDirect(,
"select id, message, parent_id from DC_Demo.Hierarchy "_
"where id %FIND DC_Demo.Hierarchy_parentIdFind(3,'all related')").%Display()
}
}Because there's a self-referencing property with a bitmap index, the hierarchy support is automatic via the MemberSuper class. Output is:
d ##class(DC.Demo.Hierarchy).RunDemo() ID message parent_id 2 BGouda croque monsieur emmental. 1 3 Manchego fromage frais airedale 2 2 Rows(s) Affected ID message parent_id 1 Bacon ipsum dolor amet pork shoulder ribs 2 BGouda croque monsieur emmental. 1 3 Manchego fromage frais airedale 2 3 Rows(s) Affected
There's nothing built-in for this, but you can simulate it via custom class queries or %SQL.AbstractFind. I have an implementation of %SQL.AbstractFind/%Library.FunctionalIndex that does some things with hierarchies but falls short of the capabilities you linked in the Oracle doc. Specifically, it can find all ancestors/descendants/both (the whole tree) in a hierarchy efficiently, but it doesn't follow the same rules around ordering and won't let you do paths and such. (I'd want to clean it up a good deal before sharing, but that's probably worthwhile at some point.)
You can use as modern HTML and CSS as you want.
I think I've seen this before when IRIS responds with a login page due to credentials being passed to the SOAP call incorrectly. https://community.intersystems.com/post/example-connecting-cach%C3%A9-w… has an example of the expected headers, though in PHP (likely not your language of choice here).
@Daniel Bertozzi , following up - I downloaded ImageMagick and the following works just fine for me (though I'm a little surprised at how slow it is):
Class DC.Demo.ImageMagick
{
ClassMethod Convert(inFile As %String = "C:\Temp\ImageMagick\inFile.jpg", outFile As %String = "C:\Temp\ImageMagick\outFile.jpg")
{
Do $zf(-100,"","magick",inFile,"-resize","640x480",outFile)
}
}I think the likely issue is that ImageMagick isn't on your PATH. You'll need to restart your instance for it to pick up PATH changes, so this might be the root cause if you just installed ImageMagick. Could also be interesting to run with the /SHELL flag and see if that works.
Hopefully this helps!
It might be helpful to see the value of $zu(56,2) after the error occurs (if you continue to get <NOTOPEN>) - of course you probably don't really need to use STDIN/STDOUT and it might be cleaner to not.
With $zf(-100) the command and its individual flags are separate arguments to the function rather than being concatenated in one string - I'd recommend trying something more like:
set sc = $ZF(-100,"/STDIN="""_imageFile_""" /STDOUT="""_tempFile_"""","magick","fd:0","-resize","640x480","fd:1")
For more details see https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cl…
In communication outside of this thread, turns out the issue stemmed from a failed %Save() - something like:
Class DC.Demo.OREFOIDDemo Extends %Persistent
{
Property Foo As %String(VALUELIST = ",Bar");
ClassMethod RunDemo()
{
Do ..%KillExtent()
Set thingOne = ..%New()
Set thingOne.Foo = "Bar"
Do thingOne.%Save()
Set thingOne.Foo = "Baz"
Do thingOne.%Save()
// Later, and elsewhere, because thingOne happens to be in memory,
// it appears that the value "Baz" has been persisted:
Set thingTwo = ..%OpenId(thingOne.%Id())
Write !,"thingOne = ",thingOne
Write !,"thingTwo = ",thingTwo
Write !,"thingOne.Foo = ",thingOne.Foo
Write !,"thingTwo.Foo = ",thingTwo.Foo
Write !,"thingOne.FooGetStored(thingOne.%Id()) = ",thingOne.FooGetStored(thingOne.%Id())
Do thingTwo.%Reload()
Write !,"After thingTwo.%Reload(), thingOne.Foo = ",thingOne.Foo
Write !,"After thingTwo.%Reload(), thingTwo.Foo = ",thingOne.Foo
}
}Which produces output:
Do ##class(DC.Demo.OREFOIDDemo).RunDemo() thingOne = 15@DC.Demo.OREFOIDDemo thingTwo = 15@DC.Demo.OREFOIDDemo thingOne.Foo = Baz thingTwo.Foo = Baz thingOne.FooGetStored(thingOne.%Id()) = Bar After thingTwo.%Reload(), thingOne.Foo = Bar After thingTwo.%Reload(), thingTwo.Foo = Bar
If what you're describing is actually that a deep save isn't working, this might just be something else entirely. :)
If I understand what you're asking correctly, this is a really great question that hits on a kind of tricky aspect of ObjectScript/persistence. In short, if you already have a persistent object in memory (with a variable, say thingOne, assigned to it), and you open the same ID again and assign another variable to it (say, thingTwo), the OREF will be reused - both variables will point to the same object, and that one in-memory instance of the object can be modified via either variable. This can easily lead to some confusing scenarios.
Here's a quick demonstration of the fact:
Class DC.Demo.OREFOIDDemo Extends %Persistent
{
Property Foo As %String;
ClassMethod RunDemo()
{
Do ..%KillExtent()
Set thingOne = ..%New()
Set thingOne.Foo = "Bar"
Do thingOne.%Save()
Set thingTwo = ..%OpenId(thingOne.%Id())
Set thingTwo.Foo = "Baz"
Write !,"thingOne = ",thingOne
Write !,"thingTwo = ",thingTwo
Write !,"thingOne.Foo = ",thingOne.Foo
Write !,"thingTwo.Foo = ",thingTwo.Foo
}
}Running the method produces the output:
Do ##class(DC.Demo.OREFOIDDemo).RunDemo() thingOne = 18@DC.Demo.OREFOIDDemo thingTwo = 18@DC.Demo.OREFOIDDemo thingOne.Foo = Baz thingTwo.Foo = Baz
It may surprise you that thingOne.Foo has also been set to "Baz" - but as you can see, thingOne and thingTwo reference the same object.
Note that if for some reason I wanted to know the current persisted value of thingOne.Foo, I could use:
thingOne.FooGetStored(thingOne.%Id())
I'll add - it should be an option (and in the HS package manager it is) to distribute some classes/routines as .OBJ and some with source within the same package.
@Evgeny Shvarov there's internal work in the HS package manager to support packaging as a studio project, which may optionally include deployed code. (I believe this didn't make it into the ZPM fork.)
The downside to this approach is that you may need different artifacts for different target platform versions. (It's always safest to assume that you do, at least on the major.minor level.) This would be a new design consideration in zpm-registry.
One possible upside to this approach is that it may be possible to install the build artifact even on environments that don't have the package manager. For the internal implementation we generate an INSTALL.mac that automates things from the different resource processor classes. Uninstallation is still a bit of a conundrum though; I think we'd be better off requiring the package manager for any ZPM implementation of packaging/installing deployed code.
I can think of one extremely valuable internal project that would only be palatable to distribute via ZPM if we didn't have to ship all the source (specifically, a Mockito-style mock framework for ObjectScript that breaks the glass on some internal things not shipped in product source).
Poking around a bit, here's the best explanation I could find for how to implement such behavior: https://stackoverflow.com/a/7317311/2323797
Ah - this is actually messages.log on an IRIS instance. (It used to be called cconsole.log on older products.)
Do you see any messages like this in your messages.log?
Is forwarding cconsole.log an option? There should be a 0-severity message there like:
05/15/19-13:52:53:824 (2144) 0 cleaned dead job, pid: 4012, jobid 0x00010013
Given that SQLCODE is 100 (in other comment thread), might you have an index on %ConfigName that has not been built?
What do you see from the following queries?
select * from X_X.X where %ConfigName IN ('X_X_X','Y_Y_Y')
select * from %IGNOREINDEX * X_X.X where %ConfigName IN ('X_X_X','Y_Y_Y')
Also, is X_X.X the table corresponding to the class where the property is defined?
Short answer: yes, ZPM can manage whatever you want other than ObjectScript, it just takes a little extra work.
Longer answer:
This "extra work" involves writing a class that extends %ZPM.PackageManager.Developer.Processor.Abstract and overrides OnBeforePhase or OnAfterPhase, then implementing whatever behavior you want. You can see a bunch of classes in the %ZPM.PackageManager.Developer.Processor package that do this.
I'd imagine being able to put something in the Resources element of module.xml like:
Where MyPackage.AptGetInstall overrides OnAfterPhase and for the "Activate" phase runs apt-get install <name of resource following "/external-dependencies/"
The catch:
If you want to support all operating systems, think about what the Windows equivalent would be and/or add defensive coding to avoid trying to run the command on Windows.