dolphindb 2.0.801 → 2.0.900
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 +80 -5
- package/README.zh.md +83 -9
- package/browser.d.ts +22 -25
- package/browser.js +155 -133
- package/browser.js.map +1 -1
- package/docs.en.json +492 -49
- package/docs.zh.json +433 -100
- package/index.d.ts +22 -25
- package/index.js +151 -130
- package/index.js.map +1 -1
- package/language.d.ts +5 -5
- package/language.js +3 -1
- package/language.js.map +1 -1
- package/package.json +7 -7
package/index.d.ts
CHANGED
|
@@ -126,12 +126,15 @@ export interface DdbArrayVectorBlock {
|
|
|
126
126
|
lengths: Uint8Array | Uint16Array | Uint32Array;
|
|
127
127
|
data: Int8Array | Int16Array | Int32Array | Float32Array | Float64Array | BigInt64Array;
|
|
128
128
|
}
|
|
129
|
+
export type DdbArrayVectorValue = DdbArrayVectorBlock[] & /* decimal32, decimal64 会有这个属性 */ {
|
|
130
|
+
scale?: number;
|
|
131
|
+
};
|
|
129
132
|
export interface DdbMatrixValue {
|
|
130
133
|
rows: DdbVectorObj;
|
|
131
134
|
cols: DdbVectorObj;
|
|
132
135
|
data: DdbVectorValue;
|
|
133
136
|
}
|
|
134
|
-
export
|
|
137
|
+
export type DdbDictValue = [DdbVectorObj, DdbVectorObj];
|
|
135
138
|
export declare enum DdbChartType {
|
|
136
139
|
area = 0,
|
|
137
140
|
bar = 1,
|
|
@@ -166,24 +169,24 @@ export interface DdbChartValue {
|
|
|
166
169
|
};
|
|
167
170
|
data: DdbMatrixObj;
|
|
168
171
|
}
|
|
169
|
-
export
|
|
172
|
+
export type DdbScalarValue = null | boolean | number | bigint | string | Uint8Array | // uuid, ipaddr, int128, blob
|
|
170
173
|
[
|
|
171
174
|
number,
|
|
172
175
|
number
|
|
173
176
|
] | // complex, point
|
|
174
177
|
DdbFunctionDefValue | DdbDurationValue | DdbDecimal32Value | DdbDecimal64Value;
|
|
175
|
-
export
|
|
178
|
+
export type DdbVectorValue = Uint8Array | Int8Array | Int16Array | Int32Array | Float32Array | Float64Array | BigInt64Array | string[] | // string[]
|
|
176
179
|
Uint8Array[] | // blob
|
|
177
180
|
DdbObj[] | // any
|
|
178
|
-
DdbSymbolExtendedValue |
|
|
179
|
-
export
|
|
180
|
-
export
|
|
181
|
-
export
|
|
182
|
-
export
|
|
183
|
-
export
|
|
184
|
-
export
|
|
185
|
-
export
|
|
186
|
-
export
|
|
181
|
+
DdbSymbolExtendedValue | DdbArrayVectorValue | DdbDecimal32VectorValue | DdbDecimal64VectorValue;
|
|
182
|
+
export type DdbValue = DdbScalarValue | DdbVectorValue | DdbMatrixValue | DdbDictValue | DdbChartValue;
|
|
183
|
+
export type DdbVectorObj = DdbObj<DdbVectorValue>;
|
|
184
|
+
export type DdbVectorAnyObj = DdbObj<DdbObj[]>;
|
|
185
|
+
export type DdbVectorStringObj = DdbObj<string[]>;
|
|
186
|
+
export type DdbTableObj = DdbObj<DdbVectorObj[]>;
|
|
187
|
+
export type DdbDictObj = DdbObj<[DdbVectorObj, DdbVectorObj]>;
|
|
188
|
+
export type DdbMatrixObj = DdbObj<DdbMatrixValue>;
|
|
189
|
+
export type DdbChartObj = DdbObj<DdbChartValue>;
|
|
187
190
|
export declare const nulls: {
|
|
188
191
|
readonly int8: -128;
|
|
189
192
|
readonly int16: -32768;
|
|
@@ -194,14 +197,6 @@ export declare const nulls: {
|
|
|
194
197
|
readonly double: number;
|
|
195
198
|
readonly bytes16: Uint8Array;
|
|
196
199
|
};
|
|
197
|
-
export declare const timezone_offset: number;
|
|
198
|
-
export declare enum StreamingStatusCode {
|
|
199
|
-
ok = 0,
|
|
200
|
-
connection_existed = 1,
|
|
201
|
-
not_leader = 2,
|
|
202
|
-
other = 3,
|
|
203
|
-
error = 4
|
|
204
|
-
}
|
|
205
200
|
/** Can represent data types in all DolphinDB databases */
|
|
206
201
|
export declare class DdbObj<TValue extends DdbValue = DdbValue> {
|
|
207
202
|
static dec: TextDecoder;
|
|
@@ -425,10 +420,10 @@ export interface StreamingData extends StreamingParams {
|
|
|
425
420
|
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 `/`
|
|
426
421
|
*/
|
|
427
422
|
topic: string;
|
|
428
|
-
/** The schema of the flow table, the type is table, there is no data in the column vector (rows === 0), only the column name and type */
|
|
429
|
-
schema: DdbTableObj;
|
|
430
423
|
/** 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 */
|
|
431
424
|
data: DdbObj<DdbVectorObj[]>;
|
|
425
|
+
/** Number of new streaming data rows */
|
|
426
|
+
rows: number;
|
|
432
427
|
window: {
|
|
433
428
|
/** The establishment of the connection starts offset = 0, and gradually increases as the window moves */
|
|
434
429
|
offset: number;
|
|
@@ -437,8 +432,10 @@ export interface StreamingData extends StreamingParams {
|
|
|
437
432
|
/** An array of data received each time */
|
|
438
433
|
segments: DdbObj<DdbVectorObj[]>[];
|
|
439
434
|
};
|
|
435
|
+
/** After successfully subscribed, if the subsequently pushed message is parsed incorrectly, the error will be set and the handler will be called. */
|
|
436
|
+
error?: Error;
|
|
440
437
|
}
|
|
441
|
-
export declare const winsize:
|
|
438
|
+
export declare const winsize: 100000;
|
|
442
439
|
export declare class ConnectionError extends Error {
|
|
443
440
|
ddb: DDB;
|
|
444
441
|
constructor(ddb: DDB);
|
|
@@ -607,7 +604,7 @@ export declare class DDB {
|
|
|
607
604
|
/** 解析服务端响应报文,返回去掉 header 的 data buf */
|
|
608
605
|
parse_message(buf: Uint8Array, parse_object?: boolean): DdbMessage;
|
|
609
606
|
/** Internal stream subscription method */
|
|
610
|
-
subscribe(): Promise<
|
|
607
|
+
subscribe(): Promise<StreamingData>;
|
|
611
608
|
}
|
|
612
609
|
export interface DdbMessageListener {
|
|
613
610
|
(message: DdbMessage, _this: DDB): any;
|
|
@@ -624,4 +621,4 @@ export interface DdbErrorMessage {
|
|
|
624
621
|
type: 'error';
|
|
625
622
|
data: Error;
|
|
626
623
|
}
|
|
627
|
-
export
|
|
624
|
+
export type DdbMessage = DdbPrintMessage | DdbObjectMessage | DdbErrorMessage;
|
package/index.js
CHANGED
|
@@ -117,15 +117,6 @@ export const nulls = {
|
|
|
117
117
|
double: -Number.MAX_VALUE,
|
|
118
118
|
bytes16: Uint8Array.from(new Array(16).fill(0))
|
|
119
119
|
};
|
|
120
|
-
export const timezone_offset = 1000 * 60 * new Date().getTimezoneOffset();
|
|
121
|
-
export var StreamingStatusCode;
|
|
122
|
-
(function (StreamingStatusCode) {
|
|
123
|
-
StreamingStatusCode[StreamingStatusCode["ok"] = 0] = "ok";
|
|
124
|
-
StreamingStatusCode[StreamingStatusCode["connection_existed"] = 1] = "connection_existed";
|
|
125
|
-
StreamingStatusCode[StreamingStatusCode["not_leader"] = 2] = "not_leader";
|
|
126
|
-
StreamingStatusCode[StreamingStatusCode["other"] = 3] = "other";
|
|
127
|
-
StreamingStatusCode[StreamingStatusCode["error"] = 4] = "error";
|
|
128
|
-
})(StreamingStatusCode = StreamingStatusCode || (StreamingStatusCode = {}));
|
|
129
120
|
/** Can represent data types in all DolphinDB databases */
|
|
130
121
|
export class DdbObj {
|
|
131
122
|
static dec = new TextDecoder('utf-8');
|
|
@@ -521,8 +512,37 @@ export class DdbObj {
|
|
|
521
512
|
// 00 reserved
|
|
522
513
|
// 70 11 01 00 block.lengths = [70000 (0x00011170)]
|
|
523
514
|
// 01 00 00 00 02 00 00 00 ... 279992 more bytes> block.data
|
|
515
|
+
// decimal array vector
|
|
516
|
+
// a = array(DECIMAL32(2)[], 0, 10)
|
|
517
|
+
// append!(a, [
|
|
518
|
+
// [1, 2, 3],
|
|
519
|
+
// [4, 5],
|
|
520
|
+
// [6, 7, 8],
|
|
521
|
+
// [9, 10]
|
|
522
|
+
// ])
|
|
523
|
+
// print(a)
|
|
524
|
+
// a
|
|
525
|
+
// [[1.00,2.00,3.00],[4.00,5.00],[6.00,7.00,8.00],[9.00,10.00]]
|
|
526
|
+
// <Buffer 65 01 type = 101 = 64 + 37 (decimal32) , form = vector
|
|
527
|
+
// 04 00 00 00 0a 00 00 00 rows = 4, cols = 10
|
|
528
|
+
// scale (只有 decimal32 才有)
|
|
529
|
+
// 02 00 00 00 scale = 2
|
|
530
|
+
// block 0
|
|
531
|
+
// 04 00 block.rows = 4
|
|
532
|
+
// 01 block.unit = 1
|
|
533
|
+
// 00 reserved
|
|
534
|
+
// 03 02 03 02 block.lengths = [3, 2, 3, 2]
|
|
535
|
+
// 64 00 00 00 c8 00 00 00 2c 01 00 00 90 01 00 00 f4 01 00 00 58 02 00 00 bc 02 00 00 ... 12 more bytes> [100, 200, 300, ...]
|
|
536
|
+
// block 1
|
|
537
|
+
// ...
|
|
538
|
+
const type_ = type - 64;
|
|
524
539
|
const cols = dv.getUint32(4, le);
|
|
525
540
|
let blocks = [];
|
|
541
|
+
// decimal32/64 会在所有 blocks 之前多一个 scale
|
|
542
|
+
if (type_ === DdbType.decimal32 || type_ === DdbType.decimal64) {
|
|
543
|
+
blocks.scale = dv.getInt32(i_items_start, le);
|
|
544
|
+
i_items_start += 4;
|
|
545
|
+
}
|
|
526
546
|
let i_block_start = i_items_start;
|
|
527
547
|
// 解析一个 block
|
|
528
548
|
for (let i_row = 0; i_row < rows;) {
|
|
@@ -551,7 +571,20 @@ export class DdbObj {
|
|
|
551
571
|
let total_length = 0;
|
|
552
572
|
for (const x of lengths)
|
|
553
573
|
total_length += x;
|
|
554
|
-
|
|
574
|
+
let len_items;
|
|
575
|
+
let data;
|
|
576
|
+
switch (type_) {
|
|
577
|
+
case DdbType.decimal32:
|
|
578
|
+
len_items = total_length * 4;
|
|
579
|
+
data = new Int32Array(buf.buffer.slice(buf.byteOffset + i_data_start, buf.byteOffset + i_data_start + len_items));
|
|
580
|
+
break;
|
|
581
|
+
case DdbType.decimal64:
|
|
582
|
+
len_items = total_length * 8;
|
|
583
|
+
data = new BigInt64Array(buf.buffer.slice(buf.byteOffset + i_data_start, buf.byteOffset + i_data_start + len_items));
|
|
584
|
+
break;
|
|
585
|
+
default:
|
|
586
|
+
[len_items, data] = this.parse_vector_items(buf.subarray(i_data_start), le, type - 64, total_length);
|
|
587
|
+
}
|
|
555
588
|
blocks.push({
|
|
556
589
|
unit,
|
|
557
590
|
rows,
|
|
@@ -866,6 +899,10 @@ export class DdbObj {
|
|
|
866
899
|
if (form === DdbForm.vector && 64 <= type && type < 128)
|
|
867
900
|
return [
|
|
868
901
|
Uint32Array.of(this.rows, this.cols),
|
|
902
|
+
...(type - 64 === DdbType.decimal32 || type - 64 === DdbType.decimal64) ?
|
|
903
|
+
[Int32Array.of(this.value.scale)]
|
|
904
|
+
:
|
|
905
|
+
[],
|
|
869
906
|
...this.value.map(block => ([
|
|
870
907
|
Uint16Array.of(block.rows),
|
|
871
908
|
Uint8Array.of(block.unit, 0),
|
|
@@ -924,10 +961,7 @@ export class DdbObj {
|
|
|
924
961
|
})();
|
|
925
962
|
if (!body)
|
|
926
963
|
return new Uint8Array(0);
|
|
927
|
-
return concat([
|
|
928
|
-
header,
|
|
929
|
-
...body
|
|
930
|
-
]);
|
|
964
|
+
return concat([header, ...body]);
|
|
931
965
|
}
|
|
932
966
|
static pack_vector_body(value, type, length) {
|
|
933
967
|
switch (type) {
|
|
@@ -1054,7 +1088,18 @@ export class DdbObj {
|
|
|
1054
1088
|
for (const length of lengths) {
|
|
1055
1089
|
let _items = new Array(Math.min(limit, length));
|
|
1056
1090
|
for (let i = 0; i < _items.length; i++)
|
|
1057
|
-
|
|
1091
|
+
if (_type === DdbType.decimal32 || _type === DdbType.decimal64) {
|
|
1092
|
+
const x = data[acc_len + i];
|
|
1093
|
+
if (x === nulls.int64 && _type === DdbType.decimal64 ||
|
|
1094
|
+
x === nulls.int32 && _type === DdbType.decimal32)
|
|
1095
|
+
return '';
|
|
1096
|
+
const { scale } = this.value;
|
|
1097
|
+
const s = String(x < 0 ? -x : x).padStart(scale, '0');
|
|
1098
|
+
const str = (x < 0 ? '-' : '') + (scale ? `${s.slice(0, -scale) || '0'}.${s.slice(-scale)}` : s);
|
|
1099
|
+
_items[i] = options.colors ? str.green : str;
|
|
1100
|
+
}
|
|
1101
|
+
else
|
|
1102
|
+
_items[i] = format(_type, data[acc_len + i], this.le, options);
|
|
1058
1103
|
items[i_items++] = format_array(_items, length > limit);
|
|
1059
1104
|
acc_len += length;
|
|
1060
1105
|
}
|
|
@@ -1423,6 +1468,7 @@ export function format(type, value, le, options = {}) {
|
|
|
1423
1468
|
}
|
|
1424
1469
|
/** formatted vector, the index-th item in the collection is a string, a null value returns a 'null' string */
|
|
1425
1470
|
export function formati(obj, index, options = {}) {
|
|
1471
|
+
assert(index < obj.rows, 'index < obj.rows');
|
|
1426
1472
|
if (64 <= obj.type && obj.type < 128) { // array vector
|
|
1427
1473
|
// 因为 array vector 目前只支持:Logical, Integral(不包括 INT128, COMPRESS 类型), Floating, Temporal
|
|
1428
1474
|
// 都对应 TypedArray 中的一格,所以 lengths.length 等于 block 中的 row 的个数
|
|
@@ -1450,7 +1496,18 @@ export function formati(obj, index, options = {}) {
|
|
|
1450
1496
|
const limit = 10;
|
|
1451
1497
|
let items = new Array(Math.min(limit, length));
|
|
1452
1498
|
for (let i = 0; i < items.length; i++)
|
|
1453
|
-
|
|
1499
|
+
if (_type === DdbType.decimal32 || _type === DdbType.decimal64) {
|
|
1500
|
+
const x = data[acc_len + i];
|
|
1501
|
+
if (x === nulls.int64 && _type === DdbType.decimal64 ||
|
|
1502
|
+
x === nulls.int32 && _type === DdbType.decimal32)
|
|
1503
|
+
return '';
|
|
1504
|
+
const { scale } = obj.value;
|
|
1505
|
+
const s = String(x < 0 ? -x : x).padStart(scale, '0');
|
|
1506
|
+
const str = (x < 0 ? '-' : '') + (scale ? `${s.slice(0, -scale) || '0'}.${s.slice(-scale)}` : s);
|
|
1507
|
+
items[i] = options.colors ? str.green : str;
|
|
1508
|
+
}
|
|
1509
|
+
else
|
|
1510
|
+
items[i] = format(_type, data[acc_len + i], obj.le, options);
|
|
1454
1511
|
return (items.join(', ') + (length > limit ? ', ...' : '')).bracket('square');
|
|
1455
1512
|
}
|
|
1456
1513
|
}
|
|
@@ -1786,10 +1843,14 @@ export class DdbTable extends DdbObj {
|
|
|
1786
1843
|
}
|
|
1787
1844
|
}
|
|
1788
1845
|
export function date2ms(date) {
|
|
1846
|
+
// 将 server 的本地时间 (以 ms 为单位,1970.01.01 00:00:00 作为零点) 当成是客户端这里的本地的时间,然后根据本地的时区信息转换为 utc 时间
|
|
1847
|
+
// 本地的时区与实际的时间值相关,timezone offset 可能会受到夏令时 (DST) 的影响
|
|
1848
|
+
// 得到的 utc 毫秒数交给 js date 或者 dayjs 去格式化
|
|
1849
|
+
const ms = 1000 * 3600 * 24 * date;
|
|
1789
1850
|
return (date === null || date === nulls.int32) ?
|
|
1790
1851
|
null
|
|
1791
1852
|
:
|
|
1792
|
-
|
|
1853
|
+
1000 * 60 * new Date(ms).getTimezoneOffset() + ms;
|
|
1793
1854
|
}
|
|
1794
1855
|
export function date2str(date, format = 'YYYY.MM.DD') {
|
|
1795
1856
|
return (date === null || date === nulls.int32) ?
|
|
@@ -1816,7 +1877,7 @@ export function time2ms(time) {
|
|
|
1816
1877
|
return (time === null || time === nulls.int32) ?
|
|
1817
1878
|
null
|
|
1818
1879
|
:
|
|
1819
|
-
|
|
1880
|
+
1000 * 60 * new Date(time).getTimezoneOffset() + time;
|
|
1820
1881
|
}
|
|
1821
1882
|
export function time2str(time, format = 'HH:mm:ss.SSS') {
|
|
1822
1883
|
return (time === null || time === nulls.int32) ?
|
|
@@ -1825,10 +1886,11 @@ export function time2str(time, format = 'HH:mm:ss.SSS') {
|
|
|
1825
1886
|
dayjs(time2ms(time)).format(format);
|
|
1826
1887
|
}
|
|
1827
1888
|
export function minute2ms(minute) {
|
|
1889
|
+
const ms = 60 * 1000 * minute;
|
|
1828
1890
|
return (minute === null || minute === nulls.int32) ?
|
|
1829
1891
|
null
|
|
1830
1892
|
:
|
|
1831
|
-
|
|
1893
|
+
1000 * 60 * new Date(ms).getTimezoneOffset() + ms;
|
|
1832
1894
|
}
|
|
1833
1895
|
export function minute2str(minute, format = 'HH:mm[m]') {
|
|
1834
1896
|
return (minute === null || minute === nulls.int32) ?
|
|
@@ -1837,10 +1899,11 @@ export function minute2str(minute, format = 'HH:mm[m]') {
|
|
|
1837
1899
|
dayjs(minute2ms(minute)).format(format);
|
|
1838
1900
|
}
|
|
1839
1901
|
export function second2ms(second) {
|
|
1902
|
+
const ms = 1000 * second;
|
|
1840
1903
|
return (second === null || second === nulls.int32) ?
|
|
1841
1904
|
null
|
|
1842
1905
|
:
|
|
1843
|
-
|
|
1906
|
+
1000 * 60 * new Date(ms).getTimezoneOffset() + ms;
|
|
1844
1907
|
}
|
|
1845
1908
|
export function second2str(second, format = 'HH:mm:ss') {
|
|
1846
1909
|
return (second === null || second === nulls.int32) ?
|
|
@@ -1849,10 +1912,11 @@ export function second2str(second, format = 'HH:mm:ss') {
|
|
|
1849
1912
|
dayjs(second2ms(second)).format(format);
|
|
1850
1913
|
}
|
|
1851
1914
|
export function datetime2ms(datetime) {
|
|
1915
|
+
const ms = 1000 * datetime;
|
|
1852
1916
|
return (datetime === null || datetime === nulls.int32) ?
|
|
1853
1917
|
null
|
|
1854
1918
|
:
|
|
1855
|
-
|
|
1919
|
+
1000 * 60 * new Date(ms).getTimezoneOffset() + ms;
|
|
1856
1920
|
}
|
|
1857
1921
|
export function datetime2str(datetime, format = 'YYYY.MM.DD HH:mm:ss') {
|
|
1858
1922
|
return (datetime === null || datetime === nulls.int32) ?
|
|
@@ -1861,10 +1925,11 @@ export function datetime2str(datetime, format = 'YYYY.MM.DD HH:mm:ss') {
|
|
|
1861
1925
|
dayjs(datetime2ms(datetime)).format(format);
|
|
1862
1926
|
}
|
|
1863
1927
|
export function timestamp2ms(timestamp) {
|
|
1928
|
+
const ms = Number(timestamp);
|
|
1864
1929
|
return (timestamp === null || timestamp === nulls.int64) ?
|
|
1865
1930
|
null
|
|
1866
1931
|
:
|
|
1867
|
-
|
|
1932
|
+
1000 * 60 * new Date(ms).getTimezoneOffset() + ms;
|
|
1868
1933
|
}
|
|
1869
1934
|
/** format timestamp (bigint) to string
|
|
1870
1935
|
- timestamp: bigint value
|
|
@@ -1879,16 +1944,18 @@ export function timestamp2str(timestamp, format = 'YYYY.MM.DD HH:mm:ss.SSS') {
|
|
|
1879
1944
|
dayjs(timestamp2ms(timestamp)).format(format);
|
|
1880
1945
|
}
|
|
1881
1946
|
export function datehour2ms(datehour) {
|
|
1947
|
+
const ms = 1000 * 3600 * datehour;
|
|
1882
1948
|
return (datehour === null || datehour === nulls.int32) ?
|
|
1883
1949
|
null
|
|
1884
1950
|
:
|
|
1885
|
-
|
|
1951
|
+
1000 * 60 * new Date(ms).getTimezoneOffset() + ms;
|
|
1886
1952
|
}
|
|
1887
1953
|
export function datehour2str(datehour, format = 'YYYY.MM.DDTHH') {
|
|
1954
|
+
const ms = 1000 * 3600 * datehour;
|
|
1888
1955
|
return (datehour === null || datehour === nulls.int32) ?
|
|
1889
1956
|
'null'
|
|
1890
1957
|
:
|
|
1891
|
-
dayjs(
|
|
1958
|
+
dayjs(1000 * 60 * new Date(ms).getTimezoneOffset() + ms).format(format);
|
|
1892
1959
|
}
|
|
1893
1960
|
/** parse timestamp string to bigint value
|
|
1894
1961
|
- str: timestamp string, If it is an empty string or 'null', it will return the corresponding empty value (nulls.int64)
|
|
@@ -1899,9 +1966,10 @@ export function datehour2str(datehour, format = 'YYYY.MM.DDTHH') {
|
|
|
1899
1966
|
export function str2timestamp(str, format = 'YYYY.MM.DD HH:mm:ss.SSS') {
|
|
1900
1967
|
if (!str || str === 'null')
|
|
1901
1968
|
return nulls.int64;
|
|
1902
|
-
assert('The length of the timestamp string must be equal to the length of the format string');
|
|
1903
|
-
|
|
1904
|
-
|
|
1969
|
+
assert(str.length === format.length, 'The length of the timestamp string must be equal to the length of the format string');
|
|
1970
|
+
const ms = dayjs(str, format).valueOf();
|
|
1971
|
+
return BigInt(-(1000 * 60 * new Date(ms).getTimezoneOffset()) +
|
|
1972
|
+
ms);
|
|
1905
1973
|
}
|
|
1906
1974
|
export function nanotime2ns(nanotime) {
|
|
1907
1975
|
return nanotimestamp2ns(nanotime);
|
|
@@ -1916,15 +1984,17 @@ export function nanotime2str(nanotime, format = 'HH:mm:ss.SSSSSSSSS') {
|
|
|
1916
1984
|
const i_second_end = i_second_start + 2;
|
|
1917
1985
|
const i_nanosecond_start = format.indexOf('SSSSSSSSS', i_second_end);
|
|
1918
1986
|
assert(i_nanosecond_start !== -1, 'Format string must contain nanosecond format (SSSSSSSSS)');
|
|
1919
|
-
|
|
1987
|
+
const ms = Number(nanotime) / 1000000;
|
|
1988
|
+
return (dayjs(1000 * 60 * new Date(ms).getTimezoneOffset() + ms).format(format.slice(0, i_second_end)) +
|
|
1920
1989
|
format.slice(i_second_end, i_nanosecond_start) +
|
|
1921
1990
|
String(nanotime % 1000000000n).padStart(9, '0'));
|
|
1922
1991
|
}
|
|
1923
1992
|
export function nanotimestamp2ns(nanotimestamp) {
|
|
1993
|
+
const ms = Number(nanotimestamp / 1000000n);
|
|
1924
1994
|
return (nanotimestamp === null || nanotimestamp === nulls.int64) ?
|
|
1925
1995
|
null
|
|
1926
1996
|
:
|
|
1927
|
-
BigInt(
|
|
1997
|
+
BigInt(1000 * 60 * new Date(ms).getTimezoneOffset()) * 1000000n + nanotimestamp;
|
|
1928
1998
|
}
|
|
1929
1999
|
/** format nanotimestamp value (bigint) to string
|
|
1930
2000
|
- nanotimestamp: bigint value
|
|
@@ -1949,7 +2019,8 @@ export function nanotimestamp2str(nanotimestamp, format = 'YYYY.MM.DD HH:mm:ss.S
|
|
|
1949
2019
|
assert(i_nanosecond_start !== -1, 'Format string must contain nanosecond format (SSSSSSSSS)');
|
|
1950
2020
|
const remainder = nanotimestamp % 1000000000n;
|
|
1951
2021
|
const borrow = remainder < 0n;
|
|
1952
|
-
|
|
2022
|
+
const ms = Number(nanotimestamp / 1000000n);
|
|
2023
|
+
return (dayjs(1000 * 60 * new Date(ms).getTimezoneOffset() +
|
|
1953
2024
|
// 去掉 9 位的纳秒部分,转化为毫秒
|
|
1954
2025
|
Number((nanotimestamp - remainder + (borrow ? -1000000000n : 0n)) / 1000000n)).format(format.slice(0, i_second_end)) +
|
|
1955
2026
|
format.slice(i_second_end, i_nanosecond_start) +
|
|
@@ -1974,8 +2045,9 @@ export function str2nanotimestamp(str, format = 'YYYY.MM.DD HH:mm:ss.SSSSSSSSS')
|
|
|
1974
2045
|
const i_second_end = i_second_start + 2;
|
|
1975
2046
|
const i_nanosecond_start = format.indexOf('SSSSSSSSS', i_second_end);
|
|
1976
2047
|
assert(i_nanosecond_start !== -1, 'Format string must contain nanosecond format (SSSSSSSSS)');
|
|
1977
|
-
|
|
1978
|
-
|
|
2048
|
+
const ms = dayjs(str.slice(0, i_second_end), format.slice(0, i_second_end)).valueOf();
|
|
2049
|
+
return (BigInt(-(1000 * 60 * new Date(ms).getTimezoneOffset()) +
|
|
2050
|
+
ms) * 1000000n
|
|
1979
2051
|
+
|
|
1980
2052
|
BigInt(str.slice(i_nanosecond_start, i_nanosecond_start + 9)));
|
|
1981
2053
|
}
|
|
@@ -2001,7 +2073,7 @@ export function int1282str(buffer, le = true) {
|
|
|
2001
2073
|
return [...buf].map(x => x.toString(16)
|
|
2002
2074
|
.padStart(2, '0')).join('');
|
|
2003
2075
|
}
|
|
2004
|
-
export const winsize =
|
|
2076
|
+
export const winsize = 10_0000;
|
|
2005
2077
|
export class ConnectionError extends Error {
|
|
2006
2078
|
ddb;
|
|
2007
2079
|
constructor(ddb) {
|
|
@@ -2374,8 +2446,9 @@ export class DDB {
|
|
|
2374
2446
|
async cancel() {
|
|
2375
2447
|
let ddb = new DDB(this.url, this);
|
|
2376
2448
|
try {
|
|
2449
|
+
// 因为是新建的连接,而且执行完脚本之后马上就关闭了,所以不用考虑变量泄漏的问题
|
|
2377
2450
|
await ddb.eval(`jobs = exec rootJobId from getConsoleJobs() where sessionId = ${this.sid}\n` +
|
|
2378
|
-
'if (size(jobs))\n' +
|
|
2451
|
+
(this.python ? 'if size(jobs):\n' : 'if (size(jobs))\n') +
|
|
2379
2452
|
' cancelConsoleJob(jobs)\n', { urgent: true });
|
|
2380
2453
|
}
|
|
2381
2454
|
finally {
|
|
@@ -2436,110 +2509,58 @@ export class DDB {
|
|
|
2436
2509
|
}
|
|
2437
2510
|
/** Internal stream subscription method */
|
|
2438
2511
|
async subscribe() {
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
// todo: 还有用吗?需要获取客户端 IP 吗
|
|
2512
|
+
await this.rpc('connect', {});
|
|
2513
|
+
if (this.autologin)
|
|
2514
|
+
await this.call('login', [this.username, this.password]);
|
|
2515
|
+
console.log('Subscribed to streaming table, colnames:',
|
|
2516
|
+
// string[3](['time', 'stock', 'price'])
|
|
2517
|
+
this.streaming.colnames = (await this.call('publishTable', [
|
|
2446
2518
|
'localhost',
|
|
2447
|
-
// todo: 端口还有用吗?
|
|
2448
2519
|
new DdbInt(0),
|
|
2449
2520
|
this.streaming.table,
|
|
2450
2521
|
(this.streaming.action ||= `api_js_${new Date().getTime()}`),
|
|
2451
2522
|
// new DdbInt(-1), // offset
|
|
2452
2523
|
// filter
|
|
2453
2524
|
// allow exists
|
|
2454
|
-
]);
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
reject(error);
|
|
2485
|
-
}
|
|
2486
|
-
}
|
|
2487
|
-
else {
|
|
2488
|
-
try {
|
|
2489
|
-
const dv = new DataView(buffer);
|
|
2490
|
-
const buf = new Uint8Array(buffer);
|
|
2491
|
-
let { streaming } = this;
|
|
2492
|
-
streaming.time = dv.getBigInt64(1, this.le);
|
|
2493
|
-
streaming.id = dv.getBigInt64(9, this.le);
|
|
2494
|
-
const i_topic_end = buf.indexOf(0, 17);
|
|
2495
|
-
streaming.topic = this.dec.decode(buf.subarray(17, i_topic_end));
|
|
2496
|
-
if (second) {
|
|
2497
|
-
second = false;
|
|
2498
|
-
// 是 table
|
|
2499
|
-
streaming.schema = DdbObj.parse(buf.subarray(i_topic_end + 1), this.le);
|
|
2500
|
-
console.log('Received streaming table schema:', streaming.schema);
|
|
2501
|
-
streaming.window = {
|
|
2502
|
-
offset: 0,
|
|
2503
|
-
rows: 0,
|
|
2504
|
-
segments: [],
|
|
2505
|
-
};
|
|
2506
|
-
assert(streaming.schema.rows === 0, 'schema.rows === 0');
|
|
2507
|
-
resolve(streaming.schema);
|
|
2508
|
-
}
|
|
2509
|
-
else {
|
|
2510
|
-
// 是 column 片段组成的 any vector
|
|
2511
|
-
const data = streaming.data = DdbObj.parse(buf.subarray(i_topic_end + 1), this.le);
|
|
2512
|
-
let { window: win } = streaming;
|
|
2513
|
-
win.rows += data.value[0].rows;
|
|
2514
|
-
win.segments.push(data);
|
|
2515
|
-
if (win.rows >= winsize * 2 && win.segments.length >= 2) {
|
|
2516
|
-
let winsize_ = 0;
|
|
2517
|
-
let i = win.segments.length - 1;
|
|
2518
|
-
// 往前移动至首个累计 winsize_ 超过 winsize 的位置
|
|
2519
|
-
for (; winsize_ < winsize; i--)
|
|
2520
|
-
winsize_ += win.segments[i].rows;
|
|
2521
|
-
win.segments = win.segments.slice(i);
|
|
2522
|
-
win.offset += win.rows - winsize_;
|
|
2523
|
-
win.rows = winsize_;
|
|
2524
|
-
console.log('exceeds winsize, shrink window.segments', win);
|
|
2525
|
-
}
|
|
2526
|
-
streaming.handler(streaming);
|
|
2527
|
-
}
|
|
2528
|
-
}
|
|
2529
|
-
catch (error) {
|
|
2530
|
-
reject(error);
|
|
2531
|
-
}
|
|
2525
|
+
])).value);
|
|
2526
|
+
this.streaming.window = {
|
|
2527
|
+
offset: 0,
|
|
2528
|
+
rows: 0,
|
|
2529
|
+
segments: [],
|
|
2530
|
+
};
|
|
2531
|
+
// 先准备好收到 websocket message 的 callback
|
|
2532
|
+
this.on_message = ({ data: buffer }) => {
|
|
2533
|
+
let { streaming } = this;
|
|
2534
|
+
try {
|
|
2535
|
+
const dv = new DataView(buffer);
|
|
2536
|
+
const buf = new Uint8Array(buffer);
|
|
2537
|
+
streaming.time = dv.getBigInt64(1, this.le);
|
|
2538
|
+
streaming.id = dv.getBigInt64(9, this.le);
|
|
2539
|
+
const i_topic_end = buf.indexOf(0, 17);
|
|
2540
|
+
streaming.topic = this.dec.decode(buf.subarray(17, i_topic_end));
|
|
2541
|
+
// 是 column 片段组成的 any vector
|
|
2542
|
+
const data = streaming.data = DdbObj.parse(buf.subarray(i_topic_end + 1), this.le);
|
|
2543
|
+
let { window: win } = streaming;
|
|
2544
|
+
win.rows += streaming.rows = data.value[0].rows;
|
|
2545
|
+
win.segments.push(data);
|
|
2546
|
+
if (win.rows >= winsize * 2 && win.segments.length >= 2) {
|
|
2547
|
+
let winsize_ = 0;
|
|
2548
|
+
let i = win.segments.length - 1;
|
|
2549
|
+
// 往前移动至首个累计 winsize_ 超过 winsize 的位置
|
|
2550
|
+
for (; winsize_ < winsize; i--)
|
|
2551
|
+
winsize_ += win.segments[i].value[0].rows;
|
|
2552
|
+
win.segments = win.segments.slice(i);
|
|
2553
|
+
win.offset += win.rows - winsize_;
|
|
2554
|
+
win.rows = winsize_;
|
|
2532
2555
|
}
|
|
2533
|
-
}
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
]));
|
|
2542
|
-
});
|
|
2556
|
+
}
|
|
2557
|
+
catch (error) {
|
|
2558
|
+
// 将 error 交给 handler 处理
|
|
2559
|
+
streaming.error = error;
|
|
2560
|
+
}
|
|
2561
|
+
this.streaming.handler(streaming);
|
|
2562
|
+
};
|
|
2563
|
+
return this.streaming;
|
|
2543
2564
|
}
|
|
2544
2565
|
}
|
|
2545
2566
|
//# sourceMappingURL=index.js.map
|