Writing data scripts with DundasScript
1. Overview
A scripting language called DundasScript is used in Dundas BI and Logi Symphony's Managed Dashboards & Reports for transformations and other customizations at the data level, including formulas, calculated elements, bridge parameters, some data connectors, and script tokens.
This article provides an overview of the DundasScript engine, including some examples and limitations to be aware of.
2. The DundasScript engine
DundasScript can be thought of as a subset of the C# programming language, but its syntax will be familiar if you have used other languages such as Java, JavaScript, or C, and it supports dynamic types.
2.1. Syntax
The DundasScript engine syntax is composed of the following elements:
- Keywords:
break case catch continue default do else false finally for foreach if in is new null return
switch throw true try var while - Built-in data types:
bool byte char decimal double float int long object string
- Operators (with the standard order of operations):
() ++ -- ! * / % + - < > <= >= == != | && || ?? = *= /= += -= |=
- Indexers, to access items in a collection, list, or array.
- Exceptions, to handle errors when the script does something unsupported:
string[] parts; try { parts = someVariable.Split(); } catch( /* NullReferenceException */ ) { parts = new string[]; }
- Generics, if a generic type is registered with the engine (see available types below):
List<int> myIntList = new List<int>(); myIntList.Add(3); myIntList.Add(2); myIntList.Add(1); myIntList.Sort();
- Access to all of an object's public methods, properties, and fields.
- Single dimensional arrays (note that inline array initialization isn't supported):
int[] bunchOfValues = new int[4]; bunchOfValues[0] = 1; bunchOfValues[1] = 1; bunchOfValues[2] = 2; bunchOfValues[3] = 3;
- IEnumerable<> extension methods on lists and other collections (without lambda expressions):
int last = myIntList.Last(); int avg = myIntList.Average();
- Strings, which can be multi-line if you use the @ verbatim identifier for a string literal:
string line = "Regular string"; string multiline = @"Multi line string";
- Both types of comments:
// Describe your code. /* Comments are useful. */
2.2. Numeric values
Numeric values typed into your code without any decimal places are interpreted as integral numbers, or the int type. Include the decimal point, or use f or d to explicitly declare numeric literals as float or double values:
- 12 – integer
- 12f – floating-point
- 12d – double-precision floating-point
The 0x prefix can also be used to specify an integer in hexadecimal digits, for example 0xC for 12.
As in most programming languages, the division of two integers always results in an integer. For example, the resulting value of r in the following script is 2.0 :
double r = 12 / 5;
Use the following script instead to get a result of 2.4 :
double r = 12.0 / 5; // Or: double r = 12d / 5;
2.3. Features
The DundasScript engine implements a custom interpreter. Although close in syntax with C#, it is a dynamically-typed script language. This results in the following features:
- You do not need to know the type of an object or cast it to access one of its properties.
- You can use the var keyword in place of any type name to simplify script.
- You can call static methods on an instance variable.
- There is no variable scoping. This means that if you redefine a variable, it is not an error but the previous value will be overwritten/lost. For example:
// Create a new string: string foo = "Hello world"; if (someCondition) { // From now on, foo is an int, not a string! int foo = 10; }
2.4. Limitations
The following elements are not supported in DundasScript:
- Multidimensional arrays.
- Indexers with multiple parameters.
- Delegates.
- Multiple variable declarations per line.
- Creating user-defined events.
- Nullable types.
- ref and out parameters.
- Lambda expressions.
- The following operators:
& ^ &= ^= >> << >>= <<= typeof sizeof ~x ++x --x
- The conditional operator (x ? y : z).
- Array creation using initializer:
int[] a = new int[] { 1, 2, 3 };
2.5. Standard .NET classes
Only registered types can be used, providing a sandbox that makes it difficult for script to make your project misbehave or crash.
The following classes, structs, and enums are exposed in the DundasScript engine. They access the .NET types directly and have not been re-implemented in the engine. All public methods, properties and fields will work as documented by Microsoft:
- Array — Provides methods for creating, manipulating, searching, and sorting arrays, thereby serving as the base class for all arrays in the common language runtime.
- bool — Boolean value (true or false)
- Boolean — Same as bool.
- byte — An 8-bit unsigned integer.
- Byte — Same as byte.
- CalendarWeekRule — Defines different rules for determining the first week of the year.
- Capture — A single successful subexpression capture.
- char — A single UTF-8 character.
- Char — Same as char.
- Collection<> — A generic collection.
- Color — Describes a color in terms of alpha, red, green, and blue channels.
- Colors — A set of predefined colors such as CornFlowerBlue.
- Convert — Converts a base data type to another base data type.
- CultureInfo — Information about a specific culture, including the names for the culture, the writing system, the calendar used, the sort order of strings, and formatting for dates and numbers.
- DateTime — A date and time value.
- DateTimeKind — Specifies whether a DateTime object represents a local, UTC or unknown time.
- DateTimeOffset — A point in time, typically expressed as a date and time of day, relative to UTC.
- DayOfWeek — Specifies the day of the week.
- decimal — A fixed-precision decimal value.
- Decimal — Same as decimal.
- Dictionary<,> — A collection of keys and values.
- double — A double precision floating-point value.
- Double — Same as double.
- Enum — The base class for enumerations.
- Exception — Errors that occur during application execution.
- float — A single precision floating-point value (faster but less accurate).
- Group — The results from a single capturing group.
- Guid — Represents a globally unique identifier.
- IConvertible — Defines methods that convert the value of the implementing reference or value type to a common language runtime type that has an equivalent value.
- ICollection<> — Defines size, enumarators, and synchronization methods for all generic collections.
- IDictionary<> — A generic collection of key/value pairs.
- IEnumerable<> — Many collection types implement this interface, which provides various helpful extension methods.
- int — A 32-bit signed integer.
- Int16 — A 16-bit signed integer.
- Int32 — A 32-bit signed integer.
- Int64 — A 64-bit signed integer.
- IList<> — A generic collection of objects that can be individually accessed by index.
- IReadOnlyCollection<> — A strongly-typed, read-only collection of elements.
- IReadOnlyDictionary<> — A generic read-only collection of key/value pairs.
- IReadOnlyList<> — A read-only collection of elements that can be accessed by index.
- KeyValuePair<,> — A key/value pair that can be set or retrieved.
- List<> — A list of objects that can be accessed by index.
- long — A 64-bit integer value.
- Match — Represents the results from a single regular expression match.
- Math — Provides constants and static methods for common mathematical functions.
- MidpointRounding — Specifies the strategy that mathematical rounding methods should use to round a number.
- object — The base class of all .NET class hierarchies.
- Object — Same as object.
- Point — an x- and y-coordinate pair in two-dimensional space.
- Random — A pseudo-random number generator.
- Regex — An immutable regular expression.
- RegexOptions — Enumerated values to use to set regular expression options.
- sbyte — An 8-bit signed integer.
- SByte — Same as sbyte.
- short — A 16-bit signed integer.
- Single — A single-precision floating-point number.
- string — A character string.
- String — Same as string.
- StringComparison — The culture, case, and sort rules to be used by certain overloads of the String.Compare and String.Equals methods.
- StringSplitOptions — Whether applicable String.Split method overloads include or omit empty substrings from the return value.
- TimeSpan — Represents a time interval.
- TimeZoneInfo — The time zone in the world.
- uint — A 32-bit signed integer.
- UInt16 — A 16-bit unsigned integer.
- UInt32 — A 32-bit unsigned integer.
- UInt64 — A 64-bit unsigned integer.
- ulong — A 64-bit unsigned integer.
- Uri — An object representation of a uniform resource identifier (URI) and easy access to the parts of the URI.
- UriBuilder — Provides a custom constructor for uniform resource identifiers (URIs) and modifies URIs for the Uri class.
- UriComponents — Specifies the parts of a Uri.
- UriFormat — Controls how URI information is escaped.
- UriHostNameType — Defines the types of host names that can be specified in a URI.
- UriKind — Defines the different kinds of URIs.
- UriPartial — Defines which parts of a URI to get in certain methods.
- ushort — A 16-bit unsigned integer.
You can create new objects using the new keyword for any classes that have been registered with the DundasScript engine.
2.6. Dundas classes
If you need information about the current user's session at the time the script is executing, you can access the variable session.
- session (type: Session) — Represents the current logon session when the script runs.
3. Debugging
To see live values and help with fixing issues with script, you can use the statement #TRACE in your script to pass a value to be entered in the application logs.
For more details, see Using TRACE statements.