You want to put the order by clause in the sub-query.
- Log in to post comments
You want to put the order by clause in the sub-query.
I'm not sure I understand the objection to %VID. I've seen a few different recommendations on how best to use it, but I think it does what you want in the following example:
select *
from (
select top all *
from Sample.Person
order by DOB
) where %vid between 10 and 19
Regardless of the where or order by clause that you put in the sub-query, %VID refers to the position in the result set.
To handle this in the general case, you would decompose the string, then strip out non-spacing marks. Unicode normalization has been requested previously, and will hopefully make it into the product at some point.
In the following screenshot, I've just typed "prop", a unique prefix of the property template, then pressed Cmd-/ (the Content Assist shortcut for Emacs key bindings on a Mac):
Since its auto insert attribute is on, I expected the template to expand immediately, rather than presenting the popup.
Worth mentioning that O/S authentication is simpler and potentially more secure than fiddling with passwords in a script. If you do prompt for a password, consider using the -s option of the read command to hide the input.
I don't understand what you mean when you say that your clinicians aren't database users, but it sounds like you need to give them access to the %Service_SQL service.
$fromJSON(stream) works for me in 2016.1.0. What problem are you having?
Greetings. Did you consult at InterSystems fifteen years ago? Long time no see.
My favorite technique to keep myself and others honest is to test with random inputs. This gives rise to two challenges: generating the input, and verifying the output. The input obviously depends on the problem: string, number, list, etc. When it comes to output, I look for invariants: x*y=(y*x), sort(x)=sort(shuffle(x)), etc. I sometimes even write another version of the code under test to act as an oracle that's perhaps slower, or not as general.
Caché has at least three ways to generate random numbers: $random(), $system.Encryption.GenCryptRand(), and the Basic Rnd() function.
$random(n) returns a number from 0 to n-1, where n'>1E17.
GenCryptRand(n) returns n bytes of cryptographically random data. You can convert it to a number using one of the $ascii() functions:
Rnd() is interesting for a tester, because you can seed it with Randomize. If you don't use a seeded PRNG, you'll want to log your inputs somehow. It's frustrating to find a one in a billion bug, but not be able to reproduce it.
You really need to consider it on a case by case basis. Some code may assume that $increment() returns a greater value at time t1 than at time t0; e.g.:
https://community.intersystems.com/post/improve-sql-performance-date-range-queries
Christian in QD came up with a bit of a hack for this. You can use one of the DSNs that is installed automatically with the product, but override all of its attributes; e.g.:
s dsn=dsn_";Database="_$namespace_";Port="_^%SYS("SSPort")_";UID="_usn_";PWD="_pwd
To find an existing DSN, use the SQLDataSources query in the %GTWCatalog class.
He used this technique to make the TestODBC() method in the %UnitTest.SQLRegression class more reliable. I don't know for sure that it will work with a different DBMS and driver, but it's worth a shot.
Does this call do what you want?
USER>w $zstrip(pHL7,">","|^")
PID|1|12345||DOE^JOHN
I dug up a pre-dynamic objects version of a utility method from a REST test and cleaned it up a bit (hopefully not introducing any bugs in the process):
ClassMethod compareArrays(ByRef actual, ByRef expected) As %Status [ PublicList = (actual, expected) ]
{
; compare root node
set deix=$d(expected,eval),daix=$d(actual,aval)
if deix'=daix {
quit $$$ERROR($$$GeneralError,"$d(actual)="_daix_" instead of "_deix)
}
if deix#2,aval'=eval {
quit $$$ERROR($$$GeneralError,"actual="""_aval_""" instead of """_eval_"""")
}
set status=$$$OK
set eix="expected",aix="actual"
for i=1:1 {
set eix=$q(@eix),aix=$q(@aix)
quit:""=eix&&(""=aix)
set seix="("_$p(eix,"(",2,*),saix="("_$p(aix,"(",2,*)
if seix'=saix {
set status=$$$ERROR($$$GeneralError,"found """_aix_""" instead of """_eix_""" at position "_i)
quit
}
set deix=$d(@eix,eval),daix=$d(@aix,aval)
if deix'=daix {
set status=$$$ERROR($$$GeneralError,"$d(aix)="_daix_" instead of "_deix_" at position "_i)
quit
}
if deix#2,aval'=eval {
set status=$$$ERROR($$$GeneralError,"actual("""_aix_"""))="""_aval_""" instead of """_eval_""" at position "_i)
quit
}
}
quit status
}
Comparing them, I only see two things I prefer in my version. First, in this line of your method I would use four-argument $piece with * as the fourth argument, just in case the subscript contains "first" or "second":
If ($Piece(tRef1,"first",2) '= $Piece(tRef2,"second",2)) {
Second, I would use a public list with first and second, rather than turning off procedure block for the entire method.
If I thought the root might be an integer, I guess I would just check:
USER>s n=27,root=n**(1/3),int=$fn(root,"",0) w $s(int**3=n:int,1:root)
3
I was also going to suggest trying logarithms, but someone already suggested that on sql.ru:
USER>w 10**($zlog(27)/3)
2.99999999999999997
USER>w $zexp($zln(27)/3)
2.999999999999999998
Unless I've misunderstood the context, it's simpler to use the ERROR macro:
$$$ERROR($$$GeneralError,"DXL Testing Run Error")
You don't need %occErrors.inc to get GeneralError, because of how ERROR (like ERRORCODE) is defined.
You can use the information from %SYS.LockQuery to graph the locks with their owners and waiters. Then do a depth-first traversal of each node, looking for a cycle.
Here's a sketch of building the graph:
s rs=##class(%ResultSet).%New("%SYS.LockQuery:Detail")
s status=rs.Execute()
k graph
f i=1:1 q:'rs.%Next() d
. s ref="L"_i,graph(ref,rs.Owner)=1
. f j=1:1:$l(rs.WaiterPID," ") d
. . s pid=$p(rs.WaiterPID," ",j) s:pid]"" graph(pid,ref)=1
The graph looks something like this:
graph(3330,"L5")=1
graph(4380,"L4")=1
graph("L1",3309)=1
graph("L2",3326)=1
graph("L3",3327)=1
graph("L4",3330)=1
graph("L5",4380)=1
I've generated IDs for the locks to avoid a SUBSCRIPT error for long references. You'll want to keep a list of the original lock names.
Here's a (minimally tested) traversal method that returns an error if it finds a cycle:
ClassMethod dfs(byref graph, node as %String, byref visited) as %Status {
s status=$$$OK
i $d(node) d
. i $d(visited(node)) d q
. . s status=$$$ERROR($$$GeneralError,"found a cycle at node "_node)
. s visited(node)=1
. s next=""
. f s next=$o(graph(node,next)) q:""=next d q:$$$ISERR(status)
. . s status=..dfs(.graph,next,.visited)
e d
. s root=""
. f s root=$o(graph(root)) q:""=root d q:$$$ISERR(status)
. . k visited
. . s status=..dfs(.graph,root,.visited)
q status
}
If you try it on the previous graph, it will return an error like the following:
USER>s status=##class(deadlock).dfs(.graph)
USER>d $system.OBJ.DisplayError(status)
ERROR #5001: found a cycle at node L5
Ugly as they are, naked references can significantly improve performance for repeated references to the same subscript level of a global.
In general, no, you can't apply string functions directly to streams. I found one such enhancement request from eight years ago that has since been closed. (There may have been others.)
For the specific case of $replace, it should be straightforward to implement Eduard's suggestion using the FindAt() method.
If you want to wait for either a signal or for termination of a process, you can use a lock:
You may need an extra synchronization step between steps 1 and 2 to ensure that A gets the lock before B does.
In steps 2 and 4, multiples processes can wait for a shared lock on the same name, and they will all be triggered at the same time.
$lts and $lfs are the abbreviated forms of $listtostring and $listfromstring, respectively. $lb(1,2,3,",",5) returns a string, which seems to be what you want. I don't understand why you are then converting it to a delimited string with $listtostring.
Even after looking at Timur and Eduard's answers, I don't understand the question. $lb(1,2,3,",",5) returns a string. Why are you trying to round trip it through a delimited string using $lts and $lfs?
A quick test suggests that data migration is indeed required after changing the type of a property from %GlobalCharacterStream to %Stream.GlobalCharacter.
I imagine the supported way to migrate is to make a new stream field and copy from the old field using CopyFrom(). I'd be tempted to diddle the stream references to point to the existing data. In any case, if it ain't broke ...
Looks like the class has been described as deprecated since 2012.1.
See the discussion in this previous post:
https://community.intersystems.com/post/unittest
Basically, you can use the /noload and /nodelete qualifiers, specifying the tests by class name. Be aware that if you forget the /nodelete qualifier, you'll delete your test classes.
You're asking two things: how to persist an object, and how to implement a singleton.
A global on its own is not able to save an object. Something needs to map the structure of its class to a global layout of some kind. The simplest way to do this is to subclass %Persistent, rather than %RegisteredObject, then call %Save().
I notice, however, that you're using %ZEN.proxyObject, presumably to avoid defining a class/schema upfront. In that case, you may be interested in looking at the document data model (DocDM) in the 2016.2 field test.
As for implementing a singleton, it depends on the context. In general, I would look at overriding %OnNew() to load an existing object if it exists. If you want to persist its state, you'll need to consider concurrency.
This indicator is new in 2016.1.
The /exportversion qualifier probably would not have helped in this case. It just strips new keywords from the class definition.
Are you aware of the /exportversion qualifier (documentation for which is hidden in the COS reference for the $system variable)? If your code is otherwise portable, this qualifier is intended to allow "reverse flow" of code by omitting anachronisms during XML export.
Visual Studio Code got a lot of praise in a recent Hacker News discussion of an extension for the Go language. One user mentioned that the PHP extension is quite good, and works well with XDebug. It's also supposed to be good for JavaScript and TypeScript.
I've been using Xamarin Studio to write NUnit tests (C#) on the Mac. I loaded the project into VSC, and it's not bad. It doesn't seem particularly fast or lightweight, as some have claimed, but it's adequate. OmniSharp is included, so you can hover over method calls to see the signature, and each method definition is preceded by a count of how many times it's called.
Java support is not nearly as good out of the box, but there may be some extensions to improve that.
For COS, you could probably configure a task runner to use Atelier's REST APIs to save and compile files to a server. Syntax highlighting and debugging would take some doing, but the hope is that Atelier will scratch that itch better than VSC ever could.
I'd say that Visual Studio Code doesn't have enough to lure me away from Emacs for any extended period of time, but it's a capable, extensible editor.
Different people are going to have different workflows for unit testing, but I would encourage you to settle on a way to get those tests out of the database. I'd be nervous about running tests in a namespace that contains my only copy, since %UnitTest is designed to load and delete by default.
If you're using Studio with the source control hooks, it works pretty well to write the tests in a development namespace, then run them in a test namespace.