目录
何为 IRIS 编程
InterSystems IRIS
(低版本为Caché
)是一个高性能的对象数据库,内置通用编程语言。它支持多个进程并提供并发控制。每个过程都可以直接、高效地访问数据。
在InterSystems IRIS
中,您可以根据自己的喜好编写routines
,类或这些的混合。在所有情况下,存储的数据最终都包含在称为全局变量(globals
)的结构中(本章后面的部分将讨论这些结构)。
InterSystems IRIS
编程具有以下特点:
Routines
和类可以互换使用,可以用多种语言编写。Routines
和类可以相互调用。- 类提供
面向对象
的功能。 - 数据库存储已集成到编程语言中。
- 类可以以简化编程的方式保存数据。如果使用持久性类,则数据可同时用作对象、SQL 表和全局变量。
- 您可以直接从
Routines
或类访问全局变量,这意味着您可以灵活地完全按照自己的意愿存储和访问数据。
较旧的 Caché
应用程序完全由routines
组成,因为这些应用程序是在 Caché
支持类定义之前编写的。相比之下,一些较新的应用程序几乎完全在类中编写。您可以选择适合您需求的方法。
Routines
在 InterSystems IRIS
中创建routines
时,请使用 ObjectScript
。下面显示了用 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"))
}
在 Caché
或 IRIS
中创建Routines
时,可以为每个Routines
选择编程语言。选项如下:
Caché ObjectScript
,它是ISO 11756-1999标准M编程语言的超集。如果您是 M 程序员,则可以在 Caché 上运行现有的 M 应用程序,而无需进行任何更改。
这是Caché
例程最常用的语言。Caché MVBasic
是MultiValue
的实现。它包括各种多值实现中使用的命令、函数和运算符,并且支持多种仿真模式,以便您可以使用您熟悉的语法。Caché Basic
是Basic
的实现。
类(Classes)
IRIS
(Caché
) 还支持类。您可以使用系统类,也可以定义自己的类。
- 在
IRIS/Caché
中,类可以包含熟悉的类元素,如属性、方法和参数(在其他类语言中称为常量)。它还可以包括通常不在类中定义的项,包括触发器、查询和索引。 - 对于每种方法,您可以指定要在定义该方法时使用的编程语言,但为简单起见,类中的所有方法通常都使用相同的语言。默认值为
ObjectScript
下面显示了一个类定义:
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
}
}
可以从routines
中使用类。例如,下面显示了例程的一部分,其中我们引用了 Sample.Person 类:
//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
}
同样,方法可以调用routines
中的标签。例如:
Method DemoRoutineCall(input) as %String
{
Set value=$$function^myroutine(input)
Quit value
}
全局变量(Globals )
IRIS
支持一种在其他编程语言中看不到的特殊类型的变量;这是一个全局变量,通常只称为全局变量。在 IRIS
中,术语“全局”表示此数据可供访问此数据库的所有进程使用。这种用法与其他编程语言不同,在其他编程语言中,global意味着“可用于此模块中的所有代码”。
全局变量的内容存储在 Caché
数据库中。重要的是要知道以下几点:
- 全局由一组节点(在某些情况下,只有一个节点)组成,由下标标识。
每个节点可以包含一个值。 Caché ObjectScript
、Caché Basic
和Caché MVBasic
统一称为 (ObjectScript
)包含的函数,用于循环访问全局节点并快速访问值。- 全局变量会自动存储在数据库中。为全局变量的节点赋值时,数据将立即写入数据库。
- 您可以通过
ObjectScript
命令或管理门户查看全局变量的内容。
访问数据的方法
在IRIS
中,数据库包含全局变量,而不包含其他任何内容;甚至代码都存储在全局变量中
,如本书后面所述。在最低级别,对数据的所有访问都是通过直接全局访问完成的,也就是说,通过使用直接与全局变量一起使用的命令和函数。
许多当前正在运行的应用程序都是在 IRIS
包含对类的支持之前很久就开发的。其中一些应用程序使用直接全局访问。其他应用程序使用自定义 API,例如属于公共领域的 FileMan。当然,这些 API 在内部使用直接全局访问。
使用持久性类时,可以通过以下任一方式创建、修改和删除存储的数据:
- 通过使用
%New()
、%Save()
、%Open()
和%Delete()
等方法。 - 通过使用
InterSystems SQL
(Caché SQL
)。
在内部,系统始终使用直接全局访问。
因为对象类提供了一个更可控的接口,而且因为 IRIS
持久类被投影到可以通过 SQL 查询的表中,所以通常需要向现有应用程序添加类接口。如果您了解全局变量的结构,则可以这样做。
使用全局变量意义
全局变量在物理上存储在高度优化的结构中,管理此结构的代码针对运行 Caché
的每个平台分别进行了优化。这些优化可确保全局变量上的操作具有高吞吐量(每单位时间的操作数)、高并发性(并发用户总数)、缓存内存的有效使用,并且不需要与性能相关的持续维护(如频繁重建、重新编制索引或压缩)。用于存储全局变量的物理结构是完全封装的;通常没有必要考虑物理数据结构。
全局存储是稀疏的,这意味着只有具有数据值的节点存储在数据库中
。这意味着 Caché
通常需要的空间不到关系数据库所需空间的一半。
全球性企业的其他好处包括:
- 与关系表相比,全局变量的分层结构通常更紧密地对实际数据进行建模。
- 稀疏性质意味着可以在没有任何开销的情况下添加新字段,并且无需重建现有数据库。
- 只需一次 I/O 操作即可读取或写入更多数据,并且可以更有效地缓存数据。
Caché SQL
如前所述,Caché
提供了SQL
的实现,称为Caché SQL
。
您可以在routines
和方法中使用 Caché SQL
。
- 动态
SQL
(%SQL.语句和 %SQL。语句Result 类),您可以在任何上下文中使用动态SQL
。如下面的示例所示:
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"
- 嵌入式
SQL
,如以下示例所示
&sql(SELECT COUNT(*) INTO :myvar FROM Sample.Person)
Write myvar
宏(Macros)
Caché ObjectScript
还支持定义替换的宏。定义可以是值、整行代码或(使用 ##Continue 指令)多行。您可以使用宏来确保一致性。例如:
#define StringMacro "Hello, World!"
write $$$StringMacro
为了让您了解在宏中可以执行的操作,下面的示例演示了内部使用的宏的定义:
#define output1(%str,%lf,%indent) do output^%fm2class(%str,%lf,%indent,$$$display)
此宏接受一个参数,就像他们中的许多人一样。它还引用另一个宏。
您可以在例程和类中使用宏。某些系统类广泛使用它们。
包含文件(Include Files)
您可以在例程中定义宏,并在以后的同一例程中使用它们。更常见的是,您可以在一个中心位置定义它们。为此,请创建并使用包含文件。包含文件定义宏,并且可以包含其他包含文件。
下面显示了系统包含文件的各个部分:
/// 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)
这是另一个完整的包含文件:
#include %occCacheDirect
#include %occExtent
#include %occTransaction
#include %occInclude
#include %msql
#include %cspInclude
然后,您可以执行以下操作:
- 在任何例程的开头都包含包含文件。该例程可以引用包含文件中定义的宏。
- 在任何类的开头都包含包含文件。该类中的方法可以引用宏。
- 在任何方法的开头都包含包含文件。该方法可以引用宏。
请注意,使用稍有不同的语法在类定义中包含包含文件。
IRIS 虚拟机工作机制
了解 IRIS
如何使用本章中介绍的代码元素非常有用。
您可以混合使用 Caché ObjectScript
、Caché SQL
、Caché MVBasic
、宏、类定义、routines
等的原因是 IRIS
不直接使用您编写的代码。相反,当您编译代码时,系统会生成它使用的代码,即 IRIS 虚拟机
使用的 OBJ 代码
。
有多个步骤;上图给出了它们的一般概念。没有必要详细了解这些步骤,但请记住以下几点:
CSP引擎
将CSP
文件转换为类定义。- 类编译器使用类定义并生成
INT
代码、Caché MVBasic
代码和Caché Basic
代码,具体取决于用于定义类中方法的语言。
在某些情况下,编译器首先使用类作为生成和保存其他类的基础。您可以在Studio
中查看这些类,但不要修改它们。例如,当您编译定义 Web 服务和 Web 客户端的类时,会发生这种情况。
类编译器还为每个类生成类描述符。系统代码在运行时使用它。 预处理器
(有时称为宏预处理器或MPP
)使用包含文件(图中未显示)并替换宏。它还处理ObjectScript
例程和MVBasic
例程中的嵌入式SQL
。
这些更改发生在临时工作区中,并且您的代码不会更改。- 其他编译器为
ObjectScript
例程创建INT
代码,为MVBasic
例程创建 MVI 代码。此层称为中间代码。在此层中,对数据的所有访问都是通过直接全局访问完成的。 INT
代码和MVI
代码都是紧凑的,但人类可读。本书后面的部分将向您展示如何查找此代码,这对于诊断非常有用。
请注意,Caché Basic 没有中间代码
。
INT
代码、MVI
代码和Caché Basic
用于生成OBJ
代码。
Caché 虚拟机使用此代码。编译代码后,例程、INT
代码和MVI
代码不再是执行代码所必需的。- 编译类后,可以将它们置于已部署模式。
Caché
有一个实用程序,可以删除给定类的类内部和中间代码;您可以在部署应用程序时使用此实用程序。
如果检查Caché 系统类
,可能会发现某些类无法看到,因为它们处于已部署模式
。