dolphindb 3.0.21 → 3.0.23
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/README.md +8 -10
- package/README.zh.md +112 -31
- package/browser.d.ts +13 -12
- package/browser.js +70 -47
- package/browser.js.map +1 -1
- package/index.d.ts +13 -12
- package/index.js +70 -47
- package/index.js.map +1 -1
- package/package.json +4 -4
- package/test.js +13 -10
- package/test.js.map +1 -1
package/index.d.ts
CHANGED
|
@@ -300,8 +300,8 @@ export declare class DdbObj<TValue extends DdbValue = DdbValue> {
|
|
|
300
300
|
- 矩阵对应 DdbMatrixData
|
|
301
301
|
- 字典对应普通的 js 对象 Record<string, any>
|
|
302
302
|
- 图对应 DdbChartValue */
|
|
303
|
-
data<TResult extends any[]>(this: DdbVectorObj): TResult;
|
|
304
|
-
data<TResult = any>(this: DdbObj): TResult;
|
|
303
|
+
data<TResult extends any[]>(this: DdbVectorObj, options?: ConvertOptions): TResult;
|
|
304
|
+
data<TResult = any>(this: DdbObj, options?: ConvertOptions): TResult;
|
|
305
305
|
[inspect.custom](depth: number, _options: InspectOptions, _inspect: any): string;
|
|
306
306
|
inspect_type(): string;
|
|
307
307
|
/** 自动转换 js string, boolean 为 DdbObj */
|
|
@@ -343,9 +343,13 @@ export interface InspectOptions extends UtilInspectOptions {
|
|
|
343
343
|
export declare function format(type: DdbType, value: DdbValue, le: boolean, options?: InspectOptions): string;
|
|
344
344
|
/** 格式化向量、集合中的第 index 项为字符串,空值返回 'null' 字符串 formatted vector, the index-th item in the collection is a string, a null value returns a 'null' string */
|
|
345
345
|
export declare function formati(obj: DdbVectorObj, index: number, options?: InspectOptions): string;
|
|
346
|
-
export
|
|
346
|
+
export interface ConvertOptions {
|
|
347
|
+
/** `'string'` blob 类型数据的格式 */
|
|
348
|
+
blob?: 'string' | 'binary';
|
|
349
|
+
}
|
|
350
|
+
export declare function convert(type: DdbType, value: DdbValue, le: boolean, { blob }?: ConvertOptions): string | number | bigint | boolean | Uint8Array | Int32Array | BigInt64Array | string[] | Int8Array | Int16Array | Float32Array | Float64Array | Uint8Array[] | number[] | DdbFunctionDefValue | DdbDurationValue | DdbDecimal32Value | DdbDecimal64Value | DdbDecimal32VectorValue | DdbDecimal64VectorValue | DdbDecimal128VectorValue | BigInt128Array | DdbSymbolExtendedValue | DdbArrayVectorValue | DdbMatrixValue | DdbObj<DdbValue>[] | DdbDurationVectorValue | DdbChartValue;
|
|
347
351
|
/** 转换一个向量到 js 原生数组 */
|
|
348
|
-
export declare function converts(type: DdbType, value: DdbVectorValue, rows: number, le: boolean): any[];
|
|
352
|
+
export declare function converts(type: DdbType, value: DdbVectorValue, rows: number, le: boolean, options?: ConvertOptions): any[];
|
|
349
353
|
export declare class DdbVoid extends DdbObj<undefined> {
|
|
350
354
|
constructor(value?: DdbVoidType);
|
|
351
355
|
}
|
|
@@ -489,31 +493,28 @@ export interface StreamingParams {
|
|
|
489
493
|
};
|
|
490
494
|
handler(message: StreamingMessage): any;
|
|
491
495
|
}
|
|
492
|
-
export interface StreamingMessage extends StreamingParams {
|
|
496
|
+
export interface StreamingMessage<TRows = any> extends StreamingParams {
|
|
493
497
|
/** server 发送消息的时间 (nano seconds since epoch) The time the server sent the message (nano seconds since epoch)
|
|
494
498
|
std::chrono::system_clock::now().time_since_epoch() / std::chrono::nanoseconds(1) */
|
|
495
499
|
time: bigint;
|
|
496
500
|
/** message id */
|
|
497
501
|
id: bigint;
|
|
498
|
-
colnames: string[];
|
|
499
|
-
/** 最新的 server 有可能先推一个 table schema 过来 */
|
|
500
|
-
schema?: DdbTableObj;
|
|
501
502
|
/** 订阅主题,即一个订阅的名称。 Subscription topic, which is the name of a subscription.
|
|
502
503
|
它是一个字符串,由订阅表所在节点的别名、流数据表名称和订阅任务名称(如果指定了 actionName)组合而成,使用 `/` 分隔
|
|
503
504
|
It is a string consisting of the alias of the node where the subscription table is located, the stream data table name, and the subscription task name (if actionName is specified), separated by `/` */
|
|
504
505
|
topic: string;
|
|
505
506
|
/** 流数据,类型是 any vector, 其中的每一个元素对应被订阅表的一个列 (没有 name),列 (DdbObj<DdbVectorValue>) 中的内容是新增的数据值
|
|
506
507
|
Stream data, the type is any vector, each element of which corresponds to a column (without name) of the subscribed table, and the content in the column (DdbObj<DdbVectorValue>) is the new data value */
|
|
507
|
-
|
|
508
|
-
/**
|
|
509
|
-
|
|
508
|
+
obj: DdbObj<DdbVectorObj[]>;
|
|
509
|
+
/** 流数据 */
|
|
510
|
+
data: DdbTableData<TRows>;
|
|
510
511
|
window: {
|
|
511
512
|
/** 建立连接开始 offset = 0, 随着 window 的移动逐渐增加 The establishment of the connection starts offset = 0, and gradually increases as the window moves */
|
|
512
513
|
offset: number;
|
|
513
514
|
/** segments 中 segment.row 的总和 sum of segment.row in segments */
|
|
514
515
|
rows: number;
|
|
515
516
|
/** 每次接收到的 data 组成的数组 An array of data received each time */
|
|
516
|
-
segments:
|
|
517
|
+
segments: DdbTableData<TRows>[];
|
|
517
518
|
};
|
|
518
519
|
/** 成功订阅后,后续推送过来的 message 解析错误,则会设置 error 并调用 handler
|
|
519
520
|
After successfully subscribed, if the subsequently pushed message is parsed incorrectly, the error will be set and the handler will be called. */
|
package/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import DayjsCustomParseFormat from 'dayjs/plugin/customParseFormat.js';
|
|
|
3
3
|
dayjs.extend(DayjsCustomParseFormat);
|
|
4
4
|
import ipaddrjs from 'ipaddr.js';
|
|
5
5
|
const { fromByteArray: buf2ipaddr } = ipaddrjs;
|
|
6
|
-
import { concat, assert, inspect, typed_array_to_buffer, connect_websocket, Lock, genid, seq, zip_object, WebSocketOpen, WebSocketClosed, WebSocketClosing, } from 'xshell';
|
|
6
|
+
import { concat, assert, inspect, typed_array_to_buffer, connect_websocket, Lock, genid, seq, zip_object, WebSocketOpen, WebSocketClosed, WebSocketClosing, decode, } from 'xshell';
|
|
7
7
|
import { t } from './i18n/index.js';
|
|
8
8
|
export const nulls = {
|
|
9
9
|
int8: -0x80, // -128
|
|
@@ -1122,20 +1122,20 @@ export class DdbObj {
|
|
|
1122
1122
|
throw new Error(t('vector {{type}} 暂不支持序列化', { type: get_type_name(type) }));
|
|
1123
1123
|
}
|
|
1124
1124
|
}
|
|
1125
|
-
data() {
|
|
1125
|
+
data(options) {
|
|
1126
1126
|
const { form, type, value, le, rows, name } = this;
|
|
1127
1127
|
switch (form) {
|
|
1128
1128
|
case DdbForm.scalar:
|
|
1129
|
-
return convert(type, value, le);
|
|
1129
|
+
return convert(type, value, le, options);
|
|
1130
1130
|
case DdbForm.vector:
|
|
1131
1131
|
case DdbForm.pair:
|
|
1132
1132
|
case DdbForm.set: {
|
|
1133
|
-
const data = converts(type, value, rows, le);
|
|
1133
|
+
const data = converts(type, value, rows, le, options);
|
|
1134
1134
|
return (form === DdbForm.set ? new Set(data) : data);
|
|
1135
1135
|
}
|
|
1136
1136
|
case DdbForm.table: {
|
|
1137
1137
|
const cols = value;
|
|
1138
|
-
const jscols = cols.map(col => col.data());
|
|
1138
|
+
const jscols = cols.map(col => col.data(options));
|
|
1139
1139
|
const keys = cols.map(({ name }) => name);
|
|
1140
1140
|
return {
|
|
1141
1141
|
name: name || '',
|
|
@@ -1146,20 +1146,20 @@ export class DdbObj {
|
|
|
1146
1146
|
}
|
|
1147
1147
|
case DdbForm.dict: {
|
|
1148
1148
|
const [keys, values] = value;
|
|
1149
|
-
return zip_object(keys.data(), values.data());
|
|
1149
|
+
return zip_object(keys.data(options), values.data(options));
|
|
1150
1150
|
}
|
|
1151
1151
|
case DdbForm.chart:
|
|
1152
1152
|
return value;
|
|
1153
1153
|
case DdbForm.matrix: {
|
|
1154
1154
|
const ncolumns = this.cols;
|
|
1155
1155
|
const { rows: _rows, cols: _cols, data } = value;
|
|
1156
|
-
const jsdata = converts(type, data, rows * ncolumns, le);
|
|
1156
|
+
const jsdata = converts(type, data, rows * ncolumns, le, options);
|
|
1157
1157
|
return {
|
|
1158
1158
|
type,
|
|
1159
1159
|
nrows: rows,
|
|
1160
1160
|
ncolumns,
|
|
1161
|
-
rows: _rows?.data(),
|
|
1162
|
-
columns: _cols?.data(),
|
|
1161
|
+
rows: _rows?.data(options),
|
|
1162
|
+
columns: _cols?.data(options),
|
|
1163
1163
|
data: seq(rows, i => seq(ncolumns, j => jsdata[j * rows + i]))
|
|
1164
1164
|
};
|
|
1165
1165
|
}
|
|
@@ -1742,7 +1742,7 @@ export function formati(obj, index, options = {}) {
|
|
|
1742
1742
|
}
|
|
1743
1743
|
}
|
|
1744
1744
|
}
|
|
1745
|
-
export function convert(type, value, le) {
|
|
1745
|
+
export function convert(type, value, le, { blob = 'string' } = {}) {
|
|
1746
1746
|
switch (type) {
|
|
1747
1747
|
case DdbType.void:
|
|
1748
1748
|
return value === DdbVoidType.null ? null : undefined;
|
|
@@ -1768,8 +1768,9 @@ export function convert(type, value, le) {
|
|
|
1768
1768
|
case DdbType.handle:
|
|
1769
1769
|
case DdbType.datasource:
|
|
1770
1770
|
case DdbType.resource:
|
|
1771
|
-
case DdbType.blob:
|
|
1772
1771
|
return value;
|
|
1772
|
+
case DdbType.blob:
|
|
1773
|
+
return blob === 'string' ? decode(value) : value;
|
|
1773
1774
|
case DdbType.complex:
|
|
1774
1775
|
case DdbType.point: {
|
|
1775
1776
|
const [x, y] = value;
|
|
@@ -1802,7 +1803,7 @@ export function convert(type, value, le) {
|
|
|
1802
1803
|
}
|
|
1803
1804
|
}
|
|
1804
1805
|
/** 转换一个向量到 js 原生数组 */
|
|
1805
|
-
export function converts(type, value, rows, le) {
|
|
1806
|
+
export function converts(type, value, rows, le, options) {
|
|
1806
1807
|
if (type < 64 || type >= 128)
|
|
1807
1808
|
switch (type) {
|
|
1808
1809
|
// 可以直接用下标取值再转换的类型
|
|
@@ -1832,7 +1833,7 @@ export function converts(type, value, rows, le) {
|
|
|
1832
1833
|
case DdbType.resource:
|
|
1833
1834
|
case DdbType.functiondef:
|
|
1834
1835
|
case DdbType.blob:
|
|
1835
|
-
return Array.prototype.map.call(value, (x) => convert(type, x, le));
|
|
1836
|
+
return Array.prototype.map.call(value, (x) => convert(type, x, le, options));
|
|
1836
1837
|
case DdbType.void:
|
|
1837
1838
|
return [];
|
|
1838
1839
|
case DdbType.symbol_extended: {
|
|
@@ -1845,14 +1846,12 @@ export function converts(type, value, rows, le) {
|
|
|
1845
1846
|
case DdbType.uuid:
|
|
1846
1847
|
case DdbType.ipaddr:
|
|
1847
1848
|
case DdbType.int128:
|
|
1848
|
-
return seq(rows, i => convert(type, value.subarray(16 * i, 16 * (i + 1)), le));
|
|
1849
|
+
return seq(rows, i => convert(type, value.subarray(16 * i, 16 * (i + 1)), le, options));
|
|
1849
1850
|
case DdbType.decimal32:
|
|
1850
1851
|
case DdbType.decimal64:
|
|
1851
1852
|
case DdbType.decimal128: {
|
|
1852
1853
|
const { scale, data } = value;
|
|
1853
|
-
|
|
1854
|
-
return seq(rows, i => {
|
|
1855
|
-
const x = data[i];
|
|
1854
|
+
return Array.prototype.map.call(data, (x) => {
|
|
1856
1855
|
if (is_decimal_null_value(type, x))
|
|
1857
1856
|
return '';
|
|
1858
1857
|
const s = String(x < 0 ? -x : x).padStart(scale, '0');
|
|
@@ -1860,7 +1859,7 @@ export function converts(type, value, rows, le) {
|
|
|
1860
1859
|
});
|
|
1861
1860
|
}
|
|
1862
1861
|
case DdbType.any:
|
|
1863
|
-
return value.map(x => x.data());
|
|
1862
|
+
return value.map(x => x.data(options));
|
|
1864
1863
|
default:
|
|
1865
1864
|
throw new Error(String(DdbType[type] || type) + '[]' + t(' 暂时不支持转换为 js 对象'));
|
|
1866
1865
|
}
|
|
@@ -1874,16 +1873,16 @@ export function converts(type, value, rows, le) {
|
|
|
1874
1873
|
case DdbType.decimal32:
|
|
1875
1874
|
case DdbType.decimal64:
|
|
1876
1875
|
case DdbType.decimal128:
|
|
1877
|
-
return converts(type_, { scale: value.scale, data: data.subarray(acc_len, acc_len + length) }, length, le);
|
|
1876
|
+
return converts(type_, { scale: value.scale, data: data.subarray(acc_len, acc_len + length) }, length, le, options);
|
|
1878
1877
|
case DdbType.complex:
|
|
1879
1878
|
case DdbType.point:
|
|
1880
|
-
return converts(type_, data.subarray(acc_len, acc_len + 2 * length), length, le);
|
|
1879
|
+
return converts(type_, data.subarray(acc_len, acc_len + 2 * length), length, le, options);
|
|
1881
1880
|
case DdbType.uuid:
|
|
1882
1881
|
case DdbType.int128:
|
|
1883
1882
|
case DdbType.ipaddr:
|
|
1884
|
-
return converts(type_, data.subarray(acc_len, acc_len + 16 * length), length, le);
|
|
1883
|
+
return converts(type_, data.subarray(acc_len, acc_len + 16 * length), length, le, options);
|
|
1885
1884
|
default:
|
|
1886
|
-
return converts(type_, data.subarray(acc_len, acc_len + length), length, le);
|
|
1885
|
+
return converts(type_, data.subarray(acc_len, acc_len + length), length, le, options);
|
|
1887
1886
|
}
|
|
1888
1887
|
})();
|
|
1889
1888
|
acc_len += length;
|
|
@@ -3044,8 +3043,9 @@ export class DDB {
|
|
|
3044
3043
|
rows: 0,
|
|
3045
3044
|
segments: [],
|
|
3046
3045
|
};
|
|
3047
|
-
|
|
3048
|
-
|
|
3046
|
+
// 流表推送过来的第一条数据是 schema,需要特殊处理
|
|
3047
|
+
let first = true;
|
|
3048
|
+
const { value: columns } = await this.call('publishTable', [
|
|
3049
3049
|
'localhost',
|
|
3050
3050
|
new DdbInt(0),
|
|
3051
3051
|
this.streaming.table,
|
|
@@ -3059,41 +3059,56 @@ export class DDB {
|
|
|
3059
3059
|
// 先准备好收到 websocket message 的 callback
|
|
3060
3060
|
on_more_messages: buffer => {
|
|
3061
3061
|
try {
|
|
3062
|
+
let data;
|
|
3062
3063
|
const dv = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
3063
3064
|
const i_topic_end = buffer.indexOf(0, 17);
|
|
3064
3065
|
// 首个 message 一定是 table schema, 后续消息是 column 片段组成的 any vector
|
|
3065
|
-
const
|
|
3066
|
+
const obj = DdbObj.parse(buffer.subarray(i_topic_end + 1), this.le);
|
|
3066
3067
|
// server 推数据时遇到错误会返回 string,一般格式为 error.xxx: 错误信息
|
|
3067
|
-
if (
|
|
3068
|
+
if (obj.form === DdbForm.scalar && obj.type === DdbType.string) {
|
|
3068
3069
|
this.disconnect();
|
|
3069
|
-
const value =
|
|
3070
|
+
const value = obj.value;
|
|
3070
3071
|
throw new Error(value.slice(value.indexOf(':') + 1).trim());
|
|
3071
3072
|
}
|
|
3072
|
-
if (
|
|
3073
|
-
|
|
3074
|
-
|
|
3073
|
+
if (first) {
|
|
3074
|
+
data = obj.data();
|
|
3075
|
+
data.name ||= this.streaming.table;
|
|
3076
|
+
first = false;
|
|
3075
3077
|
}
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3078
|
+
else {
|
|
3079
|
+
const { rows } = obj.value[0];
|
|
3080
|
+
const types = [];
|
|
3081
|
+
const js_cols = [];
|
|
3082
|
+
// 遍历每一列
|
|
3083
|
+
obj.value.forEach(({ type, value }) => {
|
|
3084
|
+
types.push(type);
|
|
3085
|
+
js_cols.push(converts(type, value, rows, obj.le));
|
|
3086
|
+
});
|
|
3087
|
+
data = {
|
|
3088
|
+
name: this.streaming.table || '',
|
|
3089
|
+
columns,
|
|
3090
|
+
types,
|
|
3091
|
+
data: seq(rows, i => zip_object(columns, seq(columns.length, j => js_cols[j][i])))
|
|
3092
|
+
};
|
|
3093
|
+
win.rows += rows;
|
|
3094
|
+
win.segments.push(data);
|
|
3095
|
+
if (win.rows >= winsize * 2 && win.segments.length >= 2) {
|
|
3096
|
+
let winsize_ = 0;
|
|
3097
|
+
let i = win.segments.length - 1;
|
|
3098
|
+
// 往前移动至首个累计 winsize_ 超过 winsize 的位置
|
|
3099
|
+
for (; winsize_ < winsize; i--)
|
|
3100
|
+
winsize_ += win.segments[i].data.length;
|
|
3101
|
+
win.segments = win.segments.slice(i);
|
|
3102
|
+
win.offset += win.rows - winsize_;
|
|
3103
|
+
win.rows = winsize_;
|
|
3104
|
+
}
|
|
3088
3105
|
}
|
|
3089
3106
|
this.streaming.handler({
|
|
3090
3107
|
...this.streaming,
|
|
3091
3108
|
id: dv.getBigInt64(9, this.le),
|
|
3092
3109
|
time: dv.getBigInt64(1, this.le),
|
|
3093
|
-
rows,
|
|
3094
3110
|
topic: this.dec.decode(buffer.subarray(17, i_topic_end)),
|
|
3095
|
-
|
|
3096
|
-
schema,
|
|
3111
|
+
obj,
|
|
3097
3112
|
data,
|
|
3098
3113
|
window: win,
|
|
3099
3114
|
});
|
|
@@ -3104,9 +3119,9 @@ export class DDB {
|
|
|
3104
3119
|
}
|
|
3105
3120
|
}
|
|
3106
3121
|
});
|
|
3107
|
-
console.log(t('订阅流表成功') + ',
|
|
3122
|
+
console.log(t('订阅流表成功') + ', columns:',
|
|
3108
3123
|
// string[3](['time', 'stock', 'price'])
|
|
3109
|
-
|
|
3124
|
+
columns);
|
|
3110
3125
|
}
|
|
3111
3126
|
}
|
|
3112
3127
|
export class BigInt128Array {
|
|
@@ -3180,6 +3195,14 @@ export class BigInt128Array {
|
|
|
3180
3195
|
return true;
|
|
3181
3196
|
}
|
|
3182
3197
|
return Reflect.set(target, key, value);
|
|
3198
|
+
},
|
|
3199
|
+
has(target, key) {
|
|
3200
|
+
if (typeof key === 'string') {
|
|
3201
|
+
const index = Number(key);
|
|
3202
|
+
if (Number.isInteger(index) && index >= 0 && index < target.length)
|
|
3203
|
+
return true;
|
|
3204
|
+
}
|
|
3205
|
+
return Reflect.has(target, key);
|
|
3183
3206
|
}
|
|
3184
3207
|
});
|
|
3185
3208
|
}
|