Skip to main content

First Look: Globals

This First Look introduces you to the concept of globals, the underlying storage structure for the InterSystems IRIS® data platform. It will show you how to access globals using a relational model and an object model, as well as how to access the globals directly.

To browse all of the First Looks, including those that can be performed on a free evaluation instance of InterSystems IRIS, see InterSystems First Looks.

What Are Globals?

One of the hallmarks of the InterSystems IRIS data platform is its ability to store data once and allow you to access it using multiple paradigms. For example, you can use InterSystems SQL to visualize your data as rows and columns, or you can use ObjectScript and think of your data in terms of objects that have properties and methods. Your application can even mix both data models, using whichever model is easiest and more efficient for a given task. But no matter how you access your data, InterSystems IRIS stores it in underlying data structures known as globals.

Globals can be thought of as persistent multidimensional sparse arrays:

  • Persistent — Globals are stored in the database and can be retrieved at any time, by any process that can access that database.

  • Multidimensional — The nodes in a global can have any number of subscripts. These subscripts can be integers, decimal numbers, or strings.

  • Sparse — Node subscripts do not have to be contiguous, meaning that subscripts without a stored value do not use any storage.

Nodes in a global can store many types of data, including:

  • Strings

  • Numeric data

  • Streams of character or binary data

  • Collections of data, such as lists or arrays

  • References to other storage locations

Even the server-side code you write is ultimately stored in globals!

Why Learn About Globals?

While it is possible to write an application on the InterSystems IRIS platform with little or no knowledge of globals, there are several reasons why you may want to learn more about them:

  • Some operations may be easier or more efficient if you access globals directly.

  • You may want to create custom data structures for data that does not conform to relational or object data models.

  • Some system administration tasks are done at the global level, and understanding globals will make these tasks more meaningful to you.

Try It: Accessing Globals Three Ways

In this First Look, you will examine the globals used to store data for objects of a class of U.S. states. Properties of the class include the name of the state, its two-letter postal abbreviation, its capital, the year it was established, and its area (in square miles). Then you will access and store objects of this class using relational and object techniques, as well as by manipulating the globals directly.

Before You Begin

To use this First Look, you will need a running InterSystems IRIS instance. Your choices include several types of licensed and free evaluation instances; the instance need not be hosted by the system you are working on (although your system must be able to access the instance over a network). For information on how to deploy each type of instance if you do not already have one to work with, see Deploying InterSystems IRIS in InterSystems IRIS Basics: Connecting an IDE.

You also need to know:

  • The URL of the instance’s web-based Management Portal, the system administration user interface for InterSystems IRIS.

  • How to access the Terminal, the InterSystems IRIS command-line tool.

  • Your username and password for the instance (not required for a web instance on InterSystems Labs).

You will also need to download two sample files from the InterSystems GitHub repo: https://github.com/intersystems/FirstLook-Globals.

  • FirstLookGlobals.xml contains the class definition for the State class.

  • FirstLookGlobals.gof contains some sample global data for the original 13 U.S. states.

For more information on how to access the Management Portal or the Terminal, see “InterSystems IRIS Connection Information” in InterSystems IRIS Basics: Connecting an IDE. You will not actually need an IDE for these exercises.

Importing and Examining the Class Definition

Start by importing the State class definition into InterSystems IRIS:

  1. From the home page in the Management Portal, select System Explorer > Classes.

  2. On the Classes page, look at the left column to make sure you are in the USER namespace. You can think of a namespace as a work space or a directory.

  3. Click Import.

  4. In the Import Classes dialog box:

    1. If your instance of InterSystems IRIS is running on a remote server, specify whether you downloaded the sample files to the remote server or to your local machine.

    2. Under Import from a File or a Directory, click File.

    3. Browse for the file FirstLookGlobals.xml, which you downloaded from GitHub.

    4. Select Compile Imported Items.

    5. For Compile Flags, specify cuk.

    6. Click Next.

    7. Click Import.

    8. When a message saying that the load finished successfully appears, click Done.

Now, on the Classes page, you should see FirstLook.State.cls in the list of classes. In InterSystems IRIS, the name of the package containing the class (FirstLook) is appended with the name of the class (State). The extension .cls is used to denote class files.

Note:

If your namespace contains a lot of classes, filter the list by entering F*.cls in the Class Name box in the left column of the page.

To the right of the FirstLook.State.cls class, click Documentation to view the documentation generated for this class.

The first thing you will notice is that the FirstLook.State class extends the class %Persistent, meaning that the data for this class will be stored in the database. (System-defined classes and methods often start with %.)

persistent class FirstLook.State extends %Persistent
Copy code to clipboard

Extending %Persistent also makes available a number of methods you can use to perform actions on this class. For example, it allows you to create a new object of this class or access an object from the database and load it into memory.

Looking further down the page, you can see that this class has five properties: Area, Capital, Established, Name, and PostalAbbr.

property Area as %Integer;
property Capital as %String;
property Established as %Integer;
property Name as %String [ Required ];
property PostalAbbr as %String;
Copy code to clipboard

This class also has two indices, CapitalIndex and PostalAbbrIndex, which speed up SQL queries and allow you to quickly find states by capital and postal abbreviation.

index (CapitalIndex on Capital) [Unique];
index (PostalAbbrIndex on PostalAbbr) [Unique];
Copy code to clipboard

Importing the Sample Data and Examining the Globals

To get a feel for the globals that store objects of the State class, start by importing some data:

  1. From the home page in the Management Portal, select System Explorer > Globals. (Or from the Classes page, click the Globals button.)

  2. On the Globals page, look at the left column to make sure you are in the USER namespace.

  3. Click Import.

  4. In the Import Globals dialog box:

    1. If your instance of InterSystems IRIS is running on a remote server, specify whether you downloaded the sample files to the remote server or to your local machine.

    2. Browse for the file FirstLookGlobals.gof, which you downloaded from GitHub.

    3. Click Next.

    4. Click Import.

    5. When a message saying that the load finished successfully appears, click Done.

Now, on the Globals page, you should see the globals FirstLook.StateD and FirstLook.StateI in the list. By default, the data for a class is stored in a global with a D appended to the name, and the indices are stored in a global with an I appended to the name. Most commonly, you will see globals displayed with a caret (^) in front of the name.

Note:

If your namespace contains a lot of globals, filter the list by entering F* in the Global Name box in the left column of the page.

To the right of the FirstLook.StateD global, click View to display a listing of the contents of the global.

^FirstLook.StateD = 13
^FirstLook.StateD(1) = $lb("","Delaware","DE","Dover",1787,2489)
^FirstLook.StateD(2) = $lb("","Pennsylvania","PA","Harrisburg",1787,46054)
^FirstLook.StateD(3) = $lb("","New Jersey","NJ","Trenton",1787,8723)
^FirstLook.StateD(4) = $lb("","Georgia","GA","Atlanta",1788,59425)
^FirstLook.StateD(5) = $lb("","Connecticut","CT","Hartford",1788,5543)
^FirstLook.StateD(6) = $lb("","Massachusetts","MA","Boston",1788,10554)
^FirstLook.StateD(7) = $lb("","Maryland","MD","Annapolis",1788,12406)
^FirstLook.StateD(8) = $lb("","South Carolina","SC","Columbia",1788,32020)
^FirstLook.StateD(9) = $lb("","New Hampshire","NH","Concord",1788,9349)
^FirstLook.StateD(10) = $lb("","Virginia","VA","Richmond",1788,42775)
^FirstLook.StateD(11) = $lb("","New York","NY","Albany",1788,54555)
^FirstLook.StateD(12) = $lb("","North Carolina","NC","Raleigh",1789,53819)
^FirstLook.StateD(13) = $lb("","Rhode Island","RI","Providence",1790,1545)
Copy code to clipboard

You can see that the node for each state is subscripted by an integer called the object ID (or ID, for short), which is generated by the system when you store a new object of this class. The root node of the global, with no subscript, contains a counter that is incremented to generate the next ID.

Data for each node is stored as a list of properties, in the order they were specified in the class definition. If you look at ^FirstLook.StateD(3), you can see that the state name is New Jersey, the postal abbreviation is NJ, the capital is Trenton, the state joined the Union in 1787, and its area is 8,723 square miles.

Click Cancel to return to the list of globals, and then click View next to the global FirstLook.StateI to view the indices for the State class.

^FirstLook.StateI("CapitalIndex"," ALBANY",11) = ""
^FirstLook.StateI("CapitalIndex"," ANNAPOLIS",7) = ""
^FirstLook.StateI("CapitalIndex"," ATLANTA",4) = ""
^FirstLook.StateI("CapitalIndex"," BOSTON",6) = ""
^FirstLook.StateI("CapitalIndex"," COLUMBIA",8) = ""
^FirstLook.StateI("CapitalIndex"," CONCORD",9) = ""
^FirstLook.StateI("CapitalIndex"," DOVER",1) = ""
^FirstLook.StateI("CapitalIndex"," HARRISBURG",2) = ""
^FirstLook.StateI("CapitalIndex"," HARTFORD",5) = ""
^FirstLook.StateI("CapitalIndex"," PROVIDENCE",13) = ""
^FirstLook.StateI("CapitalIndex"," RALEIGH",12) = ""
^FirstLook.StateI("CapitalIndex"," RICHMOND",10) = ""
^FirstLook.StateI("CapitalIndex"," TRENTON",3) = ""
^FirstLook.StateI("PostalAbbrIndex"," CT",5) = ""
^FirstLook.StateI("PostalAbbrIndex"," DE",1) = ""
^FirstLook.StateI("PostalAbbrIndex"," GA",4) = ""
^FirstLook.StateI("PostalAbbrIndex"," MA",6) = ""
^FirstLook.StateI("PostalAbbrIndex"," MD",7) = ""
^FirstLook.StateI("PostalAbbrIndex"," NC",12) = ""
^FirstLook.StateI("PostalAbbrIndex"," NH",9) = ""
^FirstLook.StateI("PostalAbbrIndex"," NJ",3) = ""
^FirstLook.StateI("PostalAbbrIndex"," NY",11) = ""
^FirstLook.StateI("PostalAbbrIndex"," PA",2) = ""
^FirstLook.StateI("PostalAbbrIndex"," RI",13) = ""
^FirstLook.StateI("PostalAbbrIndex"," SC",8) = ""
^FirstLook.StateI("PostalAbbrIndex"," VA",10) = ""
Copy code to clipboard

Take a closer look at the first node in the global ^FirstLook.StateI. Here, the first subscript ("CapitalIndex") is the name of the index, the second subscript is the value of the property being indexed (" ALBANY"), and the third subscript is the ID of the state with the capital of Albany (11). If you look back at the data global, you see that ^FirstLook.StateD(11) is the state of New York.

Globals are automatically stored in sorted order, using the array subscripts.

Accessing Globals Relationally

Now, take a look at the table InterSystems IRIS generated for the State class:

  1. From the home page in the Management Portal, select System Explorer > SQL.

  2. On the SQL page, look at the top of the page to make sure you are in the USER namespace. If you are not, click Switch to change namespaces.

  3. In the left column, expand the Tables section to view the tables in the namespace.

  4. Under Tables, click the FirstLook.State table.

  5. On the Catalog Details tab, click Fields, and you’ll see a field generated for each property of the State class, plus an extra field called ID (sometimes referred to as a RowID). This field is analogous to the object ID you saw in the globals for the class.

    Note:

    If your namespace contains a lot of tables, filter the list by entering F* in the Filter box in the left column of the page.

  6. Click the Execute Query tab to open a text area where you can write queries to run against the FirstLook.State table.

  7. Type the following query:

    SELECT * FROM FirstLook.State WHERE ID = 6
    Copy code to clipboard

    and click Execute. The query returns the row you requested, for the state of Massachusetts.

  8. Type the following query:

    INSERT INTO FirstLook.State(Area, Capital, Established, Name, PostalAbbr) 
    VALUES (9616, 'Montpelier', 1791, 'Vermont', 'VT')
    Copy code to clipboard

    and click Execute to insert a row into the table for Vermont, the 14th state.

To see the effects of inserting a row into the FirstLook.State table, go back to the Globals page for the namespace USER and view the globals again.

  1. From the home page in the Management Portal, select System Explorer > Globals.

  2. On the Globals page, look at the left column to make sure you are in the USER namespace.

Looking at the data global, ^FirstLook.StateD, you see that the ID counter has been incremented:

^FirstLook.StateD = 14
Copy code to clipboard

And a new node has been added to the global:

^FirstLook.StateD(14) = $lb("","Vermont","VT","Montpelier",1791,9616)
Copy code to clipboard

Looking at the index global, ^FirstLook.StateI, you see that the indices have been updated with two new nodes:

^FirstLook.StateI("CapitalIndex"," MONTPELIER",14) = ""
Copy code to clipboard

and

^FirstLook.StateI("PostalAbbrIndex"," VT",14) = ""
Copy code to clipboard

Accessing Globals as Objects

Remember that, when you created the State class, you extended the class %Persistent, which gives you access to some helpful methods that let you store data in the globals for the class and retrieve it again. Next, test some of these methods, by writing some ObjectScript in the InterSystems Terminal. (If you have not used the Terminal before, see “InterSystems IRIS Connection Information” in InterSystems IRIS Basics: Connecting an IDE.)

After you launch a Terminal session, you should see a prompt that indicates which namespace you are in. If you are not in the USER namespace, execute the following command:

set $namespace = "USER"
Copy code to clipboard

Start by loading the data for the state of Vermont, which you just added with your SQL query, into memory. Call the %OpenId() method of the FirstLook.State class and assign the return value to the variable vt. %OpenId() returns a “handle” to the object, more formally known as an object reference, or OREF.

USER>set vt = ##class(FirstLook.State).%OpenId(14)
Copy code to clipboard

You can look at the name of the state you just loaded by accessing the Name property of the object:

USER>write vt.Name
Vermont
Copy code to clipboard

You can get a summary of the all of the object’s properties by using the zwrite command. The other information provided by the command is beyond the scope of this First Look.

USER>zwrite vt
vt=2@FirstLook.State  ; <OREF>
+----------------- general information ---------------
|      oref value: 2
|      class name: FirstLook.State
|           %%OID: $lb("14","FirstLook.State")
| reference count: 2
+----------------- attribute values ------------------
|       %Concurrency = 1  <Set>
|               Area = 9616
|            Capital = "Montpelier"
|        Established = 1791
|               Name = "Vermont"
|         PostalAbbr = "VT"
+-----------------------------------------------------
Copy code to clipboard

To create a new State object, use the %New() method, which returns an OREF to the new object.

USER>set newstate = ##class(FirstLook.State).%New()
Copy code to clipboard

Now, set the properties for the 15th state, Kentucky.

USER>set newstate.Name = "Kentucky"
 
USER>set newstate.PostalAbbr = "KY"
 
USER>set newstate.Capital = "Frankfort"
 
USER>set newstate.Established = 1792
 
USER>set newstate.Area = 40408
Copy code to clipboard

Inspect all of the properties.

USER>zwrite newstate
newstate=4@FirstLook.State  ; <OREF>
+----------------- general information ---------------
|      oref value: 4
|      class name: FirstLook.State
| reference count: 2
+----------------- attribute values ------------------
|       %Concurrency = 1  <Set>
|               Area = 40408
|            Capital = "Frankfort"
|        Established = 1792
|               Name = "Kentucky"
|         PostalAbbr = "KY"
+-----------------------------------------------------
Copy code to clipboard

If you are happy with the way everything looks, save the object to disk by calling the %Save() method of the new object. The %Save() method returns a status, which has the value 1 on a successful save.

USER>set status = newstate.%Save()
 
USER>write status
1
Copy code to clipboard

Once again, check your work by going to the Globals page in the Management Portal. Looking at the data global, ^FirstLook.StateD, you see that the ID counter has been incremented once more:

^FirstLook.StateD = 15
Copy code to clipboard

And a new node has been added to the global:

^FirstLook.StateD(15) = $lb("","Kentucky","KY","Frankfort",1792,40408)
Copy code to clipboard

Looking at the index global, ^FirstLook.StateI, you see that the indices have been updated with two new nodes:

^FirstLook.StateI("CapitalIndex"," FRANKFORT",15) = ""
Copy code to clipboard

and

^FirstLook.StateI("PostalAbbrIndex"," KY",15) = ""
Copy code to clipboard

Accessing Globals Directly

Though data in InterSystems IRIS is most commonly accessed from either SQL or using the object layer, you can also directly access globals for classes that extend %Persistent. This method is trickier because you need to know the structure of the global.

First, find the name of the state with the ID 15.

From the Terminal, assign the variable ky to the node in the data global with subscript 15.

USER>set ky = ^FirstLook.StateD(15)
Copy code to clipboard

You can use zwrite to examine the value stored at this node:

USER>zwrite ky
ky=$lb("","Kentucky","KY","Frankfort",1792,40408)
Copy code to clipboard

Next, use the $list() function to get the second item in the list:

USER>write $list(ky, 2)
Kentucky
Copy code to clipboard

Based upon what you learned from examining the globals after adding a state using SQL or object methods, write some code to add a new state.

First, prepare the data, putting each property (thinking in terms of objects) or field (thinking in terms of SQL) into a different variable.

USER>set name = "Tennessee"
 
USER>set postalabbr = "TN"
 
USER>set capital = "Nashville"
 
USER>set established = 1796
 
USER>set area = 42144
Copy code to clipboard

Then use the $listbuild() function to build a list of properties that can be stored.

USER>set properties = $listbuild("", name, postalabbr, capital, established, area)
 
USER>zwrite properties
properties=$lb("","Tennessee","TN","Nashville",1796,42144)
Copy code to clipboard

With a single ObjectScript statement, increment the ID counter of the ^FirstLook.StateD global and assign the new value to the variable id.

USER>set id = $increment(^FirstLook.StateD)
 
USER>write ^FirstLook.StateD
16
USER>write id
16
Copy code to clipboard

Now, store the data in the data global.

USER>set ^FirstLook.StateD(id) = properties
 
USER>zwrite ^FirstLook.StateD(id)
^FirstLook.StateD(16)=$lb("","Tennessee","TN","Nashville",1796,42144)
Copy code to clipboard

Now we need to manually update the indices, or an SQL query with a WHERE clause on Capital or PostalAbbr will not include the state of Tennessee. This process is a bit more involved than storing the data.

For indices on string values, InterSystems IRIS converts the strings to uppercase and prepends a space character, to allow for easier sorting. Concatenate a space to the front of the capital using the _ operator and then convert it to uppercase with the $zconvert() function. Then do the same for the postal abbreviation.

USER>set capital = $zconvert(" "_capital, "U")

USER>set postalabbr = $zconvert(" "_postalabbr, "U")
Copy code to clipboard

Finally, store the index entries in the index global.

USER>set ^FirstLook.StateI("CapitalIndex", capital, id) = ""
 
USER>set ^FirstLook.StateI("PostalAbbrIndex", postalabbr, id) = ""
Copy code to clipboard

To make sure you’ve done your work correctly, go to the Globals page in the Management Portal and view the ^FirstLook.StateD and ^FirstLook.StateI globals. You can also use zwrite ^FirstLook.StateD and zwrite ^FirstLook.StateI from the Terminal to display the complete contents of each global.

More About Globals

Creating Globals Using SQL

In this First Look, the globals you looked at were created by storing objects of a class specified using a class definition. You could have created globals with a very similar structure by creating a table and indices on the table using SQL. InterSystems IRIS would then have generated a class for you, based on the table you created.

As an exercise, go to the SQL page in the Management Portal for the USER namespace and execute each of the following statements using the Execute Query tab.

CREATE TABLE FirstLook.SQL (%CLASSPARAMETER USEEXTENTSET 0, %CLASSPARAMETER DEFAULTGLOBAL = '^FirstLook.SQL', 
Name CHAR(30) NOT NULL, PostalAbbr CHAR(2), Capital CHAR(30), Established INT, Area INT)
CREATE UNIQUE INDEX CapitalIndex ON FirstLook.SQL (Capital)
CREATE UNIQUE INDEX PostalAbbrIndex ON FirstLook.SQL (PostalAbbr)
INSERT INTO FirstLook.SQL (Name, PostalAbbr, Capital, Established, Area) 
VALUES ('Maine', 'ME', 'Augusta', 1820, 35380)
Copy code to clipboard

In the left column of the SQL page, you should now see the table FirstLook.SQL.

Go to the Classes page, find the class FirstLook.SQL.cls and view its documentation. Do you notice any difference? The class has an additional index, called a Bitmap Extent Index. Then go to the Globals page and find the ^FirstLook.SQLD and ^FirstLook.SQLI globals. Take a look at ^FirstLook.SQLI and see if you can find the additional index.

Creating Custom Globals

So far, you’ve looked at the globals that are created when you extend the %Persistent class. However, globals can be used to store schema-less data that may not lend itself to a class or relational paradigm. For example, using the Terminal or the Management Portal, switch to the %SYS namespace, and examine the ^CONFIG global, which stores some of the InterSystems IRIS configuration settings. A portion of a sample ^CONFIG global is shown below:

^CONFIG("Cluster","CommIPAddress") = ""
^CONFIG("Cluster","JoinCluster") = 0
^CONFIG("ConfigFile","Version") = "2018.20"
^CONFIG("Conversions","LastConvertTime") = "2019-03-13 08:39:45"
^CONFIG("Databases","ENSLIB") = "/usr/irissys/mgr/enslib/"
^CONFIG("Databases","IRISAUDIT") = "/usr/irissys/mgr/irisaudit/"
^CONFIG("Databases","IRISLIB") = "/usr/irissys/mgr/irislib/"
^CONFIG("Databases","IRISLOCALDATA") = "/usr/irissys/mgr/irislocaldata/"
^CONFIG("Databases","IRISSYS") = "/usr/irissys/mgr/"
^CONFIG("Databases","IRISTEMP") = "/usr/irissys/mgr/iristemp/"
^CONFIG("Databases","USER") = "/usr/irissys/mgr/user/"
Copy code to clipboard

If you want to create and store your own custom data structures, you can easily do so using ObjectScript. Using the example below, you can write a few lines of code to define a directed graph to store the airfare between airports:

USER>set ^Fares("BOS", "ORD") = 87
 
USER>set ^Fares("ORD", "BOS") = 63
 
USER>set ^Fares("BOS", "LAX") = 143
 
USER>set ^Fares("LAX", "BOS") = 143
 
USER>set ^Fares("ORD", "LAX") = 57
 
USER>set ^Fares("LAX", "ORD") = 94
 
USER>zwrite ^Fares
^Fares("BOS","LAX")=143
^Fares("BOS","ORD")=87
^Fares("LAX","BOS")=143
^Fares("LAX","ORD")=94
^Fares("ORD","BOS")=63
^Fares("ORD","LAX")=57
Copy code to clipboard

Accessing Globals with InterSystems IRIS APIs

If you are writing an application in Java, .NET, Node.js, or Python, InterSystems IRIS provides APIs that allow you to manipulate your database using the three models discussed in this First Look:

  • Relational access through JDBC, ADO.NET, or PyODBC API

  • Object access through the InterSystems XEP API

  • Direct access to globals through the InterSystems Native API

Now you know that, no matter how you decide to store or access your data, what you’re doing is using globals.

Note:

Not all forms of access are supported for all languages.

Learn More About Globals

Use the resources listed below to learn more about globals and how to access them.

Globals and Their Structure

  • Globals QuickStart — Provides a visual look at global structures and gives an example of storing data in a custom global structure.

  • Using Globals — Discusses the structure of globals, how to manage them, and how to access them using SQL or ObjectScript.

  • Globals — This section in Defining and Using Classes explains the naming conventions for globals created for classes that extend the %Persistent class.

Multi-Model Development

  • Multi-Model QuickStart — Describes how InterSystems IRIS allows you to use the data models of your choice with a variety of different languages, including Java, .NET, and ObjectScript.

  • Java QuickStart — Shows you how to use the Java APIs for relational, object, and direct access to InterSystems IRIS databases.

  • .NET QuickStart — Shows you how to use the .NET APIs for relational, object, and direct access to InterSystems IRIS databases.

  • Python QuickStart — Shows you how to use the Python APIs for relational and direct access to InterSystems IRIS databases.

InterSystems Native API