go to post Timothy Leavitt · Aug 18, 2017 Yes: select ID from %Dictionary.StorageSQLMapDefinition If I may ask - why?
go to post Timothy Leavitt · Aug 17, 2017 To provide server-side enforcement as well (from a security perspective, in addition to what you have client-side to provide a nicer experience for well-behaved users), you should be able to use %CSP.SessionEvents with OnLogin overridden to check a global (or something) and return an error set %session.EndSession = 1 if logins are disabled. This class would need to be set up for the web application(s) through which your application is accessed - see "Event Class" here.
go to post Timothy Leavitt · Aug 3, 2017 When working with files, it's much better to use %Stream classes rather than an instance of %Library.File. If you're looking to get the attributes of a file/directory, the Attributes method in %Library.File is probably your best option. According to the class reference (which has all the details), it returns a combination of bits, the meaning of which varies depending on the operating system. This is kind of ugly, but here's an example on Windows: USER>set attributes = ##class(%Library.File).Attributes("C:\Users\tleavitt\AppData\") USER>w attributes 8210 USER>for i=0:1:16 { w:$zboolean(attributes,2**i,1) 2**i,! } 2 16 8192 According to the class reference, this is a directory (16) that is hidden (2) and not indexed (8192). %Library.File also has some OS-independent classmethods that may be easier to use for simpler things like seeing if a file is read-only.
go to post Timothy Leavitt · Aug 1, 2017 In a bit of testing, I was able to see this by using the wrong protocol - i.e., navigating to the web socket directly in the browser, or using http or https in the client code when it should be ws or wss. The "client code" in the documentation you linked should go in a separate page (CSP or just plain old HTML/JS) from the class that extends %CSP.WebSocket, and navigating to /csp/user/MyApp.MyWebSocketServer.cls (as in that example) directly will not work.If that isn't clear or doesn't solve the problem, could you share your code and your Caché version ($zv)? Your web server and browser version may also be relevant, since web sockets are fairly new.
go to post Timothy Leavitt · Jul 18, 2017 To expand on Rubens' comment about a variable arity of arguments, I often use the following pattern: Set tQuery = "select fields from some_table" Set tWhereList = "" If (pFilter1 '= "") { Set tWhereList = tWhereList_$ListBuild("field1 = ?") Set tArgs($i(tArgs)) = pFilter1 } If (pFilter2 '= "") { Set tWhereList = tWhereList_$ListBuild("field2 = ?") Set tArgs($i(tArgs)) = pFilter2 } // and so on... If (tWhereList '= "") { Set tQuery = tQuery_" "_$ListToString(tWhereList," and ") } Set tResult = ##class(%SQL.Statement).%ExecDirect(,tQuery,tArgs...) Perhaps also generating and appending an ORDER BY similarly. Regarding other comments about multiple uses of the same parameter value, an approach I've seen used for that is to JOIN to a list of parameters - something like: select t.fields from some_table t join (select ? as field1, ? as field2) params where t.field1 = params.field1 and t.field2 = params.field2 and Some_Stored_Procedure(t.field3,params.field1) > params.field2 This is perhaps a little more readable/maintainable than trying to keep track of what all the ?'s mean when the query expects the same value to be repeated multiple times. I can imagine a similar general pattern for building such queries dynamically (e.g., build an array of parameters by name, then construct the subquery for the join and add values to the tArgs array in the order they appear in that subquery).
go to post Timothy Leavitt · Jul 11, 2017 Thanks, Ray! This sounds really promising.(To confirm: it ended up working.)
go to post Timothy Leavitt · Jul 11, 2017 That does look useful, but I'm looking to compare all the globals in two databases (the output of different but theoretically equivalent build processes) to see if some globals are present from one / missing in another or if the contents of any are different, and (if so) what the differences are.
go to post Timothy Leavitt · Jun 26, 2017 The Caché installation directory is easy: USER>w $System.Util.InstallDirectory() c:\intersystems\healthshare_4\ The OS version is OS-dependent. On Windows only: USER>write $System.Util.GetOSVersionInfo() 6.1.7601 On Unix: USER>set sc = ##class(%Net.Remote.Utility).RunCommandViaZF("uname -r",,.tOutput) write tOutput 2.6.32-220.el6.x86_64 USER>set sc = ##class(%Net.Remote.Utility).RunCommandViaZF("lsb_release -a",,.tOutput) write tOutput LSB Version: :core-4.0-amd64:core-4.0-noarch:graphics-4.0-amd64:graphics-4.0-noarch:printing-4.0-amd64:printing-4.0-noarch Distributor ID: RedHatEnterpriseServer Description: Red Hat Enterprise Linux Server release 6.2 (Santiago) Release: 6.2 Codename: Santiago
go to post Timothy Leavitt · Jun 26, 2017 At a low level, there are two options:Pipes / command pipes - useful if you want to be able to read command output OR write to the command. Unfortunately, you have to pick one or the other. To answer Nikita's question - maybe there's some tricky way around this by building a command that redirects stdout to a file, which is read using a separate device?$zf(-1) / $zf(-2) - these are a little bit easier to use. $zf(-1) spawns a child process and waits for it to return; $zf(-2) doesn't wait.Needless to say, if you're building these into an application, make sure that you're careful about building user input into the commands that you execute.
go to post Timothy Leavitt · Jun 23, 2017 System-wide: Set ^%oddENV("callererrorinfo")=1 Or for the current namespace: Set ^%oddENV("callererrorinfo",$namespace)=1 For more information, see macro definitions in %occEnvironment.inc. You can also set this global to 2 instead of 1, which has the side effect of including a full stack trace when a %Status is converted to a human-readable string (e.g., via $System.Status.GetErrorText()). This is handy for debugging, but probably not something to use on a production system (since it could end up exposing more information about your code than you'd really want).
go to post Timothy Leavitt · Jun 22, 2017 I can't think of a built-in stored procedure for this, but it would be relatively simple to create one to wrap $System.Encryption.SHAHash(bitlength, text). For example, approximating HASHBYTES with the features built in to $System.Encryption: Class DC.Demo.SQL { ClassMethod HashBytes(pAlgorithm As %String, pText As %String) As %Binary [ SqlProc ] { // Note: will result in <ILLEGAL VALUE> if pAlgorithm is not supported Quit $Case($ZConvert(pAlgorithm,"L"), "md5":$System.Encryption.MD5Hash(pText), "sha":$System.Encryption.SHA1Hash(pText), "sha1":$System.Encryption.SHA1Hash(pText), "sha2_256":$System.Encryption.SHAHash(256,pText), "sha2_512":$System.Encryption.SHAHash(512,pText)) } } Use (in SAMPLES): select top 5 Name,DC_Demo.SQL_HashBytes('sha2_512',DOB) from Sample.Person
go to post Timothy Leavitt · Jun 19, 2017 Not the most creative output: USER>write ##class(ITPlanet.BlackBox).Main(<left as a mystery>,<also left as a mystery>) Hello World! @Eduard, I'm assuming you don't want spoilers here beyond that? One non-spoiler: there are actually two valid options for the first argument that will produce this output.
go to post Timothy Leavitt · Jun 15, 2017 A common and simple approach is to Base64-encode binary data. See $System.Encryption.Base64Encode()/$System.Encryption.Base64Decode(), plus the atob and btoa functions in JavaScript (maybe not relevant in your particular case, depending on what the client is).
go to post Timothy Leavitt · Jun 12, 2017 For a more direct approach, see the class query %SYS.ProcessQuery:PPG - it's not [SqlProc] so you need to call it the old-fashioned way. For example: Terminal 1: USER>w $j 10740 USER>s ^||demo(2)=5,^||demo=2 USER>zw ^||demo ^||demo=2 ^||demo(2)=5 Terminal 2: %SYS>set rs = ##class(%ResultSet).%New("%SYS.ProcessQuery:PPG") %SYS>set sc = rs.Execute("demo",10740) %SYS>while rs.%Next() { do rs.%Print() } demo 2 demo(2) 5
go to post Timothy Leavitt · Jun 7, 2017 Generally speaking, the parameters defined in %ZEN.DataModel.objectModelParameters can be used to customize the appearance/behavior/really anything about the controls in a dynaForm. One such parameter is: /// Optional. /// id of a group component that the control used for this property /// should be added to. This provides a way to control layout.<br> /// If not defined, the control is added directly to the <class>dynaForm</class>. Parameter ZENGROUP As STRING; For example, given the model class: Class DC.Demo.ZenDynaForm.Model Extends %ZEN.DataModel.ObjectDataModel { Property FirstName As %String(ZENGROUP = "nameGroup"); Property MiddleInitial As %String(ZENGROUP = "nameGroup"); Property LastName As %String(ZENGROUP = "nameGroup"); Property HomePhone As %String(ZENGROUP = "phoneGroup"); Property CellPhone As %String(ZENGROUP = "phoneGroup"); } The following <dynaForm> will display the three name fields in one horizontal row, and the two phone fields in another: Class DC.Demo.ZenDynaForm Extends %ZEN.Component.page { /// This XML block defines the contents of this page. /// Setting XMLNamespace turns on StudioAssist for this XML block. XData Contents [ XMLNamespace = "http://www.intersystems.com/zen" ] { <page xmlns="http://www.intersystems.com/zen"> <dataController id="myController" modelClass="DC.Demo.ZenDynaForm.Model" /> <dynaForm controllerId="myController"> <hgroup id="nameGroup" /> <hgroup id="phoneGroup" /> </dynaForm> </page> } }
go to post Timothy Leavitt · Jun 7, 2017 Here's some relevant documentation, if I'm understanding your question correctly: http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GZAP_customizationThere are two topics covered here: custom Zen components, which have their own HTML rendering, and composite components, which are simply reusable groupings of other Zen components.These really wouldn't be "system-defined" - you'd have them in a separate XML namespace and they'd be distinct from the "system-defined" Zen component classes, but they can be used in the same page alongside standard Zen components.
go to post Timothy Leavitt · Jun 6, 2017 19 in non-expression mode: Set ^oddDEF("ITPlanet.Task2","m","main",30,1)=" q $lg("""_$c(7,4)_"ê"_$c(22)_"°L"_$c(2)_""")" Do $System.OBJ.Compile("ITPlanet.Task2") The actual class code contains a few control characters, but not ASCII 0-9.