├── COSQuickRef.md
├── LICENSE
└── README.md
/COSQuickRef.md:
--------------------------------------------------------------------------------
1 | # Caché ObjectScript Quick Reference
2 | A list of some common ObjectScript expressions
3 |
4 | ## Object/SQL Basics
5 |
6 | | Action | Code |
7 | |----------------------------------------------|-----------------------------------------------------------------------------------|
8 | | Call a class method | `Do ##class(package.class).method(arguments)`
`Set variable = ##class(package.class).method(arguments)`
Note: place a . before each pass-by-reference argument |
9 | | Call an instance method | `Do object.method(arguments)`
`Set variable = object.method(arguments)`
Note: place a . before each pass-by-reference argument |
10 | | Create a new object | `Set object = ##class(package.class).%New()` |
11 | | Open an existing object | `Set object = ##class(package.class).%OpenId(id, concurrency, .status)` |
12 | | Open an existing object by unique index value| `Set object = ##class(package.class).IndexNameOpen(value, concurrency, .status)` |
13 | | Save an object | `Set status = object.%Save()` |
14 | | Retrieve the ID of a saved object | `Set id = object.%Id()` |
15 | | Retrieve the OID of a saved object | `Set oid = object.%Oid()` |
16 | | Retrieve property of a saved object | `Set variable = ##class(package.class).GetStoredPropertyName(id)` |
17 | | Determine if an object was modified | `Set variable = object.%IsModified()` |
18 | | Validate an object without saving | `Set status = object.%ValidateObject()` |
19 | | Validate a property without saving | `Set status = ##class(package.class).PropertyIsValid(object.Property)` |
20 | | Print status after error | `Do $system.Status.DisplayError(status)`
`Write $system.Status.GetErrorText(status)` |
21 | | Obtain status details after error | `Do $system.Status.DecomposeStatus(status, .err)` |
22 | | Remove an object from process memory | `Set object = ""` |
23 | | Delete an existing object of a class | `Set status = ##class(package.class).%DeleteId(id)` |
24 | | Delete all saved objects of a class | `Do ##class(package.class).%DeleteExtent()`
`Do ##class(package.class).%KillExtent()` |
25 | | Reload properties of a saved object | `Do object.%Reload()` |
26 | | Clone an object | `Set clonedObject = object.%ConstructClone()` |
27 | | Write a property | `Write object.property` |
28 | | Set a property | `Set object.property = value` |
29 | | Write a class parameter | `Write ##class(package.class).#PARAMETER` |
30 | | Set a serial (embedded) property | `Set object.property.embeddedProperty = value` |
31 | | Link two objects | `Set object1.referenceProperty = object2` |
32 | | Populate a class | `Do ##class(package.class).Populate(count, verbose)` |
33 | | Remove all objects in process memory | `Kill` |
34 | | List all objects in process memory | `Do $system.OBJ.ShowObjects()` |
35 | | Display all properties of an object | `Do $system.OBJ.Dump(object)`
`Zwrite object` (v2012.2+) |
36 | | Determine If variable is an object reference | `If $isobject(variable) ; 1=yes, 0=no` |
37 | | Find classname of an object | `Write $classname(oref)` |
38 | | Start the SQL shell | `Do $system.SQL.Shell()` |
39 | | Test a class query | `Do ##class(%ResultSet).RunQuery(class, query)` |
40 | | Declare a variable's type for Studio Assist | `#dim object as package.class` |
41 |
42 | ## ObjectScript Commands
43 |
44 | | Command | Description |
45 | |-------------------------------|-------------------------------------------------------------------------------------|
46 | | `Write` | Display text strings, value of variable or expression |
47 | | `Zwrite` | Display array, list string, bit string |
48 | | `Set` | Set value of variable |
49 | | `Do` | Execute method, procedure, or routine |
50 | | `Quit` or `Return` (v2013.1) | Terminate method, procedure, or routine. Optionally return value to calling method |
51 | | `Continue` | Stop current loop iteration, and continue looping |
52 | | `Halt` | Stop Caché process and close Terminal |
53 | | `Kill` | Destroy variable(s) |
54 | | `If {} ElseIf {} Else {}` | Evaluate conditions and branch |
55 | | `For {}`, `While {}`, `Do {} While` | Execute block of code repeatedly |
56 | | `Try {} Catch {}`, `Throw` | Handle errors |
57 |
58 | ## ObjectScript Date/Time Functions and Special Variables
59 |
60 | | Action | Code |
61 | |--------------------------------------------------|-------------------------------------------------------------|
62 | | Date conversion (external → internal) | `Set variable = $zdh("mm/dd/yyyy")` |
63 | | Date conversion (internal → external) | `Set variable = $zd(internalDate, format)` |
64 | | Time conversion (external → internal) | `Set variable = $zth("hh:mm:ss")` |
65 | | Time conversion (internal → external) | `Set variable = $zt(internalTime, format)` |
66 | | Display current internal date/time string | `Write $horolog` |
67 | | Display UTC date/time string | `Write $ztimestamp` |
68 | | Get the date relative to other date (any type) | `Write $system.SQL.DATEADD("hh", -4, "yyyy-mm-dd hh:mm:ss")` |
69 | | Get the difference between two dates (any type) | `Write $system.SQL.DATEDIFF("hh", horolog-or-ztimestamp, horolog-or-ztimestamp)`|
70 |
71 | ## ObjectScript Branching Functions
72 |
73 | | Action | Code |
74 | |--------------------------------------------------|------------------------------------------------------------------------|
75 | | Display result for value of expression | `Write $case(expression, value1:result1, value2:result2, …, :resultN)` |
76 | | Display result for first true condition | `Write $select(condition1:result1, condition2:result2, …, 1:resultN)` |
77 |
78 | ## ObjectScript String Functions
79 |
80 | | Action | Code |
81 | |----------------------------------------------------------|---------------------------------------------------------------|
82 | | Display substring extracted from string | `Write $extract(string, start, end)` |
83 | | Display right-justified string within width characters | `Write $justify(string, width)` |
84 | | Display length of string | `Write $length(string)` |
85 | | Display number of delimited pieces in string | `Write $length(string, delimiter)` |
86 | | Display piece from delimited string | `Write $piece(string, delimiter, pieceNumber)` |
87 | | Set piece into delimited string | `Set $piece(string, delimiter, pieceNumber) = piece` |
88 | | Display string after replacing substring | `Write $replace(string, subString, replaceString)` |
89 | | Display reversed string | `Write $reverse(string)` |
90 | | Display string after replacing characters | `Write $translate(string, searchChars, replaceChars)` |
91 | | Build a list | `Set listString = $listbuild(list items, separated by comma)` |
92 | | Retrieve an item from a list | `Set variable = $list(listString, position)` |
93 | | Retrieves elements sequentially from a list | `Set pointerToNextElement = 0`
`While = $ListNext(listString, pointerToNextElement, value) {}` |
94 | | Put item into list string | `Set $list(listString, position) = substring` |
95 | | Display the length of a list | `Write $listlength(listString)` |
96 | | Search a value in a list | `Write $listfind(listString, value)` |
97 | | Build a list from a string | `Set listString = $listFromString(string, delimiter)` |
98 |
99 | ## ObjectScript Existence Functions
100 |
101 | | Action | Code |
102 | |--------------------------------------------------|-------------------------------------------------------------|
103 | | Check if variable exists | `Write $data(variable)` |
104 | | Return value of variable, or default If undefined | `Write $get(variable, default)` |
105 | | Return next valid subscript in array | `Write $order(array(subscript))` |
106 |
107 | ## Additional ObjectScript Functions
108 |
109 | | Action | Code |
110 | |--------------------------------------------------|---------------------------------------------------------------------|
111 | | Increment ^global by increment | `$increment(^global, increment)`
`$sequence(^global)` |
112 | | Match a regular expression | `Set matches = $match(string, regularexpression)` |
113 | | Display random integer from start to start+count | `Write $random(count) + start` |
114 |
115 | ## ObjectScript Special Variables
116 |
117 | | Action | Code |
118 | |-----------------------------------|---------------------------------------|
119 | | Display process ID | `Write $job` |
120 | | Display current namespace | `Write $namespace` |
121 | | Change current namespace | `Set $namespace = newnamespace` |
122 | | Display username | `Write $username` |
123 | | Display roles | `Write $roles` |
124 |
125 | ## Utilities
126 |
127 | | Action | Code |
128 | |-----------------------------------|---------------------------------------|
129 | | Change current namespace | `Do ^%CD`
`zn "newnamespace"` |
130 | | Display a ^global | `Do ^%G`
`zwrite ^global` |
131 |
132 | ## Collections
133 |
134 | | Action | Code |
135 | |--------------------------------------------------------------|------------------------------------------------------------------------------------------------------------|
136 | | Create a new standalone list
Work with a list property | `Set listObject=##class(%ListOfDataTypes).%New()`
Use methods below on a list collection property |
137 | | Insert an element at the end of a list | `Do listObject.Insert(value)`
`Do object.listProperty.Insert(value)` |
138 | | Insert an element into a list | `Do listObject.SetAt(value, position)`
`Do object.listProperty.SetAt(value, position)` |
139 | | Remove an element from a list | `Do listObject.RemoveAt(position)`
`Do object.listProperty.RemoveAt(position)` |
140 | | Display an element of a list | `Write listObject.GetAt(position)`
`Write object.listProperty.GetAt(position)` |
141 | | Display the size of a list | `Write listObject.Count()`
`Write object.listProperty.Count()` |
142 | | Clear all the elements of a list | `Do listObject.Clear()`
`Do object.listProperty.Clear()` |
143 | | Create a new standalone array
Work with an array property | `Set arrayObject=##class(%ArrayOfDataTypes).%New()`
Use methods below on an array collection property |
144 | | Insert an element into an array | `Do arrayObject.SetAt(value, key)`
`Do object.arrayProperty.SetAt(value, key)` |
145 | | Remove an element from an array | `Do arrayObject.RemoveAt(key)`
`Do object.arrayProperty.RemoveAt(key)` |
146 | | Display an element of an array | `Write arrayObject.GetAt(key)`
`Do object.arrayProperty.GetAt(key)` |
147 | | Display the size of an array | `Write arrayObject.Count()`
`Do object.arrayProperty.Count()` |
148 | | Clear all elements of an array | `Do arrayObject.Clear()`
`Do object.arrayProperty.Clear()` |
149 |
150 | ## Relationships
151 |
152 | | Action | Code |
153 | |-----------------------------------------|--------------------------------------------------------------------------------------------------------------|
154 | | Parent-to-children object linking | `Do parentObject.childRefProperty.Insert(chilDobject)`
`Set chilDobject.parentRefProperty = parentObject` |
155 | | One-to-many object linking | `Do oneObject.manyRefProperty.Insert(manyObject)`
`Set manyObject.OneRefProperty = OneObject` |
156 | | Write a property of a child object | `Write parentObject.childRefProperty.GetAt(position).property` |
157 | | Write a property of a many object | `Write oneObject.manyRefProperty.GetAt(position).property` |
158 | | Display the count of child/many objects | `Write parentObject.childRefProperty.Count()`
`Write oneObject.manyRefProperty.Count()` |
159 | | Open a many/child object directly | `Set object = ##class(package.class).IDKEYOpen(parentID, childsub)` |
160 | | Retrieve the id of a child object | `Set status = ##class(package.class).IDKEYExists(parentID, childsub, .childID)` |
161 | | Clear the child/many objects | `Do parentObject.childRefProperty.Clear()
Do oneObject.manyRefProperty.Clear()` |
162 |
163 | ## Streams
164 |
165 | | Action | Code |
166 | |-------------------------------------------|---------------------------------------------------------------------------------------|
167 | | Create a new stream | `Set streamObject=##class(%Stream.GlobalCharacter).%New()`
`Set streamObject=##class(%Stream.GlobalBinary).%New()`
Use methods below on a stream property |
168 | | Add text to a stream | `Do streamObject.Write(text)`
`Do object.streamProperty.Write(text)` |
169 | | Add a line of text to a stream | `Do streamObject.WriteLine(text)`
`Do object.streamProperty.WriteLine(text)` |
170 | | Read len characters of text from a stream | `Write streamObject.Read(len)`
`Write object.streamProperty.Read(len)` |
171 | | Read a line of text from a stream | `Write streamObject.ReadLine(len)`
`Write object.streamProperty.ReadLine(len)` |
172 | | Go to the beginning of a stream | `Do streamObject.Rewind()`
`Do object.streamProperty.Rewind()` |
173 | | Go to the end of a stream, for appending | `Do streamObject.MoveToEnd()`
`Do object.streamProperty.MoveToEnd()` |
174 | | Clear a stream | `Do streamObject.Clear()`
`Do object.streamProperty.Clear()` |
175 | | Display the length of a stream | `Write streamObject.Size`
`Write object.streamProperty.Size` |
176 |
177 | ## Unit Testing Macros
178 |
179 | | Action | Code |
180 | |-----------------------------|--------------------------------------------------|
181 | | Assert equality | `Do $$$AssertEquals(value1, value2, message)` |
182 | | Assert inequality | `Do $$$AssertNotEquals(value1, value2, message)` |
183 | | Assert status is OK | `Do $$$AssertStatusOK(status, message)` |
184 | | Assert status isn't OK | `Do $$$AssertStatusNotOK(status, message)` |
185 | | Assert condition is true | `Do $$$AssertTrue(condition, message)` |
186 | | Assert condition isn't true | `Do $$$AssertNotTrue(condition, message)` |
187 | | Log message | `Do $$$LogMessage(message)` |
188 |
189 | ## Other Macros
190 |
191 | | Action | Code |
192 | |----------------------------------|-------------------------------------------|
193 | | Return a good status | `Quit $$$OK` |
194 | | Return an error status | `Quit $$$ERROR($$$GeneralError, message)` |
195 | | Throw exception on error | `$$$ThrowOnError(status, code)` or `$$$TOE(status, code)` |
196 | | Check if status is good | `If $$$ISOK(status)` |
197 | | Check if status is an error | `If $$$ISERR(status)` |
198 | | Return a null object reference | `Quit $$$NULLOREF` |
199 | | Place a new line within a string | `Write string1_$$$NL_string2` |
200 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 InterSystems Corp.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Caché ObjectScript Code Guidelines
2 |
3 | This is the first approximation of Caché ObjectScript guidelines we use for github.com/intersystems-ru projects. There are mandatory and recommended parts.
4 |
5 | We do not plan to be very restrictive, but want be rather flexible enough and allow any *reasonable* style.
6 | Here is the general advice: use common sense and try to *be consistent* wherever you write code.
7 | If there is some style already established in the class or utility being modified then we recommend
8 | to continue use that same style, than introducing yet another one, which may be more recommended
9 | but which will be introducing some unnecessary inconsistency.
10 |
11 | ## Quick Reference Guide
12 |
13 | For Caché ObjectScript quick reference guide see [here](COSQuickRef.md).
14 |
15 | ## Mandatory Part
16 |
17 | * Only "modern" syntax permitted, dotted syntax is not generally allowed (with few exceptions);
18 | * No short name for statements keywords or built-in functions allowed - use fully expanded names;
19 | * Comment your code appropriately, use English in comments to make your code easy to understand by your international colleagues. Same English-based rule applies to global, local, and type names.
20 |
21 | ## Recommended Part
22 | * We recommend to use fully expanded keyword or function name in lower case or capitalized. Whatever you'll select should be consistent across class or utility, i.e.
23 | ```
24 | If (expression) {
25 | Do ##class(Sample).%New(initexpresion)
26 | For i=1:1:10 {
27 | Write something, $ZVersion, !
28 | }
29 | }
30 | ```
31 | or
32 |
33 | ```
34 | if (expression) {
35 | do ##class(Sample).%New(initexpresion)
36 | for i=1:1:10 {
37 | write something, $zversion, !
38 | }
39 | }
40 | ```
41 | * We recommend to use fully qualified package name of a class (except `%Library` package)
42 | ```
43 | Set obj = ##class(Sample.Person).%New(initexpresion)
44 | ```
45 | instead of
46 | ```
47 | Set obj = ##class(Person).%New(initexpresion)
48 | ```
49 | * In general, use the reasonable name convention consistently across whole hierarchy. We recommend to use CamelCase for classes, methods and properties (e.g. `Sample.Person`, `OpenFile`, `LastIndex`, etc.), but smallCamelCase for local variables (e.g. `startDate`, `endDate`), but please be consistent and use local schema if it's different than current recommendation.
50 | * We recommend to use `#dim` statement for declaration of local variables types, e.g.
51 | ```
52 | #dim array as %ArrayOfDataTypes = ##class(%ArrayOfDataTypes).%New()
53 | do array.SetAt(id, "id")
54 | #dim status As %Status = $$$OK
55 | ```
56 | This will help editor to provide better auto-complete, and eventually will be used by static checker for type information extraction.
57 | * Please indent blocks reasonably. We recommend to use 8, 4 or 2 spaces indentations. Pick your level, and apply consistently.
58 | ```
59 | if (expression) {
60 | do ..Method(args...)
61 | set i = j + 1
62 | } else {
63 | while (condition) {
64 | write arg1, arg2, !
65 | }
66 | }
67 | ```
68 | * For better readability please insert spaces after comma in functions/methods argument list, i.e.
69 | ```
70 | Write 1, 2, 3
71 | Do ..Method(arg1, arg2, argN)
72 | ```
73 | For obvious reasons this recommendation not applies to arguments in `$$$macro`-call, where such extra spaces will break final result.
74 | * For better readability please insert spaces around assignment. You may align several neighbour assignments according to your tastes, i.e.
75 | ```
76 | #dim index As %Integer = 0
77 | #dim countOfItems As %Integer = ..Count()
78 | set j = k + 1
79 | set iN = jN \ l
80 | ```
81 |
82 | ## Related discussion
83 | [Standards document for Objectscript developers](https://community.intersystems.com/post/standards-document-objectscript-developers)
84 |
--------------------------------------------------------------------------------