搜索​​​​

清除过滤器
问题
天恒 周 · 八月 6, 2022

cache题目

cache的题目资源,类似于Oracle的OCP试题那种,能反应出对基础概念的掌握。 回答您的问题: 1. 我们海外在招募考试平台测试者,您可以直接给certification@intersystems.com 发邮件申请,具体内容可以参考:https://community.intersystems.com/post/beta-testers-needed-our-upcoming-intersystems-iris-system-administration-specialist; 2. 我们国内也即将推出初中高级的培训认证体系,敬请关注。 这还有网上的一些体验题目:https://community.intersystems.com/sites/default/files/post-associated-docs/sysadmin_practice_questions_0.pdf 谢谢您的关注! 好的,感谢!
公告
Claire Zheng · 十二月 22, 2022

直播预告 | 卫生健康信息标准应用管理培训班 (第二期)

2022年12月24日-25日,卫生健康信息标准应用管理培训班 (第二期)将于线上举办,此次培训班由国家卫生健康委统计信息中心指导、由《中国卫生信息管理杂志》社、深圳市卫生健康信息协会主办,InterSystems协办。详细日程请点击此处了解。您可以通过以下方式参与: 报名观看(可申请学分) 视频号(可观看直播) 如需要回看,请扫描“可申请学分”的二维码观看
文章
Weiwei Gu · 九月 14, 2023

VS Code 无法连接到服务器的原因之一

昨天,我在一个客户网站提供从 Studio 迁移到 VS Code 的定制咨询时,就遇到了这种情况。 该站点的服务器已配置为使用delegated authentication,但尚未针对 /api/atelier Web 应用程序设置“delegated”复选框,而 InterSystems ObjectScript 扩展包的成员正是使用该复选框进行连接的。 一旦我们的应用程序设置了其复选框并单击了服务器管理器刷新按钮,就可以在服务器上枚举命名空间。
文章
Louis Lu · 一月 7, 2021

创建“虚拟”的SOAP Web 服务

在 Caché 中处理 SOAP 请求时,有时需要通过直接访问(有时是编辑)所发送的 XML(即 SOAP 请求和随后的 SOAP 响应)来调试错误。 如果要调试 Caché Web 服务,使用 SoapUI (https://www.soapui.org/) 之类的工具手动创建和控制 SOAP 请求通常很有用,这样可以很容易地在 Caché Web 服务上看到调整的效果。 但是如果已经有 Web 服务(可能不是 Caché),并且想要调试相关的 Caché Web 客户端该怎么办? 您可能已将 SOAP 响应 XML 保存在文件中(例如 Caché SOAP 日志),您需要一个“虚拟”Web 服务将其发送到 Caché Web 客户端,就像实际的 Web 服务一样操作。 由于我经常在技术支持的过程中需要调试客户的 Caché Web 客户端,我创建了这样一个“虚拟”的Web 服务 – 见下文: Class JSUtil.DummyWebService Extends %CSP.Page { /// Mimic a SOAP Web Service by sending the specified SOAP Response XML. /// Typically this XML will be copied-and-pasted from a SOAP log. Parameter CONTENTTYPE = "text/xml"; /// File containing the SOAP Response XML: Parameter XMLFILENAME = "C:\data\soapresponse.txt"; ClassMethod OnPage() As %Status { set XML="" set stream = ##class(%Stream.FileCharacter).%New() set sc = stream.LinkToFile(..#XMLFILENAME) while 'stream.AtEnd { set XML = XML_stream.Read() } write XML quit $$$OK } } 要使用 JSUtil.DummyWebService 类: 1.将参数 XMLFILENAME 的值更改为包含来自 Web 服务的 SOAP 响应的 XML 的位置。 通常,此文件可内容可通过手动剪切和粘贴 Caché SOAP 日志中的响应 XML 消息来创建。 2.使用 Studio 的“View Web Page”获取此 CSP 页面的 URL,它应显示响应的XML消息内容。 3.将上面的 URL 粘贴到 Caché Web 客户端的 LOCATION 参数中。 现在,当调用 Caché Web 客户端时,它将收到参数 XMLFILENAME 指向的 SOAP 请求 XML。 我已经多次使用这种方法来帮助调试 Caché Web 客户端。 参考以下示例: SOAP 日志的“Web 客户端的输入”中包含以下错误: ERROR #6203: Unexpected Element (完整的 SOAP 日志可在此处找到:[_https://github.com/ISC-schulman/InterSystems/raw/master/soaplog.txt_](https://github.com/ISC-schulman/InterSystems/raw/master/soaplog.txt)) 我们还有 Web 服务的 WSDL ([_https://github.com/ISC-schulman/InterSystems/raw/master/example.wsdl_](https://github.com/ISC-schulman/InterSystems/raw/master/example.wsdl)),但无法访问 Web 服务本身。 (虽然这对于 InterSystems 支持来说很常见,但不可否认,对于客户可能并不常见 – 这只是一个简单的示例,说明如何使用 DummyWebService。) 首先,使用 DummyWebService 重现错误: 1.使用 SOAP 向导从提供的 WSDL 生成 Web 客户端。 所有参数均使用默认值(尽管您可以指定包名称。) 2.查看 SOAP 日志,然后将 Web 服务响应的XML(“Input to Web client”)剪切并粘贴到文件中: OK   3.通过 JSUtil.DummyWebService 中的参数 XMLFILENAME 指向此文件。 4.使用 Studio 的“Display Web Page”查看 DummyWebService – 它应显示步骤 2 中创建的文件内容。 5.将步骤 4 中的 URL 剪切并粘贴到步骤 1 中生成的 Web 客户端的 LOCATION 参数中。 6.调用 Web 客户端,例如  set client = ##class(MyWebService.RequestWSSoapHttpPort).%New()  do client.createAsynchronuosRequest("x") quit 7. 验证(例如通过 SOAP 日志)是否发生相同错误,即“ERROR #6203: Unexpected Element”。   接下来我们解决这个错误。 这里会经历一些过程或反复试验,但同样只是为了说明如何使用 DummyWebService。 1.像之前一样使用 SOAP 向导和提供的 WSDL 生成 Web 客户端 – 指定不同的包名称以防止覆盖第一个 Web 客户端。 另外,参数全部采用默认值,除了一处: 在 SOAP 向导的步骤 3 中选择“对于文档样式的 Web 方法使用未包装的消息格式(Use unwrapped message format for document style web methods)” 2.重复上面的步骤 5 和 6。 3.验证(例如通过 SOAP 日志)Web 客户端错误是否已修正。 _(注意:使用“未包装的消息格式(unwrapped message format)”是解决 Web 客户端问题的常见解决方案 – 有关详细信息,请参见我们的文档中的“使用 SOAP 向导_”。)   **总结** 可以使用 DummyWebService 类将指定的 SOAP 响应(例如,从 SOAP 日志)发送到 Caché Web 客户端,以模拟 Web 服务的响应。
文章
姚 鑫 · 三月 13, 2021

第九章 SQL查询数据库(二)

# 第九章 SQL查询数据库(二) # 调用用户定义函数的查询 InterSystems SQL允许您在SQL查询中调用类方法。这为扩展SQL语法提供了强大的机制。 若要创建用户定义的函数,请在持久性InterSystems IRIS类中定义一个类方法。该方法必须具有文字(非对象)返回值。这必须是一个类方法,因为在SQL查询中将没有对象实例可以在其上调用实例方法。还必须将其定义为SQL存储过程。 例如,我们可以在`MyApp.Person`类中定义一个`Cube()`方法: ```java Class MyApp.Person Extends %Persistent [DdlAllowed] { /// Find the Cube of a number ClassMethod Cube(val As %Integer) As %Integer [SqlProc] { RETURN val * val * val } } ``` 可以使用`CREATE FUNCTION`,`CREATE METHOD`或`CREATE PROCEDURE`语句创建SQL函数。 要调用SQL函数,请指定SQL过程的名称。可以在可能指定标量表达式的任何地方以SQL代码调用SQL函数。函数名称可以使用其架构名称进行限定,也可以不限定。不合格的函数名称采用用户提供的模式搜索路径或系统范围内的默认模式名称。函数名称可以是定界标识符。 SQL函数必须具有用括号括起来的参数列表。参数列表可以为空,但括号是强制性的。所有指定的参数均充当输入参数。不支持输出参数。 SQL函数必须返回一个值。 例如,以下SQL查询将用户定义的SQL函数作为方法调用,就像它是内置SQL函数一样: ```sql SELECT %ID, Age, Sample.Person_Cube(Age) FROM Sample.Person ``` ![image](/sites/default/files/inline/images/1_25.png) 对于`Age`的每个值,此查询将调用`Cube()`方法并将其返回值放入结果中。 SQL函数可能是嵌套的。 如果找不到指定的功能,则InterSystems IRIS会发出`SQLCODE -359`错误。如果指定的函数名称不明确,则InterSystems IRIS会发出`SQLCODE -358`错误。 # 查询串行对象属性 使用默认存储(`%Storage.Persistent`)从类中映射为SQL的子表的串行对象属性也将在该类映射表中的单个列中映射。该列的值是串行对象属性的序列化值。该单列属性被映射为SQL `%List`字段。 例如,`Sample.Person`中的`Home`列定义为`Property Home As Sample.Address;`。它将映射到类`Sample.Address`扩展(`%SerialObject`),其中包含属性`Street`,`City`,`State`和`PostalCode`。 以下示例从各个串行对象列返回值: ```sql SELECT TOP 4 Name,Home_Street,Home_City,Home_State,Home_PostalCode FROM Sample.Person ``` 以下示例将所有串行对象列的值(按顺序)作为单个%List格式字符串返回,并将每一列的值作为%List的元素: ```sql SELECT TOP 4 Name,$LISTTOSTRING(Home,'^'),$length(Name) FROM Sample.Person ``` ![image](/sites/default/files/inline/images/2_14.png) 默认情况下,此“主页”列是隐藏的,并且不映射为`Sample.Person`的列。 # 查询集合 可以从SQL `WHERE`子句引用集合,如下所示: ```sql WHERE FOR SOME %ELEMENT(collectionRef) [AS label] (predicate) ``` `FOR SOME%ELEMENT`子句可用于指定`STORAGEDEFAULT =“ list`”的列表集合和数组。谓词可以包含对伪列`%KEY`,`%VALUE`或两者的引用。一些示例应有助于阐明如何使用`FOR SOME%ELEMENT`子句。以下返回其最喜欢的颜色包括`“红色”`的每个人的名字和最喜欢的颜色的列表。 ```sql SELECT Name,FavoriteColors FROM Sample.Person WHERE FOR SOME %ELEMENT(FavoriteColors) (%Value = 'Red') ``` ![image](/sites/default/files/inline/images/3_12.png) 任何SQL谓词都可能出现在`%Value`(或`%Key`)之后,因此例如以下也是合法语法: ```sql SELECT Name,FavoriteColors FROM Sample.Person WHERE FOR SOME %ELEMENT(Sample.Person.FavoriteColors) (%Value IN ('Red', 'Blue', 'Green')) ``` ![image](/sites/default/files/inline/images/4_8.png) 列表集合被认为是具有连续数字键1、2等的数组集合的特例。数组集合可以具有任意的非空键: ```sql FOR SOME (children) (%Key = 'betty' AND %Value > 5) ``` 除了内置列表和数组集合类型之外,还可以通过为任何属性提供`BuildValueArray()`类方法来创建通用集合。 `BuildValueArray()`类方法将属性的值转换为本地数组,其中数组的每个下标是一个`%KEY`,该值是对应的`%VALUE`。 除了可以在`%KEY`或`%VALUE`上进行简单选择之外,还可以在逻辑上连接两个集合,如以下示例所示: ```sql FOR SOME %ELEMENT(flavors) AS f (f.%VALUE IN ('Chocolate', 'Vanilla') AND FOR SOME %ELEMENT(toppings) AS t (t.%VALUE = 'Butterscotch' AND f.%KEY = t.%KEY)) ``` 此示例有两个集合:`Favors`和`TOPING`,这两个集合通过键在位置上相关。该查询限定了将`巧克力`或`香草`指定为`口味元素`的行,并且还将`奶油糖果`列为相应的`配料`,其中通过`%key`建立对应关系。 可以使用`$SYSTEM.SQL`配置方法`GetCollectionProjection()`和`SetCollectionProjection()`来确定如果将集合映射为子表,则是否将集合映射为列。在编译或重新编译该类时,对该系统范围的设置所做的更改将对每个类生效。 ## 使用说明和限制 - **`FOR SOME%ELEMENT`只能出现在`WHERE`子句中。** - **`%KEY`和`/`或`%VALUE`只能出现在`FOR`谓词中。** - **任何特定的`%KE`Y或`%VALUE`只能被引用一次。** - **`%KEY`和`%VALUE`可能不会出现在外部联接中。** - **`%KEY`和`%VALUE`可能不会出现在值表达式中(仅在谓词中)。** # 调用文本搜索的查询 InterSystems IRIS支持所谓的`“自由文本搜索”`,包括支持: - 通配符 - 填充物 - 多词搜索(也称为n-gram) - 自动分类 - 词典管理 此功能使SQL能够支持全文索引,还使SQL能够索引和引用集合的单个元素,而无需将集合属性映射为子表。虽然支持集合索引和全文索引的底层机制密切相关,但文本检索具有许多特殊属性,因此为文本检索提供了特殊的类和SQL功能。 # 伪字段 InterSystems SQL查询支持以下伪字段值: - **`%ID` —返回`RowID`字段值,而不管`RowID`字段的实际名称是什么。** - `%TABLENAME` —返回在`FROM`子句中指定的现有表的限定名称。定义表时,使用限定的字母大小写返回合格的表名,而不是`FROM`子句中指定的字母大小写。如果`FROM`子句指定了不合格的表名,则`%TABLENAME`将返回合格的表名(`schema.table`),以及从用户提供的模式搜索路径或系统范围内的默认模式名称提供的模式名称。例如,如果`FROM`子句指定`mytable`,则`%TABLENAME`变量可能返回`SQLUser.MyTable`。 - `%CLASSNAME` —返回与`FROM`子句中指定的现有表相对应的合格类名称(`package.class`)。例如,如果`FROM`子句指定了`SQLUser.mytable`,则`%CLASSNAME`变量可能返回`User.MyTable`。 注意:请勿将`%CLASSNAME`伪字段值与`%ClassName()`实例方法混淆。它们返回不同的值。 伪字段变量只能为包含数据的表返回。 如果在`FROM`子句中指定了多个表,则必须使用表别名,如以下嵌入式SQL示例所示: ```java /// d ##class(PHA.TEST.SQL).Query3() ClassMethod Query3(val As %Integer) As %Integer [ SqlProc ] { &sql(SELECT P.Name,P.%ID,P.%TABLENAME,E.%TABLENAME INTO :name,:rid,:ptname,:etname FROM Sample.Person AS P,Sample.Employee AS E) IF SQLCODEd ##class(PHA.TEST.SQL).Query3() Sample.PersonPerson table Name is: Adams,Diane F. Sample.PersonPerson table RowId is: 95 P alias TableName is: Sample.Person E alias TableName is: Sample.Employee ``` 为`%TABLE NAME`和`%CLASS NAME`列分配了默认的列名称`Literal N`,其中`n`是`SELECT`语句中伪字段变量的`select-item`位置。 # 查询元数据 可以使用Dynamic SQL返回有关查询的元数据,例如查询中指定的列数,查询中指定的列的名称(或别名)以及查询中指定的列的数据类型。 下面的ObjectScript Dynamic SQL示例为`Sample.Person`中的所有列返回列名和该列的ODBC数据类型的整数代码: ```java /// d ##class(PHA.TEST.SQL).Query4() ClassMethod Query4() { SET myquery="SELECT * FROM Sample.Person" SET rset = ##class(%SQL.Statement).%New() SET qStatus = rset.%Prepare(myquery) IF qStatus'=1 { WRITE "%Prepare failed:" DO $System.Status.DisplayError(qStatus) QUIT } SET x=rset.%Metadata.columns.Count() WHILE x>0 { SET column=rset.%Metadata.columns.GetAt(x) WRITE !,x," ",column.colName," ",column.ODBCType SET x=x-1 } WRITE !,"end of columns" } ``` ```java DHC-APP>d ##class(PHA.TEST.SQL).Query4() 15 Office_Zip 12 14 Office_Street 12 13 Office_State 12 12 Office_City 12 11 Home_Zip 12 10 Home_Street 12 9 Home_State 12 8 Home_City 12 7 Spouse 4 6 SSN 12 5 Name 12 4 FavoriteColors 12 3 DOB 9 2 Age 4 1 ID 4 end of columns ``` 在此示例中,列以反向列顺序列出。请注意,包含列表结构化数据的`FavoriteColors`列返回的数据类型为`12(VARCHAR)`,因为ODBC将InterSystems IRIS列表数据类型值表示为以逗号分隔的值的字符串。 # 快速查询 InterSystems IRIS支持快速选择,这是一种内部优化,用于通过ODBC和JDBC快速执行查询。此优化将InterSystems全局变量映射到Java对象。它将全局节点(数据记录)的内容作为Java对象传递。收到这些Java对象后,它将从它们中提取所需的列值并生成结果集。 InterSystems IRIS会尽可能自动应用此优化。这种优化是自动的,用户看不见。当准备好查询时,InterSystems IRIS会将查询标记为使用快速选择机制执行还是使用标准查询机制执行。 如果查询仅引用字段,常量或引用字段和`/`或常量的表达式,则快速选择将应用于`%PARALLEL`查询和针对分片表的查询。 服务器和客户端都必须支持快速选择。要在客户端中启用或禁用“快速选择”,请在类实例的定义中使用“属性”,如下所示: ```java Properties p = new Properties(); p.setProperty("FeatureOption","3"); / 1 is fast Select, 2 is fast Insert, 3 is both ``` 由于性能上的差异,对于用户来说重要的是要知道什么情况限制了快速选择的应用。 表限制:无法使用快速选择来查询以下类型的表: - 链接表 - 一个表,其主/数据映射具有多个节点 - 具有映射到同一数据位置的多个字段的表(仅可使用`%Storage.SQL`来实现) 字段限制:如果选择项列表中包含以下列,则无法使用“快速选择”执行查询。这些类型的列可以在表中定义,但是查询无法选择它们: - 流字段(数据类型`%Stream.GlobalCharacter`或`%Stream.GlobalBinary`) - 查询时计算的字段(计算的`COMPUTECODE`或瞬态) - 是列表集合的字段(具有`LogicalToOdbc`转换) - 一个执行`LogicalToOdbc`转换并且不是数据类型`%Date`,`%Time`或%PosixTime`的字段 - 覆盖了`LogicalToOdbc`转换代码的字段 - 执行`LogicalToStorage`转换的字段 - 地图数据输入使用检索码的字段 - 一个其地图数据条目具有定界符的字段(不是`%List`存储) - 映射到一块嵌套存储的字段 索引限制:如果选择项目列表仅由`%ID`字段和`/`或均映射到同一索引的字段组成,则不使用快速选择。 如果使用“快速选择”执行查询,则在启用了`%System `/`%SQL` / `XDBCStatement`的情况下,在审计数据库的SELECT审计事件中会标记此事实。 ## 查询和企业缓存协议Enterprise Cache Protocol (ECP) 使用企业缓存协议(ECP)的InterSystems IRIS实现(例如分布式缓存群集)可以同步查询结果。 ECP是一种分布式数据缓存体系结构,用于管理服务器系统的异构网络之间的数据分布和锁定。 如果ECP同步处于活动状态,则每次执行`SELECT`语句时,InterSystems IRIS都会将所有未决的ECP请求强制发送到数据服务器。完成后,这可以确保客户端缓存是同步的。此同步发生在查询的“打开”逻辑中。如果这是游标查询,则在`OPEN`游标执行中。 要激活ECP同步,请使用`%SYSTEM.SQL`类的`SetECPSync()`方法。若要确定当前设置,请调用`$SYSTEM.SQL.CurrentSettings()`。
文章
姚 鑫 · 四月 8, 2021

第二十章 用户、角色和权限

# 第二十章 用户、角色和权限 InterSystems IRIS®具有系统级安全性,以及一组与sql相关的额外安全性特性。 在数据库级保护之外,InterSystems SQL安全性提供了额外级别的安全功能。 SQL和系统级安全性之间的一些关键区别是: - SQL保护比系统级保护更细粒度。可以为表、视图和存储过程定义特权。 - SQL权限既可以授予用户,也可以授予角色。 系统级权限只分配给角色。 - 持有SQL特权会隐式授予执行SQL操作所需的任何相关系统特权。 (相反,系统级特权并不意味着表级特权。) InterSystems SQL在InterSystems IRIS数据平台上对ODBC、JDBC、Dynamic SQL和SQL Shell接口进行权限检查。 嵌入式SQL语句不执行特权检查; 假定使用嵌入式SQL的应用程序在使用嵌入式SQL语句之前会检查特权。 # SQL权限和系统权限 要通过特定于SQL的机制操作表或其他SQL实体,用户必须具有适当的SQL权限。 系统级权限不足。 用户可以直接被授予SQL权限,也可以属于具有SQL权限的角色。 注意:角色是由SQL和系统级安全共享的:单个角色可以包括系统和SQ权限。 下面的例子,以Windows机器上的InterSystems IRIS为例: - 在用户名称空间中有一个名为`User.MyPerson`的持久化类。 这个类被投影到SQL中作为`SQLUser.MyPerson`表。 - 有一个名为`Test`的用户,他不属于任何角色(因此没有系统权限),并且拥有`SQLUser.MyPerson`表的所有权限(没有其他SQL权限)。 - 还有第二个用户,名为`test2`。此用户被分配给以下角色:`%DB_USER`(因此可以读取或写入用户数据库上的数据);`%SQL`(因此可以通过`%Service_BINDINGS`服务访问SQL);并且通过自定义角色具有使用控制台和`%Development`的权限。 如果测试用户尝试通过任何特定于SQL的机制(如使用ODBC的机制)在`SQLUser.MyPerson`表中读取或写入数据,则尝试将成功。这是因为InterSystems IRIS使测试用户成为`%SQL`角色(包括`%SERVICE_SQL:USE`权限)和`%DB_USER`角色的成员,因此该用户具有建立连接所需的权限;这在连接生成的审核事件(如`%SYSTEM/%Login/Login event`)中可见。(如果测试用户尝试使用终端对象机制,则这些尝试将失败,因为用户对这些机制没有足够的权限。) 如果`Test2`用户尝试通过任何特定于SQL的机制(如使用ODBC的机制)在`SQLUser.MyPerson`表中读取或写入数据,则该尝试将失败,因为该用户没有足够的权限访问该表。(如果`Test2`用户尝试使用对象机制查看终端中的相同数据,则尝试成功-因为该用户有足够的权限进行这种类型的连接。) # 用户 InterSystems SQL用户与为InterSystems安全性定义的用户相同。可以使用SQL命令或管理门户定义用户。 - 在SQL中,可以使用`CREATE USER`语句创建用户。这只会创建一个用户名和用户密码。新创建的用户没有角色。必须使用`GRANT`语句为用户分配权限和角色。可以使用`ALTER USER`和`DROP USER`语句修改现有用户定义。 - 在管理门户中选择System Administration(系统管理),选择Security(安全性),然后选择Users(用户)。单击页面顶部的Create New User(创建新用户)按钮。这会将带到编辑用户页,可以在其中指定用户名、用户口令和其他参数。创建用户后,其他选项卡即可用,可以在其中指定用户拥有哪些角色、用户拥有哪些常规SQL权限、用户拥有哪些表级权限、哪些视图可用以及可以执行哪些存储过程。 如果用户具有SQL表权限或一般SQL权限,则在用户的角色选项卡上授予或撤消的角色不会影响用户通过基于SQL的服务(如ODBC)对表的访问。这是因为,在基于SQL的服务中,基于表的权限优先于基于资源的权限。 ![image](/sites/default/files/inline/images/1_32.png) 可以使用`%Library.SQLCatalogPriv`类查询列出: - 所有用户`SQLUsers()` - 授予指定用户`SQLUserPrivs(“username”)`的所有权限 - 授予指定用户`SQLUserSysPrivs(“username”)`的所有系统权限 - 授予指定用户`SQLUserRole(“username”)`的所有角色 以下示例列出了授予当前用户的权限: ```java /// d ##class(PHA.TEST.SQL).Sqluser2() ClassMethod Sqluser2() { SET statemt=##class(%SQL.Statement).%New() SET cqStatus=statemt.%PrepareClassQuery("%Library.SQLCatalogPriv","SQLUserPrivs") IF cqStatus'=1 {WRITE "%PrepareClassQuery failed:" DO $System.Status.DisplayError(cqStatus) QUIT} SET rset=statemt.%Execute($USERNAME) WRITE "Privileges for ",$USERNAME DO rset.%Display() } ``` ## 架构形式的用户名 在某些情况下,用户名可以隐式用作SQL模式名称。如果用户名包含SQL标识符中禁止的字符,这可能会带来问题。例如,在多域配置中,用户名包含“@”字符。 根据分隔标识符配置参数的设置,InterSystems IRIS会以不同的方式处理此情况: - 如果启用了分隔标识符的使用,则不会进行特殊处理。 - 如果禁用分隔标识符的使用,则会从用户名中删除所有禁用字符,以形成架构名称。例如,用户名`“Documentation@intersystems.com”`将成为模式名称`“Documentationintersystemscom”`。 这不会影响`SQL CURRENT_USER`函数返回的值。它始终与`$USERNAME`相同。 # 角色 将SQL权限分配给用户或角色。角色使能够为多个用户设置相同的权限。角色由SQL和系统级安全性共享:单个角色可以同时包括系统权限和SQL权限。 管理门户、系统管理、安全性、角色页提供了InterSystems IRIS实例的角色定义列表。要查看或更改特定角色的详细信息,请选择该角色的名称链接。在出现的编辑角色页面上,有关于角色权限以及哪些用户或角色拥有该权限的信息。 常规选项卡列出角色对系统间安全资源的权限。如果角色仅拥有SQL权限,则一般信息选项卡的资源表会将该角色的权限列为“未定义”。 SQL权限选项卡列出了角色对InterSystems SQL资源的权限,其中命名空间的下拉列表允许查看每个命名空间的资源。因为权限是按名称空间列出的,所以在特定名称空间中没有权限的角色的列表显示为`“None”`。 注:应该使用角色定义权限,并将特定用户与这些角色相关联。这有两个原因: 1. 与检查单个用户条目相比,SQL引擎通过检查相对较小的角色数据库来确定权限级别的效率要高得多。 2. 与具有多个单独用户设置的系统相比,使用少量角色集管理系统要容易得多。 例如,可以定义具有特定访问权限的名为`“ACCOUNTING”`的角色。随着 `Accounting Department`的发展,可以定义新用户并将其与会计角色相关联。如果需要修改`Accounting`权限,只需修改一次,系统会自动覆盖`Accounting Department`的所有成员。 一个角色可以担任其他角色。例如,会计角色可以拥有`BILLINGCLERK`角色。被授予会计角色的用户将同时拥有会计角色和`BILLINGCLERK`角色的权限。 还可以使用以下SQL命令定义用户和角色:`CREATE USER`、`CREATE ROLE`、`ALTER USER`、`GRANT`、`DROP USER`和`DROP ROLE`。 可以使用`%Library.SQLCatalogPriv`类查询列出: - 所有角色`SQLRoles()` - 授予指定角色`SQLRolePrivileges(“Rolename”)`的所有权限 - 授予指定角色`SQLRoleUser(“Rolename”)`的所有角色或用户 - 授予指定用户`SQLUserRole(“username”)`的所有角色 # SQL权限 将SQL权限分配给用户或角色。角色使能够为多个用户设置相同的权限。 InterSystems SQL支持两种类型的权限:管理权限和对象权限。 - 管理权限是特定于命名空间的。 管理权限包括创建、更改和删除对象类型,例如创建表所需的`%CREATE_TABLE`权限。不仅需要`%ALTER_TABLE`特权来更改表,还需要`%ALTER_TABLE`特权来创建或删除索引、创建或删除触发器以及运行`TUNE TABLE`。 管理权限还包括`%NOCHECK`、`%NOINDEX`、`%NOLOCK`和`%NOTRIGGER`,它们确定用户在执行`INSERT`、`UPDATE`、`INSERT`或`UPDATE`或`DELETE`时是否可以应用相应的关键字限制。用户需要分配`%NOTRIGGER`管理权限才能执行`TRUNCATE TABLE`。 - 对象权限特定于表、视图或存储过程。它们指定对特定命名SQL对象的访问类型(在SQL意义上:表、视图、列或存储过程)。如果用户是SQL对象的所有者(创建者),则会自动向该用户授予该对象的所有权限。 表级对象权限提供对表或视图的所有列中的数据的访问(`%ALTER`、`DELETE`、`SELECT`、`INSERT`、`UPDATE`、`EXECUTE`、`REFERENCES`),包括当前存在的列和任何后续添加的列。 列级对象权限仅提供对表或视图的指定列中的数据的访问权。不需要为具有系统定义的值(如`RowID`和`Identity`)的列分配列级权限。 存储过程对象权限允许将过程的`EXECUTE`权限分配给指定的用户或角色。 ## 授予SQL权限 可以通过以下方式授予权限: - 使用管理门户。从系统管理中选择安全性,然后选择用户或角色。选择所需的用户或角色,然后选择相应的选项卡:管理权限的SQL权限、对象权限的SQL表、SQL视图或SQL过程。 - 在SQL中,使用`GRANT`命令向指定用户或角色(或用户或角色列表)授予特定管理权限或对象权限。可以使用`REVOKE`命令删除权限。 - 在ObjectScript中,使用`$SYSTEM.SQL.Security.GrantPrivileve()`方法将特定对象权限授予指定用户(或用户列表)。 ## 列出SQL权限 - 使用管理门户。从系统管理中选择安全性,然后选择用户或角色。选择所需的用户或角色,然后选择相应的选项卡:管理权限的SQL权限、对象权限的SQL表、SQL视图或SQL过程。 - 在SQL中,使用`%CHECKPRIV`命令确定当前用户是否具有特定的管理或对象权限。 - 在ObjectScript中,使用`$SYSTEM.SQL.Security.CheckPrivileve()`方法确定指定用户是否具有特定的对象权限。 ## 审核权限错误 当InterSystems IRIS进程调用用户没有特权的SQL语句时,操作将失败,并生成`SQLCODE-99`错误。启用审核事件`%SYSTEM/%SQL/PrivilegeFailure`时,将在`Audit`数据库中为遇到的每个`SQLCODE-99`错误放置一条记录。默认情况下,此审核数据库选项处于禁用状态。 怎么使用sql查询用户的权限,包括表权限,视图权限
文章
姚 鑫 · 四月 12, 2021

第一章 SQL性能优化简介

# 第一章 SQL性能优化简介 InterSystems SQL支持几个特性来优化InterSystems IRIS®数据平台的SQL性能。 # 表定义优化 SQL性能从根本上取决于良好的数据架构。 将数据划分为多个表并在这些表之间建立关系对于高效的SQL是必不可少的。 描述了以下优化表定义的操作。 这些操作要求定义表,但不要求用数据填充表: - 数据存储策略:可以选择使用`%Storage.Persistent`、`%Storage.SQL`或自定义存储来存储数据。 - 全局变量命名策略:可以使用`USEEXTENTSET`参数为数据和索引查找操作指定更短、更高效的散列全局名称。 - 索引:可以为一个表字段或一组字段定义索引。可以定义几种不同类型的索引:标准索引、位图索引、位图索引和位图范围索引。SQL优化使用定义的索引而不是数据值本身来访问查询、更新或删除操作的特定记录。 # 表数据优化 根据对表中典型数据的分析,可以执行以下操作来优化表访问: - Tune Table:检查典型的表数据并生成`ExtentSize`(行数)、选择性(具有特定值的行的百分比)和`BlockCount`元数据。查询优化器使用此信息来确定最有效的查询执行计划。 - 选择性和异常值选择性:确定某个字段具有特定值的行的百分比,以及某个值是否为异常值,该值明显比该字段的其他值更常见。 # 查询优化 **在几乎所有情况下,用嵌入式SQL编写的查询的执行速度都比用动态SQL编写的查询快。还要注意,由于存在缓存查询,对于嵌入式SQL和动态SQL,重新执行查询的速度都比初始执行快得多。** 可以执行以下操作来优化特定查询的执行。这些查询优化使用现有的表定义和表数据优化: - 运行时统计:用于衡量系统上查询执行的性能。 - 显示计划显示查询的执行计划。 - 缓存查询和文字替换:维护最近动态查询的缓存,允许重新执行查询,而不会重复准备查询的开销。 - SQL语句和冻结计划允许保留查询执行计划,从而允许在不降低现有查询性能的情况下更改表。 - 索引配置和使用:用于指定如何使用现有索引。 - 索引优化提示:`%ALLINDEX`、`%IGNOREINDEX` - 联接优化提示:`%FIRSTTABLE`、`%FULL`、`%INORDER`、`%STARTTABLE` - 子查询优化提示:`%NOFLATTEN`、`%NOMERGE`、`%NOREDUCE`、`%NOSVSO` - 并行查询执行:`%Parallel` - 联合优化: `UNION %PARALLEL`, `UNION/OR` 还可以通过使用数据分片来提高对大型数据库表的查询性能。 # 配置优化 默认情况下,内存和启动设置默认为自动配置,每个进程的最大内存默认为262144 kb。要优化在生产系统上运行的SQL,应该将默认值更改为手动配置,并增加每进程的最大内存设置。 # 分片 分片是跨多个系统对数据及其关联缓存进行分区。分片集群跨多个InterSystems IRIS实例(称为碎片数据服务器)水平(即按行)对大型数据库表进行分区,同时允许应用程序通过单个实例(称为碎片主数据服务器)透明地访问这些表。 必须将表定义为分片。分片表只能在分片环境中使用;非分片表可以在分片或非分片环境中使用。并不是所有的表都适合进行分片。分片环境中的最佳性能通常是通过组合使用分片表(通常非常大的表)和非分片表来实现的 # 快速命令 InterSystems SQL支持快速选择、快速插入和快速截断表。“快速”意味着这些SQL命令的标准调用是使用高效的内部代码执行的。这些快速操作“就是工作”;没有使用特殊语法,也没有提供优化选项。 通过ODBC或JDBC的`SELECT`查询支持快速选择。JDBC上的插入操作支持快速插入。对于不涉及参照完整性的截断表操作,支持快速截断表。 并不是所有的表都支持快速操作,也不是所有的命令语法都可以使用快速执行来执行。InterSystems SQL在可能的情况下执行快速执行;如果无法执行快速执行,InterSystems SQL将执行指定命令的标准执行。
公告
Claire Zheng · 三月 7, 2021

如何更好地成为社区贡献者/活跃用户?

亲爱的开发者, 最近我们收到很多类似“如何成为一个活跃(Active)、有贡献值的成员”的问题。 条件很简单! 1. 回答问题 我们有许多未得到回答的问题, 以及 还没有收到有效回答的问题. 非常欢迎您在这些问题上共享您的见解和回答,帮助其他社区成员成长! 2. 撰写文章,发布帖子 撰写您使用InterSystems技术的经验和心得:解决方案、开发心得、解决bug的小技巧、部署等等。 这里是一些 帖子示例 ,这些帖子都对我们的社区建设很有帮助。 除了中文社区外,我们还有英语社区、日语社区、葡语社区等等,我们也欢迎您将这些社区里的文章翻译成中文进行发布! 3. 在Open Exchange提交应用程序 通过Github、Gitlab或任何其他公共存储库,在Open Exchange上共享您的库、解决方案和工具。 如果您对社区有什么问题和建议,欢迎跟帖回复、畅所欲言!我们欢迎大家共同建设社区,使这个社区对中国使用InterSystems技术的开发者们越来越有用! 请新注册的同学们阅读这篇文章,多问问题发帖子/有效评论; 或者多回答问题,中英文都可以: https://cn.community.intersystems.com/?filter=questions; https://community.intersystems.com/?filter=questions
文章
Jingwei Wang · 六月 6, 2022

Object Script基础知识(六)

Object Script(六) 变量的类型 ObjectScript中的变量是没有类型的,也就是说,它们没有一个指定的数据类型,可以接受任何数据值。 ObjectScript支持以下几种类型的变量: 1. 本地变量 :只有创建它的进程可以访问的变量,当该进程终止时,改变量将自动删除。一个本地变量可以从任何命名空间访问。 示例: SET str = "A string" 2. 进程私有的全局变量 : 只有创建它的进程可以访问的变量,并且在进程结束时不再存在。一个进程专用的全局变量可以从任何命名空间访问,因为它与命名空间无关。进程私有的全局变量对于临时存储大数据值特别有用。在许多情况下,它们可以替代Mgr/Temp目录的使用,在进程终止时提供自动清理。 示例: SET ^||flintstones(1)="Fred" SET ^||flintstones(2)="Wilma" 3. 全局变量 : 一个存储在InterSystems IRIS数据库中的持久性变量。一个全局变量可以从任何进程中访问,并且在创建它的进程终止后仍然存在。全局变量是针对个别命名空间的。 示例: SET ^myglobal = "This is a global stored in the current namespace" 4. i%property实例变量 当你创建任何类的实例时,系统会为该类的每个非计算属性创建一个实例变量。实例变量持有该属性的值。例如,如果一个类有Name和DOB属性,那么实例变量i%Name和i%DOB就可以在该类的任何实例方法中使用。实例变量有进程私有的。请注意,这些变量不在本地变量符号表中,不受Kill命令的影响。InterSystems IRIS也使用额外的实例变量,名称为r%PropName和m%PropName,但这些变量不支持直接使用。 5. 特殊变量(也称为系统变量) : 一组特殊的内置变量之一,用于某些应用程序使用的系统信息。所有的特殊变量都是由InterSystems IRIS提供的,并以"$"字符前缀命名。用户不能定义额外的特殊变量。特殊变量集被映射为可从所有命名空间访问。 示例: $HOROLOG
文章
姚 鑫 · 二月 16

第二十六章 S 开头的术语

# 第二十六章 S 开头的术语 ### 共享锁 (shared lock) **对象(Objects)** 共享锁在对象从数据库加载期间保持共享锁,并在保存期间保持独占锁(如果跨多个节点或正在更新)。对于第一次在单个节点上保存的对象,不会获取锁。 ### 共享保留锁 (shared retained lock) **对象(Objects)** 共享保留锁从对象从数据库加载到关闭期间保持共享锁,并在保存期间保持独占锁(如果跨多个节点或正在更新)。对于第一次在单个节点上保存的对象,不会获取锁。 ### SOAP **通用** 用于实现 Web 服务的协议规范。它使用 `XML` 作为消息格式,通常依赖其他应用层协议,例如远程过程调用(`RPC`)和 `HTTP`,用于消息协商和传输。`` 曾是“简单对象访问协议”(`Simple Object Access Protocol`)的缩写,但现在不再是缩写——它只是该协议的名称。 ### 特殊变量 (special variable) **系统** `IRIS` 维护的众多变量之一。应用程序开发人员可以检查特殊变量以获取有关系统的信息。 ### SQL **通用** 结构化查询语言(`Structured Query Language`)。`SQL` 是 `ANSI` 标准的第四代编程语言,专为访问和维护关系数据库而设计。 ### SQLCODE **InterSystems SQL** 一个本地变量,保存已执行 `SQL` 语句的状态。如果执行期间发生错误,`SQLCODE` 包含错误号。 ### SQL 计算字段 (SQL computed field) **对象(Objects)** SQL 计算字段按需计算,基于存储在其他字段中的值。 ### SQL 映射 (SQL mapping) **对象(Objects)** SQL 映射用于将现有数据结构映射到类和表。 ### SQL 查询 (SQL query) **InterSystems SQL** `SQL` 查询使用 `SQL` 来定位和检索存储在数据库中的信息。 ### SQL 保留字 (SQL reserved words) **InterSystems SQL** `SQL`保留字在 `SQL` 中具有特殊含义,不能用作表、字段、查询、视图、存储过程或索引名称。如果定义了备用表和字段名称,`SQL` 保留字可以用作类和属性名称。 ### 状态码 (status code) **对象(Objects)** 一些方法返回的状态码,指示方法是否成功执行。请参见 `%Status`。 ### 存储定义 (storage definition) **对象(Objects)** 存储定义由存储类和任何定义的 `SQL` 映射组成。这些元素共同决定数据的存储方式。
文章
Johnny Wang · 十一月 21, 2021

全球案例--灵活、快速且领先:关于加州大学戴维斯分校健康中心如何利用InterSystems 技术构建医疗数字领域的门户

当我和加州大学戴维斯分校健康中心的同事着手简化提供者对基因组数据报告的访问时,我们希望这些信息能帮助临床医生提供更好、更个性化的护理。 我们的基因组数据没有操作界面,既不可搜索,也不与患者图表相关联。 如果我们可以在 FHIR(快速医疗互操作性资源)连接器上利用SMART原则在平台之间实现单点登录,我们的护理团队就可以更早地获得数据,患者将能够更好地得到照顾,并在与癌症的斗争中取得积极成果。 而这也是正在实现的事情。 我们支持基因组数据报告的工作为临床医生带来了 50 个离散数据点,这意味着医生用于搜索报告的时间更少,也拥有了更多具有重要洞察力的离散数据,简化了对临床试验信息的访问,最终患者也得到了及时的护理。 但我们并没有停下脚步,这不过是迈向更广阔数字领域的第一步。在 InterSystems 的帮助下,我们拥有了规模越来越大、类型更多样的数据集。 回到本文的标题——什么是医疗数字领域的门户?它是某人(通常是患者)与您的医疗单位的每次虚拟来往的总和。根据研究公司 IDC 的数据,到 2023 年,65% 的患者都将会通过这样的门户和对应的医疗机构进行来往,但剩下的其他人呢?所以在加州大学戴维斯分校健康中心,我们决心建立一个欢迎所有人的数字门户——不仅是基因组数据供应商,还有患者、付款人和合作伙伴。 通过变得更加灵活和高效,我们不断推陈出新,提高整个健康中心的效率,并优化对患者的护理。 以下是我总结的为什么数字门户可以帮助每个医疗机构的观点: 1. 是时候加强互操作性工作了 在加州大学戴维斯分校健康中心,我们决定推动我们的数字门户战略,也因为我们不想被 FHIR 潮流所抛弃。随着苹果等公司的健康应用工具使用率的不断上升,基于SMART原则和FHIR构建的应用程序一直在不断提醒供应商们尽快去拿到多年来一直对第三方关闭的数据,而我们的数字门户成为了我们巧妙地驾驭 FHIR 潮流所需的工具和技术。 此外,很明显,《21世纪药物法案草案》将要求医疗系统支持更进一步的互操作性,以便患者访问其数据。 没有多少医疗机构为此制定了数字门户战略。 尽管我们花了数年时间从本土遗留系统和内部应用程序过渡到同类最佳技术,但互操作性描述了数据在内部移动,而不是外部移动。 我们本可以选择将付款人和合作伙伴直接连接到我们的 EHR,但这无法访问位于其他地方的数据。 对于我们的合作伙伴来说,这也可能意味着更高的成本和更大的难度,同时每个应用程序和合作伙伴连接都受制于各自的供应商。 现在,我们加州大学戴维斯分校健康中心使用首选的解决方案堆栈开发了自己的架构——InterSystems IRIS for Health™ 和 HealthShare® 处理了平台外存储的大量数据、连接的非 FHIR 应用程序,并使我们能够创建确保所有合作伙伴都能访问的规则。 在一年多一点的时间里,我们为 InterSystems API 管理器部署了一个开发端点,我们正在与几个合作伙伴合作开展试点项目,以将它们连接到我们的 API 库。 世界正在快速发展时,医疗行业也必须如此。 2. 你真的想用大量不同的技术去拼凑你的数字门户吗? 加州大学戴维斯分校健康中心的数字门户之所以能脱颖而出,是因为我们决心要打造围绕一个互操作性的先进中心。 大多数医疗系统采用联合模型,在一个桶中解决临床数据聚合以及与 FHIR、接口和研究相关的举措。 在加州大学戴维斯分校健康中心,我们有一个专门的团队和一个支持模型来推动整个组织内的数据交换。这意味着强大的灵活性。 例如,新冠病毒的来临颠覆了一切,许多医院不得不与三个甚至更多的供应商争吵,以适应对虚拟服务不断增长的需求。 而我们只用一个小组就快速完成了工作。 随着美国互操作性核心数据 (USCDI) 标准的实施,医疗系统必须能够访问电子健康信息,这些信息存在于医疗系统、数字生态系统的每个角落和缝隙中。 共享存在于 EHR 中的临床数据是不够的。宽阔的数字门户——通过一个入口点就可以进入——是我们最好的选择。 3. 走在时代的前沿 我知道并非所有医疗系统都拥有相同的资源,但任何人都可以适应的技术才是真正的创新。 医疗机构需要根据 USCDI 标准为患者数据的访问去开发解决方案。 如果您具备了这样的开发能力,为什么不多做一步——授权患者、付款人和合作伙伴都能够使用这种资源呢? 如果您这样做了,您会发现您已准备好应对围绕基因组学、远程患者监测以及未来的任何其他事物所带来的创新。 关于作者:Michael Marchant Michael Marchant 在过去 25 年多的时间里一直在和复杂的技术打交道,他一直致力于整合数据,以引领医疗机构的发展。Michael 一直与应用程序供应商、提供商组织以及政府密切合作,领导团队并提供所需的解决方案、技术、工作流程,致力于内部以及当地乃至全国的互操作性推动。 Michael 目前担任加州大学戴维斯分校健康中心的健康信息交换和系统集成总监,他和他的团队为他的组织和社区解决了大量复杂的技术难题和互操作性层面的挑战。 Michael 热衷于推动将患者和患者的健康信息联系起来的技术,并帮助患者能够控制何人、何时以及何地可以访问这些信息。 点击查看原文 2021年12月8日——全球领导力峰会,立刻注册! InterSystems 可以帮助您实现互操作性和数据集成目标。立刻联系我们!
问题
li wang · 四月 23, 2022

浏览器地址中输入HealtConnect发布的webService地址报CSP应用程序错误

各位老师,你们好 我在浏览器地址中输入HealtConnect发布的webService地址报 CSP应用程序错误,并记录了此错误,不过该地址还是能正常访问。 我想知道怎么解决这种报错问题,谢谢! 以下图片为HealthConnect的版本,以及具体出现的错误 建议联系我们WRC团队support@intersystems.com 或者电话:4006019890或者对应的客户经理,谢谢! 应该是没开启SOAP测试页能力。搜一下三级等保文章,里面有介绍 https://cn.community.intersystems.com/smartsearch?search=InterSystems+数据平台与三级等保+-+第一篇
文章
Michael Lei · 六月 26, 2022

以程序化的方式检查审计设置

下面的代码允许用户查看其实例的审计设置。通过运行类方法 "test "来运行该代码。: class objectscript.checkAudit Extends %RegisteredObject { classmethod test() { w "Checking for Auditing...",! Set SYSOBJ = ##class(Security.System).%OpenId("SYSTEM") If +SYSOBJ = 0 Set SYSOBJ = ##class(Security.System).%New() i SYSOBJ.AuditEnabled { w "Security Auditing is enabled for the following services",! s rs=##class(%ResultSet).%New("Security.Events:ListAllSystem") s sc=rs.Execute() If $$$ISERR(sc) Do DisplayError^%apiOBJ(sc) Quit while rs.%Next() { d:rs.Data("Enabled")="Yes" rs.%Print() } d rs.Close() s rs=##class(%ResultSet).%New("Security.Events:ListAllUser") s sc=rs.Execute() If $$$ISERR(sc) Do DisplayError^%apiOBJ(sc) Quit while rs.%Next() { d:rs.Data("Enabled")="Yes" rs.%Print() } d rs.Close() } } } 这是 GitHub的链接: https://github.com/intersystems-community/code-snippets/blob/master/src/cls/objectscript/checkAudit.cls
文章
Hao Ma · 一月 30, 2021

精华文章--WebGateway系列(1): Web Gateway介绍

本文介绍InterSystems Web Gateway的安装和配置。 在2018以前的ISC产品中, InterSystems Web Gateway被称为CSP Gateway。, CSP是Cache'的页面技术。InterSystems的产品页面,Web服务等大多是CSP写成的。IRIS发布后CSP Gateway改名成Web Gateway, 但内部的配置文件,说明等等还到处可见CSP Gateway的叫法。在本文里不同的地方有这两个说法别奇怪,他们是一个东西。 IRIS通过它和外部Web服务器连接。 本文的内容适用任何ISC产品的部署,包括页面的选项Cache'. IRIS,HealthConnect, Ensemble等等。它的作用和表现是一样的。 无论您使用的是Cache',IRIS , HealthConnect还是HealthShare, 只有在生产环境中使用HTTP请求,基本上都需要使用Web Gateway。 如果需要更详细的内容,请参考在线文档:[InterSystems Web Gateway](https://docs.intersystems.com/healthconnectlatest/csp/docbook/DocBook.UI.Page.cls?KEY=PAGE_web_gateway) ### 什么是Web Gateway CSP是Cache' Server Page的缩写,如同JSP(Java Server Page)是Java的前端技术, CSP是InterSystems的前端技术。要在IRIS或者HealthConnect上提供一个HTTP服务,唯一安全可靠的技术是CSP. 创建HTTP,REST服务直接创建CSP页面, 创建SOAP服务使用%SOAP.WebService或者EnsLib.SOAP.Service, 它们都是%CSP.Page的子类,因此在IRIS的在线文档中有CSP Server的称法,指的就是IRIS中负责CSP处理的那部分功能。 CSP Server并不监听TCP端口得到HTTP消息,它只能通过CSP Gateway从Web服务器接收请求。用户的请求要先发给IIS/Apach/Nginx等Web服务器,转发给IRIS, 而Web Gateway就是Web服务器发请求给IRIS所使用的网关。 或者说, 它是InterSystems提供的给第三方Web服务器的一个组件,或者称为模块。在Windows系统中是若干DLL库文件,在LINUX环境是SO动态链接库。安装CSP Gateway就是诸如”CSPa24.so"等文件拷贝到Web服务器的目录,将这些模块配置到Web服务器,并将以.csp,.cls,.zen结尾的HTTP请求发送给IRIS。如果Web服务器和IRIS独立安装在不同的硬件服务器上(更安全的方式),发送的是TCP消息,到IRIS的superserver端口,默认是51773(Cache'是1972)。 CSP Gateway支持3种Web服务器:IIS, Apache Web Server, Nginx。 后面的链接提供了完整的在各种操作系统中ISC产品支持的Web Server的版本: [IRIS支持的第三方Web Server列表](https://docs.intersystems.com/healthconnectlatest/csp/docbook/platforms/ISP_technologies.html#ISP_webservers) 听上去是不是挺简单?那用户还有什么可糊涂的? ### Private Web Server(PWS)带来的混乱 混乱来自IRIS的安装过程会安装一个私有的Apache Web服务器,被称作PWS。它的作用有两个:支持访问维护页面;给一个测试环境提供测试Web服务的能力。在线文档是这么描述PWS的: >> The PWS is not supported for any other purpose. For deployments of http-based applications, including REST, CSP, Zen, and SOAP over http or https, you should not use the private web server for any application other than the Management Portal; instead, you must install and deploy one of the supported web servers. For information, see the section “Supported Web Servers” in the online InterSystems Supported Platforms document for this release.(**如果要部署http应用, 包括在http或者https上层的REST, CSP, Zen, SOAP,你绝不能让除Management Portal以外的任何应用使用PWS. 你必须安装一个IRIS兼容的Web服务器。了解这部分内容, 请查看InterSystems在线文档的"Supported Web Servers"部分**) 然后很多用户没有意识到这个提醒。当安装IRIS时被问到”你想要安装CSP网关并未CSP网关配置外部Web服务器(IIS和Apache)吗?"时,他们选择了“不要安装CSP网关",然后浏览器接入维护界面,开发了若干Web服务,一直没有意识使用PWS访问IRIS上的Web服务在生产环境是不可接受的。PWS是一个非常轻量级的Apache Web服务器。它的程序包在IRIS安装目录下的httpd子目录里。IRIS启动后, 它开始工作,监听IRIS上配置的Web端口,默认是57772,或者52773.它的工作机制决定了它无法承受大的负载,因此不能用于生产环境的http应用。 它和CSP/IRIS Server的连接用的是与上面讲的CSP Gateway完全相同的方式,也就是说,这里有一个PWS专用的Gateway, 我们可以称它为Private CSP Gateway。为了写的更清楚,总结了下面几点: ***CSP Gateway*** - 安装IRIS实例时用户可以选择是否安装CSP Gateway. 如果这时没选择安装,后面可以用单独的安装包安装。 - 安装的程序可以放在任何位置。比如在Linux默认放在"/opt/webgateway"目录,配置文件在Web Gateway的配置文件目录。 - 访问CSP Gateway的管理页面是 http://WebServer:80/csp/bin/Systems/Module.cxw 。 (这里的WebServer是Web服务器的地址,➕它的端口是默认的80) ***PWS*** - 安装时自动安装 - 程序和配置都在IRIS的安装目录,比如"C:/InterSystems/HealthConnect/CSP/bin/" - 访问管理页面的地址是 http://IRIS:57772/csp/bin/Systems/Module.cxw,这里的IRIS是IRIS服务器的地址,如果是本机登录,也就是localhost. 注意一点:从PWS访问IRIS管理页面, 比如 http://localhost/csp/sys/UtilHome.csp, 选择其中的 “系统管理 > 配置 > Web网关管理"进入的是PWS的配置。如果是从 http://WebServer/csp/sys/UtilHome.csp进入的IRIS管理页面, 那么同样的操作进入的是CSP Gateway的管理页面。 这很容易从页面显示的Web Server的类型和版本发现区别。 ### 其他关于部署CSP Gateway的疑问 - 一个Web服务器可以连接多个CSP Gateway吗? 如果你真正理解了CSP Gateway, 你就明白它是Web服务器工作的一部分,比如在IIS里面它就是配置的一个虚拟路径。技术上你可以多配一个,但完全没有必要。 如果要把HTTP从一个Web服务器发到多个IRIS, 可以在一个Web Gateway里配置多个"Server Access"连接。 - 一个CSP Gateway是怎么连接多个IRIS Server的? CSP Gateway可以配置多个"Server Access”, 只是要区分出收到的请求应该发给那个IRIS Server.如果分发给不同的IRIS的URL是不同的,比如CSP Gateway可以路由"/csp/demo1"到第一个IRIS, "/csp/demo2"到第2个IRIS。 - Web Server要和IRIS部署在一台服务器吗? 生产环境中, 部署单独的Web Server通常是好选择。为了安全起见,很多用户会部署Web Server的高可用。 如果Web Server和Caché/IRIS分别装在两台服务器,IRIS安装时选择“不要安装CSP网关”,在Web Server的服务器上安装单独的Web Gateway软件包,测试和Caché/IRIS的连接。 如果是Web Server和Caché/IRIS装在同一台服务器, 那么应该先安装Web Server, 然后使用Caché/IRIS安装包安装Caché, 选择 “安装CSP网关”, 这样CSP网关会被安装在Web Server的目录下, 相关的模块和Web Server配置也会自动完成。 如果顺序反过来, 那么需要手工配置Web Server, 增加的不必要的复杂步骤。 - 安装外部Web Server能使用私有Web Gateway吗? 对Web服务器有了解的用户更会有这样的疑问。既然Web Gateway只是给Web Gateway工作的程序组件,那么是否从外部服务器就可以直接使用私有的Web Gateway了,何必再多安装一个。 是的,技术上这样是可行的。前提是,1. 外部Web服务器和IRIS在一台硬件服务器上。2. 客户要对外部服务器的配置非常熟悉,可以手工配置外部Web服务器对私有Web Gateway的访问, 包括路径或者虚假路径,文件夹的访问权限,用户或者用户组的权限等等。总的说, 这样既麻烦,又不便于后期的管理,因此我推荐还是重新装一个Web Gateway。只是要分清它和私有的连接PWS的Web Gateway的区别,而永远不要让他们混在一起。 安装CSP Gateway的具体步骤请参考下面的文章: WebGateway系列(2): 配置Apache连接IRIS WebGateway系列(3): 配置IIS连接IRIS
文章
姚 鑫 · 五月 18, 2021

第四章 使用Setup和tear Down方法执行测试

# 第四章 使用Setup和tear Down方法执行测试 # 示例:使用Setup和tear Down方法执行测试 以通常的方式执行新的单元测试。 1. 在一直在使用的命名空间中打开终端。 2. 将`^UnitTestRoot`的值设置为包含测试类的目录的父级: ```java USER> Set ^UnitTestRoot="c:\unittests" ``` 3. 使用`%UnitTest.Manager`执行测试: ```jav USER> Do ##class(%UnitTest.Manager).RunTest("mytests") ``` 4. IRIS加载测试类、编译类、执行测试并向终端发送报告。 ```java =============================================================================== Directory: C:\unittests\mytests\cls\MyPackage\ =============================================================================== mytests\cls\MyPackage begins ... Load of directory started on 01/09/2018 14:36:57 '*.xml;*.XML;*.cls;*.mac;*.int;*.inc;*.CLS;*.MAC;*.INT;*.INC' Loading file C:\unittests\mytests\cls\MyPackage\Tests.xml as xml Imported class: MyPackage.Tests Compilation started on 01/09/2018 15:44:01 with qualifiers '' Compiling class MyPackage.Tests Compiling routine MyPackage.Tests.1 Compilation finished successfully in 0.033s. Load finished successfully. MyPackage.Tests begins ... TestAdd() begins ... AssertEquals:Test Add(2,2)=4 (passed) AssertNotEquals:Test Add(2,2)'=5 (passed) LogMessage:Duration of execution: .000073 sec. TestAdd passed TestEditContact() begins ... AssertStatusNotOK:ContactType = Friend (passed) AssertStatusOK:ContactType = Personal (passed) LogMessage:Duration of execution: .001227 sec. TestEditContact passed MyPackage.Tests passed mytests\cls\MyPackage passed Use the following URL to view the result: http://10.0.75.1:52773/csp/sys/%25UnitTest.Portal.Indices.cls?Index=10&$NAMESPACE=USER All PASSED ``` # 执行测试的选项:测试规格和限定符 通常,可以使用以下形式的命令执行`RunTest`: ```java Do ##class(%UnitTest.Manager).RunTest("testspec","qualifiers") ``` `Testspec`参数确定要运行哪些测试以及在哪里可以找到它们。`Testspec`的一般形式是`testSuite:testcase:testmethod`,其中 - `testsuite`(必填)。包含导出的测试类的文件目录。该目录必须是名为`^UnitTestRoot`的目录的子目录。默认情况下,测试管理器执行此目录及其子目录中包含的所有文件中的所有测试。 - `testcase`测试用例(可选)。选择包含要执行的测试方法的单个类。格式为`PackageName.ClassName`。如果存在,则测试管理器仅执行命名类中的测试。 - `testmethod`(可选)。挑选由测试用例指示的测试类的一个方法来执行。 限定符参数指定用于运行测试的各种选项。正如我们已经看到的,当想要从`.cls`文件加载测试时,可以使用`“/loadudl”`限定符。还可以使用限定符来控制测试类在执行后是否从服务器中删除,是否应该从这些外部文件加载测试,或者系统是否应该在测试失败后进入调试模式,等等。限定符参数是一个可选的命令行参数字符串,用于打开或关闭某些测试管理器行为。例如,`“/NoLoad/DEBUG”`告诉管理器不要从目录加载任何测试,也就是说,使用当前在InterSystems IRIS中的测试,并在调试模式下运行测试。这些限定符就是所谓的可否定布尔值。例如,这意味着`“/NoLoad”`等同于`“/Load=0”`。 限定符 | 含义 ---|--- `/load` (default) |从目录加载测试。使用`/NoLoad`不加载测试,并执行InterSystems IRIS中已包含的测试。 `/run` (default) |运行测试。使用`/norun`加载但不运行任何测试。 `/delete` (default) |执行后从InterSystems IRIS中删除测试类。使用`/nodelete`保存类。 `/recursive` (default)| 在指定目录的子目录中查找测试。使用`/norecsive`不执行子目录中包含的测试。 `/debug` (default is /nodebug)| 使用/DEBUG,第一次测试失败后不会执行任何测试。从终端执行时,终端将在第一次故障后进入调试模式。 `/autoload` |使用`/autoload=dir`从`^UnitTestRoot`目录的子目录`“dir”`加载测试。 `/loadudl`|从`.cls`而不是`XML`文件加载测试。 # RunTest 示例 以下是使用`RunTest`执行单元测试的一些示例。 要使用`RunTest`,必须首先为`^UnitTestRoot`分配一个有效的目录名: ```java USER>Set ^UnitTestRoot = "C:\UnitTests" ``` 例1: ```java USER>Do ##class(%UnitTest.Manager).RunTest() ``` 在`^UnitTestRoot`目录的所有子目录中搜索包含测试类的XML文件。加载它找到的任何测试类并执行测试。 执行后从InterSystems IRIS中删除所有加载的测试类。 例2: ```java USER>Do ##class(%UnitTest.Manager).RunTest("mytests") ``` - 加载并执行`^UnitTestRoot`的`mytests`子目录(及其子目录)中的测试。 - 在测试类执行后从InterSystems IRIS中删除它们。 例3: ```java USER>Do ##class(%UnitTest.Manager).RunTest("mytests:MyPackage.Tests") ``` - 从`^UnitTestRoot`目录的`mytest`子目录(及其子目录)加载测试。仅执行`MyPackage.Tests`中的测试。 - 执行测试后从InterSystems IRIS中删除所有测试类。 例4: ```java USER>Do ##class(%UnitTest.Manager).RunTest("mytests:MyPackage.Tests", "/noload/nodelete") ``` - 不将测试加载到IRIS。 - 在`MyPackage.Tests`中执行测试。请注意,`mytest`必须仍然包含带有`MyPackage.Tests`类的XML文件。 - 不从IRIS中删除`MyPackage.Tests`。 # DebugRunTestCase `%UnitTest.Manager`类还包含`DebugRunTestCase`方法。若要使用此方法,仍必须先将`^UnitTestRoot`分配给有效目录: ```java USER>Set ^UnitTestRoot="C:\UnitTests" ``` 例如: ```java USER>Do ##class(%UnitTest.Manager).DebugRunTestCase("mytests","MyPackage.Tests","","") ``` - 该方法不从任何目录加载任何类,也不从InterSystems IRIS删除任何类。 - 该方法执行`MyPackage.Tests`中包含的测试。 - 可选的第三个参数用于限定符。 - 可选的第四个参数用于指定测试类中要执行的单个测试方法。 - 如果测试失败,该方法将继续执行其余的测试方法,但将在测试完成时中断。因此,如果从终端执行,则终端将进入调试模式。 **注意:使用`DebugRunTestCase`时,`mytest`目录实际上不需要包含`MyPackage.Tests`。相比之下,`RunTest`总是要求要执行的测试包含在`^UnitTestRoot`的子目录中,即使在使用`NoLoad”`时也是如此。** # 练习 练习1:`MyPackage.TestMe`包含一个名为`CreateContact`的方法。此方法创建并返回`Contact`实例。它接受`Name`和`ContactType`值作为参数。创建一个测试以下内容的单元测试: - 从`CreateContact`返回的`Contact`实例具有正确的`Name`值。 - 从`CreateContact`返回的`Contact`实例具有正确的`ContactType`值。 - `CreateContact`返回的`Contact`实例保存正确,即`%Save`返回`OK`状态。 练习2:`MyPackage.Contact`包含名为`ByContactType`的类查询。它返回具有`ContactType`指定值的所有`Contact`实例的`ID`值。将单元测试添加到`MyPackages.Tests`,用于测试以下各项: - 该查询返回指定`ContactType`的正确`ID`值数量。为此,必须正确初始化数据库。 - 查询返回的每个`ID`值对应于一个具有指定`ContactType`值的联系人。 请注意,添加此测试不应破坏在完成教程正文中的示例时添加到`MyPackage.Tests`中的测试。因此,必须以正确的方式初始化和恢复数据库。 > 把答案发到评论上!!! 或加群QQ 410039091 分享 # [源码](https://download.csdn.net/download/yaoxin521123/18703118)