自定义过程无法收集 class 参数的属性;为什么?
Custom procedure fails to collect properties of a class parameter; why?
好的,首先,我是Caché的菜鸟,所以代码可能会很差,但是...
我需要能够查询 Java 中的 Caché 数据库,以便在 Studio 外重建源文件。
我可以毫不费力地转储方法等,但是有一件事让我无法理解...出于某种原因,我无法从 class [=15= 转储参数 EXTENTQUERYSPEC
的属性](命名空间:SAMPLES
)。
class 在 Studio 中是这样的:
Class Sample.Person Extends (%Persistent, %Populate, %XML.Adaptor)
{
Parameter EXTENTQUERYSPEC = "Name,SSN,Home.City,Home.State";
// etc etc
}
程序代码如下:
CREATE PROCEDURE CacheQc.getParamDesc(
IN className VARCHAR(50),
IN methodName VARCHAR(50),
OUT description VARCHAR(8192),
OUT type VARCHAR(50),
OUT defaultValue VARCHAR(1024)
) RETURNS NUMBER LANGUAGE COS {
set ref = className _ "||" _ methodName
set row = ##class(%Dictionary.ParameterDefinition).%OpenId(ref)
if (row = "") {
quit 1
}
set description = row.Description
set type = row.Type
set defaultValue = row.Default
quit 0
}
和 Java 代码:
private void getParamDetail(final String className, final String paramName)
throws SQLException
{
final String call
= "{ ? = call CacheQc.getParamDesc(?, ?, ?, ?, ?) }";
try (
final CallableStatement statement = connection.prepareCall(call);
) {
statement.registerOutParameter(1, Types.INTEGER);
statement.setString(2, className);
statement.setString(3, paramName);
statement.registerOutParameter(4, Types.VARCHAR);
statement.registerOutParameter(5, Types.VARCHAR);
statement.registerOutParameter(6, Types.VARCHAR);
statement.executeUpdate();
final int ret = statement.getInt(1);
// HERE
if (ret != 0)
throw new SQLException("failed to read parameter");
System.out.println(" description: " + statement.getString(4));
System.out.println(" type : " + statement.getString(5));
System.out.println(" default : " + statement.getString(6));
}
}
现在,对于前面提到的 class/parameter 对,标记为 // HERE
的条件总是被触发,因此会抛出异常...如果我注释整行,那么我会看到所有三个 OUT
参数为空,甚至defaultValue
!
我本来希望后者具有 Studio 中提到的价值...
那么,为什么会这样呢?我的程序有问题吗?
首先,您应该检查您发送的 className 和 paramName 值、全名以及大小写是否正确。为什么选择存储程序,什么时候可以使用select?您可以在系统管理门户中调用您的过程以查看可能的错误。
select description, type,_Default "Default" from %Dictionary.ParameterDefinition where id='Sample.Person||EXTENTQUERYSPEC'
你的例子很适合我。
package javaapplication3;
import com.intersys.jdbc.CacheDataSource;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Types;
public class JavaApplication3 {
/**
* @param args the command line arguments
*/
public static void main(String[] args) throws SQLException {
CacheDataSource ds = new CacheDataSource();
ds.setURL("jdbc:Cache://127.0.0.1:56775/Samples");
ds.setUser("_system");
ds.setPassword("SYS");
Connection dbconnection = ds.getConnection();
String call = "{ ? = call CacheQc.getParamDesc(?, ?, ?, ?, ?)}";
CallableStatement statement = dbconnection.prepareCall(call);
statement.registerOutParameter(1, Types.INTEGER);
statement.setString(2, "Sample.Person");
statement.setString(3, "EXTENTQUERYSPEC");
statement.registerOutParameter(4, Types.VARCHAR);
statement.registerOutParameter(5, Types.VARCHAR);
statement.registerOutParameter(6, Types.VARCHAR);
statement.executeUpdate();
int ret = statement.getInt(1);
System.out.println("ret = " + ret);
System.out.println(" description: " + statement.getString(4));
System.out.println(" type : " + statement.getString(5));
System.out.println(" default : " + statement.getString(6));
}
}
最终结果
ret = 0
description: null
type : null
default : Name,SSN,Home.City,Home.State
更新:
尝试更改您的程序代码并像此处添加一些调试
Class CacheQc.procgetParamDesc Extends %Library.RegisteredObject [ ClassType = "", DdlAllowed, Owner = {UnknownUser}, Not ProcedureBlock ]
{
ClassMethod getParamDesc(className As %Library.String(MAXLEN=50), methodName As %Library.String(MAXLEN=50), Output description As %Library.String(MAXLEN=8192), Output type As %Library.String(MAXLEN=50), Output defaultValue As %Library.String(MAXLEN=1024)) As %Library.Numeric(SCALE=0) [ SqlName = getParamDesc, SqlProc ]
{
set ref = className _ "||" _ methodName
set row = ##class(%Dictionary.ParameterDefinition).%OpenId(ref)
set ^debug($i(^debug))=$lb(ref,row,$system.Status.GetErrorText($g(%objlasterror)))
if (row = "") {
quit 1
}
set description = row.Description
set type = row.Type
set defaultValue = row.Default
quit 0
}
}
在 java 的一些测试之后,检查 zw ^debug
SAMPLES>zw ^debug
^debug=4
^debug(3)=$lb("Sample.Person||EXTENTQUERYSPEC","31@%Dictionary.ParameterDefinition","ERROR #00: (no error description)")
嗯,呃,我发现问题了……说个笨蛋吧
碰巧我在 Studio 中打开了 Samples.Person class 并对其制作了 "modification";并在之后将其删除。因此文件是 "as new"...
但是程序好像不符合这个说法
我关闭了该文件所在的 Studio,选择不修改 "changes",再次运行程序,它成功了...
奇怪的是,SQL 查询甚至对我的 "fake modification" 也有效。我想这是一些缓存问题...
好的,首先,我是Caché的菜鸟,所以代码可能会很差,但是...
我需要能够查询 Java 中的 Caché 数据库,以便在 Studio 外重建源文件。
我可以毫不费力地转储方法等,但是有一件事让我无法理解...出于某种原因,我无法从 class [=15= 转储参数 EXTENTQUERYSPEC
的属性](命名空间:SAMPLES
)。
class 在 Studio 中是这样的:
Class Sample.Person Extends (%Persistent, %Populate, %XML.Adaptor)
{
Parameter EXTENTQUERYSPEC = "Name,SSN,Home.City,Home.State";
// etc etc
}
程序代码如下:
CREATE PROCEDURE CacheQc.getParamDesc(
IN className VARCHAR(50),
IN methodName VARCHAR(50),
OUT description VARCHAR(8192),
OUT type VARCHAR(50),
OUT defaultValue VARCHAR(1024)
) RETURNS NUMBER LANGUAGE COS {
set ref = className _ "||" _ methodName
set row = ##class(%Dictionary.ParameterDefinition).%OpenId(ref)
if (row = "") {
quit 1
}
set description = row.Description
set type = row.Type
set defaultValue = row.Default
quit 0
}
和 Java 代码:
private void getParamDetail(final String className, final String paramName)
throws SQLException
{
final String call
= "{ ? = call CacheQc.getParamDesc(?, ?, ?, ?, ?) }";
try (
final CallableStatement statement = connection.prepareCall(call);
) {
statement.registerOutParameter(1, Types.INTEGER);
statement.setString(2, className);
statement.setString(3, paramName);
statement.registerOutParameter(4, Types.VARCHAR);
statement.registerOutParameter(5, Types.VARCHAR);
statement.registerOutParameter(6, Types.VARCHAR);
statement.executeUpdate();
final int ret = statement.getInt(1);
// HERE
if (ret != 0)
throw new SQLException("failed to read parameter");
System.out.println(" description: " + statement.getString(4));
System.out.println(" type : " + statement.getString(5));
System.out.println(" default : " + statement.getString(6));
}
}
现在,对于前面提到的 class/parameter 对,标记为 // HERE
的条件总是被触发,因此会抛出异常...如果我注释整行,那么我会看到所有三个 OUT
参数为空,甚至defaultValue
!
我本来希望后者具有 Studio 中提到的价值...
那么,为什么会这样呢?我的程序有问题吗?
首先,您应该检查您发送的 className 和 paramName 值、全名以及大小写是否正确。为什么选择存储程序,什么时候可以使用select?您可以在系统管理门户中调用您的过程以查看可能的错误。
select description, type,_Default "Default" from %Dictionary.ParameterDefinition where id='Sample.Person||EXTENTQUERYSPEC'
你的例子很适合我。
package javaapplication3;
import com.intersys.jdbc.CacheDataSource;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Types;
public class JavaApplication3 {
/**
* @param args the command line arguments
*/
public static void main(String[] args) throws SQLException {
CacheDataSource ds = new CacheDataSource();
ds.setURL("jdbc:Cache://127.0.0.1:56775/Samples");
ds.setUser("_system");
ds.setPassword("SYS");
Connection dbconnection = ds.getConnection();
String call = "{ ? = call CacheQc.getParamDesc(?, ?, ?, ?, ?)}";
CallableStatement statement = dbconnection.prepareCall(call);
statement.registerOutParameter(1, Types.INTEGER);
statement.setString(2, "Sample.Person");
statement.setString(3, "EXTENTQUERYSPEC");
statement.registerOutParameter(4, Types.VARCHAR);
statement.registerOutParameter(5, Types.VARCHAR);
statement.registerOutParameter(6, Types.VARCHAR);
statement.executeUpdate();
int ret = statement.getInt(1);
System.out.println("ret = " + ret);
System.out.println(" description: " + statement.getString(4));
System.out.println(" type : " + statement.getString(5));
System.out.println(" default : " + statement.getString(6));
}
}
最终结果
ret = 0
description: null
type : null
default : Name,SSN,Home.City,Home.State
更新: 尝试更改您的程序代码并像此处添加一些调试
Class CacheQc.procgetParamDesc Extends %Library.RegisteredObject [ ClassType = "", DdlAllowed, Owner = {UnknownUser}, Not ProcedureBlock ]
{
ClassMethod getParamDesc(className As %Library.String(MAXLEN=50), methodName As %Library.String(MAXLEN=50), Output description As %Library.String(MAXLEN=8192), Output type As %Library.String(MAXLEN=50), Output defaultValue As %Library.String(MAXLEN=1024)) As %Library.Numeric(SCALE=0) [ SqlName = getParamDesc, SqlProc ]
{
set ref = className _ "||" _ methodName
set row = ##class(%Dictionary.ParameterDefinition).%OpenId(ref)
set ^debug($i(^debug))=$lb(ref,row,$system.Status.GetErrorText($g(%objlasterror)))
if (row = "") {
quit 1
}
set description = row.Description
set type = row.Type
set defaultValue = row.Default
quit 0
}
}
在 java 的一些测试之后,检查 zw ^debug
SAMPLES>zw ^debug
^debug=4
^debug(3)=$lb("Sample.Person||EXTENTQUERYSPEC","31@%Dictionary.ParameterDefinition","ERROR #00: (no error description)")
嗯,呃,我发现问题了……说个笨蛋吧
碰巧我在 Studio 中打开了 Samples.Person class 并对其制作了 "modification";并在之后将其删除。因此文件是 "as new"...
但是程序好像不符合这个说法
我关闭了该文件所在的 Studio,选择不修改 "changes",再次运行程序,它成功了...
奇怪的是,SQL 查询甚至对我的 "fake modification" 也有效。我想这是一些缓存问题...