#InterSystems IRIS

0 关注者 · 1.1K 帖子

InterSystems IRIS 是一个完整的数据平台
InterSystems IRIS 为您提供了捕获、共享、理解组织最宝贵的资产(数据)并采取相应行动所需的一切。
作为一个完整的平台,InterSystems IRIS 不需要集成多种开发技术。应用程序需要更少的代码、更少的系统资源和更少的维护。

文章 cheng yu · 15 分鐘 前 1m read

这是我的SQLgateway系列文章的第6篇。作为InterSystems的产品,Caché
,自然成了一个相当自然的选择。除了其他技术之外,SQLgateway还提供了
多种迁移至 IRIS 的途径之一。如果只是部分
且需要反复更新

这次,获取正确的JDBC驱动程序非常容易,因为它已包含在安装包中。
 相关文档内容详尽且清晰。 

注意:
要与 Caché 建立网络连接,您需要相应的许可证。
Caché 默认仅支持单用户且不支持网络连接。 
请添加有效的许可证,并在 /cache/Dockerfile 中启用复制功能。

构建完成后,容器运行完美,迁移过程
十分顺利。DDL 版本方面未出现任何问题。我使用默认的 SAMPLES 命名空间
作为数据源。此外,您还有丰富的选择。

但与其他所有情况一样,请注意跨依赖关系。

警告:这只是经典技术
——IRIS仅支持SQL、Java和ISOS 
——没有机器学习、没有人工智能、没有 Python,也没有其他花哨的工具。
您可能会期待看到更多关于 SQLgateway 的演示。

0
0 1
文章 cheng yu · 16 分鐘 前 1m read

这是我的SQLgateway系列文章的第7篇。 
最后但同样重要的是,作为 InterSystems 旗下产品,IRIS 本身也自然而然地成为了目标。 
除了其他变体外,SQLgateway 还提供了一种与 
。无论是部分迁移,还是需要 
重复更新(归档?)

这次,获取正确的JDBC驱动程序非常容易,因为它已包含在安装包中。
 相关的文档内容详尽且清晰。 

我面临的主要挑战是让 Docker-Compose 运行同一个 Docker 构建
,但需要使用不同的配置——这些配置必须在容器启动时进行设置。

我使用了Caché-SAMPLES中广为人知的Sample.*类子集 
中广为人知的 Sample.* 类的一个子集,并控制其规模适中,以确保启动和测试速度达到可接受的水平。

按要求配置完成后,容器运行完美,模拟的
“迁移”过程十分顺利。DDL 版本无问题,也无依赖关系问题。

警告:这只是经典技术
——仅使用 SQL、Java 和 ISOS 的 IRIS 
——没有机器学习、没有人工智能、没有 Python,也没有其他花哨的工具。

0
0 1
文章 cheng yu · 17 分鐘 前 1m read

这是我关于 IRIS SQLgateway 系列文章的最后一篇。

                         
在介绍了7个将DB_Migration迁移到IRIS的示例后,我实在忍不住将 
将围绕 IRIS 的各个独立包整合到一个包中。
将8个容器整合到1个 Docker-Compose 文件中,感觉就像驾驶一辆八缸发动机汽车一样。

  • sqlgateway-magnificent-7 > IRiS1
  • 1 个 oracle21c
  • 2 个 MySQL
  • 3 个 PostgreSQL
  • 4 IBM DB2
  • 5 MS SQL
  • 6 Caché
  • 7 IRIS2

各个映射的同步是最大的挑战。
其次是提供的测试数据量。下载部分
GB数据的下载过程令人煎熬,还引发了一些麻烦。

再次衷心感谢@Yuri Marx提供的这套出色的数据集。
测试系列与独立软件包中的完全一致
可能只有IP端口发生了变化。尝试连接其他数据库是一次有趣的体验
接触其他数据库。MSSQL 带来了最多的麻烦。
提示:
此外,我的 Docker Desktop 在单个 Compose 文件中同时启动 8 个容器时似乎遇到了困难。
通过 Docker 控制台手动重启容器解决了该问题:
若缺少 Cache.Key,则需重建镜像或手动添加。

在我个人的评分中,IRIS 毫无疑问是赢家。 
你感到惊讶吗?

0
0 1
文章 cheng yu · 17 分鐘 前 2m read

我之前关于SQLgateway 迁移的系列文章,是一篇篇幅较长的文章,介绍了
了可用的各种方案。不过它既不易操作,又难以追踪。
因此,我的挑战是:如何“吃掉一头大象”?>> 把它切成小块!!

我的目标是兼顾两点:既能独立创建每个容器,又能
同时支持一键构建整个集合。因此现在可以
在不影响其他容器的情况下修复单个容器的问题。

结果证明,这变成了一次关于 Docker 网络和脚本编写的实践,

  • 每次执行 Docker-Compose Up 都会创建一个独立的网络。因此,与
    前面的示例那样简单地启动,也会生成8个彼此隔离的网络。
    解决方案:定义一个公共网络并将容器加入其中。
    现在 TCP/JDBC 可以找到服务器,而且我们再也不会遇到端口冲突了
  • 为了启动所有容器而连续执行 8 次 `docker-compose up -d` 实在不太好玩 
  • 解决方案:Docker Compose 提供了一个 INCLUDE 指令。只需点击一下,一切就搞定了。
include:   
  - ./iris1/docker-compose.yml   
  - ./cache/docker-compose.yml    
  - ./ibmDB2/docker-compose.yml   
  - ./iris2/docker-compose.yml    
  - ./MSsql/docker-compose.yml   
  - ./mysql/docker-compose.yml   
  - ./ORACLE/docker-compose.yml   
  - ./postgres/docker-compose.yml
0
0 1
文章 cheng yu · 19 分鐘 前 2m read

通过邮件发送信息是网络中历史最悠久的技术之一
。邮件传输标准于1980年正式发布。
SMTP 代表简单邮件传输协议。
IRIS自诞生之初乃至更早之前就已支持SMTP。
随着时间的推移,各种功能不断演进,特别是与
安全、编码、身份验证、多部分邮件等方面……
相关文档在各个细节上都十分详尽。您可以在
类、方法、实用程序和示例。

本示例提供了一个非常简单的入门起点。
如果您要发送电子邮件,就需要一台能够接收邮件的 SMTP 服务器。
这可以是你选择的某个外部服务器,但同样,IRIS
已做好充分准备为您提供服务。互操作性功能可满足您的所有需求。
因此,该软件包为您提供了一个用于测试的最小规模生产环境。
该服务不会将数据写入真实的生产环境,而是将输入写入一个全局
,您可以立即查看。
因此,该演示程序可以在单个实例中运行,以发送和接收邮件。
提供了一个涵盖所有必要步骤的精简测试例程。

所有操作均通过一个包含 5 个操作的命令行会话进行控制

  • do mail; 编写一封包含2行的简单邮件
    若需更多文本,请向字符流 %mail.TextData 中添加内容
    ,同时别忘了调整文本大小
  • do start ; 启动 SMTP 服务器生产环境
    • 17:27:37.285:Ens.Director: Production 'mail.Receive' starting...
      17:27:37.332:Ens.Director: Production 'mail.Receive' started.1
0
0 1
文章 cheng yu · 19 分鐘 前 2m read

IRIS 在处理和管理表格中的数据方面表现非常出色。
但正如您在标准包中所见,它在逻辑处理方面同样表现出色
分析、互操作性、所有与健康相关的处理,最重要的是,
来自我们全球合作伙伴的庞大应用程序集合。

所有这些应用程序都有一个共同的需求:
总有一些中小规模的信息需要处理,
,这些数据根本无法适应任何重复的表格结构。我常举的例子 
就是一串文本行,比如我从妻子那里收到的购物清单。

  • 它具有有限的生命周期, 
  • 维度有限, 
  • 结构难以预测
  • ,且每一条都是独一无二的作品 

将此类信息强行塞入表格是可行的,且这种情况经常发生。
但这种做法效率低下,特别是对于易变信息而言。

一种典型的做法是将信息保存在本地数组中:
但这可能会导致处理分区的内存达到极限。
因此,请将原始信息保存到一个全局数组中,该数组应采用与
处理机制的 GLOBAL 数组中保存原始信息。
这种方法速度很快,而且作为一名经验丰富的ObjectScript开发者,你会使用
“进程私有全局变量”(Process Private Global)来规避日志处理的开销
,一旦工作完成,它就会随你的进程一同消失,不留痕迹。

下一个挑战:  
由于处理过程可能耗时较长,可能会阻塞进程中的交互式
用户界面。那么,你可以将处理任务移交给一个 
后台作业,其优势在于可以预先选择要
:食品购物清单可能与园艺购物清单有所不同。
此时,您的“流程私有全局变量”将无法正常工作。它在后台环境中不可用。

0
0 1
文章 cheng yu · 20 分鐘 前 1m read

OEX半持久化表中的前一个示例与一篇 
,该文发表于2020年, 题为《半持久类与表》,其内容 侧重于传统的 
存储模型,并通过间接引用实现存储全局变量的动态变更。
这种方法存在局限性和风险,而本文则避免了这些问题。  

描述

基类(User.Common)是一个模板,可应用于
USER、CLERKS、CUSTOMERS、PPG……等类,这些类彼此独立
。 
区别在于:User.Common 类使用了[NoExtent]参数
,因此不包含存储定义。
随后,将在各个类中指定要使用的存储。 
现在,它是一个静态值,用于定义要使用的全局变量。 
而且这是一个非常简单的定义。例如:

Class User.USR Extends User.Common [ Not NoExtent ]
{
Parameter DEFAULTGLOBAL As STRING = "^USR";
}

其余所有工作均由编译器完成。
副作用:POPULATE 现在针对每个类/表都是特定的。

0
0 1
文章 cheng yu · 22 分鐘 前 2m read

在 OEX 上浏览我的包时,我想起了一个
关于SQL主机变量的示例。 

您可能看过我关于《Open Exchange Reviews》的系列文章
每条报告行都会被分配一个系列编号(末尾的 #76)
一旦发布,我就不再太关注它了。 
我只关注最后那份尚未发布的、带有 MAX(serial) 的报告。
简单思路:

SELECT serial,label, . . . from oex.dir WHERE serial = MAX(serial)

哎呀:: SQLCODE=-19
   聚合函数不能用于WHERE或GROUP BY子句中  
此外:对每个“serial”的出现位置都运行MAX(),性能并不理想。 
我当时想找一种方法,计算出一个静态值来与之进行比较。
因此,我编写了一个名为 SMX 的自定义静态 SQL 方法,如下所示:

ClassMethod SMX(dif As %Integer = 0) As %Integer [ SqlName = SMX, SqlProc ]
{
 set max=$g(^||max,0)
 if 'max {
    &sql(SELECT max(serial) into :max from oex.dir)
    set ^||max=max
 }
 quit max+dif
}
0
0 1
文章 cheng yu · 26 分鐘 前 4m read

这是对Caché问世前历史的一种相当个人化的看法。
这绝非意在与前文中讨论的迈克·卡多(Mike Kadow)所著的那些优秀书籍相抗衡。
我们的经历各不相同,因此本文旨在从另一个角度来审视过去。

整个故事始于 1966 年,地点在MGH(马萨诸塞州总医院),当时一台序列号为 103 的PDP-7
,该机配备 8K 内存(18 位字)[相当于今天的 18K 字节],当时作为备用系统使用。

“序列号103——当时位于现已拆除的塞耶大楼(Thayer Building)地下室,地址为
,目前 [2014年]该地是MGH考克斯癌症中心(Cox Cancer Center)的所在地。”
“尼尔·帕帕拉多(Neil Papparlardo)和柯特·马布尔(Curt Marble)在奥克托·巴内特(Octo Barnett)的指导下,开发并发布了
——这是该机器上的首款软件。” 
他们将其命名为MUMPS。(来源)


PDP-7

该语言本身与旧式的Basic语言相当接近。
但与其他编程语言相比,它有着显著的改进:

  • 其核心理念在于无需处理文件系统即可存储和检索持久数据。
0
0 2
文章 cheng yu · 29 分鐘 前 5m read

大家好,

本文旨在说明如何在 IRIS 和 Microsoft Teams 之间建立消息传递功能。

在我们公司,为了监控错误消息,我们曾使用 Ens.Alert 类通过一个业务操作将这些错误消息重定向,该操作会发送一封电子邮件。
问题在于,这些错误消息被发送到一个支持邮箱,而该邮箱已积压了大量邮件。我们希望为特定的团队提供专属的错误通知机制。

因此,我们研究了如何让这些消息直接送达开发团队,使他们能够实时收到生产环境出现错误的通知。
由于公司将 Microsoft Teams 作为企业级协作工具,我们便思考:如何让这些消息直接送达 IRIS 开发团队?

0
0 1
文章 cheng yu · 30 分鐘 前 2m read

大家好

对于感兴趣的朋友,这里分享一个我在某个项目中使用的实现示例,该示例利用 pymongo 包实现了与 MongoDB 的互操作。

iris-mongodb

通过 pymongo 包实现 InterSystems IRIS 与 MongoDB 的互操作(包括出站适配器)

请务必导入pymongo包。

此处提供用于测试的实现示例

NAMESPACE> do ##class(custom.python.pymongo.test).TestMongoDBCrud()

为了实现互操作性,请在业务操作中使用以下适配器:

Parameter ADAPTER = "custom.python.pymongo.outboundAdapter";

Parameter INVOCATION = "Queue";

查询示例:

/// parameters: (dbName, collectionName, query, fields, sort, limit) => query, fields and sort are %DynamicObjects
/// resultset is an array of objects (%DynamicArray)
set resultset = ..Adapter.Query("mydb","mycollection", {"_id":(tId)})
0
0 1
文章 cheng yu · 38 分鐘 前 19m read

我每天都在使用嵌入式 Python,至今已有两年多了。 也许现在是时候分享一下这段经历的感想了。

为什么要写这篇心得?因为,我想,我和这里的大多数人一样,都是一名ObjectScript开发者,而且我认为这些心得能给社区带来帮助,让大家更好地了解在IRIS中选择嵌入式Python进行开发所涉及的利弊,同时也避免一些陷阱。

image

引言

我自2010年起从事开发工作,自2013年起开始使用ObjectScript。

0
0 1
文章 cheng yu · 41 分鐘 前 17m read

引言

如今,像Claude、GitHub Copilot和Cursor这样的编码助手已经彻底改变了开发者编写代码的方式。 然而,这些工具因与开发人员日常使用的系统和数据源隔离而受到限制。这一限制可以通过模型上下文协议(MCP)来克服——这是一项开放标准,旨在以安全且标准化的方式将 AI 助手与外部数据源和工具连接起来。

在这篇综述文章中,我们将探讨 InterSystems 生态系统内 MCP 的最新发展状况。 此外,我们将探讨该开放标准如何将 AI 助手与外部数据源连接起来,并展示一个用 Python 开发且与intersystems-irispython 包集成的自定义 MCP 服务器的首个示例。

目录

目录

  • 第 1 部分:什么是模型上下文协议?
    • 1.1 起源与背景
    • 1.2 为什么 MCP 很重要
  • 第 2 部分:了解 MCP 架构
    • 2.1 客户端-主机-服务器模型
    • 2.2 传输层
    • 2.3 数据层
    • 2.4 核心原语
  • 第 3 部分:使用 Python 从零开始构建 MCP 服务器
    • 3.1 使用 uv 创建新的 Python 包
    • 3.2 MCP 服务器的基本结构
    • 3.3 实现核心原语
  • 第 4 部分:将 MCP 与 AI 开发工具结合使用
    • 4.1 配置 MCP 服务器
  • 第 5 部分:使用 uv 和 uvx 分发和运行 MCP 服务器
    • 5.1 本地克隆(开发模式)
    • 5.2 GitHub 仓库
    • 5.3 PyPI
      • 5.3.
0
0 1
文章 cheng yu · 42 分鐘 前 8m read

https://media.giphy.com/media/Nxu57gIbNuYOQ/giphy.gif

别急,别急,我可不是在鼓吹那种科幻片里常见的“反机器战争”,为了阻止奥创或天网统治世界。 还没到那一步,还没到那一步 🤔

我邀请大家通过使用 ObjectScript 并嵌入 Python 来制作一款非常简单的游戏,以此向机器发起挑战。

我必须说,InterSystems IRIS 上的“嵌入式 Python”功能让我超级兴奋,它为创建精彩的应用打开了无数可能性,简直令人难以置信。

让我们来制作一个井字棋游戏吧,规则非常简单,我相信大家都知道怎么玩。

在孩子们还没有手机或平板电脑的年代,正是这个游戏让我在童年时期与家人长途驾车旅行时免于无聊——没有什么比在模糊的车窗玻璃上挑战兄弟姐妹来几局更让人乐在其中的了。

所以,系好安全带,我们开始吧!

规则

如前所述,规则非常简单:

  • 每局仅限2名玩家
  • 在3×3的网格上轮流下棋
  • 人类玩家始终代表字母X,电脑代表字母O
  • 玩家只能将字母填入空格中
  • 最先在水平、垂直或对角线上连成3个相同字母的一方获胜
  • 当9个空格全部被填满时,即为平局,比赛结束

所有机制和规则都将用ObjectScript编写,而电脑玩家的机制将用Python编写。

让我们动手实践吧

我们将通过一个全局变量来控制棋盘,其中每一行对应一个节点,每一列对应一枚棋子。

0
0 1
文章 cheng yu · 44 分鐘 前 2m read

与图片中提到的电影(对于不了解的人来说,就是1999年的《黑客帝国》)不同,在动态SQL和嵌入式SQL之间做出选择,并非在现实与幻想之间抉择,但这仍然是一个需要做出的决定。下面,我将尝试帮助您更轻松地做出选择。

如果您的需求是客户端与应用程序(进而与数据库)之间的交互,那么动态 SQL 可能更合适,因为它能非常轻松地“适应”这些查询变化。然而,这种动态性是有代价的:每次新的查询都会重新构建,这可能会导致更高的执行成本。下面是一个简单的 Python 代码片段示例。

0
0 2
文章 cheng yu · 50 分鐘 前 6m read

引言

REST API(表征状态转移)是一种接口,它允许不同的应用程序通过HTTP协议,利用GET、POST、PUT和DELETE等标准操作进行相互通信。REST API在软件开发中被广泛应用,用于提供可供其他应用程序访问的服务,从而实现不同系统之间的集成。

然而,为了确保 API 易于理解和使用,完善的文档至关重要。这就是 OpenAPI 发挥作用的地方。

OpenAPI 是一种用于描述 RESTful API 的标准。它允许以结构化的方式定义 API 的功能,包括指定可用的端点、接受和返回的数据类型、必需的参数以及预期的响应。 所有这些信息都汇总在一个规范文件中(通常扩展名为 .yaml 或 .json),自动化工具可以解析该文件以生成代码、文档等内容。

OpenAPI 规范旨在同时满足机器和人类的可读性,从而以标准化方式实现 RESTful Web 服务的描述、生成、使用和可视化。因此,OpenAPI 文档代表了对 API 的正式描述,既有助于需要使用该API 的开发者,也便于相关工具利用它来自动化各种流程。

定义规范文件有什么用处?

采用 OpenAPI 来记录 API 具有以下几个好处:

  • 清晰度:它提供了详细且结构化的文档,使开发人员能够快速了解如何与 API 交互、应发送哪些请求以及响应中会包含哪些数据。
  • 自动化:文档可从代码中自动生成,并能随着 API 的任何变更而保持最新。
0
0 2
文章 cheng yu · 1 小时 前 6m read

Prettier 适用于 ObjectScript

如果您在 JavaScript 或 TypeScript 代码中使用Prettier,现在也可以将其用于 ObjectScript 了。prettier-plugin-objectscript是一个 Prettier 插件,可对类(.cls)、例程(.mac, .int)以及包含文件()。

前后对比

该插件使用tree-sitter-objectscript 的语法规则、用于类的 UDL 语法以及用于例程和包含文件的例程语法来解析文件,并通过 Prettier 3 进行格式化输出。语法规则的选用依据文件扩展名、命令行参数以及 VS Code 中的设置。以以下类为例:

Class Demo.Greeter Extends %RegisteredObject {
Property Name As %String [Required];

/// Returns a greeting for the given name.
ClassMethod Greet(name As %String="world",times As %Integer=1) As %String [ Private ]
{
 s result=""
 f i=1:1:times {
 s result=result_"Hello, "_name_"! "
 }
 q:name="" "nobody"
 i times>1 { w "Greeted ",times," times",! }
 q result
}
}
0
0 4
公告 Claire Zheng · 17 小时 前

InterSystems Reports 26.2 版本现已在 InterSystems 软件分发网站的“组件”部分发布。该软件以“InterSystems Reports Designer”和“InterSystems Reports Server”的名义列出,支持 macOS、Windows 和 Linux 操作系统。

此版本对通过 Reports Server 提供的 Page Studio 和 Web Studio 的焕新用户界面进行了进一步优化。(请参阅下文的许可更新。)其他增强功能包括通过 TrueType 字体扩展了字体支持,新增了 2D 条形码,以及来自我们的合作伙伴 insightsoftware 的众多修复、安全更新和其他增强功能。

InterSystems Reports 26.2 基于 Logi Report 26.2 Service Pack 2 构建。如需了解更多信息,请参阅 insightsoftware 提供的发布说明。

2026 年的许可更新

自 2026 年 1 月起,InterSystems 增加了对Page Report Studio和Web Report Studio 的访问权限。这些功能使客户能够直接在报告服务器上执行更多报告编辑操作,从而减少了许多报告设计任务对安装 Report Designer 的需求。

0
0 6
文章 John Pan · 十一月 5 5m read

Hugging Face 提供了一个庞大的数据集集合,涵盖自然语言处理、分类、问答以及其他机器学习任务。要在 InterSystems IRIS 中使用这些数据集之一,开发人员通常需要下载该数据集,将其字段映射到 SQL 数据类型,创建表,并加载数据行。

iris-hf-import简化了这一流程。它允许您通过单个 ObjectScript 调用,将 Hugging Face 数据集导入到 IRIS SQL 表中。

该项目实现了Ideas Portal 中的 DPI-I-543 提案:将 Hugging Face 数据集加载到 IRIS 中,并为社区赏金计划的第三轮而创建。

导入数据集

安装包后,打开 IRIS 终端并运行:

write ##class(dc.hfloader.Loader).Load("hitorilabs/iris", "train")

该命令将加载数据集 hitorilabs/iris 的 train 分割集,创建目标表,并插入相关行。

在我的测试环境中,该调用返回了如下结果:

{
  "status": "success",
  "error": "",
  "dataset": "hitorilabs/iris",
  "config": "default",
  "split": "train",
  "table": "HFData.iris",
  "rowsWritten": 150,
  "columns": 5
}
0
0 8
文章 cheng yu · 十一月 5 10m read

人工智能代理即使出错,依然可能很有用

回复丢失了,但变更依然生效。我觉得我以前遇到过这种情况。

一个管理请求可以成功到达 InterSystems IRIS,修改配置,但在返回途中丢失了响应。操作员看到一条错误提示,但配置变更实际上已经生效。如果软件将无响应视为失败并重新发送请求,那么自动化反而会引发下一起故障事件。

这一切始于“请求超时。IRIS 是否已更改?”。首要任务是让不确定性保持可见,并防止因回复丢失而导致重复操作。现在,我们要求代理协助调查这种不确定性,同时仍坚持对证据的相同要求。

在《让创造力引领》一文中 让执行可追溯》一文中,我曾探讨如何在给予人员和代理创新空间的同时,确保最终工作结果能经得起证据检验。在那一阶段,Battery 已具备合成演示环境和经过测试的实时只读连接。下一步是进行真实的配置变更,通过原生 AI Hub 进行审查,并找出我们的信心超前于实际实现的环节。

这就是接下来的这一步。代理出错了,我们的代码也出错了。但我们继续前行。

这正是我希望Armada Battery去面对的问题。我打算通过让机器对其行为负责来取得成功。这当然不是什么特殊的设计难题,但很少有人会将此视为一项耀眼的成就。这是一个值得坚守的真理:怀疑并非弱点。批判性的眼光比盲目的崇拜更有价值。

那个比响应更持久的变更

我们的联机测试使用了 IRIS AI Hub EAP 109 版的一次性安装环境。

0
0 6
文章 John Pan · 十一月 5 5m read

大多数 IRIS 开发人员每天都在使用 $LISTBUILD —— 往往自己都浑然不觉。

它不仅仅是一个用于构建列表的便捷函数,更是数据库引擎内部用于存储行数据、全局值以及许多中间结构的默认格式。

尽管如此,关于 $LISTBUILD 值的实际二进制表示形式却鲜少被提及。大多数开发者仅依赖其行为表现,却从未探究过数据究竟是如何存储的。

本文严格聚焦于**$LISTBUILD 值的** 二进制布局 ,并基于通过 zzdump 进行的直接检查。


元素结构

一个 值是由一系列元素组成的序列。每个元素的编码形式如下:

[length][type][payload]

对于较小的元素:

  • length 占用 1 字节,并包含该元素的全部内容
  • type 表示 1 字节
  • payload 长度可变

示例:


字节序

更新:感谢 @Steven Hobbs

本文中的所有示例均采用小端字节序——这绝非偶然。

尽管 IRIS 内部同时支持小端和大数据字节序平台,但 对所有二进制有效载荷都采用统一的小端编码。

这适用于:

  • 整数值
  • 十进制尾数
  • 浮点数值 (08, 09)
  • UTF-16 字符串(UTF-16LE)

例如:

0
0 6
文章 cheng yu · 十一月 4 2m read

……你并不孤单。 

有帮助可寻。

我花了一段时间才弄明白这一点,我想可能还有其他人也在为此苦恼。 我仔细研究了所有关于 Entra 的资料,试图设置一个客户端凭据工作流,以便通过 Microsoft 365 账户发送电子邮件。虽然我成功获取了令牌,但始终无法使用 %Net.SMTP 类通过 SMTP 服务器进行身份验证。解决这个问题主要涉及两个方面。

首先,身份验证器的访问令牌不能仅仅是访问令牌本身。它必须采用以下格式:

set smtp.authenticator.AccessToken = "user="_emailaddress_$C(1)_"auth=Bearer "_token_$C(1,1)

其中 emailaddress 是您用于发送邮件的邮箱地址,token 是从服务器获取的 OAuth 令牌。

其次,默认的 %Net.SASL.XOAUTH2 机制的行为方式与 SMTP 服务器所期望的不一致。 具体来说,它不会向服务器发送初始响应就直接开始身份验证,但服务器期望立即收到该访问令牌。为解决此问题,您需要创建一个继承自 %Net.SASL.XOAUTH2 的类,并重写一个简单的方法:

Class User.MSOAUTH2 Extends %Net.SASL.XOAUTH2
{

/// Start authentication based on UserName and AccessToken using the XOAUTH2 SASL mechanism.
Method Start(ByRef response As %String) As %Boolean
{
 if (..AccessToken="") quit 0
 set response=..AccessToken		;in the original class, no response is sent here
 set ..state=1
 quit 1
}

}
0
0 8
文章 cheng yu · 十一月 4 8m read

这是两篇系列文章中的第二篇,我将带您逐步了解:

  • 第一部分——简介与快速导览(上一篇文章)
    • 这是什么?
    • 部署 InterSystems IRIS Cloud Document
    • 通过服务用户界面快速浏览该服务
  • 第二部分——示例(基于 Docker 的)Java 应用程序(本文)
    • 获取连接详细信息和 TLS 证书
    • 审阅一个简单的 Java 示例,该示例用于创建集合、插入文档并查询文档
    • 配置并运行 Java(Docker 化)端到端示例

如前所述,我们的目标是为您提供流畅的“首次运行”体验。

0
0 7
文章 John Pan · 十一月 4 7m read

Supabase 是一款基于 Postgres 的流行后端即服务(BaaS)平台。它为您的数据表提供了 API、身份验证、Studio 以及 Edge Functions 功能。然而,大量有价值的数据存储在InterSystems IRIS中, 且不会迁移。 本文将介绍iris-supabase-fdw,这是我针对社区奖励计划*“从创意到应用”(第三轮)*中Ideas Portal 创意“为 Supabase 添加 InterSystems 封装层”(DPI-I-663)所做的实现。 它使 IRIS 表在 Supabase 中以普通 Postgres 表的形式呈现,因此您可以对其进行查询、连接和 更新操作。

select p.name, a.startsat, a.doctor
from iris.appointment a
join iris.patient p on p.id = a.patient
where p.city = 'Roma' and a.status = 'scheduled';

iris.appointment 和 iris.patient 是 IRIS 表。数据绝不会被复制。

0
0 8
文章 John Pan · 十一月 4 7m read

某交易伙伴在凌晨2点更改了订单的日期格式。到了早上,你收到了五十条警报,每条对应一笔失败的订单。而你真正想要的只是一条通知:哪里出了问题、原因是什么,以及如何解决。

这正是我开发 OcuTalon 的初衷。 OcuTalon 是一款在 InterSystems IRIS 环境中作为互操作性生产环境运行的个人助理。它会监控您的生产环境,在出现需要您处理的问题时及时通知您,并提出待您确认的修复方案。其代理程序是 IRIS AI Hub 代理,相关工作记录会显示在 Visual Trace 中——这正是您目前用于管理数据流的工具。

the OcuTalon page on the online demo, with the incident card for 50 failed orders and the Simulated phone showing the same approval request

无需安装,两分钟即可体验

访问demo.ocutalon.com。登录信息显示在启动画面上。该演示运行的是实时模型 Claude Haiku 5.5:您所看到的并非录屏内容。演示中的 Visual Trace 处于共享状态,因此请勿输入任何个人信息。

页面顶部的演示指南包含五个步骤:观看、提醒、中断数据流、批准和打开跟踪记录。

1. 监控。点击“发送”,指南会以通俗语言向 OcuTalon 发出指令:“监控‘订单’生产流程,仅在需要我介入时通知我。”‘订单’是一个由模拟合作伙伴提供数据的小型演示生产环境。步骤 2(提醒)为可选操作。

2. 中断数据流。点击“中断数据流”。合作伙伴将以新的日期格式发送 50 份订单,这些订单会在“订单”生产环境中真实地失败。

0
0 11
文章 Murilo Przybyloviecz · 十一月 4 7m read
安全往往要拖到应用快要上线时才被考虑。对初学者来说,这种推迟会让身份验证、角色、资源和审计看起来像是互不相关的管理任务。更好的做法是,在一个小巧且可复现的示例中把它们一起引入。

我仍然是 InterSystems IRIS 的初学者,这也是我写这篇文章的主要动机之一。在学习这个平台的过程中,我希望通过亲手构建、测试和观察来理解安全,而不是只阅读各种定义。看到同一个端点从 401 Unauthorized 变为 403 Forbidden,最终变为 200 OK,让我明白了不同的安全层是如何协同工作的。我决定把这段经历记录下来,让其他初学者也能复现这个过程,并从同样的递进中学到东西。

在本文中,我在 InterSystems IRIS 中构建了一个最小化的 REST API,并用它演示三种不同的安全结果:

不带凭据的请求会收到 401 Unauthorized。
已通过身份验证但没有所需权限的用户会收到 403 Forbidden。
已通过身份验证且已获授权的用户会收到 200 OK 以及虚构的数据。

最后,我会在 IRIS 审计数据库中验证这次成功的请求。这个示例刻意保持小巧,但它用到了与大型应用相同的安全概念。

本演示返回的所有名称和记录均为虚构。该项目是一个教学示例,而不是生产环境的患者 API。

示例包含的内容

该项目使用三个 ObjectScript 类:

SecurityDemo.REST 提供 GET /security-demo/api/patients。
SecurityDemo.Installer 创建受保护的资源、角色、审计事件和 REST Web 应用。
SecurityDemo.Audit 写入安全的审计记录,不存储密码、令牌或患者数据。

授权模型使用一个名为 SecurityDemo.PatientData 的自定义资源和一个名为 SecurityDemoReader 的角色。该角色授予对该自定义资源的 READ 权限。由于这个本地示例把类存放在 USER 数据库中,该角色还被授予 %DB_USER:READ,这是加载 REST 类所必需的。

第二项权限是一个重要的设计细节。对于这个隔离的本地实验环境,这样做是可以接受的,但生产应用通常应使用专用的数据库和命名空间,这样它的数据库权限就不会覆盖无关的代码或数据。

实验环境设置

在这个实验中,我使用了本地的 InterSystems IRIS 实例和 USER 命名空间。一个小型的安装类创建了演示所需的安全元素:

SecurityDemo.PatientData 资源;
SecurityDemoReader 角色;
SecurityDemo/PatientAPI/ReadPatients 审计事件;
/security-demo/api Web 应用。

该 Web 应用使用密码身份验证,并且不启用未经身份验证的访问。这样设置的目的并不是展示一个完整的应用或安装教程,而是提供一个可控的环境,使每一种安全结果都能被清楚地观察到。

技巧 1:把身份验证和授权当作两种不同的检查

身份验证回答的是:是谁在发出请求?

授权回答的是:这个身份被允许做什么?

当我们在三种条件下调用同一个端点时,这种区别就变得清晰了。

首先,我发送了一个不带凭据的请求:

objectscript
curl.exe -i "http://localhost:52773/security-demo/api/patients"

IRIS 返回了 401 Unauthorized。

Mostrar Imagem

图 1 — InterSystems IRIS 以 HTTP 401 Unauthorized 拒绝不带凭据的请求。

这个响应发生在返回任何应用数据之前。客户端尚未建立 IRIS 可以信任的身份。

技巧 2:使用普通用户而不是管理员进行测试

在下一个测试中,我在 System Administration > Security > Users 下创建了一个已启用的账户,名为 ArticleUser。起初我没有给它分配 SecurityDemoReader。

使用管理员会让这个测试产生误导。特别是,拥有 %All 的用户持有所有权限,因此无法复现授权失败的情形。

我再次调用了该端点,并让 curl 提示输入密码,而不是把密码直接写在命令里:

objectscript
curl.exe -i --user ArticleUser "http://localhost:52773/security-demo/api/patients"

这一次身份验证成功了,但由于该用户没有所需的权限,IRIS 返回了 403 Forbidden。

Mostrar Imagem

图 2 — InterSystems IRIS 阻止了没有所需权限的已验证用户。

这种区分在排查问题时很有用:

401 通常意味着身份没有被成功建立。
403 意味着身份已知,但该操作未获授权。
技巧 3:用资源而不是用户名来保护操作

REST 类中不包含 If $Username = "ArticleUser" 这样的逻辑。把用户名硬编码进去既难以维护,也无法扩展。

相反,端点检查的是一个安全资源:

objectscript
ClassMethod Patients() As %Status
{
    Set allowed = $System.Security.Check("SecurityDemo.PatientData", "READ")
    Do ##class(SecurityDemo.Audit).Record(allowed)

    If 'allowed {
        Quit ..WriteError(403, "FORBIDDEN", "The SecurityDemoReader role is required.")
    }

    // Build and return fictional records.
}

用户通过角色获得权限,而应用检查的是资源,并不需要知道哪些具体用户应该被允许。这种分离使得添加或移除用户时无需修改应用代码。

在管理门户中,我把 SecurityDemoReader 分配给了 ArticleUser。然后我重复了同样的请求,并建立了一个新的已验证连接。IRIS 返回了 200 OK 和两条虚构的记录:

Mostrar Imagem

图 3 — 拥有 SecurityDemoReader 角色的用户成功访问了受保护的 REST 端点。

响应中还包含两个小而有用的防御性标头:

objectscript
Cache-Control: no-store
X-Content-Type-Options: nosniff

no-store 告诉客户端和中间节点不要保留该响应。nosniff 告诉浏览器不要重新解释所声明的内容类型。这些标头不能取代身份验证、授权或 TLS,但对于返回敏感信息的 API 来说,它们是合理的补充。

该演示还禁用了跨源处理,因为它不需要来自其他源的浏览器客户端。在没有实际需求的情况下启用 CORS 会带来不必要的暴露。

技巧 4:审计有意义的应用事件

身份验证和授权决定一个操作能否发生。审计则有助于回答事后发生了什么。

该演示定义了一个用户审计事件,其标识符如下:

objectscript
Event Source: SecurityDemo
Event Type: PatientAPI
Event Name: ReadPatients

审计辅助方法只记录用户名和授权结果:

objectscript
ClassMethod Record(allowed As %Boolean) As %Status
{
    Set outcome = $Select(allowed:"Allowed", 1:"Denied")
    Set eventData = "username=" _ ..SafeValue($Username, 64) _ ";outcome=" _ outcome
    Set description = "Patient list access " _ outcome

    Quit $System.Security.Audit("SecurityDemo", "PatientAPI", "ReadPatients", eventData, description)
}

这段代码刻意避免记录密码、授权标头、返回的记录或其他敏感内容。审计日志本身就是安全资产;收集不必要的机密信息,会让审计轨迹变成另一个风险来源。

我打开了 System Administration > Security > Auditing > View Audit Database,找到了由这次成功请求产生的事件。

Mostrar Imagem

图 4 — IRIS 审计轨迹记录了已验证的用户以及对受保护端点的成功访问。

该记录标明了 ArticleUser、PatientAPI 事件类型、ReadPatients 事件以及 Allowed 结果。这证明了受保护的操作是由一个已通过身份验证且已获授权的身份执行的。

技巧 5:如实说明演示与生产环境安全的差距

这个实验聚焦于一个狭窄的学习目标。真正的部署还需要额外的控制措施,包括:

对每一个承载凭据或敏感数据的连接使用 TLS;
适合所在组织的身份验证机制,例如 OAuth 2.0、OpenID Connect、Kerberos 或 LDAP;
专用的应用数据库和命名空间;
使用密钥管理,而不是把凭据放在源代码或脚本中;
数据库加密以及有文档记录的密钥管理流程;
审计日志的监控、保留、保护和审查;
禁用未使用的服务和应用;
定期审查用户、角色和权限;
同时针对成功访问和预期的安全失败进行测试。

最重要的一课是,安全应当是可观察、可测试的。仅仅创建一个角色并假定它有效是不够的。请分别使用无凭据、权限不足以及具备预期角色的方式发出请求。验证确切的 HTTP 结果,然后在审计轨迹中确认相应的活动。

结论

仅用一个小小的 REST 端点,这个示例就演示了 IRIS 的若干核心安全概念,而无需一个完整的应用:

身份验证拒绝匿名请求;
授权区分了已验证用户和已授权用户;
资源描述了被保护的对象;
角色把应用用户所需的权限归为一组;
编程式检查在靠近受保护操作的地方强制执行访问控制;
审计提供了有意义活动的踪迹。

对初学者来说,401 → 403 → 200 这个序列是理解这些层如何协同工作的实用方法。它还能产生可重复的证据,证明安全配置按预期运行。

构建并测试这个小项目,让我对 IRIS 安全的理解比分别学习每个概念时清晰得多。作为初学者,能够在一个实验中同时看到身份验证、授权、角色、资源和审计的运作,尤其令人受到鼓舞。我希望这份演练能为其他开发者提供一个简单的起点,并鼓励他们探索 InterSystems IRIS 中更广泛的安全功能。

官方文档
InterSystems IRIS Security
Privileges and Permissions
Securing REST Services
Managing Applications
Auditing

作者:Murilo Przybyloviecz
0
0 8
文章 John Pan · 十一月 4 8m read

管理门户是我们大多数人管理 IRIS 的地方,它经过多次版本更新已日趋完善。 当InterSystems邀请社区成员构建我们自己的管理门户时,我希望一举解答两个问题: 如果我们今天从头开始构建,这个门户会是什么样子?以及,要让一个AI 代理在无需信任的情况下协助运行IRIS实例,需要满足哪些条件?

最终成果便是OcuPilot:这是一个针对竞赛所列六个领域重新构建的管理门户,每个界面 旁都配有一个智能代理。它能够解释您当前所见的内容,并为您调整设置——但只有 在您审阅了更改内容并点击“确认”之后,它才会执行操作。

只需两分钟即可体验

打开ocupilot.org,使用用户名 demo 和密码 ocupilot-demo 登录。该系统运行在真实的 IRIS for Health 实例上。

  • **无需模型密钥。**该演示的代理运行在 Claude Opus 5.5 上。
  • **更改需要片刻时间。**涉及更改的请求最多可能需要一分钟。
  • **该实例为共享模式。**所有用户均使用同一实例,因此如果 /csp/myapp 已启用,请先让 代理将其禁用。该功能每整点重置一次,重置期间系统将离线几分钟 。
  • 请勿输入任何私人信息。
0
0 11
文章 John Pan · 十一月 4 4m read

当计划任务运行缓慢时,其执行历史记录是一个有用的切入点。系统消息和资源观察结果则提供了背景信息。将它们一起保存下来,便可以将此次事件与后续的运行情况进行对比。

Harbor 会存储调查过程中所需的各项资料:诊断快照、笔记、检查清单以及管理变更的链接。本分步指南将演示如何创建调查,并在不更改 IRIS 配置的情况下比较两个快照。

源代码库包含安装说明、操作指南和验证记录。

运行 Harbor

提供的软件栈需要配备 Compose v2 的 Docker 以及 Linux 容器,至少 4 GB 的可用内存和约 5 GB 的可用磁盘空间。

git clone https://github.com/Igorandor/harbor.git
cd harbor
docker compose up -d --build
docker compose ps

首次构建需要几分钟时间。打开 http://localhost:3100,并使用 HarborLocal-2026! 以 SuperUser 的身份登录。这些是捆绑实例的公共快速入门凭据。 两个已发布的端口均绑定到回环地址;请将此堆栈保留在您自己的机器上。若要进行共享部署,则需要使用您自己的账户、HTTPS 以及部署指南中的设置。

该捆绑镜像固定为 IRIS Community 2026.2 版本。

0
0 11
文章 John Pan · 十一月 4 6m read

在一项针对模拟医疗决策的随机研究中,仅凭大型语言模型(LLM)的强劲表现,并不能直接转化为使用这些模型的人员做出更优的决策。 阅读《自然·医学》上的这项研究。

**AI辅助使得构思和构建软件变得更加容易。**一个人可以描述一个问题,智能代理可以提出架构方案,双方共同探索那些在僵化的规格说明中可能永远无法涌现的解决方案。他们不同的声音、品味和建立联系的方式,正是创造力的源泉。

一个听起来合理的想法,并不意味着系统就行为正确。

语言模型可能自信地描述一个并不存在的API,从成功的HTTP响应中推断出成功,或者为它从未验证过的结果给出看似合理的解释。 人在疲劳、时间压力或信息不完整的情况下,也会犯类似的错误。当二者快速协作时,彼此的自信会相互强化。此时,产品就需要一种独立的方式来回答:请求了什么?实际发生了什么?还有哪些未知?

一起公开事件让这一区别难以被忽视。2025年, SaaStr创始人杰森·莱姆金(Jason Lemkin)描述了Replit的一款编码代理在宣布的代码冻结期间删除了其应用程序的生产数据库。 Replit的首席执行官承认了此次删除事件,并宣布将着手分离开发数据库和生产数据库。我从中得到的启示是:对话中的指令无法完全承担技术边界的全部责任。一个代理不应仅仅因为承诺过不触碰生产数据,就能够访问生产数据。

0
0 8
文章 cheng yu · 十一月 4 9m read

MyOwn Portal 将一个 AI 代理部署在 InterSystems IRIS 互操作性生产环境中:该代理会分析事件和访问请求,解释其发现的情况,并提出变更建议,但最终决策始终由人类做出。 本文介绍了我们如何利用 AI Hub(版本 2026.3.0AI.154.0)构建该系统,以参与“互操作性工作流中的 AI 代理”竞赛。

问题与核心思路

IRIS 管理员需要处理各种需要关注的信号:磁盘空间不足、任务失败、日志警报以及角色请求。 AI 代理可协助进行分诊;然而,授予其写入权限是我们不愿承担的风险。项目规则很简单:代理仅提出建议。它拥有只读工具,且任何变更仅以带有效期的建议形式存在,需由人员使用其自有凭据进行确认。

MyOwn Portal 是我们上一届竞赛中的管理门户。如今,它已拥有 MyOwn.Production.Main 生产环境,其中 AI Hub 代理作为工作流中的一个步骤。

链接

0
0 7