dolphindb 3.0.123 → 3.0.125

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/i18n/dict.json CHANGED
@@ -103,5 +103,8 @@
103
103
  },
104
104
  "iotany sub vector 不支持非 vector 类型": {
105
105
  "en": "iotany sub vector does not support non-vector types"
106
+ },
107
+ "iotany 的 meta vector 长度至少为 2": {
108
+ "en": "The length of the iotany meta vector is at least 2"
106
109
  }
107
110
  }
package/index.js CHANGED
@@ -822,41 +822,20 @@ export class DdbObj {
822
822
  ];
823
823
  }
824
824
  case DdbType.iotany: {
825
- // 构造 indexes
826
- const dv = new DataView(buf.buffer, buf.byteOffset);
827
- let i_value_start = 0;
828
- const size = Number(dv.getUint32(i_value_start, le));
829
- i_value_start += 4;
830
- const indexes = new Array(size * 2);
831
- for (let i = 0; i < size; i++) {
832
- const type = dv.getUint32(i_value_start, le);
833
- i_value_start += 4;
834
- const idx = dv.getUint32(i_value_start, le);
835
- i_value_start += 4;
836
- indexes[i * 2] = type;
837
- indexes[i * 2 + 1] = idx;
838
- }
839
- // 构造 sub vector
840
- const type_size = dv.getUint32(i_value_start, le);
841
- i_value_start += 4;
842
- const sub_vec = new Map();
843
- for (let i = 0; i < type_size; i++) {
844
- const flag = dv.getUint16(i_value_start, le);
845
- i_value_start += 2;
846
- const form = flag >> 8;
847
- const sub_type = flag & 0xff;
848
- assert(form === DdbForm.vector, t('iotany sub vector 不支持非 vector 类型'));
849
- const sub_size = dv.getUint32(i_value_start, le);
850
- i_value_start += 8; // 同时跳过 sub_size 和 cols
851
- let [len, vector] = this.parse_vector_items(buf.subarray(i_value_start), le, sub_type, sub_size);
852
- vector = converts(sub_type, vector, sub_size, le);
853
- i_value_start += len;
854
- sub_vec.set(sub_type, vector);
825
+ const [len, anys] = this.parse_vector_items(buf, le, DdbType.any, length);
826
+ const metas = anys[0].data();
827
+ assert(metas.length >= 2, t('iotany 的 meta vector 长度至少为 2'));
828
+ const size = metas[0];
829
+ // let sub_vec_count = meta_vec[1]
830
+ let sub_vecs = new Map();
831
+ for (let i = 1; i < length; i++) {
832
+ const sub_vector = anys[i];
833
+ const sub_type = sub_vector.type;
834
+ sub_vecs.set(sub_type, converts(sub_type, sub_vector.data(), sub_vector.length, le));
855
835
  }
856
836
  return [
857
- i_value_start,
858
- // 根据 indexes 数组构建最终的 value 数组
859
- seq(size, i => (sub_vec.get(indexes[i * 2]))[indexes[i * 2 + 1]])
837
+ len,
838
+ seq(size, i => (sub_vecs.get(metas[i + size + 2]))[metas[i + 2]])
860
839
  ];
861
840
  }
862
841
  // 25 01 type = decimal32, form = vector
@@ -2967,46 +2946,52 @@ export class DDB {
2967
2946
  await this.connect();
2968
2947
  const { script, func, args: _args = [], vars = [], urgent, listener, on_more_messages, } = options;
2969
2948
  if (func === 'pnode_run')
2970
- await (this.ppnode_run ??= this.eval(this.python ?
2971
- '\n' +
2972
- 'def pnode_run (nodes, func_name, args, add_node_alias):\n' +
2973
- ' nargs = size(args)\n' +
2974
- ' func = funcByName(func_name)\n' +
2975
- ' \n' +
2976
- ' if not nargs:\n' +
2977
- ' return pnodeRun(func, nodes, add_node_alias)\n' +
2978
- ' \n' +
2979
- ' args_partial = [ ]\n' +
2980
- ' args_partial.append(func)\n' +
2981
- ' for a in args:\n' +
2982
- ' args_partial.append(a)\n' +
2983
- ' \n' +
2984
- ' return pnodeRun(\n' +
2985
- ' unifiedCall(partial, args_partial),\n' +
2986
- ' nodes,\n' +
2987
- ' add_node_alias\n' +
2988
- ' )\n'
2989
- :
2990
- // 这个开头的空行很重要,应该可以绕过 webLoginRequired = true 时禁止执行代码
2991
- // 搜一下 APISocketConsole::execute
2992
- // https://dolphindb1.atlassian.net/browse/D20-4991
2949
+ try {
2950
+ await (this.ppnode_run ??= this.eval(this.python ?
2993
2951
  '\n' +
2994
- 'def pnode_run (nodes, func_name, args, add_node_alias = true) {\n' +
2952
+ 'def pnode_run (nodes, func_name, args, add_node_alias):\n' +
2995
2953
  ' nargs = size(args)\n' +
2996
2954
  ' func = funcByName(func_name)\n' +
2997
2955
  ' \n' +
2998
- ' if (!nargs)\n' +
2956
+ ' if not nargs:\n' +
2999
2957
  ' return pnodeRun(func, nodes, add_node_alias)\n' +
3000
2958
  ' \n' +
3001
- ' args_partial = array(any, 1 + nargs, 1 + nargs)\n' +
3002
- ' args_partial[0] = func\n' +
3003
- ' args_partial[1:] = args\n' +
2959
+ ' args_partial = [ ]\n' +
2960
+ ' args_partial.append(func)\n' +
2961
+ ' for a in args:\n' +
2962
+ ' args_partial.append(a)\n' +
2963
+ ' \n' +
3004
2964
  ' return pnodeRun(\n' +
3005
2965
  ' unifiedCall(partial, args_partial),\n' +
3006
2966
  ' nodes,\n' +
3007
2967
  ' add_node_alias\n' +
3008
- ' )\n' +
3009
- '}\n', { urgent: true }));
2968
+ ' )\n'
2969
+ :
2970
+ // 这个开头的空行很重要,应该可以绕过 webLoginRequired = true 时禁止执行代码
2971
+ // 搜一下 APISocketConsole::execute
2972
+ // https://dolphindb1.atlassian.net/browse/D20-4991
2973
+ '\n' +
2974
+ 'def pnode_run (nodes, func_name, args, add_node_alias = true) {\n' +
2975
+ ' nargs = size(args)\n' +
2976
+ ' func = funcByName(func_name)\n' +
2977
+ ' \n' +
2978
+ ' if (!nargs)\n' +
2979
+ ' return pnodeRun(func, nodes, add_node_alias)\n' +
2980
+ ' \n' +
2981
+ ' args_partial = array(any, 1 + nargs, 1 + nargs)\n' +
2982
+ ' args_partial[0] = func\n' +
2983
+ ' args_partial[1:] = args\n' +
2984
+ ' return pnodeRun(\n' +
2985
+ ' unifiedCall(partial, args_partial),\n' +
2986
+ ' nodes,\n' +
2987
+ ' add_node_alias\n' +
2988
+ ' )\n' +
2989
+ '}\n', { urgent: true }));
2990
+ }
2991
+ catch (error) {
2992
+ this.ppnode_run = undefined;
2993
+ throw error;
2994
+ }
3010
2995
  // this 上的当前配置需要在 message 到达后使用,先保存起来
3011
2996
  const _listeners = [...this.listeners].reverse();
3012
2997
  // rpc 请求期间需要独占 websocket,所以设计了一个锁,申请之后才能使用
@@ -3233,34 +3218,6 @@ export class DDB {
3233
3218
  - add_node_alias?: 设置 nodes 参数时选传,其它情况不传
3234
3219
  - listener?: 处理本次 rpc 期间的消息 (DdbMessage) */
3235
3220
  async invoke(func, args, options) {
3236
- try {
3237
- await (this.pinvoke ??= this.eval(this.python ?
3238
- '\n' +
3239
- 'def invoke (func, args_json):\n' +
3240
- ' args = fromStdJson(args_json)\n' +
3241
- ' func_ = func\n' +
3242
- ' if type(func) == STRING:\n' +
3243
- ' func_ = funcByName(func)\n' +
3244
- ' if type(args) != ANY:\n' +
3245
- ' args = cast(args, ANY)\n' +
3246
- ' return unifiedCall(func_, args)\n'
3247
- :
3248
- '\n' +
3249
- 'def invoke (func, args_json) {\n' +
3250
- ' args = fromStdJson(args_json)\n' +
3251
- ' func_ = func\n' +
3252
- ' if (type(func) == STRING)\n' +
3253
- ' func_ = funcByName(func)\n' +
3254
- ' if (type(args) != ANY)\n' +
3255
- ' args = cast(args, ANY)\n' +
3256
- ' return unifiedCall(func_, args)\n' +
3257
- '}\n', { urgent: true }));
3258
- }
3259
- catch (error) {
3260
- // invoke 没有正确执行时,重新将 pinvoke 赋值为 undefined
3261
- this.pinvoke = undefined;
3262
- throw error;
3263
- }
3264
3221
  // 检查 args 是否全部为简单参数,是则直接调用 call,避免 invoke 间接调用
3265
3222
  // 逻辑类似 DdbObj.to_ddbobjs, 需要同步修改
3266
3223
  let simple = true;
@@ -3277,11 +3234,42 @@ export class DDB {
3277
3234
  break;
3278
3235
  }
3279
3236
  }
3280
- if (!simple && has_ddbobj)
3281
- throw new Error(t('调用 ddb.invoke 的参数中不能同时有 DdbObj 与复杂 js 原生对象'));
3282
- const result = simple
3283
- ? await this.call(func, args, options)
3284
- : await this.call('invoke', [func, JSON.stringify(args)], options);
3237
+ let result;
3238
+ if (simple)
3239
+ result = await this.call(func, args, options);
3240
+ else {
3241
+ if (has_ddbobj)
3242
+ throw new Error(t('调用 ddb.invoke 的参数中不能同时有 DdbObj 与复杂 js 原生对象'));
3243
+ try {
3244
+ await (this.pinvoke ??= this.eval(this.python ?
3245
+ '\n' +
3246
+ 'def invoke (func, args_json):\n' +
3247
+ ' args = fromStdJson(args_json)\n' +
3248
+ ' func_ = func\n' +
3249
+ ' if type(func) == STRING:\n' +
3250
+ ' func_ = funcByName(func)\n' +
3251
+ ' if type(args) != ANY:\n' +
3252
+ ' args = cast(args, ANY)\n' +
3253
+ ' return unifiedCall(func_, args)\n'
3254
+ :
3255
+ '\n' +
3256
+ 'def invoke (func, args_json) {\n' +
3257
+ ' args = fromStdJson(args_json)\n' +
3258
+ ' func_ = func\n' +
3259
+ ' if (type(func) == STRING)\n' +
3260
+ ' func_ = funcByName(func)\n' +
3261
+ ' if (type(args) != ANY)\n' +
3262
+ ' args = cast(args, ANY)\n' +
3263
+ ' return unifiedCall(func_, args)\n' +
3264
+ '}\n', { urgent: true }));
3265
+ }
3266
+ catch (error) {
3267
+ // invoke 没有正确执行时,重新将 pinvoke 赋值为 undefined
3268
+ this.pinvoke = undefined;
3269
+ throw error;
3270
+ }
3271
+ result = await this.call('invoke', [func, JSON.stringify(args)], options);
3272
+ }
3285
3273
  return result.data(options);
3286
3274
  }
3287
3275
  /** 执行 dolphindb 脚本,返回 js 原生对象或值(调用 DdbObj.data() 后的结果)