# 数据模型

# 导入

通过如下方式导入数据模型api

import dw from "svr-api/dw";

# 方法

/**
 * 模型相关API
 */

/**
 * 获取指定的模型。
 *
 * @param resIdOrPath 模型的路径或者资源id。
 * @param throwIfNotExist 不存在时是否抛出异常,默认为`false`。
 * @returns 返回模型表的信息对象,不存在时返回`null`。
 */
export function getDwTable(resIdOrPath: string, throwIfNotExist?: boolean): DwTableCompiledInfo;

/**
 * 获取指定的模型的表结构的元数据信息。
 * 
 * 此函数基于指定的表的字段和维键结构,构造一个对应的数据库表的元数据信息返回,返回的信息可以直接用于创建物理表。
 *
 * @param resIdOrPath 模型的路径或者资源id。
 * @param throwIfNotExist 不存在时是否抛出异常,默认为`false`。
 * @returns 返回模型表的信息对象,不存在时返回`null`。
 */
export function getDwTableMetaInfo(resIdOrPath: string, throwIfNotExist?: boolean): TableMetaData;

/**
 * 打开模型表的数据,可以对数据进行增删改查操作。
 *
 * @param path 元数据路径,可以是如下形式:
 *  1. 完整的绝对路径,如`/ProjectName/data/path/to/yourfile.tbl`。
 *  2. 相对路径,相对于当前执行的脚本文件,如
 *     `yourfile.tbl`、`../folder/yourfile.tbl`。
 *  3. 没有后缀时默认使用`.tbl`。
 * @param throwIfNotExist 不存在时是否抛出异常,默认为`false`。
 * @returns 返回模型表的数据对象,不存在时返回`null`。
 */
export function openDwTableData(path: string, throwIfNotExist?: boolean): DwTableData;

/**
 * 根据传入的数据包,修改模型表的数据。
 *
 * @param resIdOrPath 模型的路径或者资源id。
 * @param data 要更新的数据包。
 * @param con 可以传入一个外部的数据库连接,此时此函数将不自动提交数据,交给外部
 *     调用者自己处理,方便实现在一个事务中进行多个表的修改。
 */
export function updateDwTableData(resIdOrPath: string, data: CommonTableSubmitDataPackage, con?: Connection): void;

/**
 * 保存标签库。
 *
 * @param labelLibInfo
 */
export function saveLabelLib(labelLibInfo: DwDataLabelLib): void;

/**
 * 执行回放服务。
 *
 * @param args 
 * @param args.schedule 推送计划,将执行属于该计划的所有正常通道。
 * @param args.parallel 并发数,默认为4。
 */
export function pushData(args: { schedule: string, parallel?: number }): void;

/**
 * 刷新一个数据表的状态。
 *
 * 数据发生变化,需要调用此方法,更新总行数等。
 *
 * @param resIdOrPath 模型的路径或者资源id。
 */
export function refreshState(resIdOrPath: string): void;

/**
 * 更新目标模型的父子维层次信息。
 *
 * 更新完成后,自动调用刷新数据缓存。
 *
 * @param resIdOrPath 模型的路径或者资源id。
 * @param ids 主键列表,不传时,刷新整个模型,传递时,只刷新传入主键对应的这些数据行
 *    考虑多字段主键情况,请传递多维数组
 * @param con 使用外部传入的conn进行修改,不传或为空,则内部自己从获取。
 */
export function refreshTableParentHierarchy(resIdOrPath: string, ids?: string[][], con?: Connection): void;

/**
 * 脚本执行一个Query查询。
 *
 * 返回值结构:
 * {
 * 		"fields": [{
 * 			"name": "",
 * 			"dataType": C
 * 		}],
 * 		"data": [[]],
 * 		"totalRowCount": 123,
 * 		"sql":["select ...", "select count(*) ...."]
 * }
 *
 * 注意:
 * 是否返回sql,需要取决于{@link SystemSettingsReader#enableShowQuerySql()}是否返回true。
 *
 * @param queryInfo query的定义。另外,可以传递一个额外的onlySql参数,表示只获取sql不执行sql。
 * @return 见{@link QueryDataResult}
 */
export function executeQuery(queryInfo: ScriptQueryInfo): QueryDataResult;

/**
 * 创建一个Query的执行器。
 * 
 * 用于预编译一个Query,当有不同参数,多次执行时,可以复用执行器。
 * 
 * @param queryInfo 
 */
export function createQueryExecutor(queryInfo: QueryInfo): QueryExecutor;

/**
 * 从物理表导入模型
 *
 * @returns 模型表的信息。`path`为模型表的路径,`dbTableName`为模型表对应的物理表
 */
export function importDWModelFromDbTables(args: {
	/**
	 * 目标项目名称
	 */
	projectName: string;
	/** 
	 * 目标schema
	 */
	targetSchema?: string;
	/**
	 * 目标目录
	 */
	targetFolder: string;
	tables: Array<{
		/**
		 * 来源数据表所在的数据源
		 */
		datasource: string,
		/**
		 * 来源数据表所在的schema
		 */
		schema: string,
		/**
		 * 来源数据表的表名
		 */
		dbTable: string,
		/**
		 * 导入后的模型的名称
		 */
		name?: string,
		/**
		 * 导入后模型的描述信息
		 */
		desc?: string
	}>;
	/**
	 * 连接方式
	 * 
	 * 1. readonly 实时连接(只读模式,用于实时数据分析)
	 * 2. readwrite 实时连接(读写模式,系统可能会更新数据或者表结构)
	 * 3. extract 提取数据(只读模式,将业务系统数据提取到指定数据源,默认为分析主数据库)
	 **/
	connectionType: DwConnectionType;
	/**
	 * 调度设置
	 */
	schedule?: string;
}): Array<{ path: string, dbTableName: string }>;

export function createIndLibCalcRunner(args: DwDataIndLibBuilderArgs): DwDataIndLibCalcRunner;

/**
 * 创建一个批量读取数据集数据的接口。
 * 
 * 对于需要读取大量数据的场景,如导出数据,推荐使用该接口流式读取。
 * 
 * @param args 参数中的约束和参数相关信息从前端的`IBODataset.getConstraintArgs()`方法获取。
 */
export function createDatasetBulkDataReader(args: DatasetBulkDataReaderArgs): BulkDataReader;

/**
 * 保存一批关联关系。
 * 
 * @param relations 
 */
export function saveRelations(relations: DwTableRelationModifyInfo[]): void;


/**
 * 服务器端脚本读取数据集数据的参数定义。
 * 
 * 参数中的约束和参数相关信息从前端的`IBODataset.getQueryConstraintArgs()`方法获取。
 */
type DatasetBulkDataReaderArgs = QueryRequestArgs & { fields?: Array<string | DatasetBulkDataReaderFieldInfo> }

/**
 * {@link DatasetBulkDataReaderArgs.fields}
 */
declare interface DatasetBulkDataReaderFieldInfo {

	/**
	 * 物理字段名。
	 */
	name: string;

	/**
	 * 字段值的显示格式。
	 * 
	 * 对于导出的场景,如果字段的格式是不兼容excel的,如`@ @txt`,需要在返回数据时就格式化好。
	 */
	valueFormat?: string;
}

# 对象

/**
 * 此文件定义数据模型相关的后端脚本接口。
 * 
 * 1. 目前有很对对象都是前后端公用的,比如`DwTableInfo`、`DwTableFieldInfo`。
 * 2. 可能前端以后会发生修改,接口发生变化,此时后端接口也可以跟着变化,但是实现类继续支持一下以前的接口返回就好了。
 */

/**
 * 一个模型表的数据对象,提供比较方便的查询和修改模型表的数据的工具函数。
 * 说明:
 * 1、大多数情况下直接调用本方法的增删改查方法即可访问数据库,不需要调用commit、rollback
 * 2、如果操作数据库需要关心事务,多个增删改操作必须在一个事务中执行,那么需要先调用`setAutoCommit(false)`,禁用自动提交。
 *    然后在操作的最后调用commit(),在try-catch中调用rollback,下面是一个示例:
 * @example
 *  import dw from "svr-api/dw";
 *  let data = dw.openDwTableData("XXXXXX");
 *  try{
 *      data.setAutoCommit(false); //禁止自动提交,整个事务在commit时提交
 *      data.insert({ID_:"A100", CAPTION_:"渔业"});
 *      data.delete({ID_:"A200"});
 *      data.commit();
 *  }catch(e){
 *      data.rollback();
 *  }
 */
interface DwTableData extends TableData {

	/**
	 * 获取模型的指定层次数据对象。
	 * 
	 * 模型未设置层次时,返回基于主键的单极维层次。
	 * 
	 * @param hierarchyId 层次id,不传默认获取模型默认层次。
	 * @param timePoint 
	 */
	getHierarchyData(hierarchyId?: string, timePoint?: string): DwTableHierarchyData;

}

interface DwTableHierarchyData {

	/**
	 * 获取维表模型的某个维项。不存在时返回null。
	 * 
	 * @param id 层次id或主键id
	 */
	getItem(id: string): DwTableDataItem;

	/**
	 * 获取一批维项,支持将上级维项一起查出。
	 * 
	 * @param ids 支持传入层次id或主键id
	 * @param options 
	 */
	getItems(ids: string[], options?: QueryItemsRequestArgs): DwTableDataItem[];

	/**
	 * 根据文本找到维项,不存在时返回null。
	 * 
	 * 优先使用文字字段查找维项,找不到时使用设置的同义词字段查找。
	 * 
	 * @param txt 要查找的文本
	 * @param synonymFieldName 
	 */
	getItemByTxt(txt: string): DwTableDataItem;

	/**
	 * 查找某个层级的所有子节点。父节点不存在时返回null,父节点存在但是没有子节点时返回空数组。
	 * 
	 * @param pid 父维项代码
	 */
	getChildren(pid: string, options?: QueryItemsRequestArgs): DwTableDataItem[];

	/**
	 * 获取根维成员
	 */
	getRootItems(options?: QueryItemsRequestArgs): DwTableDataItem[];

	/**
	 * 判断一个维项是否是另一个维项的父节点或父节点的父节点(祖先节点)……
	 * @param pid 父维项代码
	 * @param id 维项id
	 * @param time 缓慢变化维有效,不传递表示当前时间
	 */
	isAncestor(pid: string, id: string): boolean;

}

/**维项信息 */
interface DwTableDataItem {
	/** 维项代码,唯一标识 */
	id: string,
	/** 维代码 */
	code: string,
	/** 名称 */
	caption: string,
	/** 父代码 */
	pid: string,
	/** 主键 */
	primaryKeyValue: string,
	/** 原始数据行 */
	row: Array<any>,
	/** 层级 */
	level: number,
	/** 是否叶子节点 */
	leaf: boolean,
	/**
	 * 其它属性,通过字段名访问
	 * @param name 字段名
	 */
	getProperty(name: string): any;
}


/**
 * 指标计算模式
 */
declare const enum DwDataIndCalcMode {

	/** 批量校验 */
	valid = "valid",

	/** 指标计算 */
	calc = "calc",

}

/**
 * 指标库的数据源定义
 */
interface DwDataIndLibValueSource extends DwTableValueSource {

	/** 主键映射,用于判断写入目标表的主键对应来源表的哪个字段。 */
	keyMap?: Array<{

		/** 目标表的字段名 */
		targetKey: string,

		/** 源表字段名,也就是当前表的字段 */
		srcKey?: string,

		/** 接收一个常量值,例如TABLE_ID */
		value?: any

	}>
}

/**
 * 指标库编译信息构造器。
 */
interface DwDataIndLibBuilderArgs {

	/** 持有当前指标库的资源id,用于获取数据范围信息 */
	ownerResPath: string;

	/** 指标引用的模型,作为编译上下文使用 */
	models: DwDataIndLibValueSource[];

	/** 全局条件,左右于所有模型上,例如表单批量校验某个单位的所有下级数据 */
	publicFilter?: ExpressionString;

	/** 默认命名空间的模型ID */
	namespace?: string;

	/** 标识是批量校验还是指标计算 */
	mode?: DwDataIndCalcMode;

	/** 行式输出,批量校验模式总是行式输出 */
	rowBased?: boolean;

	/** 
	 * 数据输出模型路径。
	 * 
	 * 批量校验模式,允许指标计算引用模型的粒度少于输出模型。
	 * 可以通过 {@link DwDataIndicatorBuilderArgs.validProperties} 补全字段值。
	 * 
	 */
	targetModel?: ReferenceResourcePath;

	/** 
	 * 结果表模型数据范围。
	 * 
	 * 用于确定当前校验的数据范围,需要将前一次校验失败,本次校验成功的数据状态更新。
	 * 校验表可能是缓慢变化表,结果表通常是周期快照表,过滤条件可能不同,这里单独提供一个配置。
	 */
	targetModelFilter?: ExpressionString;

	/** 校验结果字段,1表示校验成功,0表示校验失败。 */
	validResultField?: string;

	/** 校验公式ID字段,用于选择指定校验公式执行时使用,只更新这部分校验公式的信息 */
	validIdField?: string;

	/** 特例说明字段,校验一批数据后,需要将上一次校验失败,这次校验成功,且没有特例说明的数据删除 */
	validExceptionDescField?: string;

	/** 
	 * 校验结束后,同步更新引用模型的校验状态字段。
	 * 
	 * 校验公式引用单表字段的,直接更新该表;引用多表字段的,更新{@link DwDataIndicatorBuilderArgs.ownerModel}
	 * 对应的模型。
	 * 
	 * 默认为true.
	 * 
	 * @see DwTablePropertiesInfo.checkErrorStateField
	 */
	updateModelValidStateField?: boolean;

	/** 
	 * 校验结果属性名,校验通过后将结果写入目标表。
	 * 
	 * 属性名约定和目标表字段名相同。
	 * 
	 * @see DwDataIndicatorBuilderArgs.validProperties
	 */
	validPropertyNames?: string[];

	/** 指标队列 */
	indicators: DwDataIndicatorBuilderArgs[];

	/** 参数 */
	params?: Array<ParamMetaInfo>;

	/** 
	 * 优先使用跨库迁移,即使查询数据和目标表来自同一个数据库。
	 * 
	 * 启用后可以使用并发迁移工具加速。
	 */
	migrateFirst?: boolean;

	/**
	 * 优先内存计算,总是尽量将计算逻辑在内存里执行。
	 */
	memCalcFirst?: boolean;


}

/**
 * 指标定义参数。
 */
interface DwDataIndicatorBuilderArgs {

	/** 指标唯一id,计算指定指标时传入 */
	id: string;

	/** 目标字段名,校验模式下忽略这个属性 */
	columnName?: string;

	/** 取值公式,批量校验模式下是校验公式 */
	valueExp: ExpressionString;

	/** 取值条件,批量校验模式下是生效条件 */
	filterExp?: ExpressionString;

	/** 
	 * 校验公式所属的模型ID。
	 * 
	 * 用于批量校验后更新所属模型数据的校验状态。
	 * 
	 * 跨表校验公式需要明确这个属性,校验公式引用的字段来自于同一张表时可不设置。
	 * @see DwDataIndLibValueSource.id
	 */
	ownerModel?: string;

	/** 
	 * 校验指标属性值,校验失败的数据将这些属性写入目标表。
	 * 
	 * 属性名在 {@link DwDataIndLibBuilderArgs.validPropertyNames} 中定义。
	 * value是个常量值,如果是需要计算的表达式,需要以等号开头。
	 */
	[propertyName: string]: any;

}

/** 指标库批量计算执行器 */
interface DwDataIndLibCalcRunner {

	/** 执行计算 */
	execute(): void;

	setProgress(progress: ProgressMonitor): void;

	/** 设置需要计算的指标id */
	setIndicators(ids: string[]): void;

	/** 设置参数值 */
	setParams(params: JSONObject): void;

}

/**
 * 脚本运行的Query,带有部分运行时参数,方便查询。
 * 
 */
interface ScriptQueryInfo extends QueryInfo {
	/** 
	 * 是否只获取sql
	 * 
	 * 当传true时,不会执行sql,只把sql返回。 
	 * 
	 * 默认为false。
	 */
	onlySql?: boolean;

	/** 是否查询总行数 
	 *
	 * 如果设置true,需要在{@link QueryInfo.options}中设置enablePaging启用总行数查询约束。 
	 * 
	 * 默认false。
	 */
	queryTotalRowCount?: boolean;

	/** 
	 * 从第几行开始
	 *
	 * =0是第一行,不传递此参数表示从第一行开始。如果要分页查询,需要在{@link QueryInfo.options}中设
	 * 置enableQueryTotalRowCount启用分页查询约束。
	 *
	 * 默认值为0 
	 */
	offset?: number;

	/** 分页时,默认每页的数据行数。
	 * 
	 * 如果要分页查询,需要在{@link QueryInfo.options}中设置enableQueryTotalRowCount启用分页查询约束。
	 * 
	 * 默认值为-1,表示返回所有行。
	 */
	limit?: number;

	/**
	 * 参数值列表 
	 *
	 * 参数的定义在{@link QueryInfo.paramNames}中,也可以不在{@link QueryInfo.paramNames}中定义,这
	 * 时将自动取params中的name进行编译。
	 *
	 * 需要注意的是,如果参数是一个多值,需要在{@link QueryInfo.paramNames}中定义其属性。
	 *
	 * 此属性是运行时传递给查询的参数值。
	 */
	params?: QueryRequestParam;
}

/**
 * 一个Query执行器。
 * 
 * 通过{@link createQueryExecutor}创建。
 */
interface QueryExecutor {

	/**
	 * 设置查询参数。
	 * 
	 * 当构造的查询中使用了参数,执行查询前需要传递参数值。
	 * 如果没有可以不设置。
	 * 
	 * @param params 
	 */
	setParams(params?: QueryRequestParam): void;

	/**
	 * 设置分页查询。
	 * 
	 * 当{@link QueryInfo.options}中enablePaging启用了分页查询时,此方法才起作用。
	 * 
	 * @param offset 开始行数,0表示第一行。
	 * @param limit 返回的行数。
	 */
	setLimit(offset: number, limit: number): void;

	/**
	 * 直接获取sql。
	 * 
	 * 可能会返回多条sql,比如:查询sql,查询总行数sql,固定维计算执行多个sql等。
	 * 
	 * 此方法不会执行查询。
	 */
	getSql(): string[];

	/**
	 * 执行查询。
	 */
	execute(): QueryDataResult;

	/**
	 * 获取总行数。
	 */
	executeCount(): number;
}
是否有帮助?
0条评论
评论