Skip to main content
Previous sectionNext section

Introduction to InterSystems IRIS Programming

This book is an orientation guide for programmers. It is not a tutorial but rather a survey of the basic features of server-side programming.

This chapter provides a high-level overview of the language elements you can use in InterSystems IRIS® server-side programs.

Introduction

InterSystems IRIS is a high-performance object database with a built-in general-purpose programming language. It supports multiple processes and provides concurrency control. Each process has direct, efficient access to the data.

In InterSystems IRIS, you can write routines, classes, or a mix of these, as suits your preferences. In all cases, stored data is ultimately contained in structures known as globals (a later section in this chapter discusses these). InterSystems IRIS programming has the following features:

  • Routines and classes can be used interchangeably.

  • Routines and classes can call each other.

  • Classes provide object-oriented features.

  • Database storage is integrated into the programming language.

  • Classes can persist data in a way that simplifies programming. If you use persistent classes, data is simultaneously available as objects, SQL tables, and globals.

  • You can access globals directly from either routines or classes, which means that you have the flexibility to store and access data exactly how you want.

You can choose the approach that is appropriate for your needs.

Routines

When you create routines in InterSystems IRIS, you use ObjectScript. The following shows part of a routine written in ObjectScript:

    SET text = ""
    FOR i=1:5:$LISTLENGTH(attrs)
    {
        IF ($ZCONVERT($LIST(attrs, (i + 1)), "U") = "XREFLABEL")
        {
            SET text = $LIST(attrs, (i + 4))
            QUIT
        }
    }
    
    IF (text = "")
    {
        QUIT $$$ERROR($$$GeneralError,$$$T("Missing xreflabel value"))
    }
Copy code to clipboard

The next chapter provides an introduction to ObjectScript.

Classes

InterSystems IRIS also supports classes. You can use the system classes and you can define your own classes.

In InterSystems IRIS, a class can include familiar class elements such as properties, methods, and parameters (known as constants in other class languages). It can also include items not usually defined in classes, including triggers, queries, and indices.

The following shows a class definition:

Class Sample.Employee Extends Person
{

/// The employee's job title.
Property Title As %String(MAXLEN = 50);

/// The employee's current salary.
Property Salary As %Integer(MAXVAL = 100000, MINVAL = 0);

/// A character stream containing notes about this employee.
Property Notes As %Stream.GlobalCharacter;

/// A picture of the employee
Property Picture As %Stream.GlobalBinary;

/// This method overrides the method in the Person class.
Method PrintPerson() 
{
    Write !,"Name: ", ..Name, ?30, "Title: ", ..Title
    Quit
}

}
Copy code to clipboard

You can use classes from within routines. For example, the following shows part of a routine, in which we refer to the Sample.Person class:

 //get details of requested person; print them
showperson() public {
    set rand=$RANDOM(10)+1        ; rand is an integer in the range 1-10
    write "Your random number: "_rand
    set person=##class(Sample.Person).%OpenId(rand)  
    write !,"This person's name: "_person.Name
    write !,"This person's age: "_person.Age
    write !,"This person's home city: "_person.Home.City
      
    }
Copy code to clipboard

Similarly, a method can invoke a label in a routine. For example:

Method DemoRoutineCall(input) as %String
{
    Set value=$$function^myroutine(input)
    Quit value
}
Copy code to clipboard

Later chapters discuss classes in InterSystems IRIS and the unique capabilities of persistent classes in InterSystems IRIS.

Introduction to Globals

InterSystems IRIS supports a special kind of variable that is not seen in other programming languages; this is a global variable, which is usually just called a global. In InterSystems IRIS, the term global indicates that this data is available to all processes accessing this database. This usage is different from other programming languages in which global means “available to all code in this module.”

The contents of a global are stored in an InterSystems IRIS database. The next chapter introduces these more thoroughly; for now, it is important just to know the following points:

  • A global consists of a set of nodes (in some cases, only one node), identified by subscripts.

    Each node can contain a value.

  • ObjectScript includes functions to iterate through the nodes of a global and quickly access values.

  • A global is automatically stored in the database. When you assign a value to a node of a global variable, the data is written immediately to the database.

  • You can see the contents of a global via an ObjectScript command or via the Management Portal.

Ways to Access Data

In InterSystems IRIS, a database contains globals and nothing else; even code is stored in globals, as described later in this book. At the lowest level, all access to data is done via direct global access — that is, by using commands and functions that work directly with globals.

When you use persistent classes, discussed later in this book, you can create, modify, and delete stored data in either of the following ways:

  • By using methods such as %New(), %Save(), %Open(), and %Delete().

  • By using InterSystems SQL.

Internally, the system always uses direct global access.

InterSystems SQL

InterSystems IRIS provides an implementation of SQL, known as InterSystems SQL.

You can use InterSystems SQL within routines and within methods. To use SQL in these contexts, you can use either or both of the following tools:

  • Dynamic SQL (the %SQL.Statement and %SQL.StatementResult classes), as in the following example:

     SET myquery = "SELECT TOP 5 Name,Home_City FROM Sample.Person ORDER BY Age"
     SET tStatement = ##class(%SQL.Statement).%New()
     SET tStatus = tStatement.%Prepare(myquery)
     SET rset = tStatement.%Execute()
     DO rset.%Display()
     WRITE !,"End of data"
    
    Copy code to clipboard

    You can use dynamic SQL in any context.

  • Embedded SQL, as in the following example:

     &sql(SELECT COUNT(*) INTO :myvar FROM Sample.Person)
     Write myvar
    Copy code to clipboard

    The first line is embedded SQL, which executes an InterSystems SQL query and writes a value into a host variable called myvar.

    The next line is ordinary ObjectScript; it simply writes the value of the variable myvar.

    You can use embedded SQL in ObjectScript routines and in methods written in ObjectScript.

Macros

ObjectScript also supports macros, which define substitutions. The definition can either be a value, an entire line of code, or (with the ##Continue directive) multiple lines. You use macros to ensure consistency. For example:

 #define StringMacro "Hello, World!"

 write $$$StringMacro
Copy code to clipboard

To give you an idea of what can be done in macros, the following example shows the definition of a macro that is used internally:

 #define output1(%str,%lf,%indent) do output^%fm2class(%str,%lf,%indent,$$$display) 
Copy code to clipboard

This macro accepts an argument, as many of them do. It also refers to another macro.

You can use macros in routines as well as in classes. Some of the system classes use them extensively.

Include Files

You can define macros in a routine and use them later in the same routine. More commonly, you define them in a central place. To do this, you create and use include files. An include file defines macros and can include other include files.

The following shows parts of a system include file:

/// Create a success %Status code
#define OK                     1
 
/// Return true if the %Status code is success, and false otherwise
/// %sc - %Status code
#define ISOK(%sc)              (+%sc)
 
/// Return true if the %Status code if an error, and false otherwise
/// %sc - %Status code
#define ISERR(%sc)             ('%sc)
Copy code to clipboard

Then you can do the following:

  • Include the include file at the start of any routine. That routine can refer to the macros defined in the include file.

  • Include the include file at the start of any class. Methods in that class can refer to the macros.

  • Include the include file at the start of any method. That method can refer to the macros.

Note that you use slightly different syntax to include an include file within a class definition. See “Macros and Include Files in Class Definitions,” later in this book.

How These Code Elements Work Together

It is useful to understand how InterSystems IRIS uses the code elements introduced in this chapter.

The reason that you can use a mix of ObjectScript, InterSystems SQL, macros, class definitions, routines, and so on is that InterSystems IRIS does not directly use the code that you write. Instead, when you compile your code, the system generates the code that it uses, which is OBJ code, used by the InterSystems IRIS virtual machine.

There are multiple steps. It is not necessary to know the steps in detail, but the following points are good to remember:

  • The class compiler uses the class definitions and generates INT code.

    In some cases, the compiler generates and saves additional classes, which you should not edit. This occurs, for example, when you compile classes that define web services and web clients.

    The class compiler also generates the class descriptor for each class. The system code uses this at runtime.

  • A preprocessor (sometimes called the macro preprocessor or MPP) uses the include files (not shown in the figure) and replaces the macros. It also handles the embedded SQL in the ObjectScript routines.

    These changes occur in a temporary work area, and your code is not changed.

  • Additional compilers create INT code for the ObjectScript routines. This layer is known as intermediate code. In this layer, all access to the data is done via direct global access.

    INT code is compact but human-readable.

  • INT code is used to generate OBJ code.

    The InterSystems IRIS virtual machine uses this code. Once you have compiled your code, the routines and INT code are no longer necessary for code execution.

  • After you compile your classes, you can put them into deployed mode. InterSystems IRIS has a utility that removes the class internals and the intermediate code for a given class; you can use this utility when you deploy your application.

    If you examine the InterSystems IRIS system classes, you might find that some classes cannot be seen because they are in deployed mode.

Note:

All routines and class definitions are stored in the same InterSystems IRIS databases as the generated code. This fact makes the code easier to manage. InterSystems IRIS provides a robust set of source control hooks that InterSystems developers have used for many years. You can use these hooks as well.