dolphindb 2.0.1022 → 2.0.1025
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/browser.d.ts +4 -1
- package/browser.js +123 -78
- package/browser.js.map +1 -1
- package/docs.en.json +55 -29
- package/docs.zh.json +88 -57
- package/i18n/dict.json +3 -0
- package/index.d.ts +4 -1
- package/index.js +123 -78
- package/index.js.map +1 -1
- package/package.json +7 -7
package/index.js
CHANGED
|
@@ -1176,6 +1176,7 @@ export class DdbObj {
|
|
|
1176
1176
|
static to_ddbobjs(values) {
|
|
1177
1177
|
return values.map(value => this.to_ddbobj(value));
|
|
1178
1178
|
}
|
|
1179
|
+
/** 将 table 转换为 rows,空值转换为 null */
|
|
1179
1180
|
to_rows() {
|
|
1180
1181
|
assert(this.form === DdbForm.table, t('form 必须是 DdbForm.table, 否则不能 to_rows'));
|
|
1181
1182
|
let rows = new Array(this.rows);
|
|
@@ -1192,6 +1193,42 @@ export class DdbObj {
|
|
|
1192
1193
|
Boolean(value);
|
|
1193
1194
|
break;
|
|
1194
1195
|
}
|
|
1196
|
+
case DdbType.char:
|
|
1197
|
+
row[name] = values[i] === nulls.int8 ? null : values[i];
|
|
1198
|
+
break;
|
|
1199
|
+
case DdbType.short:
|
|
1200
|
+
row[name] = values[i] === nulls.int16 ? null : values[i];
|
|
1201
|
+
break;
|
|
1202
|
+
case DdbType.int:
|
|
1203
|
+
case DdbType.date:
|
|
1204
|
+
case DdbType.month:
|
|
1205
|
+
case DdbType.time:
|
|
1206
|
+
case DdbType.minute:
|
|
1207
|
+
case DdbType.second:
|
|
1208
|
+
case DdbType.datetime:
|
|
1209
|
+
case DdbType.datehour:
|
|
1210
|
+
row[name] = values[i] === nulls.int32 ? null : values[i];
|
|
1211
|
+
break;
|
|
1212
|
+
case DdbType.long:
|
|
1213
|
+
case DdbType.timestamp:
|
|
1214
|
+
case DdbType.nanotime:
|
|
1215
|
+
case DdbType.nanotimestamp:
|
|
1216
|
+
row[name] = values[i] === nulls.int64 ? null : values[i];
|
|
1217
|
+
break;
|
|
1218
|
+
case DdbType.int128:
|
|
1219
|
+
row[name] = values[i] === nulls.int128 ? null : values[i];
|
|
1220
|
+
break;
|
|
1221
|
+
case DdbType.float:
|
|
1222
|
+
row[name] = values[i] === nulls.float32 ? null : values[i];
|
|
1223
|
+
break;
|
|
1224
|
+
case DdbType.double:
|
|
1225
|
+
row[name] = values[i] === nulls.double ? null : values[i];
|
|
1226
|
+
break;
|
|
1227
|
+
case DdbType.decimal32:
|
|
1228
|
+
case DdbType.decimal64:
|
|
1229
|
+
case DdbType.decimal128:
|
|
1230
|
+
row[name] = is_decimal_null_value(type, values[i]) ? null : values[i];
|
|
1231
|
+
break;
|
|
1195
1232
|
case DdbType.ipaddr:
|
|
1196
1233
|
row[name] = values.subarray(16 * i, 16 * (i + 1));
|
|
1197
1234
|
break;
|
|
@@ -2255,7 +2292,7 @@ export class DDB {
|
|
|
2255
2292
|
this.lwebsocket.resource = await connect_websocket(this.url, {
|
|
2256
2293
|
protocols: this.streaming ? ['streaming'] : this.python ? ['python'] : undefined,
|
|
2257
2294
|
on_message: (buffer, websocket) => {
|
|
2258
|
-
this.on_message(buffer, websocket);
|
|
2295
|
+
this.on_message(new Uint8Array(buffer), websocket);
|
|
2259
2296
|
},
|
|
2260
2297
|
on_error: error => {
|
|
2261
2298
|
this.error ??= new DdbConnectionError(this.url, error);
|
|
@@ -2341,7 +2378,7 @@ export class DDB {
|
|
|
2341
2378
|
let error = new DdbDatabaseError('', this.url, type, options, id);
|
|
2342
2379
|
if (!options.skip_connection_check)
|
|
2343
2380
|
await this.connect();
|
|
2344
|
-
const { script, func, args: _args = [], vars = [], urgent, listener, } = options;
|
|
2381
|
+
const { script, func, args: _args = [], vars = [], urgent, listener, on_more_messages, } = options;
|
|
2345
2382
|
if (func === 'pnode_run')
|
|
2346
2383
|
await (this.ppnode_run ??= this.eval(this.python ?
|
|
2347
2384
|
'\n' +
|
|
@@ -2442,37 +2479,42 @@ export class DDB {
|
|
|
2442
2479
|
})());
|
|
2443
2480
|
// 使用资源发送请求并等待请求完成
|
|
2444
2481
|
const result = await new Promise((resolve, reject) => {
|
|
2482
|
+
let first_message = true;
|
|
2445
2483
|
this.on_error = () => {
|
|
2446
2484
|
// 这里一定有了 this.error, 不需要再 || new DdbConnectionError(this)
|
|
2447
2485
|
reject(this.error);
|
|
2448
2486
|
};
|
|
2449
2487
|
this.on_message = buffer => {
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2488
|
+
if (!on_more_messages || first_message)
|
|
2489
|
+
try {
|
|
2490
|
+
if (this.print_message_buffer)
|
|
2491
|
+
console.log(typed_array_to_buffer(buffer));
|
|
2492
|
+
const message = this.parse_message(buffer, error);
|
|
2493
|
+
listener?.(message, this);
|
|
2494
|
+
for (const listener of _listeners)
|
|
2495
|
+
listener(message, this);
|
|
2496
|
+
const { type, data } = message;
|
|
2497
|
+
switch (type) {
|
|
2498
|
+
case 'print':
|
|
2499
|
+
if (this.print_message)
|
|
2500
|
+
console.log(data);
|
|
2501
|
+
break;
|
|
2502
|
+
case 'object':
|
|
2503
|
+
first_message = false;
|
|
2504
|
+
resolve(data);
|
|
2505
|
+
break;
|
|
2506
|
+
case 'error':
|
|
2507
|
+
first_message = false;
|
|
2508
|
+
reject(data);
|
|
2509
|
+
break;
|
|
2510
|
+
}
|
|
2470
2511
|
}
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2512
|
+
catch (error) {
|
|
2513
|
+
// 这里的错误并非 websocket 错误,而是 rpc 错误
|
|
2514
|
+
reject(error);
|
|
2515
|
+
}
|
|
2516
|
+
else
|
|
2517
|
+
on_more_messages(buffer);
|
|
2476
2518
|
};
|
|
2477
2519
|
websocket.send(concat([
|
|
2478
2520
|
this.enc.encode(`API2 ${this.sid} ${command.length} / ${this.get_rpc_options({ urgent })}\n`),
|
|
@@ -2526,7 +2568,7 @@ export class DDB {
|
|
|
2526
2568
|
将这个 flag 设为 true 跳过连接状态检查
|
|
2527
2569
|
(internal use) When await ddb.connect() establishes a connection for the first time, you cannot call await this.connect() again to ensure the connection status, which will lead to circular dependencies.
|
|
2528
2570
|
Set this flag to true to skip connection status checks */
|
|
2529
|
-
async call(func, args = [], { urgent, node, nodes, func_type, add_node_alias, listener, parse_object, skip_connection_check } = {}) {
|
|
2571
|
+
async call(func, args = [], { urgent, node, nodes, func_type, add_node_alias, listener, parse_object, skip_connection_check, on_more_messages } = {}) {
|
|
2530
2572
|
if (node) {
|
|
2531
2573
|
assert(func_type in DdbFunctionType, t('指定 node 时必须设置 func_type'));
|
|
2532
2574
|
args = [
|
|
@@ -2557,7 +2599,8 @@ export class DDB {
|
|
|
2557
2599
|
urgent,
|
|
2558
2600
|
listener,
|
|
2559
2601
|
parse_object,
|
|
2560
|
-
skip_connection_check
|
|
2602
|
+
skip_connection_check,
|
|
2603
|
+
on_more_messages
|
|
2561
2604
|
});
|
|
2562
2605
|
}
|
|
2563
2606
|
/** upload variable through websocket (variable command) */
|
|
@@ -2639,6 +2682,12 @@ export class DDB {
|
|
|
2639
2682
|
}
|
|
2640
2683
|
/** 内部的流订阅方法 Internal stream subscription method */
|
|
2641
2684
|
async subscribe() {
|
|
2685
|
+
let win = {
|
|
2686
|
+
offset: 0,
|
|
2687
|
+
rows: 0,
|
|
2688
|
+
segments: [],
|
|
2689
|
+
};
|
|
2690
|
+
let schema;
|
|
2642
2691
|
const { value: colnames } = await this.call('publishTable', [
|
|
2643
2692
|
'localhost',
|
|
2644
2693
|
new DdbInt(0),
|
|
@@ -2647,58 +2696,54 @@ export class DDB {
|
|
|
2647
2696
|
// new DdbInt(-1), // offset
|
|
2648
2697
|
// filter
|
|
2649
2698
|
// allow exists
|
|
2650
|
-
], {
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2699
|
+
], {
|
|
2700
|
+
skip_connection_check: true,
|
|
2701
|
+
// 先准备好收到 websocket message 的 callback
|
|
2702
|
+
on_more_messages: buffer => {
|
|
2703
|
+
try {
|
|
2704
|
+
const dv = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
2705
|
+
const i_topic_end = buffer.indexOf(0, 17);
|
|
2706
|
+
// 首个 message 一定是 table schema, 后续消息是 column 片段组成的 any vector
|
|
2707
|
+
const data = DdbObj.parse(buffer.subarray(i_topic_end + 1), this.le);
|
|
2708
|
+
if (data.form === DdbForm.table) {
|
|
2709
|
+
schema = data;
|
|
2710
|
+
return;
|
|
2711
|
+
}
|
|
2712
|
+
assert(schema, t('流数据订阅后一定先返回 schema'));
|
|
2713
|
+
const { rows } = data.value[0];
|
|
2714
|
+
win.rows += rows;
|
|
2715
|
+
win.segments.push(data);
|
|
2716
|
+
if (win.rows >= winsize * 2 && win.segments.length >= 2) {
|
|
2717
|
+
let winsize_ = 0;
|
|
2718
|
+
let i = win.segments.length - 1;
|
|
2719
|
+
// 往前移动至首个累计 winsize_ 超过 winsize 的位置
|
|
2720
|
+
for (; winsize_ < winsize; i--)
|
|
2721
|
+
winsize_ += win.segments[i].value[0].rows;
|
|
2722
|
+
win.segments = win.segments.slice(i);
|
|
2723
|
+
win.offset += win.rows - winsize_;
|
|
2724
|
+
win.rows = winsize_;
|
|
2725
|
+
}
|
|
2726
|
+
this.streaming.handler({
|
|
2727
|
+
...this.streaming,
|
|
2728
|
+
id: dv.getBigInt64(9, this.le),
|
|
2729
|
+
time: dv.getBigInt64(1, this.le),
|
|
2730
|
+
rows,
|
|
2731
|
+
topic: this.dec.decode(buffer.subarray(17, i_topic_end)),
|
|
2732
|
+
colnames,
|
|
2733
|
+
schema,
|
|
2734
|
+
data,
|
|
2735
|
+
window: win,
|
|
2736
|
+
});
|
|
2671
2737
|
}
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
if (win.rows >= winsize * 2 && win.segments.length >= 2) {
|
|
2676
|
-
let winsize_ = 0;
|
|
2677
|
-
let i = win.segments.length - 1;
|
|
2678
|
-
// 往前移动至首个累计 winsize_ 超过 winsize 的位置
|
|
2679
|
-
for (; winsize_ < winsize; i--)
|
|
2680
|
-
winsize_ += win.segments[i].value[0].rows;
|
|
2681
|
-
win.segments = win.segments.slice(i);
|
|
2682
|
-
win.offset += win.rows - winsize_;
|
|
2683
|
-
win.rows = winsize_;
|
|
2738
|
+
catch (error) {
|
|
2739
|
+
// 将 error 交给 handler 处理
|
|
2740
|
+
this.streaming.handler({ ...this.streaming, error });
|
|
2684
2741
|
}
|
|
2685
|
-
this.streaming.handler({
|
|
2686
|
-
...this.streaming,
|
|
2687
|
-
id: dv.getBigInt64(9, this.le),
|
|
2688
|
-
time: dv.getBigInt64(1, this.le),
|
|
2689
|
-
rows,
|
|
2690
|
-
topic: this.dec.decode(buf.subarray(17, i_topic_end)),
|
|
2691
|
-
colnames,
|
|
2692
|
-
schema,
|
|
2693
|
-
data,
|
|
2694
|
-
window: win,
|
|
2695
|
-
});
|
|
2696
|
-
}
|
|
2697
|
-
catch (error) {
|
|
2698
|
-
// 将 error 交给 handler 处理
|
|
2699
|
-
this.streaming.handler({ ...this.streaming, error });
|
|
2700
2742
|
}
|
|
2701
|
-
};
|
|
2743
|
+
});
|
|
2744
|
+
console.log(t('订阅流表成功') + ', colnames:',
|
|
2745
|
+
// string[3](['time', 'stock', 'price'])
|
|
2746
|
+
colnames);
|
|
2702
2747
|
}
|
|
2703
2748
|
}
|
|
2704
2749
|
// const ddb_gateway = {
|