Peter Steiwer · Jan 23, 2020 go to post

Also for your test, the same with my note for Eduard -  the output is hardcoded, so the first output line is for i=1, the second is for i=2, the third for i=3, the last for i=4

Peter Steiwer · Jan 23, 2020 go to post

Hi @Vitaliy Serdtsev ,

Try with larger numbers. With the smaller numbers, there will be slight variations which can flip the order.

With 1e9:

Time for If: 28.111261 seconds
Time for ElseIf #1: 38.782421 seconds
Time for ElseIf #2: 49.21395 seconds
Time for Else: 48.58113 seconds

Peter Steiwer · Jan 23, 2020 go to post

Hi Eduard,

Please note that the output is hardcoded, so your output for "Time for ElseIf #2" is actually for your If statement

Peter Steiwer · Jan 21, 2020 go to post

Also, it looks like your calculated measure name is the same as your built in measure name. This means you should change to be something like the following:
WITH MEMBER [Measures].[CondicionesContCompleta]   ->
WITH MEMBER [Measures].[CondicionesContCompletaCalc]  

Peter Steiwer · Jan 21, 2020 go to post

Hi Rodrigo,

Instead of using IIF here, you can us ISNULL(). ISNULL takes in a measure as the first parameter and the second parameter is the value to use if the first is null. So it would look like this:

ISNULL([Measures].[CondicionesContCompleta],0)

Peter Steiwer · Jan 21, 2020 go to post

Yes, I agree that the article you reference is also helpful. I wrote this article as a guide for someone who is receiving the error message without knowing why this is caused. The other article is perhaps better for someone who knows what is wrong but does not know how to fix it.

Peter Steiwer · Jan 12, 2020 go to post

Hi @Evgeny Shvarov

AnalyzeThis.Utils.cls has a method called RefreshCube.

At one point, this was briefly in then UI. We took out the UI reference since we weren't (and still aren't) sure how this should fit into AnalyzeThis. Historically the goal was to be able to quickly get a personalized preview of DeepSee. It was not intended to be an automatic cube generator. The goal was to let people see the benefit of DeepSee, but then allow them to create their own cube and no longer rely on the generated cube from AnalyzeThis. However, I do know of multiple cases where people are using it as you explain in this case and would like to refresh the data once a new CSV has been produced with updated data.

Please let me know your thoughts on the Pros vs Cons of using the AnalyzeThis generated cube VS using your own cube once you have a model you like and would like to continue using.

Peter Steiwer · Jan 6, 2020 go to post

It is worth noting that with Atelier, APIs were created to automatically store the classes on the file system. I believe these APIs are used by VSCode's ObjectScript integration also

Peter Steiwer · Jan 3, 2020 go to post

Hi Mike,

As you have seen, Class files are stored within Caché and not on the file system. We have Studio hooks available as documented here. These allow you to write code to perform the export and import automatically as you interact with your classes in Studio. After files have been automatically exported, you will be able to run Git commands to commit and push your changes as desired.

Instead of doing all of this yourself, there does seem to be an Open Exchange app available that does something like this. I have not used this before, but @Alexander.Koblov may be able to add more details of how complete it is

Peter
 

Peter Steiwer · Jan 2, 2020 go to post

How can I browse files on the server? My ObjectScript explorer is empty when I open VSCode. I configured my settings properly and it says I am connected

Peter Steiwer · Jan 1, 2020 go to post

You can just check $$$ISERR(sc) directly here, you do not need to run it through $system.Status.GetErrorText(sc)  first.

$$$ISERR(status) will compile into ('status). In the case where sc=1, status will become = "". This means that 'status will evaluate to true when sc=1, which means it will think there is an error when there is not.

USER>set sc=1
 
USER>set status=$system.Status.GetErrorText(sc)
 
USER>zw sc
sc=1
 
USER>zw status
status=""
 
USER>w ('status)
1
USER>w ('sc)
0
Peter Steiwer · Jan 1, 2020 go to post

Hi Vivek,

Does something like this work:

Set file=##class(%Stream.FileBinary).%New()
Set sc=file.LinkToFile("D:/temp/test.png")
w $system.Status.GetErrorText(sc)
set contents=file.Read()
set base64contents=$SYSTEM.Encryption.Base64Encode(contents)
Peter Steiwer · Dec 31, 2019 go to post

Also, I am not sure what the rest of the code looks like, but it will also need to be saved:

set sc=file.%Save()
Peter Steiwer · Dec 31, 2019 go to post

Are you testing this through terminal or your web API? If you are testing through your web API you will need to log the status codes instead of writing them

Peter Steiwer · Dec 31, 2019 go to post

Have you checked the error codes? Is the file being created?

Set file=##class(%Stream.FileBinary).%New()
Set sc=file.LinkToFile(path)
w $system.Status.GetErrorText(sc)
set sc=file.Write(decode)
w $system.Status.GetErrorText(sc)
Peter Steiwer · Dec 31, 2019 go to post

Hi Vivek,

I would suggest using %Stream.FileBinary and then using the LinkToFile method:

Set file=##class(%Stream.FileBinary).%New()
Set sc=file.LinkToFile("c:\myfile.txt")
Do file.Write(decode)
Peter Steiwer · Dec 30, 2019 go to post

@Kejia Lin 
This appears to be a reward on Global Masters. You can also find a quick link at the light blue bar on the top of this page. Once you join Global Masters you can get points for interacting with the community and ultimately use these points to claim rewards, such as the one mentioned here.

Peter Steiwer · Dec 30, 2019 go to post

Hi @Evgeny Shvarov 
 

In Step "2. Install Package Manager client", it says to run the following code:

Do $System.OBJ.Load("/yourpath/zpm.xml")  

It also needs to be compiled and should probably be:

Do $System.OBJ.Load("/yourpath/zpm.xml","ck")
Peter Steiwer · Dec 26, 2019 go to post

Hi Lawrence,

I suggest opening a new WRC with Support. Here are a couple first step diagnosis options that can be helpful, but without a deeper understanding of the DeepSee Engine, it may be difficult to debug or correct the issues.

1) Run MDXUtils and produce a performance report.

This tool will kill your DeepSee Cache and then execute the query. It will log statistics about the query and the cube. It then runs the query a second time which will use the Cache that was just generated. Depending on the query, this can often be much faster.

2) Run DeepSeeButtons.

This will give a snapshot of your entire DeepSee environment. It will also look for recommended configurations and alert if the recommendations are not followed. For example, if the Database your Cache globals are stored in is journaled, this can negatively impact query performance. Lots of globals are modified during query execution, so it is recommended to not have this journaled. If DeepSeeButtons detects that the Database your DeepSee Cache is in is journaled, it will create an alert.

As I mentioned earlier, it is probably a good idea to contact Support, but these are two good steps to start with (and the WRC will probably ask for these as well)

Peter Steiwer · Dec 16, 2019 go to post

Ha, I was planning on making a post tomorrow asking what this was called and how to find more information about it:

Thanks for the information!

Peter Steiwer · Dec 12, 2019 go to post

Would this be for a Development System or a Production System?

If it is a Development System you could consider using source control hooks to basically prevent people from modifying the class unless they first check out the file. If they attempt to modify it without first checking it out, they will get a message saying they need to first check out the file. If they do not have permission to do so, they will not be able to. If they do have permission to, using source control will allow you to revert any changes that end up causing issues.

If it is a Production System, you can consider using deployed mode. See documentation here. The documentation says: "You can open the class definition in Atelier, but it is read-only." (This is true for Studio also).

As you mention, making the Database Read Only is also an option.

Peter Steiwer · Dec 11, 2019 go to post

By the way, after running the populate method, the test method outputs the following:

SAMPLES>do ##class(DCSolutions.TwoWayJSONAdaptor.TeacherStudent).Test()
{"Name":"Peter","Teachers":[{"ID":1,"Teacher":{"Name":"Teacher1Name"}},{"ID":2,"Teacher":{"Name":"Teacher2Name"}}]}
{"Name":"Nael","Teachers":[{"ID":3,"Teacher":{"Name":"Teacher1Name"}},{"ID":4,"Teacher":{"Name":"Teacher3Name"}}]}
{"Name":"Teacher1Name","Students":[{"ID":1,"Student":{"Name":"Peter"}},{"ID":3,"Student":{"Name":"Nael"}}]}
{"Name":"Teacher2Name","Students":[{"ID":2,"Student":{"Name":"Peter"}}]}
{"Name":"Teacher3Name","Students":[{"ID":4,"Student":{"Name":"Nael"}}]}
Peter Steiwer · Dec 11, 2019 go to post

Hi Nael,

I was able to make this work using an XData Map (Documentation here). I have uploaded my Sample to GitHub so you can see how I implemented it. I will also summarize what I did here:

This Sample uses 3 classes: Teacher, Student, and TeacherStudent. As you describe and as your JSON output suggests, Teacher and Student have a reference to TeacherStudent, which simply has an ID. To allow this to output the link to the next object (depending on the direction) I had to use Calculated properties. This means I can access data from TeacherStudent, but I am not storing the references again. The calculations to get the Teacher/Student are pretty simple, just an SQL statement to get the related record. At this point, if you try and use %JSONExport() on a student, it will print out the teachers as expected, but then the teachers print out all the students, and the students print the teachers again. This continues until reaching an error.

To avoid this, I used the XData Map. One map for "Student" and one map for "Teacher". Each is named based on the starting point. When using the Teacher map, the Teacher class will output the name and the link to TeacherStudent. TeacherStudent will then output the name and the link to Student. Student will then output only the name and will not link back to TeacherStudent. The same is true for using the Student map for Student (but going the other way).

I hope this accomplishes what you are looking for!

Peter

Peter Steiwer · Dec 11, 2019 go to post

Here are a couple of ways for getting information about a file:

Get file size:

set file=##class(%Stream.FileBinary).%New()
write file.LinkToPath("C:\temp\test.csv")
write file.Size

Get number of lines:

set file=##class(%Stream.FileBinary).%New()
write file.LinkToPath("C:\temp\test.csv")
while 'file.AtEnd {
    do file.ReadLine()
    set linecount=$i(linecount)
}
write linecount